mirror of
https://github.com/swc-project/swc.git
synced 2024-12-24 22:22:34 +03:00
feat(html/minifier): Compress style
and media
attributes (#5022)
This commit is contained in:
parent
035d1f0089
commit
47d34a33d4
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3968,6 +3968,7 @@ dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_cached",
|
||||
"swc_common",
|
||||
"swc_css_ast",
|
||||
"swc_css_codegen",
|
||||
"swc_css_minifier",
|
||||
"swc_css_parser",
|
||||
|
@ -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" }
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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">
|
||||
|
@ -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">
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
@ -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>
|
||||
|
@ -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>
|
@ -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="">
|
||||
|
||||
|
@ -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>
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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><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><circle></text></a></svg><script></script><script>console.log("test")</script><xmp>
|
||||
|
||||
test
|
||||
|
||||
|
@ -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><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><circle></text> </a></svg> <script></script> <script>console.log("test")</script> <xmp>
|
||||
|
||||
test
|
||||
|
||||
|
@ -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><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><circle></text> </a></svg> <script></script> <script>console.log("test")</script> <xmp>
|
||||
|
||||
test
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user