예제 #1
0
        private static SymbolMap ReadSymbolMapElement(XmlReader reader)
        {
            bool flag;
            var  symbolMapNode = new SymbolMap();

            while (reader.Read())
            {
                // attributes, no child elements
                if (reader.Name == SymbolMapElementName && reader.HasAttributes)
                {
                    while (reader.MoveToNextAttribute())
                    {
                        switch (reader.Name)
                        {
                        case NameAttributeName:
                            symbolMapNode.Name = reader.Value;
                            break;

                        case PathAttributeName:
                            symbolMapNode.Path = reader.Value;
                            break;

                        case SourceRootAttributeName:
                            symbolMapNode.SourceRoot = reader.Value;
                            break;

                        case SafeAttributeName:
                            if (bool.TryParse(reader.Value, out flag))
                            {
                                symbolMapNode.SafeHeader = flag;
                            }
                            break;
                        }
                    }

                    // back to element
                    reader.MoveToElement();
                }
            }

            ((IDisposable)reader).Dispose();
            return(symbolMapNode);
        }
예제 #2
0
        void ProcessJavaScript(IList <InputGroup> inputGroups, UglifyCommandParser uglifyCommandParser, string outputPath, SymbolMap symbolMap, Encoding outputEncoding)
        {
            var        settings  = uglifyCommandParser.JSSettings;
            TextWriter mapWriter = null;
            ISourceMap sourceMap = null;

            try
            {
                // if we want a symbols map, we need to set it up now
                if (symbolMap != null && !settings.PreprocessOnly)
                {
                    // if we specified the path, use it. Otherwise just use the output path with
                    // ".map" appended to the end. Eg: output.js => output.js.map
                    var symbolMapPath = symbolMap.Path.IsNullOrWhiteSpace()
                        ? outputPath + ".map"
                        : symbolMap.Path;

                    // create the map writer and the source map implementation.
                    // look at the Name attribute and implement the proper one.
                    // the encoding needs to be UTF-8 WITHOUT a BOM or it won't work.
                    if (!FileWriteOperation(symbolMapPath, uglifyCommandParser.Clobber, () =>
                    {
                        mapWriter = new StreamWriter(symbolMapPath, false, new UTF8Encoding(false));
                        sourceMap = SourceMapFactory.Create(mapWriter, symbolMap.Name);
                        if (sourceMap != null)
                        {
                            // if we get here, the symbol map now owns the stream and we can null it out so
                            // we don't double-close it
                            mapWriter = null;
                            settings.SymbolsMap = sourceMap;

                            // copy some property values
                            sourceMap.SourceRoot = symbolMap.SourceRoot.IfNullOrWhiteSpace(null);
                            sourceMap.SafeHeader = symbolMap.SafeHeader.GetValueOrDefault(false);

                            // start the package
                            sourceMap.StartPackage(outputPath, symbolMapPath);
                        }

                        return(true);
                    }))
                    {
                        // could not write file
                        Log.LogError(Strings.CouldNotWriteOutputFile, symbolMapPath);
                    }
                }

                // save the original term settings. We'll make sure to set this back again
                // for the last item in the group, but we'll make sure it's TRUE for all the others.
                var originalTermSetting = settings.TermSemicolons;
                var currentSourceOrigin = SourceOrigin.Project;

                var parser = new JSParser();
                parser.CompilerError += (sender, ea) =>
                {
                    // if the input group isn't project, then we only want to report sev-0 errors.
                    // regardless, don't show any errors that have a severity lower (greater numeric value)
                    // than the warning level specified.
                    if ((currentSourceOrigin == SourceOrigin.Project || ea.Error.Severity == 0) &&
                        ea.Error.Severity <= uglifyCommandParser.WarningLevel)
                    {
                        LogContextError(ea.Error);
                    }
                };

                var outputBuilder = new StringBuilder(8192);
                using (var writer = new StringWriter(outputBuilder, CultureInfo.InvariantCulture))
                {
                    for (var inputGroupIndex = 0; inputGroupIndex < inputGroups.Count; ++inputGroupIndex)
                    {
                        var inputGroup = inputGroups[inputGroupIndex];
                        currentSourceOrigin = inputGroup.Origin;

                        // for all but the last item, we want the term-semicolons setting to be true.
                        // but for the last entry, set it back to its original value
                        settings.TermSemicolons = inputGroupIndex < inputGroups.Count - 1 ? true : originalTermSetting;

                        if (settings.PreprocessOnly)
                        {
                            parser.EchoWriter = writer;

                            if (inputGroupIndex > 0)
                            {
                                // not the first group, so output the appropriate newline
                                // sequence before we output the group.
                                writer.Write(settings.LineTerminator);
                            }
                        }
                        else
                        {
                            // not preprocess-only, so make sure the echo writer is null
                            parser.EchoWriter = null;
                        }

                        // parse the input
                        var block = parser.Parse(inputGroup.Source, settings);
                        if (block != null && !settings.PreprocessOnly)
                        {
                            if (inputGroupIndex > 0)
                            {
                                // not the first group, so output the appropriate newline
                                // sequence before we output the group.
                                writer.Write(settings.LineTerminator);
                            }

                            // minify the AST to the output
                            if (settings.Format == JavaScriptFormat.JSON)
                            {
                                if (!JsonOutputVisitor.Apply(writer, block, settings))
                                {
                                    Log.LogError(Strings.InvalidJSONOutput);
                                }
                            }
                            else
                            {
                                OutputVisitor.Apply(writer, block, settings);
                            }
                        }
                    }
                }

                // write output
                if (!Log.HasLoggedErrors)
                {
                    if (!FileWriteOperation(outputPath, uglifyCommandParser.Clobber, () =>
                    {
                        using (var writer = new StreamWriter(outputPath, false, outputEncoding))
                        {
                            // write the combined minified code
                            writer.Write(outputBuilder.ToString());

                            if (!settings.PreprocessOnly)
                            {
                                // give the map (if any) a chance to add something
                                settings.SymbolsMap.IfNotNull(m => m.EndFile(
                                                                  writer,
                                                                  settings.LineTerminator));
                            }
                        }

                        return(true);
                    }))
                    {
                        // could not write file
                        Log.LogError(Strings.CouldNotWriteOutputFile, outputPath);
                    }
                }
                else
                {
                    Log.LogWarning(Strings.DidNotMinify, outputPath, Strings.ThereWereErrors);
                    if (File.Exists(outputPath))
                    {
                        File.Delete(outputPath);
                    }
                }
            }
            finally
            {
                if (sourceMap != null)
                {
                    mapWriter           = null;
                    settings.SymbolsMap = null;
                    sourceMap.EndPackage();
                    sourceMap.Dispose();
                }

                if (mapWriter != null)
                {
                    mapWriter.Close();
                }
            }
        }