Let esbuild handle closing script and style tag escaping
This commit is contained in:
parent
920133fc18
commit
7612244a10
|
@ -5,6 +5,7 @@
|
|||
<title><title></titl></title>
|
||||
</head>
|
||||
<body>
|
||||
<ScrIPT></scRIpt>let x = 1;
|
||||
<div =x =x=1 ===>&l<!-- -->t;</div>
|
||||
<div>x<!ac > a <!ac > b <!ac > c</div>
|
||||
<div>x<? ?> a <? > b <? > c</div>
|
||||
|
|
|
@ -312,7 +312,6 @@ pub fn minify_attr(
|
|||
&mut value_raw_wrapped_min,
|
||||
&value_raw_wrapped,
|
||||
&MINIFY_CSS_TRANSFORM_OPTIONS.clone(),
|
||||
None,
|
||||
);
|
||||
// If input was invalid, wrapper syntax may not exist anymore.
|
||||
if value_raw_wrapped_min.starts_with(b"x{") {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#[cfg(feature = "js-esbuild")]
|
||||
use {
|
||||
crate::minify::esbuild::minify_using_esbuild,
|
||||
aho_corasick::{AhoCorasick, AhoCorasickBuilder},
|
||||
esbuild_rs::{Charset, Loader, SourceMap, TransformOptions, TransformOptionsBuilder},
|
||||
esbuild_rs::{Charset, LegalComments, Loader, SourceMap, TransformOptions, TransformOptionsBuilder},
|
||||
lazy_static::lazy_static,
|
||||
std::sync::Arc,
|
||||
};
|
||||
|
@ -11,9 +10,6 @@ use crate::cfg::Cfg;
|
|||
|
||||
#[cfg(feature = "js-esbuild")]
|
||||
lazy_static! {
|
||||
static ref STYLE_END: AhoCorasick = AhoCorasickBuilder::new()
|
||||
.ascii_case_insensitive(true)
|
||||
.build(&["</style"]);
|
||||
pub static ref MINIFY_CSS_TRANSFORM_OPTIONS: Arc<TransformOptions> = {
|
||||
let mut builder = TransformOptionsBuilder::new();
|
||||
builder.charset = Charset::UTF8;
|
||||
|
@ -41,7 +37,6 @@ pub fn minify_css(cfg: &Cfg, out: &mut Vec<u8>, code: &[u8]) {
|
|||
out,
|
||||
code,
|
||||
&MINIFY_CSS_TRANSFORM_OPTIONS.clone(),
|
||||
Some(&STYLE_END),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,42 +1,20 @@
|
|||
#[cfg(feature = "js-esbuild")]
|
||||
use {aho_corasick::AhoCorasick, crossbeam::sync::WaitGroup, esbuild_rs::TransformOptions};
|
||||
use {crossbeam::sync::WaitGroup, esbuild_rs::TransformOptions};
|
||||
|
||||
#[cfg(feature = "js-esbuild")]
|
||||
// TODO The use of WG is ugly and we don't want to be multi-threaded; wait for Rust port esbuild-transform-rs.
|
||||
// `tag_to_escape` must be case insensitive if provided.
|
||||
pub fn minify_using_esbuild(
|
||||
out: &mut Vec<u8>,
|
||||
code: &[u8],
|
||||
transform_options: &TransformOptions,
|
||||
tag_to_escape: Option<&'static AhoCorasick>,
|
||||
) {
|
||||
let wg = WaitGroup::new();
|
||||
unsafe {
|
||||
let wg = wg.clone();
|
||||
// esbuild now officially handles escaping `</script` and `</style`.
|
||||
esbuild_rs::transform_direct_unmanaged(code, transform_options, move |result| {
|
||||
let min_code = result.code.as_str().trim().as_bytes();
|
||||
match tag_to_escape {
|
||||
None => out.extend_from_slice(min_code),
|
||||
// TODO (JS) Handle other forms:
|
||||
// 1 < /script/.exec(a).length
|
||||
// ` ${` ${a</script/} `} `
|
||||
// // </script>
|
||||
// /* </script>
|
||||
// Considerations:
|
||||
// - Need to parse strings (e.g. "", '', ``) so syntax within strings aren't mistakenly interpreted as code.
|
||||
// - Need to be able to parse regex literals to determine string delimiters aren't actually characters in the regex.
|
||||
// - Determining whether a slash is division or regex requires a full-blown JS parser to handle all cases (this is a well-known JS parsing problem).
|
||||
// - `/</script` or `/</ script` are not valid JS so don't need to be handled.
|
||||
// TODO (CSS) Are there other places that can have unintentional closing tags?
|
||||
Some(tag_to_escape) => {
|
||||
tag_to_escape.replace_all_with_bytes(min_code, out, |_, orig, dst| {
|
||||
dst.extend(b"<\\/");
|
||||
// Keep original case.
|
||||
dst.extend(&orig[2..]);
|
||||
true
|
||||
})
|
||||
}
|
||||
}
|
||||
out.extend_from_slice(min_code);
|
||||
drop(wg);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#[cfg(feature = "js-esbuild")]
|
||||
use {
|
||||
crate::minify::esbuild::minify_using_esbuild,
|
||||
aho_corasick::{AhoCorasick, AhoCorasickBuilder},
|
||||
esbuild_rs::{Charset, LegalComments, SourceMap, TransformOptions, TransformOptionsBuilder},
|
||||
lazy_static::lazy_static,
|
||||
std::sync::Arc,
|
||||
|
@ -11,9 +10,6 @@ use crate::Cfg;
|
|||
|
||||
#[cfg(feature = "js-esbuild")]
|
||||
lazy_static! {
|
||||
static ref SCRIPT_END: AhoCorasick = AhoCorasickBuilder::new()
|
||||
.ascii_case_insensitive(true)
|
||||
.build(&["</script"]);
|
||||
static ref TRANSFORM_OPTIONS: Arc<TransformOptions> = {
|
||||
let mut builder = TransformOptionsBuilder::new();
|
||||
builder.charset = Charset::UTF8;
|
||||
|
@ -36,6 +32,10 @@ pub fn minify_js(cfg: &Cfg, out: &mut Vec<u8>, code: &[u8]) {
|
|||
if !cfg.minify_js {
|
||||
out.extend_from_slice(&code);
|
||||
} else {
|
||||
minify_using_esbuild(out, code, &TRANSFORM_OPTIONS.clone(), Some(&SCRIPT_END));
|
||||
minify_using_esbuild(
|
||||
out,
|
||||
code,
|
||||
&TRANSFORM_OPTIONS.clone(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue