feat(es/minifier): Support script fully (#6455)

This commit is contained in:
Alexander Akait 2022-11-17 09:00:42 +03:00 committed by GitHub
parent 7716f58303
commit 4d7b920bd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 308 additions and 63 deletions

View File

@ -1150,6 +1150,14 @@ where
n.visit_children_with(&mut *self.with_ctx(ctx))
}
fn visit_script(&mut self, n: &Script) {
let ctx = Ctx {
skip_standalone: true,
..self.ctx
};
n.visit_children_with(&mut *self.with_ctx(ctx))
}
fn visit_named_export(&mut self, n: &NamedExport) {
if n.src.is_some() {
return;

View File

@ -336,6 +336,10 @@ where
{
noop_visit_mut_type!();
fn visit_mut_script(&mut self, n: &mut Script) {
self.optimize_unit_repeatedly(n);
}
fn visit_mut_module(&mut self, n: &mut Module) {
self.optimize_unit_repeatedly(n);
}

View File

@ -66,7 +66,7 @@ where
///
/// If the cargo feature `debug` is disabled or the environment variable
/// `SWC_RUN` is not `1`, this function is noop.
pub(crate) fn invoke(module: &Module) {
pub(crate) fn invoke_module(module: &Module) {
debug_assert_valid(module);
let _noop_sub = tracing::subscriber::set_default(tracing::subscriber::NoSubscriber::default());
@ -153,3 +153,94 @@ pub(crate) fn invoke(module: &Module) {
)
}
}
/// Invokes code using node.js.
///
/// If the cargo feature `debug` is disabled or the environment variable
/// `SWC_RUN` is not `1`, this function is noop.
pub(crate) fn invoke_script(script: &Script) {
debug_assert_valid(script);
let _noop_sub = tracing::subscriber::set_default(tracing::subscriber::NoSubscriber::default());
let should_run =
cfg!(debug_assertions) && cfg!(feature = "debug") && option_env!("SWC_RUN") == Some("1");
let should_check = cfg!(debug_assertions) && option_env!("SWC_CHECK") == Some("1");
if !should_run && !should_check {
return;
}
let script = script
.clone()
.fold_with(&mut hygiene())
.fold_with(&mut fixer(None));
let script = drop_span(script);
let mut buf = vec![];
let cm = Lrc::new(SourceMap::default());
{
let mut emitter = Emitter {
cfg: Default::default(),
cm: cm.clone(),
comments: None,
wr: Box::new(JsWriter::new(cm, "\n", &mut buf, None)),
};
emitter.emit_script(&script).unwrap();
}
let code = String::from_utf8(buf).unwrap();
debug!("Validating with node.js:\n{}", code);
if should_check {
let mut child = Command::new("node")
.arg("-")
.arg("--check")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.expect("failed to spawn node");
{
let child_stdin = child.stdin.as_mut().unwrap();
child_stdin
.write_all(code.as_bytes())
.expect("failed to write");
}
let output = child.wait_with_output().expect("failed to check syntax");
if !output.status.success() {
panic!(
"[SWC_CHECK] Failed to validate code:\n{}\n===== ===== ===== ===== =====\n{}\n{}",
code,
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr),
);
}
} else {
let output = Command::new("node")
.arg("-e")
.arg(&code)
.output()
.expect("[SWC_RUN] failed to validate code using `node`");
if !output.status.success() {
panic!(
"[SWC_RUN] Failed to validate code:\n{}\n===== ===== ===== ===== =====\n{}\n{}",
code,
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr),
);
}
tracing::info!(
"[SWC_RUN]\n{}\n{}",
code,
String::from_utf8_lossy(&output.stdout)
)
}
}

View File

@ -87,7 +87,7 @@ pub(crate) static HEAVY_TASK_PARALLELS: Lazy<usize> = Lazy::new(|| *CPU_COUNT *
pub(crate) static LIGHT_TASK_PARALLELS: Lazy<usize> = Lazy::new(|| *CPU_COUNT * 100);
pub fn optimize(
mut m: Program,
mut n: Program,
_cm: Lrc<SourceMap>,
comments: Option<&dyn Comments>,
mut timings: Option<&mut Timings>,
@ -99,7 +99,7 @@ pub fn optimize(
let mut marks = Marks::new();
marks.unresolved_mark = extra.unresolved_mark;
debug_assert_valid(&m);
debug_assert_valid(&n);
if let Some(defs) = options.compress.as_ref().map(|c| &c.global_defs) {
let _timer = timer!("inline global defs");
@ -111,7 +111,7 @@ pub fn optimize(
if !defs.is_empty() {
let defs = defs.iter().map(|(k, v)| (k.clone(), v.clone())).collect();
m.visit_mut_with(&mut global_defs::globals_defs(
n.visit_mut_with(&mut global_defs::globals_defs(
defs,
extra.unresolved_mark,
extra.top_level_mark,
@ -119,7 +119,7 @@ pub fn optimize(
}
}
let module_info = match &m {
let module_info = match &n {
Program::Script(_) => ModuleInfo::default(),
Program::Module(m) => ModuleInfo {
blackbox_imports: m
@ -162,20 +162,20 @@ pub fn optimize(
if let Some(_options) = &options.compress {
let _timer = timer!("precompress");
m.visit_mut_with(&mut precompress_optimizer());
debug_assert_valid(&m);
n.visit_mut_with(&mut precompress_optimizer());
debug_assert_valid(&n);
}
if options.compress.is_some() {
m.visit_mut_with(&mut info_marker(
n.visit_mut_with(&mut info_marker(
options.compress.as_ref(),
comments,
marks,
extra.unresolved_mark,
));
debug_assert_valid(&m);
debug_assert_valid(&n);
}
m.visit_mut_with(&mut unique_scope());
n.visit_mut_with(&mut unique_scope());
if options.wrap {
// TODO: wrap_common_js
@ -191,8 +191,8 @@ pub fn optimize(
}
if let Some(options) = &options.compress {
if options.unused {
perform_dce(&mut m, options, extra);
debug_assert_valid(&m);
perform_dce(&mut n, options, extra);
debug_assert_valid(&n);
}
}
@ -207,7 +207,7 @@ pub fn optimize(
if options.rename && DISABLE_BUGGY_PASSES {
// toplevel.figure_out_scope(options.mangle);
// TODO: Pass `options.mangle` to name expander.
m.visit_mut_with(&mut name_expander());
n.visit_mut_with(&mut name_expander());
}
if let Some(ref mut t) = timings {
@ -217,14 +217,14 @@ pub fn optimize(
{
let _timer = timer!("compress ast");
m.visit_mut_with(&mut compressor(&module_info, marks, options, &Minification))
n.visit_mut_with(&mut compressor(&module_info, marks, options, &Minification))
}
// Again, we don't need to validate ast
let _timer = timer!("postcompress");
m.visit_mut_with(&mut postcompress_optimizer(options));
n.visit_mut_with(&mut postcompress_optimizer(options));
let mut pass = 0;
loop {
@ -241,7 +241,7 @@ pub fn optimize(
debug_infinite_loop: false,
},
);
m.visit_mut_with(&mut v);
n.visit_mut_with(&mut v);
if !v.changed() || options.passes <= pass {
break;
}
@ -263,30 +263,30 @@ pub fn optimize(
let _timer = timer!("mangle names");
// TODO: base54.reset();
let preserved = idents_to_preserve(mangle.clone(), &m);
let preserved = idents_to_preserve(mangle.clone(), &n);
let chars = CharFreq::compute(
&m,
&n,
&preserved,
SyntaxContext::empty().apply_mark(marks.unresolved_mark),
)
.compile();
m.visit_mut_with(&mut name_mangler(mangle.clone(), preserved, chars));
n.visit_mut_with(&mut name_mangler(mangle.clone(), preserved, chars));
if let Some(property_mangle_options) = &mangle.props {
mangle_properties(&mut m, &module_info, property_mangle_options.clone(), chars);
mangle_properties(&mut n, &module_info, property_mangle_options.clone(), chars);
}
}
m.visit_mut_with(&mut merge_exports());
n.visit_mut_with(&mut merge_exports());
if let Some(ref mut t) = timings {
t.section("hygiene");
t.end_section();
}
m
n
}
fn perform_dce(m: &mut Program, options: &CompressOptions, extra: &ExtraOptions) {

View File

@ -191,12 +191,23 @@ impl VisitMut for InfoMarker<'_> {
fn visit_mut_lit(&mut self, _: &mut Lit) {}
fn visit_mut_module(&mut self, m: &mut Module) {
m.visit_mut_children_with(self);
fn visit_mut_script(&mut self, n: &mut Script) {
n.visit_mut_children_with(self);
if self.state.is_bundle {
tracing::info!("Running minifier in the bundle mode");
m.span = m.span.apply_mark(self.marks.bundle_of_standalone);
n.span = n.span.apply_mark(self.marks.bundle_of_standalone);
} else {
tracing::info!("Running minifier in the normal mode");
}
}
fn visit_mut_module(&mut self, n: &mut Module) {
n.visit_mut_children_with(self);
if self.state.is_bundle {
tracing::info!("Running minifier in the bundle mode");
n.span = n.span.apply_mark(self.marks.bundle_of_standalone);
} else {
tracing::info!("Running minifier in the normal mode");
}

View File

@ -121,6 +121,13 @@ impl Visit for Preserver {
fn visit_ident(&mut self, _: &Ident) {}
fn visit_script(&mut self, n: &Script) {
for n in n.body.iter() {
self.in_top_level = true;
n.visit_with(self);
}
}
fn visit_module_items(&mut self, n: &[ModuleItem]) {
for n in n {
self.in_top_level = true;

View File

@ -69,7 +69,42 @@ impl CompileUnit for Module {
{
self.visit_mut_with(&mut *visitor);
crate::debug::invoke(self);
crate::debug::invoke_module(self);
}
fn remove_mark(&mut self) -> Mark {
Mark::root()
}
}
impl CompileUnit for Script {
fn is_module() -> bool {
false
}
fn force_dump(&self) -> String {
let _noop_sub =
tracing::subscriber::set_default(tracing::subscriber::NoSubscriber::default());
dump(
&self
.clone()
.fold_with(&mut fixer(None))
.fold_with(&mut hygiene())
.fold_with(&mut as_folder(DropSpan {
preserve_ctxt: false,
})),
true,
)
}
fn apply<V>(&mut self, visitor: &mut V)
where
V: VisitMut,
{
self.visit_mut_with(&mut *visitor);
crate::debug::invoke_script(self);
}
fn remove_mark(&mut self) -> Mark {

View File

@ -242,12 +242,11 @@ where
if contains_eval(s, true) {
s.visit_mut_children_with(self);
return;
} else {
let map = self.get_map(s, false, true);
s.visit_mut_with(&mut rename_with_config(&map, self.config.clone()));
}
let map = self.get_map(s, false, true);
s.visit_mut_with(&mut rename_with_config(&map, self.config.clone()));
}
}

View File

@ -8,5 +8,5 @@
<circle onmouseover='alert("test")' cx=50 cy=50 r=30 style=fill:url(#gradient) />
</svg>
<div type=text onmouseover=myFunction()>test</div>
<a href=https://datacadamia.com onclick="console.log(`Navigation to ${this.href} cancelled`);return false">Click me</a>
<a href=https://datacadamia.com onclick="console.log(`Navigation to ${this.href} cancelled`);return false">Click me</a>
<a href=https://datacadamia.com onclick="return console.log(`Navigation to ${this.href} cancelled`),!1">Click me</a>
<a href=https://datacadamia.com onclick="return console.log(`Navigation to ${this.href} cancelled`),!1">Click me</a>

View File

@ -1,6 +1,6 @@
<!doctype html><script defer>console.log()</script><script>console.log();console.log()</script><script type=module>console.log(),console.log()</script><script>window.jQuery||document.write('<script src="jquery.js"><\/script>')</script><script type=text/html>
<!doctype html><script defer>console.log()</script><script>console.log(),console.log()</script><script type=module>console.log(),console.log()</script><script>window.jQuery||document.write('<script src="jquery.js"><\/script>')</script><script type=text/html>
<div>
test
</div>
<!-- aa -->\n
</script><script type="">alert(1)</script><script type=modules>alert(1)</script><script>alert(1);alert(1)</script><script type=module src=app.mjs></script><script nomodule defer src=classic-app-bundle.js></script><script>alert(1)</script><script type=text/vbscript>MsgBox("foo bar")</script><script type="">MsgBox("foo bar")</script><script type=;;;;;>MsgBox("foo bar")</script><script>alert(1);alert(1);alert(1);alert(1);alert(1);alert(1);alert(1)</script>
</script><script type="">alert(1)</script><script type=modules>alert(1)</script><script>alert(1),alert(1)</script><script type=module src=app.mjs></script><script nomodule defer src=classic-app-bundle.js></script><script>alert(1)</script><script type=text/vbscript>MsgBox("foo bar")</script><script type="">MsgBox("foo bar")</script><script type=;;;;;>MsgBox("foo bar")</script><script>alert(1),alert(1),alert(1),alert(1),alert(1),alert(1),alert(1)</script>

View File

@ -1,33 +1,33 @@
<!doctype html><html lang=en><title>Document</title><div>breaker</div>
<script>var o="test";console.log(o);var e="test";console.log(e)</script>
<script>var a="test";console.log(a);var b="test";console.log(b)</script>
<div>breaker</div>
<script>var o="test";console.log(o);var e="test";console.log(e)</script>
<script>var a="test";console.log(a);var b="test";console.log(b)</script>
<div>breaker</div>
<script>var o="test";console.log(o);var e="test";console.log(e)</script>
<script>var a="test";console.log(a);var b="test";console.log(b)</script>
<div>breaker</div>
<script>var o="test";console.log(o);var e="test";console.log(e)</script>
<script>var a="test";console.log(a);var b="test";console.log(b)</script>
<div>breaker</div>
<script>var o="test";console.log(o)</script><script crossorigin=use-credentials>var o="test";console.log(o)</script>
<script>var a="test";console.log(a)</script><script crossorigin=use-credentials>var b="test";console.log(b)</script>
<div>breaker</div>
<script crossorigin=use-credentials>var o="test";console.log(o);var e="test";console.log(e)</script>
<script crossorigin=use-credentials>var a="test";console.log(a);var b="test";console.log(b)</script>
<div>breaker</div>
<script>(function o(){let o="1";console.log(o)})();let o="1";console.log(o)</script>
<script>console.log("1");let test="1";console.log(test)</script>
<div>breaker</div>
<script type=module>var a="test";console.log(a)</script><script>var o="test";console.log(o)</script>
<script type=module>var a="test";console.log(a)</script><script>var b="test";console.log(b)</script>
<div>breaker</div>
@ -35,26 +35,26 @@
<div>breaker</div>
<script>var o="test";console.log(o)</script><script type=unknown>var b = "test";console.log(b)</script>
<script>var a="test";console.log(a)</script><script type=unknown>var b = "test";console.log(b)</script>
<div>breaker</div>
<script src=test.js></script><script>var o="test";console.log(o)</script>
<script src=test.js></script><script>var b="test";console.log(b)</script>
<div>breaker</div>
<div>breaker</div>
<script>var o="test";console.log(o);var e="test";console.log(e)</script>
<script>var a="test";console.log(a);var b="test";console.log(b)</script>
<div>breaker</div>
<script>var o="test";console.log(o);var e="test";console.log(e)</script>
<script>var a="test";console.log(a);var b="test";console.log(b)</script>
<div>breaker</div>
<script type=module>var a="test";console.log(a);var a1="test";console.log(a1)</script>
<div>breaker</div>
<script type=module>var a="test";console.log(a)</script><script>var o="test";console.log(o)</script>
<script type=module>var a="test";console.log(a)</script><script>var a="test";console.log(a)</script>
<div>breaker</div>
<script type=module>var a="test";console.log(a);var a1="test";console.log(a1)</script>
@ -63,34 +63,34 @@
<script type=module>var a="test";console.log(a);var a1="test";console.log(a1)</script>
<div>breaker</div>
<script>let e="test";console.log(e);let l="test";console.log(l);let e="test";console.log(e);let l="test";console.log(l)</script>
<script>let a="test";console.log(a);let b="test";console.log(b);let a="test";console.log(a);let b="test";console.log(b)</script>
<div>breaker</div>
<script type=module>let a="test";console.log(a);const b="test";console.log("test");let a1="test";console.log(a1);const b1="test";console.log("test")</script>
<div>breaker</div>
<script>let e=[1,2,3];[()=>{console.log("test")},2,3][0]()</script>
<script>let foo=[1,2,3];[()=>{console.log("test")},2,3][0]()</script>
<div>breaker</div>
<script type=module>let a="test";console.log(a),console.log(a),console.log(a);let a1="test";console.log(a1),console.log(a1),console.log(a1)</script>
<div>breaker</div>
<script>let o="test";console.log(o);console.log(o);console.log(o);let o="test";console.log(o);console.log(o);console.log(o)</script>
<script>let a="test";console.log(a),console.log(a),console.log(a);let a="test";console.log(a),console.log(a),console.log(a)</script>
<div>breaker</div>
<script>var o="test";console.log(o);console.log(o);console.log(o);var o="test";console.log(o);console.log(o);console.log(o)</script>
<script>var a="test";console.log(a),console.log(a),console.log(a);var a="test";console.log(a),console.log(a),console.log(a)</script>
<div>breaker</div>
<script>var o="test";console.log(o);console.log(o);console.log(o);var o="test";console.log(o);console.log(o);console.log(o);var o="test";console.log(o);console.log(o);console.log(o)</script>
<script>var a="test";console.log(a),console.log(a),console.log(a);var a="test";console.log(a),console.log(a),console.log(a);var a="test";console.log(a),console.log(a),console.log(a)</script>
<div>breaker</div>
<script type=module>var a="test";console.log(a),console.log(a),console.log(a);var a1="test";console.log(a1),console.log(a1),console.log(a1);var a2="test";console.log(a2),console.log(a2),console.log(a2)</script>
<div>breaker</div>
<script type=module>var a="test";console.log(a),console.log(a),console.log(a)</script><script>var o="test";console.log(o);console.log(o);console.log(o)</script><script type=module>var a="test";console.log(a),console.log(a),console.log(a)</script>
<script type=module>var a="test";console.log(a),console.log(a),console.log(a)</script><script>var a="test";console.log(a),console.log(a),console.log(a)</script><script type=module>var a="test";console.log(a),console.log(a),console.log(a)</script>
<div>breaker</div>
<script>var o="test";console.log(o);console.log(o);console.log(o)</script><script type=module>var a="test";console.log(a),console.log(a),console.log(a)</script><script>var o="test";console.log(o);console.log(o);console.log(o)</script>
<script>var a="test";console.log(a),console.log(a),console.log(a)</script><script type=module>var a="test";console.log(a),console.log(a),console.log(a)</script><script>var a="test";console.log(a),console.log(a),console.log(a)</script>
<div>breaker</div>

View File

@ -0,0 +1,17 @@
{
"minifyJs": {
"parser": {
"comments": true,
"syntax": "ecmascript",
"target": "es2022"
},
"minifier": {
"mangle": {
"topLevel": true
}
},
"codegen": {
"asciiOnly": true
}
}
}

View File

@ -0,0 +1,36 @@
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<div>Script:</div>
<script>
/* Should mangle top level stuff */
var topLevel = function test() {
let foo = "bar";
if (foo) {
foo += "baz";
}
console.log(foo);
};
</script>
<div>Module:</div>
<script type="module">
/* Should mangle top level stuff */
var topLevel = function test() {
let foo = "bar";
if (foo) {
foo += "baz";
}
console.log(foo);
};
</script>
</body>
</html>

View File

@ -0,0 +1,5 @@
<!doctype html><html lang=en><title>Document</title><div>Script:</div>
<script>/* Should mangle top level stuff */ var o=function(){let o="bar";o&&(o+="baz"),console.log(o)}</script>
<div>Module:</div>
<script type=module>/* Should mangle top level stuff */ var o=function(){let o="bar";o&&(o+="baz"),console.log(o)}</script>

View File

@ -186,5 +186,32 @@
<script>window.jQuery || document.write('<script src="jquery.js"><\/script>')</script>
<div>test</div>
<script></script>
<div>topLevel - script</div>
<script>
/* Should keep top level stuff */
var topLevel = function test() {
let foo = "bar";
if (foo) {
foo += "baz";
}
console.log(foo);
};
</script>
<div>topLevel - module</div>
<script type="module">
/* Should keep top level stuff */
var topLevel = function test() {
let foo = "bar";
if (foo) {
foo += "baz";
}
console.log(foo);
};
</script>
</body>
</html>

View File

@ -19,7 +19,7 @@
</script><script id=data type=application/json>{"foo":"bar"}</script><script>
broken broken
</script><script>var a=3,a=9</script><script type=module>import t from"foo.js";let test=58800,test1="testtest"</script><script>let e=new Date;alert("Today's date is "+e)</script><script src=javascript.js>
</script><script>var a=3,a=9</script><script type=module>import t from"foo.js";let test=58800,test1="testtest"</script><script>let d=new Date;alert("Today's date is "+d)</script><script src=javascript.js>
@ -27,7 +27,7 @@
var q = "WRONG" ;
</script><script>let t="testtest";alert("<!--");alert("<!-- foo -->");alert("-->");alert("testtest");function e(){var t=1,e=2;alert(t+" "+e)}</script><h2>Party coffee cake recipe</h2>
</script><script>let foo="testtest";function test(){alert("1 2")}alert("<!--"),alert("<!-- foo -->"),alert("-->"),alert("testtest")</script><h2>Party coffee cake recipe</h2>
<p>
<i>by Mary Stone, 2018-03-10</i>
</p>
@ -54,5 +54,10 @@
alert('test')
</script>
</math>
<script blocking="a render">console.log("block")</script><script>(function(t){var t="test"+Math.random()+t,r=1,o=2+Math.random();alert(r+" "+o);console.log(Math.random())})("test");window.jQuery||document.write('<script src="jquery.js"><\/script>')</script>
<div>test</div>
<script blocking="a render">console.log("block")</script><script>!function(t){var t="test"+Math.random()+t;alert("1 "+(2+Math.random())),console.log(Math.random())}("test"),window.jQuery||document.write('<script src="jquery.js"><\/script>')</script>
<div>test</div>
<div>topLevel - script</div>
<script>var topLevel=function(){let o="bar";o&&(o+="baz"),console.log(o)}</script>
<div>topLevel - module</div>
<script type=module>var topLevel=function(){let o="bar";o&&(o+="baz"),console.log(o)}</script>

View File

@ -29,4 +29,4 @@
foo
baz
</pre> <div> a <input> c </div> <div>Empty </div> <!--[if lte IE 6]> <span>A</span> <span title=" sigificant whitespace ">blah blah</span> <![endif]--> <div> <a href=#> <span> <b> foo </b> <i> bar </i> </span> </a> </div> <div>a b</div> <div>a b c d</div> <div> text </div> <span> text </span> <span> text </span> <div> <style>a{color:red}</style> <span>test</span> <style>a{color:red}</style> </div> <div> <style>a{color:red}</style> </div> <div> <style>a{color:red}</style> <span>test</span> <span>test</span> <style>a{color:red}</style> </div> <div> <script>console.log("test");console.log("test")</script> </div>
</pre> <div> a <input> c </div> <div>Empty </div> <!--[if lte IE 6]> <span>A</span> <span title=" sigificant whitespace ">blah blah</span> <![endif]--> <div> <a href=#> <span> <b> foo </b> <i> bar </i> </span> </a> </div> <div>a b</div> <div>a b c d</div> <div> text </div> <span> text </span> <span> text </span> <div> <style>a{color:red}</style> <span>test</span> <style>a{color:red}</style> </div> <div> <style>a{color:red}</style> </div> <div> <style>a{color:red}</style> <span>test</span> <span>test</span> <style>a{color:red}</style> </div> <div> <script>console.log("test"),console.log("test")</script> </div>

View File

@ -29,4 +29,4 @@
foo
baz
</pre><div>a <input> c</div><div>Empty</div><!--[if lte IE 6]> <span>A</span> <span title=" sigificant whitespace ">blah blah</span> <![endif]--><div><a href=#> <span><b>foo </b><i> bar </i></span></a></div><div>a b</div><div>a b c d</div><div>text</div><span> text </span><span> text </span><div><span>test</span> <span>test</span></div><div><span>test</span> <command>test</command><span>test</span></div><div><span>test</span><link rel=stylesheet href=""> <span>test</span></div><div><span>test</span><meta name=content> <span>test</span></div><div><span>test</span><script>console.log("test")</script> <span>test</span></div><div><span>test</span><style>a{color:red}</style> <span>test</span></div><div><span>test</span><title>test</title> <span>test</span></div><div><meta name=test><meta name=test></div><div><link rel=stylesheet href=""><link rel=stylesheet href=""></div><div><script>console.log("test");console.log("test")</script></div><div><script>console.log("test")</script> <span>test</span><script>console.log("test")</script></div><div><style>a{color:red}</style></div><div><script>console.log("test")</script><style>a{color:red}</style></div><div><span itemscope><meta itemprop=name content="The Castle">test</span> <span>test</span></div><div><meta name=test></div><div><style>a{color:red}</style></div><div><meta name=test><div>test</div><meta name=test></div><div><meta name=test> <span>test</span><meta name=test></div><svg> <title>test</title> <metadata>test</metadata> <desc>test</desc> </svg><svg> <a>test</a> <a>test</a> </svg><svg><text x=20 y=35><tspan font-weight=bold fill=red>This is bold and red</tspan> <tspan font-weight=bold fill=red>This is bold and red</tspan></text></svg><svg> <tspan>test</tspan><foreignObject>test</foreignObject></svg><svg><text x=20 y=35><tspan font-weight=bold fill=red>This is bold and red</tspan> <tspan font-weight=bold fill=red>This is bold and red</tspan></text></svg><svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice" style=width:100%;height:100%;position:absolute;top:0;left:0;z-index:-1> <linearGradient id=gradient><stop class=begin offset=0% /><stop class=end offset=100% /></linearGradient><rect width=100 height=100 style=fill:url(#gradient) /> <circle cx=50 cy=50 r=30 style=fill:url(#gradient) /> </svg><svg> <script>console.log("test")</script></svg><svg> <style>a{color:red}</style></svg><div><span>test</span> a b <span>test</span> <span>test</span> a b <span>test</span> <span>test</span> a b <span>test</span></div><div><foo-bar> <span>test</span> </foo-bar> <foo-bar> <span>test</span> </foo-bar></div><div><svg> <linearGradient id=gradient /> </svg><span>a</span></div>
</pre><div>a <input> c</div><div>Empty</div><!--[if lte IE 6]> <span>A</span> <span title=" sigificant whitespace ">blah blah</span> <![endif]--><div><a href=#> <span><b>foo </b><i> bar </i></span></a></div><div>a b</div><div>a b c d</div><div>text</div><span> text </span><span> text </span><div><span>test</span> <span>test</span></div><div><span>test</span> <command>test</command><span>test</span></div><div><span>test</span><link rel=stylesheet href=""> <span>test</span></div><div><span>test</span><meta name=content> <span>test</span></div><div><span>test</span><script>console.log("test")</script> <span>test</span></div><div><span>test</span><style>a{color:red}</style> <span>test</span></div><div><span>test</span><title>test</title> <span>test</span></div><div><meta name=test><meta name=test></div><div><link rel=stylesheet href=""><link rel=stylesheet href=""></div><div><script>console.log("test"),console.log("test")</script></div><div><script>console.log("test")</script> <span>test</span><script>console.log("test")</script></div><div><style>a{color:red}</style></div><div><script>console.log("test")</script><style>a{color:red}</style></div><div><span itemscope><meta itemprop=name content="The Castle">test</span> <span>test</span></div><div><meta name=test></div><div><style>a{color:red}</style></div><div><meta name=test><div>test</div><meta name=test></div><div><meta name=test> <span>test</span><meta name=test></div><svg> <title>test</title> <metadata>test</metadata> <desc>test</desc> </svg><svg> <a>test</a> <a>test</a> </svg><svg><text x=20 y=35><tspan font-weight=bold fill=red>This is bold and red</tspan> <tspan font-weight=bold fill=red>This is bold and red</tspan></text></svg><svg> <tspan>test</tspan><foreignObject>test</foreignObject></svg><svg><text x=20 y=35><tspan font-weight=bold fill=red>This is bold and red</tspan> <tspan font-weight=bold fill=red>This is bold and red</tspan></text></svg><svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice" style=width:100%;height:100%;position:absolute;top:0;left:0;z-index:-1> <linearGradient id=gradient><stop class=begin offset=0% /><stop class=end offset=100% /></linearGradient><rect width=100 height=100 style=fill:url(#gradient) /> <circle cx=50 cy=50 r=30 style=fill:url(#gradient) /> </svg><svg> <script>console.log("test")</script></svg><svg> <style>a{color:red}</style></svg><div><span>test</span> a b <span>test</span> <span>test</span> a b <span>test</span> <span>test</span> a b <span>test</span></div><div><foo-bar> <span>test</span> </foo-bar> <foo-bar> <span>test</span> </foo-bar></div><div><svg> <linearGradient id=gradient /> </svg><span>a</span></div>

View File

@ -1 +1 @@
<!doctype html><meta charset=utf-8><title>element-details - web component using &lt;template> and &lt;slot></title><style>dl{margin-left:6px}dt{font-weight:700;color:#217ac0;font-size:110%;font-family:Consolas,"Liberation Mono",Courier}dd{margin-left:16px}</style><h1>element-details - web component using <code>&lt;template></code> and <code>&lt;slot></code></h1><template id=element-details-template-1> VALUE: !<slot>?</slot>! </template> <element-details> <span>test</span> <span>foo</span> </element-details> <script>customElements.define("element-details",class extends HTMLElement{constructor(){super();let e=document.getElementById("element-details-template-1").content;this.attachShadow({mode:"open"}).appendChild(e.cloneNode(true))}})</script>
<!doctype html><meta charset=utf-8><title>element-details - web component using &lt;template> and &lt;slot></title><style>dl{margin-left:6px}dt{font-weight:700;color:#217ac0;font-size:110%;font-family:Consolas,"Liberation Mono",Courier}dd{margin-left:16px}</style><h1>element-details - web component using <code>&lt;template></code> and <code>&lt;slot></code></h1><template id=element-details-template-1> VALUE: !<slot>?</slot>! </template> <element-details> <span>test</span> <span>foo</span> </element-details> <script>customElements.define("element-details",class extends HTMLElement{constructor(){super();let e=document.getElementById("element-details-template-1").content;this.attachShadow({mode:"open"}).appendChild(e.cloneNode(!0))}})</script>

View File

@ -1 +1 @@
<!doctype html><meta charset=utf-8><title>element-details - web component using &lt;template> and &lt;slot></title><style>dl{margin-left:6px}dt{font-weight:700;color:#217ac0;font-size:110%;font-family:Consolas,"Liberation Mono",Courier}dd{margin-left:16px}</style><h1>element-details - web component using <code>&lt;template></code> and <code>&lt;slot></code></h1><template id=element-details-template-1> VALUE: <slot name=q>?</slot> </template><template id=element-details-template-2> VALUE:<slot name=q>?</slot> </template><template id=element-details-template-3><div>VALUE:</div><slot name=q>?</slot> </template> <element-details> <span slot=q>1</span> </element-details> <element-details> <span slot=q>2</span> </element-details> <element-details-more> <span slot=q>3</span> </element-details-more> <element-details-more> <span slot=q>4</span> </element-details-more> <script>customElements.define("element-details",class extends HTMLElement{constructor(){super();let e=document.getElementById("element-details-template-1").content;this.attachShadow({mode:"open"}).appendChild(e.cloneNode(true))}});customElements.define("element-details-more",class extends HTMLElement{constructor(){super();let e=document.getElementById("element-details-template-2").content;this.attachShadow({mode:"open"}).appendChild(e.cloneNode(true))}})</script>
<!doctype html><meta charset=utf-8><title>element-details - web component using &lt;template> and &lt;slot></title><style>dl{margin-left:6px}dt{font-weight:700;color:#217ac0;font-size:110%;font-family:Consolas,"Liberation Mono",Courier}dd{margin-left:16px}</style><h1>element-details - web component using <code>&lt;template></code> and <code>&lt;slot></code></h1><template id=element-details-template-1> VALUE: <slot name=q>?</slot> </template><template id=element-details-template-2> VALUE:<slot name=q>?</slot> </template><template id=element-details-template-3><div>VALUE:</div><slot name=q>?</slot> </template> <element-details> <span slot=q>1</span> </element-details> <element-details> <span slot=q>2</span> </element-details> <element-details-more> <span slot=q>3</span> </element-details-more> <element-details-more> <span slot=q>4</span> </element-details-more> <script>customElements.define("element-details",class extends HTMLElement{constructor(){super();let e=document.getElementById("element-details-template-1").content;this.attachShadow({mode:"open"}).appendChild(e.cloneNode(!0))}}),customElements.define("element-details-more",class extends HTMLElement{constructor(){super();let e=document.getElementById("element-details-template-2").content;this.attachShadow({mode:"open"}).appendChild(e.cloneNode(!0))}})</script>