feat(html/minifier): Compress style and media attributes (#5022)

This commit is contained in:
Alexander Akait 2022-06-23 06:29:00 +03:00 committed by GitHub
parent 035d1f0089
commit 47d34a33d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 339 additions and 39 deletions

1
Cargo.lock generated
View File

@ -3968,6 +3968,7 @@ dependencies = [
"swc_atoms",
"swc_cached",
"swc_common",
"swc_css_ast",
"swc_css_codegen",
"swc_css_minifier",
"swc_css_parser",

View File

@ -22,6 +22,7 @@ serde_json = "1.0.61"
swc_atoms = { version = "0.2.9", path = "../swc_atoms" }
swc_cached = { version = "0.1.0", path = "../swc_cached" }
swc_common = { version = "0.18.0", path = "../swc_common" }
swc_css_ast = { version = "0.93.1", path = "../swc_css_ast" }
swc_css_codegen = { version = "0.103.0", path = "../swc_css_codegen" }
swc_css_parser = { version = "0.102.0", path = "../swc_css_parser" }
swc_css_minifier = { version = "0.68.0", path = "../swc_css_minifier" }

View File

@ -214,6 +214,8 @@ static COMMA_SEPARATED_HTML_ATTRIBUTES: &[(&str, &str)] = &[
("style", "media"),
];
static COMMA_SEPARATED_SVG_ATTRIBUTES: &[(&str, &str)] = &[("style", "media")];
static SPACE_SEPARATED_GLOBAL_ATTRIBUTES: &[&str] = &[
"class",
"part",
@ -251,6 +253,12 @@ enum TextChildrenType {
Module,
}
enum CssMinificationMode {
Stylesheet,
ListOfDeclarations,
MediaQueryList,
}
#[inline(always)]
fn is_whitespace(c: char) -> bool {
matches!(c, '\x09' | '\x0a' | '\x0c' | '\x0d' | '\x20')
@ -342,6 +350,9 @@ impl Minifier {
}
_ => COMMA_SEPARATED_HTML_ATTRIBUTES.contains(&(&element.tag_name, attribute_name)),
},
Namespace::SVG => {
COMMA_SEPARATED_SVG_ATTRIBUTES.contains(&(&element.tag_name, attribute_name))
}
_ => false,
}
}
@ -837,16 +848,115 @@ impl Minifier {
Some(minified)
}
fn minify_css(&self, data: String) -> Option<String> {
fn minify_sizes(&self, value: &str) -> Option<String> {
let values = value
.rsplitn(2, |c| matches!(c, '\t' | '\n' | '\x0C' | '\r' | ' '))
.collect::<Vec<&str>>();
if values.len() != 2 {
return None;
}
let media_condition =
// It should be `MediaCondition`, but `<media-query> = <media-condition>` and other values is just invalid size
match self.minify_css(values[1].to_string(), CssMinificationMode::MediaQueryList) {
Some(minified) => minified,
_ => return None,
};
let source_size_value = values[0];
let mut minified = String::with_capacity(media_condition.len() + source_size_value.len());
minified.push_str(&media_condition);
minified.push(' ');
minified.push_str(source_size_value);
Some(minified)
}
fn minify_css(&self, data: String, mode: CssMinificationMode) -> Option<String> {
let mut errors: Vec<_> = vec![];
let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let fm = cm.new_source_file(FileName::Anon, data);
let mut stylesheet = match swc_css_parser::parse_file(&fm, Default::default(), &mut errors)
{
Ok(stylesheet) => stylesheet,
_ => return None,
let mut stylesheet = match mode {
CssMinificationMode::Stylesheet => {
match swc_css_parser::parse_file(&fm, Default::default(), &mut errors) {
Ok(stylesheet) => stylesheet,
_ => return None,
}
}
CssMinificationMode::ListOfDeclarations => {
match swc_css_parser::parse_file::<Vec<swc_css_ast::DeclarationOrAtRule>>(
&fm,
Default::default(),
&mut errors,
) {
Ok(list_of_declarations) => {
let declaration_list: Vec<swc_css_ast::ComponentValue> =
list_of_declarations
.into_iter()
.map(swc_css_ast::ComponentValue::DeclarationOrAtRule)
.collect();
swc_css_ast::Stylesheet {
span: Default::default(),
rules: vec![swc_css_ast::Rule::QualifiedRule(
swc_css_ast::QualifiedRule {
span: Default::default(),
prelude: swc_css_ast::QualifiedRulePrelude::SelectorList(
swc_css_ast::SelectorList {
span: Default::default(),
children: vec![],
},
),
block: swc_css_ast::SimpleBlock {
span: Default::default(),
name: '{',
value: declaration_list,
},
},
)],
}
}
_ => return None,
}
}
CssMinificationMode::MediaQueryList => {
match swc_css_parser::parse_file::<swc_css_ast::MediaQueryList>(
&fm,
Default::default(),
&mut errors,
) {
Ok(media_query_list) => swc_css_ast::Stylesheet {
span: Default::default(),
rules: vec![swc_css_ast::Rule::AtRule(swc_css_ast::AtRule {
span: Default::default(),
name: swc_css_ast::AtRuleName::Ident(swc_css_ast::Ident {
span: Default::default(),
value: "media".into(),
raw: "media".into(),
}),
prelude: Some(swc_css_ast::AtRulePrelude::MediaPrelude(
media_query_list,
)),
block: Some(swc_css_ast::SimpleBlock {
span: Default::default(),
name: '{',
// TODO make the `compress_empty` option for CSS minifier and remove
// it
value: vec![swc_css_ast::ComponentValue::Str(swc_css_ast::Str {
span: Default::default(),
value: "placeholder".into(),
raw: "placeholder".into(),
})],
}),
})],
},
_ => return None,
}
}
};
// Avoid compress potential invalid CSS
@ -867,7 +977,41 @@ impl Minifier {
swc_css_codegen::CodegenConfig { minify: true },
);
swc_css_codegen::Emit::emit(&mut gen, &stylesheet).unwrap();
match mode {
CssMinificationMode::Stylesheet => {
swc_css_codegen::Emit::emit(&mut gen, &stylesheet).unwrap();
}
CssMinificationMode::ListOfDeclarations => {
let swc_css_ast::Stylesheet { rules, .. } = &stylesheet;
// Because CSS is grammar free, protect for fails
if let Some(swc_css_ast::Rule::QualifiedRule(swc_css_ast::QualifiedRule {
block,
..
})) = rules.get(0)
{
swc_css_codegen::Emit::emit(&mut gen, &block).unwrap();
minified = minified[1..minified.len() - 1].to_string();
} else {
return None;
}
}
CssMinificationMode::MediaQueryList => {
let swc_css_ast::Stylesheet { rules, .. } = &stylesheet;
// Because CSS is grammar free, protect for fails
if let Some(swc_css_ast::Rule::AtRule(swc_css_ast::AtRule { prelude, .. })) =
rules.get(0)
{
swc_css_codegen::Emit::emit(&mut gen, &prelude).unwrap();
minified = minified.trim().to_string();
} else {
return None;
}
}
}
Some(minified)
}
@ -1079,19 +1223,48 @@ impl VisitMut for Minifier {
value = values.join(" ");
} else if self.is_comma_separated_attribute(self.current_element.as_ref().unwrap(), &n.name)
{
let values = value.trim().split(',');
let is_sizes = matches!(&*n.name, "sizes" | "imagesizes");
let mut new_values = vec![];
for value in values {
new_values.push(value.trim());
for value in value.trim().split(',') {
if is_sizes {
let trimmed = value.trim();
match self.minify_sizes(trimmed) {
Some(minified) => {
new_values.push(minified);
}
_ => {
new_values.push(trimmed.to_string());
}
};
} else {
new_values.push(value.trim().to_string());
}
}
value = new_values.join(",");
if self.minify_css && &*n.name == "media" && !value.is_empty() {
if let Some(minified) =
self.minify_css(value.clone(), CssMinificationMode::MediaQueryList)
{
value = minified;
}
}
} else if self
.is_trimable_separated_attribute(self.current_element.as_ref().unwrap(), &n.name)
{
value = value.trim().to_string();
if self.minify_css && &*n.name == "style" && !value.is_empty() {
if let Some(minified) =
self.minify_css(value.clone(), CssMinificationMode::ListOfDeclarations)
{
value = minified;
}
}
} else if is_element_html_namespace && &n.name == "contenteditable" && value == "true" {
n.value = Some(js_word!(""));
@ -1253,10 +1426,11 @@ impl VisitMut for Minifier {
n.data = minified.into();
}
Some(TextChildrenType::Css) => {
let minified = match self.minify_css(n.data.to_string()) {
Some(minified) => minified,
None => return,
};
let minified =
match self.minify_css(n.data.to_string(), CssMinificationMode::Stylesheet) {
Some(minified) => minified,
None => return,
};
n.data = minified.into();
}

View File

@ -18,17 +18,17 @@
<header class="lg:px-20 mb-12 mx-auto text-center">
<h2 class="font-bold leading-normal mb-2 text-2xl text-black">What We Do</h2>
<svg version=1.1 x=0px y=0px viewBox="0 0 100 60" style="margin: 0 auto;height: 35px;" xml:space=preserve>
<circle cx=50.1 cy=30.4 r=5 class=stroke-primary style="fill: transparent;stroke-width: 2;stroke-miterlimit: 10;"/>
<line x1=55.1 y1=30.4 x2=100 y2=30.4 class=stroke-primary style="stroke-width: 2;stroke-miterlimit: 10;"/>
<line x1=45.1 y1=30.4 x2=0 y2=30.4 class=stroke-primary style="stroke-width: 2;stroke-miterlimit: 10;"/>
<svg version=1.1 x=0px y=0px viewBox="0 0 100 60" style="margin:0 auto;height:35px" xml:space=preserve>
<circle cx=50.1 cy=30.4 r=5 class=stroke-primary style=fill:transparent;stroke-width:2;stroke-miterlimit:10 />
<line x1=55.1 y1=30.4 x2=100 y2=30.4 class=stroke-primary style=stroke-width:2;stroke-miterlimit:10 />
<line x1=45.1 y1=30.4 x2=0 y2=30.4 class=stroke-primary style=stroke-width:2;stroke-miterlimit:10 />
</svg>
<p class="font-light leading-relaxed mx-auto pb-2 text-gray-500 text-xl">Save time managing advertising & Content for your business.</p>
</header>
<div class="-mx-4 flex flex-row flex-wrap text-center">
<div class="fadeInUp flex-shrink lg:px-6 lg:w-1/3 max-w-full px-4 sm:w-1/2 w-full wow" data-wow-duration=1s style="visibility: visible; animation-duration: 1s; animation-name: fadeInUp;">
<div class="fadeInUp flex-shrink lg:px-6 lg:w-1/3 max-w-full px-4 sm:w-1/2 w-full wow" data-wow-duration=1s style=visibility:visible;animation-duration:1s;animation-name:fadeInUp>
<div class="bg-gray-50 border-b border-gray-100 duration-300 ease-in-out hover:-translate-y-2 mb-12 px-12 py-8 transform transition">
<div class="inline-block mb-4 text-gray-900">
@ -42,7 +42,7 @@
</div>
</div>
<div class="fadeInUp flex-shrink lg:px-6 lg:w-1/3 max-w-full px-4 sm:w-1/2 w-full wow" data-wow-duration=1s data-wow-delay=.1s style="visibility: visible; animation-duration: 1s; animation-delay: 0.1s; animation-name: fadeInUp;">
<div class="fadeInUp flex-shrink lg:px-6 lg:w-1/3 max-w-full px-4 sm:w-1/2 w-full wow" data-wow-duration=1s data-wow-delay=.1s style=visibility:visible;animation-duration:1s;animation-delay:.1s;animation-name:fadeInUp>
<div class="bg-gray-50 border-b border-gray-100 duration-300 ease-in-out hover:-translate-y-2 mb-12 px-12 py-8 transform transition">
<div class="inline-block mb-4 text-gray-900">
@ -57,7 +57,7 @@
</div>
</div>
<div class="fadeInUp flex-shrink lg:px-6 lg:w-1/3 max-w-full px-4 sm:w-1/2 w-full wow" data-wow-duration=1s data-wow-delay=.3s style="visibility: visible; animation-duration: 1s; animation-delay: 0.3s; animation-name: fadeInUp;">
<div class="fadeInUp flex-shrink lg:px-6 lg:w-1/3 max-w-full px-4 sm:w-1/2 w-full wow" data-wow-duration=1s data-wow-delay=.3s style=visibility:visible;animation-duration:1s;animation-delay:.3s;animation-name:fadeInUp>
<div class="bg-gray-50 border-b border-gray-100 duration-300 ease-in-out hover:-translate-y-2 mb-12 px-12 py-8 transform transition">
<div class="inline-block mb-4 text-gray-900">
@ -72,7 +72,7 @@
</div>
</div>
<div class="fadeInUp flex-shrink lg:px-6 lg:w-1/3 max-w-full px-4 sm:w-1/2 w-full wow" data-wow-duration=1s style="visibility: visible; animation-duration: 1s; animation-name: fadeInUp;">
<div class="fadeInUp flex-shrink lg:px-6 lg:w-1/3 max-w-full px-4 sm:w-1/2 w-full wow" data-wow-duration=1s style=visibility:visible;animation-duration:1s;animation-name:fadeInUp>
<div class="bg-gray-50 border-b border-gray-100 duration-300 ease-in-out hover:-translate-y-2 mb-12 px-12 py-8 transform transition">
<div class="inline-block mb-4 text-gray-900">
@ -87,7 +87,7 @@
</div>
</div>
<div class="fadeInUp flex-shrink lg:px-6 lg:w-1/3 max-w-full px-4 sm:w-1/2 w-full wow" data-wow-duration=1s data-wow-delay=.1s style="visibility: visible; animation-duration: 1s; animation-delay: 0.1s; animation-name: fadeInUp;">
<div class="fadeInUp flex-shrink lg:px-6 lg:w-1/3 max-w-full px-4 sm:w-1/2 w-full wow" data-wow-duration=1s data-wow-delay=.1s style=visibility:visible;animation-duration:1s;animation-delay:.1s;animation-name:fadeInUp>
<div class="bg-gray-50 border-b border-gray-100 duration-300 ease-in-out hover:-translate-y-2 mb-12 px-12 py-8 transform transition">
<div class="inline-block mb-4 text-gray-900">
@ -101,7 +101,7 @@
</div>
</div>
<div class="fadeInUp flex-shrink lg:px-6 lg:w-1/3 max-w-full px-4 sm:w-1/2 w-full wow" data-wow-duration=1s data-wow-delay=.3s style="visibility: visible; animation-duration: 1s; animation-delay: 0.3s; animation-name: fadeInUp;">
<div class="fadeInUp flex-shrink lg:px-6 lg:w-1/3 max-w-full px-4 sm:w-1/2 w-full wow" data-wow-duration=1s data-wow-delay=.3s style=visibility:visible;animation-duration:1s;animation-delay:.3s;animation-name:fadeInUp>
<div class="bg-gray-50 border-b border-gray-100 duration-300 ease-in-out hover:-translate-y-2 mb-12 px-12 py-8 transform transition">
<div class="inline-block mb-4 text-gray-900">

View File

@ -1,4 +1,4 @@
<!doctype html><html lang=en><title>Document</title><link rel=preload as=image imagesrcset="dog-cropped-1x.jpg,dog-cropped-2x.jpg 2x" media="(max-width: 800px)"><link rel=preload as=image imagesrcset="dog-wide-1x.jpg,dog-wide-2x.jpg 2x" media="(min-width: 801px)"><link rel=preload as=image imagesrcset="wolf_400px.jpg 400w,wolf_800px.jpg 800w,wolf_1600px.jpg 1600w" imagesizes=50vw><link rel=preload as=image imagesrcset="wolf_400px.jpg 400w,wolf_800px.jpg 800w,wolf_1600px.jpg 1600w" imagesizes="(max-width: 600px) 480px,800px"><body>
<!doctype html><html lang=en><title>Document</title><link rel=preload as=image imagesrcset="dog-cropped-1x.jpg,dog-cropped-2x.jpg 2x" media=(max-width:800px)><link rel=preload as=image imagesrcset="dog-wide-1x.jpg,dog-wide-2x.jpg 2x" media=(min-width:801px)><link rel=preload as=image imagesrcset="wolf_400px.jpg 400w,wolf_800px.jpg 800w,wolf_1600px.jpg 1600w" imagesizes=50vw><link rel=preload as=image imagesrcset="wolf_400px.jpg 400w,wolf_800px.jpg 800w,wolf_1600px.jpg 1600w" imagesizes="(max-width:600px) 480px,800px"><body>
<div>test</div>
<img srcset="elva-fairy-480w.jpg 480w,elva-fairy-800w.jpg 800w" sizes="(max-width: 600px) 480px,800px" src=elva-fairy-800w.jpg alt="Elva dressed as a fairy">
<img srcset="elva-fairy-480w.jpg 480w,elva-fairy-800w.jpg 800w" sizes="(max-width:600px) 480px,800px" src=elva-fairy-800w.jpg alt="Elva dressed as a fairy">

View File

@ -5,7 +5,7 @@
<div type=text onmouseover=myFunction()>test</div>
<div type=text onmouseover=myFunction()>test</div>
<div type=text>test</div>
<svg version=1.1 viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice" style="width:100%; height:100%; position:absolute; top:0; left:0; z-index:-1;">
<svg version=1.1 viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice" style=width:100%;height:100%;position:absolute;top:0;left:0;z-index:-1>
<circle onmouseover='alert("test")' cx=50 cy=50 r=30 style=fill:url(#gradient) />
</svg>

View File

@ -0,0 +1,60 @@
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
<link rel="stylesheet" type="text/css" href="//msiter.ru/theme.css">
<link rel="stylesheet" type="text/css" href="//msiter.ru/print.css" media="print">
<link rel="stylesheet" type="text/css" href="//msiter.ru/theme.css" media="(prefers-color-scheme: dark)">
<link rel="preload" as="image"
imagesrcset="dog-cropped-1x.jpg, dog-cropped-2x.jpg 2x"
media="(max-width: 800px)">
<link rel="preload" as="image"
imagesrcset="dog-wide-1x.jpg, dog-wide-2x.jpg 2x"
media="(min-width: 801px)">
<style media="screen and (min-width: 900px)">
.class {
color: red;
}
</style>
<style media="(min-width: 900px) and (min-width: 800px)">
.class {
color: red;
}
</style>
</head>
<body>
<picture>
<source srcset="dog-cropped-1x.jpg, dog-cropped-2x.jpg 2x"
media="(max-width: 800px)">
<img src="dog-wide-1x.jpg" srcset="dog-wide-2x.jpg 2x"
alt="An awesome dog">
</picture>
<style media="screen and (min-width: 30em) and (orientation: landscape)">
.class {
color: red;
}
</style>
<style media="(min-width: 1em) and (max-width: 500em)">
.class {
color: red;
}
</style>
<style media="(30em <= width <= 50em )">
.class {
color: red;
}
</style>
<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
<style media="(min-width: 1000px)">
circle {
fill: gold;
stroke: maroon;
stroke-width: 2px;
}
</style>
<circle cx="5" cy="5" r="4" />
</svg>
</body>
</html>

View File

@ -0,0 +1,14 @@
<!doctype html><html lang=en><title>Document</title><link rel=stylesheet href=//msiter.ru/theme.css><link rel=stylesheet href=//msiter.ru/print.css media=print><link rel=stylesheet href=//msiter.ru/theme.css media=(prefers-color-scheme:dark)><link rel=preload as=image imagesrcset="dog-cropped-1x.jpg,dog-cropped-2x.jpg 2x" media=(max-width:800px)><link rel=preload as=image imagesrcset="dog-wide-1x.jpg,dog-wide-2x.jpg 2x" media=(min-width:801px)><style media="screen and (min-width:900px)">.class{color:red}</style><style media="(min-width:900px)and (min-width:800px)">.class{color:red}</style><body>
<picture>
<source srcset="dog-cropped-1x.jpg,dog-cropped-2x.jpg 2x" media=(max-width:800px)>
<img src=dog-wide-1x.jpg srcset="dog-wide-2x.jpg 2x" alt="An awesome dog">
</picture>
<style media="screen and (min-width:30em)and (orientation:landscape)">.class{color:red}</style>
<style media="(min-width:1em)and (max-width:500em)">.class{color:red}</style>
<style media="(30em<=width<=50em)">.class{color:red}</style>
<svg viewBox="0 0 10 10">
<style media=(min-width:1e3px)>circle{fill:gold;stroke:maroon;stroke-width:2px}</style>
<circle cx=5 cy=5 r=4 />
</svg>

View File

@ -20,6 +20,15 @@
<img src="favicon72.png"
alt="MDN logo"
srcset=" favicon144.png 2x ">
<img srcset="/img/new-york-sm.jpg 120w,
/img/new-york-md.jpg 200w,
/img/new-york-lg.jpg 300w"
sizes="((min-width: 10em) and (max-width: 20em)) 10em,
((min-width: 30em) and (max-width: 40em)) 30em,
(min-width: 40em) 40em">
<img style="width: 100%;"
srcset="https://webref.ru/example/image/mushroom_portrait.jpg 300w, https://webref.ru/example/image/mushroom_landscape.jpg 600w"
sizes="(max-width: 650px) 100vw, calc(150px + 150px)"
alt="">
</body>
</html>

View File

@ -1,8 +1,9 @@
<!doctype html><html lang=en><title>Document</title><body>
<img srcset="elva-fairy-480w.jpg 480w,elva-fairy-800w.jpg 800w" sizes="(max-width: 600px) 480px,800px" src=elva-fairy-800w.jpg alt="Elva dressed as a fairy">
<img srcset="elva-fairy-480w.jpg 480w,elva-fairy-800w.jpg 800w" sizes="(max-width:600px) 480px,800px" src=elva-fairy-800w.jpg alt="Elva dressed as a fairy">
<img srcset="elva-fairy-320w.jpg,elva-fairy-480w.jpg 1.5x,elva-fairy-640w.jpg 2x" src=elva-fairy-640w.jpg alt="Elva dressed as a fairy">
<img src=favicon72.png alt="MDN logo" srcset="favicon144.png 2x">
<img srcset="/img/new-york-sm.jpg 120w,/img/new-york-md.jpg 200w,/img/new-york-lg.jpg 300w" sizes="((min-width:10em)and (max-width:20em)) 10em,((min-width:30em)and (max-width:40em)) 30em,(min-width:40em) 40em">
<img style=width:100% srcset="https://webref.ru/example/image/mushroom_portrait.jpg 300w,https://webref.ru/example/image/mushroom_landscape.jpg 600w" sizes="(max-width:650px) 100vw,calc(150px + 150px)" alt="">

View File

@ -29,6 +29,28 @@
</head>
<body>
<p style=" color: red; background-color: rgb(100, 75, 200); "></p>
<p style="
color: red;
background-color: rgb(100, 75, 200);
"></p>
<p style="display : block;"></p>
<p style="display : block;"></p>
<p style="color:green">This is a paragraph.</p>
<p style="color:green;">This is a paragraph.</p>
<p style=" color : green ">This is a paragraph.</p>
<p style="--color: red; color: var(--color);">test</p>
<p style="margin: 15px; line-height: 1.5; text-align: center;">
Well, I am the slime from your video<br>
Oozin' along on your livin' room floor.</p>
<svg width="100%" height="100%" viewBox="-100 -100 200 200" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<circle cx="-50" cy="-50" r="30" style="fill:red" />
<image style=" background: red; " x="10" y="20" width="80" height="80" href="recursion.svg" />
</svg>
<p style="color: red;;;;"></p>
<p style="color: red;;;;color: blue"></p>
<p style=" "></p>
<p style="broken"></p>
<p style="broken:"></p>
</body>
</html>

View File

@ -5,6 +5,24 @@
h1 {color:red;}
p {color:blue;}
</style><body>
<p style="color: red; background-color: rgb(100, 75, 200);"></p>
<p style=color:red;background-color:#644bc8></p>
<p style=color:red;background-color:#644bc8></p>
<p style=display:block></p>
<p style=display:block></p>
<p style=color:green>This is a paragraph.</p>
<p style=color:green>This is a paragraph.</p>
<p style=color:green>This is a paragraph.</p>
<p style=--color:red;color:var(--color)>test</p>
<p style=margin:15px;line-height:1.5;text-align:center>
Well, I am the slime from your video<br>
Oozin' along on your livin' room floor.</p>
<svg width=100% height=100% viewBox="-100 -100 200 200" version=1.1>
<circle cx=-50 cy=-50 r=30 style=fill:red />
<image style=background:red x=10 y=20 width=80 height=80 href=recursion.svg />
</svg>
<p style=color:red></p>
<p style=color:red;color:blue></p>
<p></p>
<p style=broken></p>
<p style=broken:></p>

View File

@ -1,3 +1,3 @@
<!doctype html><html lang=en><meta charset=UTF-8><meta name=viewport content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Document</title><body>
<iframe sandbox="allow-same-origin allow-scripts allow-popups allow-forms" src=https://platform.twitter.com/widgets/tweet_button.html style="border: 0; width:130px; height:20px;"></iframe>
<iframe sandbox="allow-same-origin allow-scripts allow-popups allow-forms" src=https://platform.twitter.com/widgets/tweet_button.html style=border:0;width:130px;height:20px></iframe>

View File

@ -1,13 +1,13 @@
<!doctype html><html lang=en><meta charset=UTF-8><meta name=viewport content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Document</title><link href=mobile.css rel=stylesheet media="screen and (max-width: 600px)"><style media="all and (max-width: 500px)">p{color:blue;background-color:yellow}</style><body>
<img srcset="elva-fairy-480w.jpg 480w,elva-fairy-800w.jpg 800w" sizes="(max-width: 600px) 480px,800px" src=elva-fairy-800w.jpg alt="Elva dressed as a fairy">
<!doctype html><html lang=en><meta charset=UTF-8><meta name=viewport content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Document</title><link href=mobile.css rel=stylesheet media="screen and (max-width:600px)"><style media="all and (max-width:500px)">p{color:blue;background-color:yellow}</style><body>
<img srcset="elva-fairy-480w.jpg 480w,elva-fairy-800w.jpg 800w" sizes="(max-width:600px) 480px,800px" src=elva-fairy-800w.jpg alt="Elva dressed as a fairy">
<img srcset="elva-fairy-320w.jpg,elva-fairy-480w.jpg 1.5x,elva-fairy-640w.jpg 2x" src=elva-fairy-640w.jpg alt="Elva dressed as a fairy">
<picture>
<source media="(max-width: 799px)" srcset=elva-480w-close-portrait.jpg>
<source media="(min-width: 800px)" srcset=elva-800w.jpg>
<source media=(max-width:799px) srcset=elva-480w-close-portrait.jpg>
<source media=(min-width:800px) srcset=elva-800w.jpg>
<img src=elva-800w.jpg alt="Chris standing up holding his daughter Elva">
</picture>
<picture>
<source media="(min-width: 1200px)" srcset=elva-480w-close-portrait.jpg>
<source media=(min-width:1200px) srcset=elva-480w-close-portrait.jpg>
<img src=mdn-logo-narrow.png alt=MDN>
</picture>
<svg width=500 height=250>

View File

@ -21,7 +21,7 @@
Foo
</textarea><div><div>Text</div></div><unknown><div>Text</div></unknown><div></div><svg version=1.1 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 x=0 y=0 width=100 height=100 style=fill:url(#gradient) /><circle cx=50 cy=50 r=30 style=fill:url(#gradient) /></svg><svg viewBox="0 0 100 100"><a href=/docs/Web/SVG/Element/circle><circle cx=50 cy=40 r=35 /></a><a href=/docs/Web/SVG/Element/text><text x=50 y=90 text-anchor=middle>&lt;circle></text></a></svg><script></script><script>console.log("test")</script><xmp>
</textarea><div><div>Text</div></div><unknown><div>Text</div></unknown><div></div><svg version=1.1 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 x=0 y=0 width=100 height=100 style=fill:url(#gradient) /><circle cx=50 cy=50 r=30 style=fill:url(#gradient) /></svg><svg viewBox="0 0 100 100"><a href=/docs/Web/SVG/Element/circle><circle cx=50 cy=40 r=35 /></a><a href=/docs/Web/SVG/Element/text><text x=50 y=90 text-anchor=middle>&lt;circle></text></a></svg><script></script><script>console.log("test")</script><xmp>
test

View File

@ -21,7 +21,7 @@
Foo
</textarea> <div> <div>Text</div> </div> <unknown> <div>Text</div> </unknown> <div> </div> <svg version=1.1 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 x=0 y=0 width=100 height=100 style=fill:url(#gradient) /><circle cx=50 cy=50 r=30 style=fill:url(#gradient) /></svg> <svg viewBox="0 0 100 100"><a href=/docs/Web/SVG/Element/circle> <circle cx=50 cy=40 r=35 /> </a><a href=/docs/Web/SVG/Element/text> <text x=50 y=90 text-anchor=middle>&lt;circle></text> </a></svg> <script></script> <script>console.log("test")</script> <xmp>
</textarea> <div> <div>Text</div> </div> <unknown> <div>Text</div> </unknown> <div> </div> <svg version=1.1 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 x=0 y=0 width=100 height=100 style=fill:url(#gradient) /><circle cx=50 cy=50 r=30 style=fill:url(#gradient) /></svg> <svg viewBox="0 0 100 100"><a href=/docs/Web/SVG/Element/circle> <circle cx=50 cy=40 r=35 /> </a><a href=/docs/Web/SVG/Element/text> <text x=50 y=90 text-anchor=middle>&lt;circle></text> </a></svg> <script></script> <script>console.log("test")</script> <xmp>
test

View File

@ -21,7 +21,7 @@
Foo
</textarea> <div> <div>Text</div> </div> <unknown> <div>Text</div> </unknown> <div> </div> <svg version=1.1 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 x=0 y=0 width=100 height=100 style=fill:url(#gradient) /><circle cx=50 cy=50 r=30 style=fill:url(#gradient) /></svg> <svg viewBox="0 0 100 100"><a href=/docs/Web/SVG/Element/circle> <circle cx=50 cy=40 r=35 /> </a><a href=/docs/Web/SVG/Element/text> <text x=50 y=90 text-anchor=middle>&lt;circle></text> </a></svg> <script></script> <script>console.log("test")</script> <xmp>
</textarea> <div> <div>Text</div> </div> <unknown> <div>Text</div> </unknown> <div> </div> <svg version=1.1 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 x=0 y=0 width=100 height=100 style=fill:url(#gradient) /><circle cx=50 cy=50 r=30 style=fill:url(#gradient) /></svg> <svg viewBox="0 0 100 100"><a href=/docs/Web/SVG/Element/circle> <circle cx=50 cy=40 r=35 /> </a><a href=/docs/Web/SVG/Element/text> <text x=50 y=90 text-anchor=middle>&lt;circle></text> </a></svg> <script></script> <script>console.log("test")</script> <xmp>
test