/// <summary> /// Creates a compilation options /// </summary> /// <returns>Compilation options</returns> private LocalJsCompilationOptions CreateCompilationOptions() { var options = new LocalJsCompilationOptions { AcceptConstKeyword = AcceptConstKeyword, AllowEs6Output = AllowEs6Output, AngularPass = AngularPass, DefinitionList = DefinitionList, ErrorList = ErrorList, ExportLocalPropertyDefinitions = ExportLocalPropertyDefinitions, ExtraAnnotationNameList = ExtraAnnotationNameList, GenerateExports = GenerateExports, LanguageInput = LanguageInput, LanguageOutput = LanguageOutput, ProcessClosurePrimitives = ProcessClosurePrimitives, ProcessJqueryPrimitives = ProcessJqueryPrimitives, SingleQuotes = SingleQuotes, ThirdParty = ThirdParty, TranspileOnly = TranspileOnly, TurnOffWarningClassList = TurnOffWarningClassList, UseOnlyCustomExterns = UseOnlyCustomExterns, WarningList = WarningList }; FillJsCompilationOptions(options); return(options); }
/// <summary> /// Creates a compilation options /// </summary> /// <returns>Compilation options</returns> private LocalJsCompilationOptions CreateCompilationOptions() { var options = new LocalJsCompilationOptions { AcceptConstKeyword = AcceptConstKeyword, AllowEs6Output = AllowEs6Output, AngularPass = AngularPass, DefinitionList = DefinitionList, ErrorList = ErrorList, ExportLocalPropertyDefinitions = ExportLocalPropertyDefinitions, ExtraAnnotationNameList = ExtraAnnotationNameList, GenerateExports = GenerateExports, LanguageInput = LanguageInput, LanguageOutput = LanguageOutput, ProcessClosurePrimitives = ProcessClosurePrimitives, ProcessJqueryPrimitives = ProcessJqueryPrimitives, SingleQuotes = SingleQuotes, ThirdParty = ThirdParty, TranspileOnly = TranspileOnly, TurnOffWarningClassList = TurnOffWarningClassList, UseOnlyCustomExterns = UseOnlyCustomExterns, WarningList = WarningList }; FillJsCompilationOptions(options); return options; }
/// <summary> /// Converts a compilation options to command line arguments /// </summary> /// <param name="options">Compilation options</param> /// <returns>Command line arguments</returns> private static string ConvertCompilationOptionsToArgs(LocalJsCompilationOptions options) { var args = new StringBuilder(); if (options.AcceptConstKeyword) { args.Append("--accept_const_keyword "); } if (options.AllowEs6Output) { args.Append("--allow_es6_out "); } if (options.AngularPass) { args.Append("--angular_pass "); } if (!string.IsNullOrWhiteSpace(options.Charset)) { args.AppendFormat("--charset {0} ", options.Charset); } args.AppendFormat("--compilation_level {0} ", ConvertCompilationLevelEnumValueToCode(options.CompilationLevel)); IDictionary<string, string> defs = ParseDefinitions(options.DefinitionList); if (defs.Count > 0) { foreach (KeyValuePair<string, string> def in defs) { string variableName = def.Key; string variableValue = def.Value; args.Append("--define "); args.Append(variableName); if (variableValue != null) { args.AppendFormat("={0}", variableValue); } args.Append(" "); } } string[] errors = Utils.ConvertToStringCollection(options.ErrorList, ',', trimItemValues: true, removeEmptyItems: true); if (errors.Length > 0) { foreach (string warningClassName in errors) { args.AppendFormat("--jscomp_error {0} ", warningClassName); } } if (options.ExportLocalPropertyDefinitions) { args.Append("--export_local_property_definitions "); } string[] extraAnnotationNames = Utils.ConvertToStringCollection(options.ExtraAnnotationNameList, ',', trimItemValues: true, removeEmptyItems: true); if (extraAnnotationNames.Length > 0) { foreach (string extraAnnotationName in extraAnnotationNames) { args.AppendFormat("--extra_annotation_name {0} ", extraAnnotationName); } } if (options.GenerateExports) { args.Append("--generate_exports "); } ExperimentalLanguageSpec languageInput = options.LanguageInput; if (languageInput != ExperimentalLanguageSpec.None) { args.AppendFormat("--language_in {0} ", ConvertLanguageSpecEnumValueToCode(languageInput)); } ExperimentalLanguageSpec languageOutput = (options.LanguageOutput != ExperimentalLanguageSpec.None) ? options.LanguageOutput : languageInput; if (languageOutput != ExperimentalLanguageSpec.None) { args.AppendFormat("--language_out {0} ", ConvertLanguageSpecEnumValueToCode(languageOutput)); } if (options.PrettyPrint) { args.Append("--formatting PRETTY_PRINT "); } if (options.ProcessClosurePrimitives) { args.Append("--process_closure_primitives "); } if (options.ProcessJqueryPrimitives) { args.Append("--process_jquery_primitives "); } if (options.SingleQuotes) { args.Append("--formatting SINGLE_QUOTES "); } if (options.ThirdParty) { args.Append("--third_party "); } if (options.TranspileOnly) { args.Append("--transpile_only "); } string[] turnOffWarningClasses = Utils.ConvertToStringCollection(options.TurnOffWarningClassList, ',', trimItemValues: true, removeEmptyItems: true); if (turnOffWarningClasses.Length > 0) { foreach (string warningClassName in turnOffWarningClasses) { args.AppendFormat("--jscomp_off {0} ", warningClassName); } } if (options.UseOnlyCustomExterns) { args.Append("--use_only_custom_externs "); } if (options.UseTypesForOptimization) { args.Append("--use_types_for_optimization "); } string[] warnings = Utils.ConvertToStringCollection(options.WarningList, ',', trimItemValues: true, removeEmptyItems: true); if (warnings.Length > 0) { foreach (string warningClassName in warnings) { args.AppendFormat("--jscomp_warning {0} ", warningClassName); } } int severity = options.Severity; if (severity >= 0 && severity <= 3) { args.Append("--warning_level "); switch (severity) { case 0: case 1: args.Append("QUIET "); break; case 2: args.Append("DEFAULT "); break; case 3: args.Append("VERBOSE "); break; } } return args.ToString(); }
/// <summary> /// Constructs a instance of local Closure Compiler /// </summary> /// <param name="javaVmPath">Path to Java Virtual Machine</param> /// <param name="closureCompilerAppPath">Path to Google Closure Compiler Application</param> /// <param name="tempDirectoryPath">Absolute path to directory that contains temporary files</param> /// <param name="commonExternsDependencies">List of common JS-externs dependencies</param> /// <param name="defaultOptions">Default compilation options</param> public ClosureLocalJsCompiler(string javaVmPath, string closureCompilerAppPath, string tempDirectoryPath, DependencyCollection commonExternsDependencies, LocalJsCompilationOptions defaultOptions) : base(commonExternsDependencies) { _javaVmPath = javaVmPath; _closureCompilerAppPath = closureCompilerAppPath; _tempDirectoryPath = tempDirectoryPath; _commonExternsTempDirectoryPath = string.Empty; _commonExternsTempDirectoryCreated = false; _commonExternsTempFilePaths = new List<string>(); _defaultOptions = defaultOptions; _defaultOptionsString = (defaultOptions != null) ? ConvertCompilationOptionsToArgs(defaultOptions) : "null"; }
/// <summary> /// "Compiles" a JS-code /// </summary> /// <param name="content">Text content written on JavaScript</param> /// <param name="path">Path to JS-file</param> /// <param name="externsDependencies">List of JS-externs dependencies</param> /// <param name="options">Compilation options</param> /// <returns>Compiled JS-code</returns> public string Compile(string content, string path, DependencyCollection externsDependencies, LocalJsCompilationOptions options = null) { string newContent; int commonExternsDependencyCount = _commonExternsDependencies.Count; string assetExternsTempDirectoryPath = Path.Combine(_tempDirectoryPath, Guid.NewGuid().ToString()); bool assetExternsTempDirectoryCreated = false; LocalJsCompilationOptions currentOptions; string currentOptionsString; if (options != null) { currentOptions = options; currentOptionsString = ConvertCompilationOptionsToArgs(options); } else { currentOptions = _defaultOptions; currentOptionsString = _defaultOptionsString; } var args = new StringBuilder(); args.AppendFormat(@"-jar ""{0}"" ", _closureCompilerAppPath); if (currentOptions.CompilationLevel == CompilationLevel.Advanced && (commonExternsDependencyCount > 0 || externsDependencies.Count > 0)) { if (!_commonExternsTempDirectoryCreated && commonExternsDependencyCount > 0) { WriteExternsToTempDirectory(_commonExternsDependencies, out _commonExternsTempDirectoryPath, out _commonExternsTempFilePaths); _commonExternsTempDirectoryCreated = true; } DependencyCollection assetExternsDependencies = new DependencyCollection(); if (commonExternsDependencyCount > 0) { foreach (Dependency externsDependency in externsDependencies) { if (!_commonExternsDependencies.ContainsUrl(externsDependency.Url)) { assetExternsDependencies.Add(externsDependency); } } } else { assetExternsDependencies.AddRange(externsDependencies); } IList<string> assetExternsTempFilePaths = new List<string>(); if (assetExternsDependencies.Count > 0) { WriteExternsToTempDirectory(assetExternsDependencies, out assetExternsTempDirectoryPath, out assetExternsTempFilePaths); assetExternsTempDirectoryCreated = true; } var allExternsTempFilePaths = new List<string>(); allExternsTempFilePaths.AddRange(_commonExternsTempFilePaths); allExternsTempFilePaths.AddRange(assetExternsTempFilePaths); foreach (string externsTempFilePath in allExternsTempFilePaths) { args.AppendFormat(@"--externs ""{0}"" ", externsTempFilePath); } } args.Append(currentOptionsString); var processInfo = new ProcessStartInfo { FileName = _javaVmPath, Arguments = args.ToString(), CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = false, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, }; var stdOutputBuilder = new StdContentBuilder(); var stdErrorBuilder = new StdContentBuilder(); Process process = null; try { process = new Process { StartInfo = processInfo }; process.OutputDataReceived += stdOutputBuilder.OnDataReceived; process.ErrorDataReceived += stdErrorBuilder.OnDataReceived; process.Start(); using (StreamWriter inputWriter = process.StandardInput) { inputWriter.Write(content); inputWriter.Flush(); } process.BeginErrorReadLine(); process.BeginOutputReadLine(); process.WaitForExit(); process.OutputDataReceived -= stdOutputBuilder.OnDataReceived; process.ErrorDataReceived -= stdErrorBuilder.OnDataReceived; string errorString = stdErrorBuilder.Content; if (!string.IsNullOrWhiteSpace(errorString)) { IList<string> errors; IList<string> warnings; ParseErrorDetails(errorString, path, out errors, out warnings); if (errors.Count > 0 || warnings.Count > 0) { if (errors.Count > 0) { throw new ClosureCompilingException(errors[0]); } if (currentOptions.Severity > 0 && warnings.Count > 0) { throw new ClosureCompilingException(warnings[0]); } } } newContent = stdOutputBuilder.Content; } finally { if (process != null) { process.Dispose(); } if (assetExternsTempDirectoryCreated && Directory.Exists(assetExternsTempDirectoryPath)) { Directory.Delete(assetExternsTempDirectoryPath, true); } } return newContent; }