Do not minify non-JS script data

This commit is contained in:
Wilson Lin 2020-07-25 13:22:25 +10:00
parent 9a26aaa493
commit 9627921cb2
4 changed files with 17 additions and 8 deletions

View File

@ -42,7 +42,7 @@ Since speed depends on the input, speed charts show performance relative to the
The settings used for each minifier can be found in [minifiers.js](./minifiers.js). Some settings to note: The settings used for each minifier can be found in [minifiers.js](./minifiers.js). Some settings to note:
- CSS minification is disabled for all, as minify-html currently does not support CSS minification (coming soon). - CSS minification is disabled for all, as minify-html currently does not support CSS minification (coming soon).
- To increase fairness, all minifiers use esbuild for JS minification, and do so asynchronously and in parallel, similar to how minify-html works. - All minifiers are configured to use esbuild for JS minification asynchronously and in parallel, similar to how minify-html works.
- `conservativeCollapse` is enabled for html-minifier as otherwise some whitespace would be unsafely removed with side affects. minify-html can safely remove whitespace with context if configured properly. - `conservativeCollapse` is enabled for html-minifier as otherwise some whitespace would be unsafely removed with side affects. minify-html can safely remove whitespace with context if configured properly.
## Running ## Running

View File

@ -168,6 +168,7 @@ fn test_script_type_attr_value_removal() {
eval(b"<script type=\"application/ecmascript\"></script>", b"<script></script>"); eval(b"<script type=\"application/ecmascript\"></script>", b"<script></script>");
eval(b"<script type=\"application/javascript\"></script>", b"<script></script>"); eval(b"<script type=\"application/javascript\"></script>", b"<script></script>");
eval(b"<script type=\"text/jscript\"></script>", b"<script></script>"); eval(b"<script type=\"text/jscript\"></script>", b"<script></script>");
eval(b"<script type=\"text/plain\"></script>", b"<script type=text/plain></script>");
} }
#[test] #[test]
@ -304,4 +305,5 @@ fn test_js_minification() {
<script>let a = 1;</script> <script>let a = 1;</script>
<script>let b = 2;</script> <script>let b = 2;</script>
"#, b"<script>let a=1;</script><script>let b=2;</script>"); "#, b"<script>let a=1;</script><script>let b=2;</script>");
eval_with_js_min(b"<script type=text/plain> alert(1.00000); </script>", b"<script type=text/plain> alert(1.00000); </script>");
} }

View File

@ -25,7 +25,7 @@ lazy_static! {
}; };
} }
pub fn process_script(proc: &mut Processor, cfg: &Cfg) -> ProcessingResult<()> { pub fn process_script(proc: &mut Processor, cfg: &Cfg, js: bool) -> ProcessingResult<()> {
#[cfg(feature = "js-esbuild")] #[cfg(feature = "js-esbuild")]
let start = Checkpoint::new(proc); let start = Checkpoint::new(proc);
loop { loop {
@ -35,7 +35,7 @@ pub fn process_script(proc: &mut Processor, cfg: &Cfg) -> ProcessingResult<()> {
// `process_tag` will require closing tag. // `process_tag` will require closing tag.
if proc.m(IsSeq(b"</script"), MatchOnly).nonempty() { if proc.m(IsSeq(b"</script"), MatchOnly).nonempty() {
#[cfg(feature = "js-esbuild")] #[cfg(feature = "js-esbuild")]
if cfg.minify_js { if js && cfg.minify_js {
let (wg, results) = proc.new_script_section(); let (wg, results) = proc.new_script_section();
let src = start.written_range(proc); let src = start.written_range(proc);
// TODO Optimise: Avoid copying to new Vec. // TODO Optimise: Avoid copying to new Vec.

View File

@ -42,7 +42,8 @@ lazy_static! {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
enum TagType { enum TagType {
Script, ScriptJs,
ScriptData,
Style, Style,
Other, Other,
} }
@ -110,8 +111,9 @@ pub fn process_tag(proc: &mut Processor, cfg: &Cfg, ns: Namespace, mut prev_sibl
// Write previously skipped name and use written code as range (otherwise source code will eventually be overwritten). // Write previously skipped name and use written code as range (otherwise source code will eventually be overwritten).
let tag_name = proc.write_range(source_tag_name); let tag_name = proc.write_range(source_tag_name);
let tag_type = match &proc[tag_name] { let mut tag_type = match &proc[tag_name] {
b"script" => TagType::Script, // Unless non-JS MIME `type` is provided, `script` tags contain JS.
b"script" => TagType::ScriptJs,
b"style" => TagType::Style, b"style" => TagType::Style,
_ => TagType::Other, _ => TagType::Other,
}; };
@ -153,13 +155,17 @@ pub fn process_tag(proc: &mut Processor, cfg: &Cfg, ns: Namespace, mut prev_sibl
let ProcessedAttr { name, typ, value } = process_attr(proc, ns, tag_name)?; let ProcessedAttr { name, typ, value } = process_attr(proc, ns, tag_name)?;
match (tag_type, &proc[name]) { match (tag_type, &proc[name]) {
(TagType::Script, b"type") => { // NOTE: We don't support multiple `type` attributes, so can't go from ScriptData => ScriptJs.
(TagType::ScriptJs, b"type") => {
// It's JS if the value is empty or one of `JAVASCRIPT_MIME_TYPES`. // It's JS if the value is empty or one of `JAVASCRIPT_MIME_TYPES`.
let script_tag_type_is_js = value let script_tag_type_is_js = value
.filter(|v| !JAVASCRIPT_MIME_TYPES.contains(&proc[*v])) .filter(|v| !JAVASCRIPT_MIME_TYPES.contains(&proc[*v]))
.is_none(); .is_none();
if script_tag_type_is_js { if script_tag_type_is_js {
erase_attr = true; erase_attr = true;
} else {
// Tag does not contain JS, don't minify JS.
tag_type = TagType::ScriptData;
}; };
} }
(_, name) => { (_, name) => {
@ -203,7 +209,8 @@ pub fn process_tag(proc: &mut Processor, cfg: &Cfg, ns: Namespace, mut prev_sibl
}; };
match tag_type { match tag_type {
TagType::Script => process_script(proc, cfg)?, TagType::ScriptData => process_script(proc, cfg, false)?,
TagType::ScriptJs => process_script(proc, cfg, true)?,
TagType::Style => process_style(proc)?, TagType::Style => process_style(proc)?,
_ => process_content(proc, cfg, child_ns, Some(tag_name))?, _ => process_content(proc, cfg, child_ns, Some(tag_name))?,
}; };