trullock / NUglify

NUglify is a HTML, JavaScript and CSS minification Library for .NET (fork of AjaxMin + new features)
Other
398 stars 79 forks source link

Support for some tags not to be minified #376

Open SplendidDream opened 1 year ago

SplendidDream commented 1 year ago

NUglify version 1.21.0

Enhancement Is it possible to keep tag elements in their raw format output without minify them, e.g. template, pre, textarea ? The reason, maybe some tags have template variables or are used to display source code or do not allow changes to the content.

To Reproduce

var settings = new NUglify.Html.HtmlSettings();
var result = NUglify.Uglify.Html(@"
<template>
    <div style=""{{if !show}}display:none;{{/if}}"">
    name: {{data.name}}
    </div>
    <script> alert(0) </script>
</template>
<pre>
    <span> name: Tom </span>
</pre>
<div>
    <span> name: Tom </span>
</div>
", settings);

Minified output result.Code:

<template><div style="{{if !show}}display:none;{{/if}}">name: {{data.name}}</div><script>alert(0)</script></template><pre>
    <span> name: Tom </span>
</pre><div><span>name: Tom</span></div>

result .Errors:

{inner_css(1,1): run-time error CSS1062: Expected semicolon or closing curly-brace, found '{'}
{inner_css(1,26): run-time error CSS1062: Expected semicolon or closing curly-brace, found '{'}

Excepted code The following settings are supported:

var settings = new NUglify.Html.HtmlSettings();
//Sets a list of tags that kept the raw output format.
settings.RawTags.Add("template");
settings.RawTags.Add("pre");
settings.RawTags.Add("textarea");

var result = NUglify.Uglify.Html(@"
<template>
    <div style=""{{if !show}}display:none;{{/if}}"">
    name: {{data.name}}
    </div>
    <script> alert(0) </script>
</template>
<pre>
    <span> name: Tom </span>
</pre>
<div>
    <span> name: Tom </span>
</div>
", settings);

result.Code:

<template>
    <div style=""{{if !show}}display:none;{{/if}}"">
    name: {{data.name}}
    </div>
    <script> alert(0) </script>
</template><pre>
    <span> name: Tom </span>
</pre><div><span>name: Tom</span></div>

Code implementation Maybe the code needs to be changed like this:

//HtmlMinifier.cs 
void ProcessNode(HtmlNode node)
{
    var element = node as HtmlElement;
    //New code start
    if (element != null && settings.RawTags.Count > 0 && settings.RawTags.Contains(element.Name))
    {
        return;
    }
    //New code end

    bool isInXml = element?.Descriptor != null && (element.Descriptor.Category & ContentKind.Xml) != 0;
    if (isInXml)
        xmlNamespaceCount++;
    //.....
}

//HtmlSettings.cs
public HtmlSettings()
{
    KeepTags = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
    //New code: initialize
    RawTags = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
    //.....
}
//New code: property
public HashSet<string> RawTags { get; }
trullock commented 1 year ago

<pre and <textarea should already not have their whitespace collapsed. Are you saying this is not working? <template is missing and will be collapsed. This can be fixed.

this: <div style=""{{if !show}}display:none;{{/if}}""> is invalid HTML and i can't predict NUglify's output in this regard

SplendidDream commented 1 year ago

By set the TagsWithNonCollapsibleWhitespaces property, <pre> and <textarea> tags are supported to keep whitespace, but still compress the children tags, for example: Input:

<pre>
    <span style=""""> name: Tom </span>
    <p></p>
</pre>

Output:

<pre>
    <span> name: Tom </span>
    <p>
</pre>

The <span> and <p> tags are still minified. I need <pre,<textarea,<template tag to keep the children tags without any change.

{{...}} are template engine syntaxes such as Handlebars/Vue Template, which save template content via <template> tags. The children tag may not be standard html before it is rendered, so the raw content needs to be kept. For example, streamline the following code, the UglifyResult instance has two errors, but is legal as a template engine syntax.

<template id="tpt">
    <div style=""{{if !show}}display:none;{{/if}}"">
    name: {{data.name}}
    </div>
</template>

If HtmlSettings class provides a setting property that keep children tags in their raw format, the UglifyResult instance will not return an error. This could be an enhancement.