HTML minifier
상속: IMarkupMinifier
        public override string MinifyString(string source)
        {
            var settings = new HtmlMinificationSettings
            {
                RemoveOptionalEndTags = false,
                AttributeQuotesRemovalMode = HtmlAttributeQuotesRemovalMode.KeepQuotes,
                RemoveRedundantAttributes = false,
                EmptyTagRenderMode = HtmlEmptyTagRenderMode.Slash,
            };

            var minifier = new HtmlMinifier(settings);
            MarkupMinificationResult result = minifier.Minify(source, generateStatistics: true);

            if (result.Errors.Count == 0)
            {
                EditorExtensionsPackage.DTE.StatusBar.Text = "Web Essentials: HTML minified by " + result.Statistics.SavedInPercent + "%";
                return result.MinifiedContent;
            }
            else
            {
                EditorExtensionsPackage.DTE.StatusBar.Text = "Web Essentials: Cannot minify the current selection.  See Output Window for details.";
                Logger.ShowMessage("Cannot minify the selection:\r\n\r\n" + String.Join(Environment.NewLine, result.Errors.Select(e => e.Message)));
                return null;
            }
        }
예제 #2
0
        /// <summary>
        /// Creates a instance of HTML minifier based on the settings
        /// that specified in configuration files (App.config or Web.config)
        /// </summary>
        /// <param name="settings">HTML minification settings</param>
        /// <param name="cssMinifier">CSS minifier</param>
        /// <param name="jsMinifier">JS minifier</param>
        /// <param name="logger">logger</param>
        /// <returns>HTML minifier</returns>
        public HtmlMinifier CreateHtmlMinifierInstance(HtmlMinificationSettings settings = null,
                                                       ICssMinifier cssMinifier          = null, IJsMinifier jsMinifier = null, ILogger logger = null)
        {
            HtmlMinificationSettings innerSettings    = settings ?? GetHtmlMinificationSettings();
            ICssMinifier             innerCssMinifier = cssMinifier ?? _wmmContext.Code.CreateDefaultCssMinifierInstance();
            IJsMinifier innerJsMinifier = jsMinifier ?? _wmmContext.Code.CreateDefaultJsMinifierInstance();
            ILogger     innerLogger     = logger ?? _wmmContext.GetDefaultLoggerInstance();

            var htmlMinifier = new HtmlMinifier(innerSettings, innerCssMinifier, innerJsMinifier, innerLogger);

            return(htmlMinifier);
        }
예제 #3
0
        internal static string Minify(string html)
        {
            var htmlMinifier = new HtmlMinifier();
            var result = htmlMinifier.Minify(html, false);

            if (result.Errors.Count == 0)
            {
                return result.MinifiedContent;
            }

            return html;
        }
        public HtmlMinificationViewModel Minify(HtmlMinificationViewModel model)
        {
            string cssMinifierName = model.Settings.CssMinifierName;
            string jsMinifierName = model.Settings.JsMinifierName;

            var settings = Mapper.Map<HtmlMinificationSettings>(model.Settings);
            ICssMinifier cssMinifier = _cssMinifierFactory.CreateMinifier(cssMinifierName);
            IJsMinifier jsMinifier = _jsMinifierFactory.CreateMinifier(jsMinifierName);

            var htmlMinifier = new HtmlMinifier(settings, cssMinifier, jsMinifier);
            var result = htmlMinifier.Minify(model.SourceCode, true);

            model.Result = Mapper.Map<MarkupMinificationResultViewModel>(result);

            return model;
        }
예제 #5
0
        /// <summary>
        /// Modifies the HTML by adding common meta tags, css and js.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="sourceStream">The source stream.</param>
        /// <param name="mode">The mode.</param>
        /// <param name="appVersion">The application version.</param>
        /// <param name="localizationCulture">The localization culture.</param>
        /// <param name="enableMinification">if set to <c>true</c> [enable minification].</param>
        /// <returns>Task{Stream}.</returns>
        public async Task<Stream> ModifyHtml(string path, Stream sourceStream, string mode, string appVersion, string localizationCulture, bool enableMinification)
        {
            using (sourceStream)
            {
                string html;

                using (var memoryStream = new MemoryStream())
                {
                    await sourceStream.CopyToAsync(memoryStream).ConfigureAwait(false);

                    html = Encoding.UTF8.GetString(memoryStream.ToArray());

                    if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
                    {
                    }
                    else if (!string.IsNullOrWhiteSpace(path) && !string.Equals(path, "index.html", StringComparison.OrdinalIgnoreCase))
                    {
                        var index = html.IndexOf("<body", StringComparison.OrdinalIgnoreCase);
                        if (index != -1)
                        {
                            html = html.Substring(index);
                            index = html.IndexOf("</body>", StringComparison.OrdinalIgnoreCase);
                            if (index != -1)
                            {
                                html = html.Substring(0, index+7);
                            }
                        }
                        var mainFile = File.ReadAllText(GetDashboardResourcePath("index.html"));

                        html = ReplaceFirst(mainFile, "<div class=\"mainAnimatedPages skinBody\"></div>", "<div class=\"mainAnimatedPages skinBody hide\">" + html + "</div>");
                    }

                    if (!string.IsNullOrWhiteSpace(localizationCulture))
                    {
                        var lang = localizationCulture.Split('-').FirstOrDefault();

                        html = html.Replace("<html", "<html data-culture=\"" + localizationCulture + "\" lang=\"" + lang + "\"");
                    }

                    if (enableMinification)
                    {
                        try
                        {
                            var minifier = new HtmlMinifier(new HtmlMinificationSettings
                            {
                                AttributeQuotesRemovalMode = HtmlAttributeQuotesRemovalMode.KeepQuotes,
                                RemoveOptionalEndTags = false,
                                RemoveTagsWithoutContent = false
                            });
                            var result = minifier.Minify(html, false);

                            if (result.Errors.Count > 0)
                            {
                                _logger.Error("Error minifying html: " + result.Errors[0].Message);
                            }
                            else
                            {
                                html = result.MinifiedContent;
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.ErrorException("Error minifying html", ex);
                        }
                    }
                }

                html = html.Replace("<head>", "<head>" + GetMetaTags(mode) + GetCommonCss(mode, appVersion));

                // Disable embedded scripts from plugins. We'll run them later once resources have loaded
                if (html.IndexOf("<script", StringComparison.OrdinalIgnoreCase) != -1)
                {
                    html = html.Replace("<script", "<!--<script");
                    html = html.Replace("</script>", "</script>-->");
                }

                html = html.Replace("</body>", GetCommonJavascript(mode, appVersion) + "</body>");

                var bytes = Encoding.UTF8.GetBytes(html);

                return new MemoryStream(bytes);
            }
        }
예제 #6
0
        /// <summary>
        /// Modifies the HTML by adding common meta tags, css and js.
        /// </summary>
        /// <param name="sourceStream">The source stream.</param>
        /// <param name="mode">The mode.</param>
        /// <param name="appVersion">The application version.</param>
        /// <param name="localizationCulture">The localization culture.</param>
        /// <param name="enableMinification">if set to <c>true</c> [enable minification].</param>
        /// <returns>Task{Stream}.</returns>
        public async Task<Stream> ModifyHtml(Stream sourceStream, string mode, string appVersion, string localizationCulture, bool enableMinification)
        {
            using (sourceStream)
            {
                string html;

                using (var memoryStream = new MemoryStream())
                {
                    await sourceStream.CopyToAsync(memoryStream).ConfigureAwait(false);

                    html = Encoding.UTF8.GetString(memoryStream.ToArray());

                    if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
                    {
                        html = ModifyForCordova(html);
                    }

                    if (!string.IsNullOrWhiteSpace(localizationCulture))
                    {
                        var lang = localizationCulture.Split('-').FirstOrDefault();

                        html = html.Replace("<html>", "<html data-culture=\"" + localizationCulture + "\" lang=\"" + lang + "\">");
                    }

                    if (enableMinification)
                    {
                        try
                        {
                            var minifier = new HtmlMinifier(new HtmlMinificationSettings
                            {
                                AttributeQuotesRemovalMode = HtmlAttributeQuotesRemovalMode.KeepQuotes,
                                RemoveOptionalEndTags = false,
                                RemoveTagsWithoutContent = false
                            });
                            var result = minifier.Minify(html, false);

                            if (result.Errors.Count > 0)
                            {
                                _logger.Error("Error minifying html: " + result.Errors[0].Message);
                            }
                            else
                            {
                                html = result.MinifiedContent;
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.ErrorException("Error minifying html", ex);
                        }
                    }

                    html = html.Replace("<body>", "<body><paper-drawer-panel class=\"mainDrawerPanel mainDrawerPanelPreInit\" forceNarrow><div class=\"mainDrawer\" drawer></div><div class=\"mainDrawerPanelContent\" main><!--<div class=\"pageContainer\">")
                        .Replace("</body>", "</div>--></div></paper-drawer-panel></body>");
                }

                var versionString = !string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase) ? "?v=" + appVersion : string.Empty;

                var imports = new[]
                {
                    "vulcanize-out.html" + versionString
                };
                var importsHtml = string.Join("", imports.Select(i => "<link rel=\"import\" href=\"" + i + "\">").ToArray());

                // It would be better to make polymer completely dynamic and loaded on demand, but seeing issues with that
                // In chrome it is causing the body to be hidden while loading, which leads to width-check methods to return 0 for everything
                //imports = "";

                html = html.Replace("<head>", "<head>" + GetMetaTags(mode) + GetCommonCss(mode, appVersion));

                html = html.Replace("</body>", GetInitialJavascript(mode, appVersion) + importsHtml + GetCommonJavascript(mode, appVersion) + "</body>");

                var bytes = Encoding.UTF8.GetBytes(html);

                return new MemoryStream(bytes);
            }
        }
예제 #7
0
        public static string MinifyString(string extension, string content)
        {
            if (extension == ".css")
            {
                Minifier minifier = new Minifier();
                CssSettings settings = new CssSettings();
                settings.CommentMode = CssComment.None;

                if (WESettings.GetBoolean(WESettings.Keys.KeepImportantComments))
                {
                    settings.CommentMode = CssComment.Important;
                }

                return minifier.MinifyStyleSheet(content, settings);
            }
            else if (extension == ".js")
            {
                Minifier minifier = new Minifier();
                CodeSettings settings = new CodeSettings()
                {
                    EvalTreatment = EvalTreatment.MakeImmediateSafe,
                    PreserveImportantComments = WESettings.GetBoolean(WESettings.Keys.KeepImportantComments)
                };

                return minifier.MinifyJavaScript(content, settings);
            }
            else if (_htmlExt.Contains(extension.ToLowerInvariant())){
                var settings = new HtmlMinificationSettings
                {
                    RemoveOptionalEndTags = false,
                    AttributeQuotesRemovalMode = HtmlAttributeQuotesRemovalMode.KeepQuotes
                };

                var minifier = new HtmlMinifier(settings);
                MarkupMinificationResult result = minifier.Minify(content, generateStatistics: true);

                if (result.Errors.Count == 0)
                {
                    EditorExtensionsPackage.DTE.StatusBar.Text = "Web Essentials: HTML minified by " + result.Statistics.SavedInPercent + "%";
                    return result.MinifiedContent;
                }
                else
                {
                    EditorExtensionsPackage.DTE.StatusBar.Text = "Web Essentials: Cannot minify the current selection";
                    return content;
                }
            }

            return null;
        }
예제 #8
0
        /// <summary>
        /// Modifies the HTML by adding common meta tags, css and js.
        /// </summary>
        /// <param name="sourceStream">The source stream.</param>
        /// <param name="mode">The mode.</param>
        /// <param name="appVersion">The application version.</param>
        /// <param name="localizationCulture">The localization culture.</param>
        /// <param name="enableMinification">if set to <c>true</c> [enable minification].</param>
        /// <returns>Task{Stream}.</returns>
        public async Task<Stream> ModifyHtml(Stream sourceStream, string mode, string appVersion, string localizationCulture, bool enableMinification)
        {
            using (sourceStream)
            {
                string html;

                using (var memoryStream = new MemoryStream())
                {
                    await sourceStream.CopyToAsync(memoryStream).ConfigureAwait(false);

                    html = Encoding.UTF8.GetString(memoryStream.ToArray());

                    if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
                    {
                        html = ModifyForCordova(html);
                    }

                    if (!string.IsNullOrWhiteSpace(localizationCulture))
                    {
                        var lang = localizationCulture.Split('-').FirstOrDefault();

                        html = html.Replace("<html>", "<html data-culture=\"" + localizationCulture + "\" lang=\"" + lang + "\">");
                    }

                    if (enableMinification)
                    {
                        try
                        {
                            var minifier = new HtmlMinifier(new HtmlMinificationSettings
                            {
                                AttributeQuotesRemovalMode = HtmlAttributeQuotesRemovalMode.KeepQuotes,
                                RemoveOptionalEndTags = false,
                                RemoveTagsWithoutContent = false
                            });
                            var result = minifier.Minify(html, false);

                            if (result.Errors.Count > 0)
                            {
                                _logger.Error("Error minifying html: " + result.Errors[0].Message);
                            }
                            else
                            {
                                html = result.MinifiedContent;
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.ErrorException("Error minifying html", ex);
                        }
                    }

                    html = html.Replace("<body>", "<body><paper-drawer-panel class=\"mainDrawerPanel mainDrawerPanelPreInit\" forceNarrow><div class=\"mainDrawer\" drawer></div><div class=\"mainDrawerPanelContent\" main><!--<div class=\"pageContainer\">")
                        .Replace("</body>", "</div>--></div></paper-drawer-panel></body>");
                }

                html = html.Replace("<head>", "<head>" + GetMetaTags(mode) + GetCommonCss(mode, appVersion));

                html = html.Replace("</body>", GetCommonJavascript(mode, appVersion) + "</body>");

                var bytes = Encoding.UTF8.GetBytes(html);

                return new MemoryStream(bytes);
            }
        }
        public override void Flush()
        {
            if (string.IsNullOrEmpty(html))
            {
                // Nothing in the filter, output served by OutputCache module
                return;
            }

            var htmlMinifier = new WebMarkupMin.Core.HtmlMinifier(new HtmlMinificationSettings
            {
                WhitespaceMinificationMode              = settings.WhitespaceMinificationMode,
                RemoveHtmlComments                      = settings.RemoveHtmlComments,
                RemoveHtmlCommentsFromScriptsAndStyles  = settings.RemoveHtmlCommentsFromScriptsAndStyles,
                RemoveCdataSectionsFromScriptsAndStyles = settings.RemoveCdataSectionsFromScriptsAndStyles,
                UseShortDoctype                   = settings.UseShortDoctype,
                PreserveCase                      = settings.PreserveCase,
                UseMetaCharsetTag                 = settings.UseMetaCharsetTag,
                EmptyTagRenderMode                = settings.EmptyTagRenderMode,
                RemoveOptionalEndTags             = settings.RemoveOptionalEndTags,
                PreservableOptionalTagList        = settings.PreservableOptionalTagList,
                RemoveTagsWithoutContent          = settings.RemoveTagsWithoutContent,
                CollapseBooleanAttributes         = settings.CollapseBooleanAttributes,
                RemoveEmptyAttributes             = settings.RemoveEmptyAttributes,
                AttributeQuotesRemovalMode        = settings.AttributeQuotesRemovalMode,
                RemoveRedundantAttributes         = settings.RemoveRedundantAttributes,
                RemoveJsTypeAttributes            = settings.RemoveJsTypeAttributes,
                RemoveCssTypeAttributes           = settings.RemoveCssTypeAttributes,
                RemoveHttpProtocolFromAttributes  = settings.RemoveHttpProtocolFromAttributes,
                RemoveHttpsProtocolFromAttributes = settings.RemoveHttpsProtocolFromAttributes,
                RemoveJsProtocolFromAttributes    = settings.RemoveJsProtocolFromAttributes,
                MinifyEmbeddedCssCode             = settings.MinifyEmbeddedCssCode,
                MinifyInlineCssCode               = settings.MinifyInlineCssCode,
                MinifyEmbeddedJsCode              = settings.MinifyEmbeddedJsCode,
                MinifyInlineJsCode                = settings.MinifyInlineJsCode,
                ProcessableScriptTypeList         = settings.ProcessableScriptTypeList,
                MinifyKnockoutBindingExpressions  = settings.MinifyKnockoutBindingExpressions,
                MinifyAngularBindingExpressions   = settings.MinifyAngularBindingExpressions,
                CustomAngularDirectiveList        = settings.CustomAngularDirectiveList
            });

            var generateStatistics = !string.IsNullOrWhiteSpace(settings.StatisticsInfoWindowPattern) && isOwner;

            var result = htmlMinifier.Minify(html, string.Empty, encoding, generateStatistics);

            foreach (var error in result.Errors)
            {
                Logger.Error(error.Message);
            }

            var shouldHaltOnWarnings = result.Warnings.Count > 0 && settings.HaltOnWarnings;

            foreach (var warning in result.Warnings)
            {
                if (shouldHaltOnWarnings)
                {
                    Logger.Error(warning.Message);
                }
                else
                {
                    Logger.Warning(warning.Message);
                }
            }

            if (result.Errors.Count == 0 && (result.Warnings.Count == 0 || !shouldHaltOnWarnings))
            {
                html = result.MinifiedContent;

                if (generateStatistics)
                {
                    var statistics = settings.StatisticsInfoWindowPattern
                                     .Replace("{Gzip-CompressionRatio}", $"{(float)result.Statistics.CompressionGzipRatio / 100:P1}")
                                     .Replace("{CompressionRatio}", $"{(float)result.Statistics.CompressionRatio / 100:P1}")
                                     .Replace("{MinificationDuration}", $"{result.Statistics.MinificationDuration} ms")
                                     .Replace("{Gzip-OriginalSize}", $"{(float)result.Statistics.OriginalGzipSize / 1000:F} KB")
                                     .Replace("{OriginalSize}", $"{(float)result.Statistics.OriginalSize / 1000:N} KB")
                                     .Replace("{Gzip-MinifiedSize}", $"{(float)result.Statistics.MinifiedGzipSize / 1000:N} KB")
                                     .Replace("{MinifiedSize}", $"{(float)result.Statistics.MinifiedSize / 1000:N} KB")
                                     .Replace("{Gzip-Saved}", $"{(float)result.Statistics.SavedGzipInBytes / 1000:N} KB")
                                     .Replace("{Gzip-SavedInPercent}", $"{(float)result.Statistics.SavedGzipInPercent / 100:P1}")
                                     .Replace("{Saved}", $"{(float)result.Statistics.SavedInBytes / 1000:N} KB")
                                     .Replace("{SavedInPercent}", $"{(float)result.Statistics.SavedInPercent / 100:P1}");

                    result = htmlMinifier.Minify(statistics, encoding);

                    var bodyIndex = html.IndexOf("</body>", StringComparison.Ordinal);

                    if (bodyIndex > 0)
                    {
                        html = html.Insert(bodyIndex, result.MinifiedContent);
                    }
                    else
                    {
                        html += result.MinifiedContent;
                    }
                }
            }

            stream.Write(encoding.GetBytes(html), 0, encoding.GetByteCount(html));
        }
예제 #10
0
        public override string MinifyString(string source)
        {
            var weHtmlSettings = WESettings.Instance.Html;
            var settings = new HtmlMinificationSettings
            {
                PreserveCase = weHtmlSettings.PreserveCase,

                // Tags
                RemoveOptionalEndTags = false,
                //EmptyTagRenderMode = HtmlEmptyTagRenderMode.Slash,

                // Attributes
                AttributeQuotesRemovalMode = weHtmlSettings.AttributeQuotesRemovalMode,
                RemoveRedundantAttributes = false,

                // JavaScript templating
                ProcessableScriptTypeList = weHtmlSettings.ProcessableScriptTypeList,
                MinifyKnockoutBindingExpressions = weHtmlSettings.MinifyKnockoutBindingExpressions,
                MinifyAngularBindingExpressions = weHtmlSettings.MinifyAngularBindingExpressions,
                CustomAngularDirectiveList = weHtmlSettings.CustomAngularDirectiveList
            };

            var minifier = new HtmlMinifier(settings);
            MarkupMinificationResult result = minifier.Minify(source, generateStatistics: true);

            if (result.Errors.Count == 0)
            {
                WebEssentialsPackage.DTE.StatusBar.Text = "Web Essentials: HTML minified by " + result.Statistics.SavedInPercent + "%";
                return result.MinifiedContent;
            }
            else
            {
                WebEssentialsPackage.DTE.StatusBar.Text = "Web Essentials: Cannot minify the current selection.  See Output Window for details.";
                Logger.ShowMessage("Cannot minify the selection:\r\n\r\n" + String.Join(Environment.NewLine, result.Errors.Select(e => e.Message)));
                return null;
            }
        }
예제 #11
0
        /// <summary>
        /// Modifies the HTML by adding common meta tags, css and js.
        /// </summary>
        /// <param name="sourceStream">The source stream.</param>
        /// <param name="mode">The mode.</param>
        /// <param name="localizationCulture">The localization culture.</param>
        /// <param name="enableMinification">if set to <c>true</c> [enable minification].</param>
        /// <returns>Task{Stream}.</returns>
        public async Task<Stream> ModifyHtml(Stream sourceStream, string mode, string localizationCulture, bool enableMinification)
        {
            using (sourceStream)
            {
                string html;

                using (var memoryStream = new MemoryStream())
                {
                    await sourceStream.CopyToAsync(memoryStream).ConfigureAwait(false);

                    html = Encoding.UTF8.GetString(memoryStream.ToArray());

                    if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
                    {
                        html = ModifyForCordova(html);
                    }

                    if (!string.IsNullOrWhiteSpace(localizationCulture))
                    {
                        var lang = localizationCulture.Split('-').FirstOrDefault();

                        html = _localization.LocalizeDocument(html, localizationCulture, GetLocalizationToken);

                        html = html.Replace("<html>", "<html lang=\"" + lang + "\">");
                    }

                    if (enableMinification)
                    {
                        try
                        {
                            var minifier = new HtmlMinifier(new HtmlMinificationSettings
                            {
                                AttributeQuotesRemovalMode = HtmlAttributeQuotesRemovalMode.KeepQuotes,
                                RemoveOptionalEndTags = false,
                                RemoveTagsWithoutContent = false
                            });
                            var result = minifier.Minify(html, false);

                            if (result.Errors.Count > 0)
                            {
                                _logger.Error("Error minifying html: " + result.Errors[0].Message);
                            }
                            else
                            {
                                html = result.MinifiedContent;
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.ErrorException("Error minifying html", ex);
                        }
                    }
                }

                var version = GetType().Assembly.GetName().Version;

                var imports = "<link rel=\"import\" href=\"thirdparty/polymer/polymer.html\">";
                imports = "";

                html = html.Replace("<head>", "<head>" + GetMetaTags(mode) + GetCommonCss(mode, version) + GetCommonJavascript(mode, version) + imports);

                var bytes = Encoding.UTF8.GetBytes(html);

                return new MemoryStream(bytes);
            }
        }
예제 #12
0
파일: MinifyHtml.cs 프로젝트: ibebbs/Wyam
        public IEnumerable<IDocument> Execute(IReadOnlyList<IDocument> inputs, IExecutionContext context)
        {
            HtmlMinifier minifier = new HtmlMinifier(_minificationSettings);

            return Minify(inputs, context, minifier.Minify, "HTML");
        }