public static bool Apply(TextWriter writer, AstNode node, CodeSettings settings)
        {
            if (node != null)
            {
                var visitor = new JSONOutputVisitor(writer, settings);
                node.Accept(visitor);
                return(visitor.IsValid);
            }

            return(false);
        }
        /// <summary>
        /// Crunched JS string passed to it, returning crunched string.
        /// The ErrorList property will be set with any errors found during the minification process.
        /// </summary>
        /// <param name="source">source Javascript</param>
        /// <param name="codeSettings">code minification settings</param>
        /// <returns>minified Javascript</returns>
        public string MinifyJavaScript(string source, CodeSettings codeSettings)
        {
            // default is an empty string
            var crunched = string.Empty;

            // reset the errors builder
            m_errorList = new List <ContextError>();

            // create the parser and hook the engine error event
            var parser = new JSParser();

            parser.CompilerError += OnJavaScriptError;

            try
            {
                var preprocessOnly = codeSettings != null && codeSettings.PreprocessOnly;
                var sb             = new StringBuilder();
                using (var stringWriter = new StringWriter(sb, CultureInfo.InvariantCulture))
                {
                    if (preprocessOnly)
                    {
                        parser.EchoWriter = stringWriter;
                    }

                    // parse the input
                    var scriptBlock = parser.Parse(new DocumentContext(source)
                    {
                        FileContext = this.FileName
                    }, codeSettings);
                    if (scriptBlock != null && !preprocessOnly)
                    {
                        // we'll return the crunched code
                        if (codeSettings != null && codeSettings.Format == JavaScriptFormat.JSON)
                        {
                            // we're going to use a different output visitor -- one
                            // that specifically returns valid JSON.
                            if (!JSONOutputVisitor.Apply(stringWriter, scriptBlock, codeSettings))
                            {
                                m_errorList.Add(new ContextError()
                                {
                                    Severity = 0,
                                    File     = this.FileName,
                                    Message  = CommonStrings.InvalidJSONOutput,
                                });
                            }
                        }
                        else
                        {
                            // just use the normal output visitor
                            OutputVisitor.Apply(stringWriter, scriptBlock, codeSettings);
                        }
                    }
                }

                crunched = sb.ToString();
            }
            catch (Exception e)
            {
                m_errorList.Add(new ContextError()
                {
                    Severity = 0,
                    File     = this.FileName,
                    Message  = e.Message,
                });
                throw;
            }

            return(crunched);
        }
Exemple #3
0
        private int ProcessJSFile(IList <InputGroup> inputGroups, SwitchParser switchParser, StringBuilder outputBuilder)
        {
            var returnCode          = 0;
            var settings            = switchParser.JSSettings;
            var currentSourceOrigin = SourceOrigin.Project;

            // blank line before
            WriteProgress();

            // create our parser object and hook up some events
            var parser = new JSParser();

            parser.UndefinedReference += OnUndefinedReference;
            parser.CompilerError      += (sender, ea) =>
            {
                var error = ea.Error;
                if (currentSourceOrigin == SourceOrigin.Project || error.Severity == 0)
                {
                    // ignore severity values greater than our severity level
                    // also ignore errors that are in our ignore list (if any)
                    if (error.Severity <= switchParser.WarningLevel)
                    {
                        // we found an error
                        m_errorsFound = true;

                        // write the error out
                        WriteError(error.ToString());
                    }
                }
            };

            // output visitor requires a text writer, so make one from the string builder
            using (var writer = new StringWriter(outputBuilder, CultureInfo.InvariantCulture))
            {
                var outputIndex         = 0;
                var originalTermSetting = settings.TermSemicolons;
                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 this is preprocess-only or echo-input, then set up the writer as the echo writer for the parser
                    if (settings.PreprocessOnly || m_echoInput)
                    {
                        parser.EchoWriter = writer;
                        if (inputGroupIndex > 0)
                        {
                            // separate subsequent input groups with an appropriate line terminator
                            writer.Write(settings.LineTerminator);
                            writer.Write(';');
                            writer.Write(settings.LineTerminator);
                        }
                    }
                    else
                    {
                        // not a preprocess-only or echo - make sure the echo writer is null
                        parser.EchoWriter = null;
                    }

                    // parse the input code. Don't use a source context because it should already be
                    // in the source using ///#SOURCE comments as we assembled the input groups.
                    var scriptBlock = parser.Parse(inputGroup.Source, settings);

                    if (m_errorsFound)
                    {
                        WriteProgress();
                    }

                    if (m_outputTimer)
                    {
                        OutputTimingPoints(parser, inputGroupIndex, inputGroups.Count);
                    }

                    if (!settings.PreprocessOnly && !m_echoInput)
                    {
                        if (scriptBlock != null)
                        {
                            if (outputIndex++ > 0)
                            {
                                // separate subsequent input groups with an appropriate line terminator
                                writer.Write(settings.LineTerminator);
                            }

                            // crunch the output and write it to debug stream, but make sure
                            // the settings we use to output THIS chunk are correct
                            if (settings.Format == JavaScriptFormat.JSON)
                            {
                                if (!JSONOutputVisitor.Apply(writer, scriptBlock, settings))
                                {
                                    returnCode = 1;
                                }
                            }
                            else
                            {
                                OutputVisitor.Apply(writer, scriptBlock, settings);
                            }
                        }
                        else
                        {
                            // no code?
                            WriteProgress(AjaxMin.NoParsedCode);
                        }
                    }
                }

                // give the symbols map a chance to write something at the bottom of the source file
                // (and if this isn't preprocess-only or echo)
                if (settings.SymbolsMap != null && !settings.PreprocessOnly && !m_echoInput)
                {
                    settings.SymbolsMap.EndFile(writer, settings.LineTerminator);
                }
            }

            if (switchParser.AnalyzeMode)
            {
                // blank line before
                WriteProgress();

                // output our report
                CreateReport(parser.GlobalScope, switchParser);
            }

            return(returnCode);
        }
Exemple #4
0
        /// <summary>
        /// Crunched JS string passed to it, returning crunched string.
        /// The ErrorList property will be set with any errors found during the minification process.
        /// </summary>
        /// <param name="source">source Javascript</param>
        /// <param name="codeSettings">code minification settings</param>
        /// <returns>minified Javascript</returns>
        public string MinifyJavaScript(string source, CodeSettings codeSettings)
        {
            // default is an empty string
            var crunched = string.Empty;

            // reset the errors builder
            m_errorList = new List <ContextError>();

            // create the parser from the source string.
            // pass null for the assumed globals array
            var parser = new JSParser(source);

            // file context is a property on the parser
            parser.FileContext = FileName;

            // hook the engine error event
            parser.CompilerError += OnJavaScriptError;

            try
            {
                if (codeSettings != null && codeSettings.PreprocessOnly)
                {
                    // just run through the preprocessor only
                    crunched = parser.PreprocessOnly(codeSettings);
                }
                else
                {
                    // parse the input
                    var scriptBlock = parser.Parse(codeSettings);
                    if (scriptBlock != null)
                    {
                        // we'll return the crunched code
                        if (codeSettings != null && codeSettings.Format == JavaScriptFormat.JSON)
                        {
                            // we're going to use a different output visitor -- one
                            // that specifically returns valid JSON.
                            var sb = new StringBuilder();
                            using (var stringWriter = new StringWriter(sb, CultureInfo.InvariantCulture))
                            {
                                if (!JSONOutputVisitor.Apply(stringWriter, scriptBlock))
                                {
                                    m_errorList.Add(new ContextError(
                                                        true,
                                                        0,
                                                        null,
                                                        null,
                                                        null,
                                                        this.FileName,
                                                        0,
                                                        0,
                                                        0,
                                                        0,
                                                        JScript.InvalidJSONOutput));
                                }
                            }

                            crunched = sb.ToString();
                        }
                        else
                        {
                            // just use the normal output visitor
                            crunched = scriptBlock.ToCode();
                        }
                    }
                }
            }
            catch (Exception e)
            {
                m_errorList.Add(new ContextError(
                                    true,
                                    0,
                                    null,
                                    null,
                                    null,
                                    this.FileName,
                                    0,
                                    0,
                                    0,
                                    0,
                                    e.Message));
                throw;
            }

            return(crunched);
        }