perf(html/minifier): Reduce allocations (#6623)

This commit is contained in:
Alexander Akait 2022-12-13 06:34:55 +03:00 committed by GitHub
parent b976551065
commit 7d3aa66bb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 409 additions and 281 deletions

View File

@ -594,7 +594,9 @@ abbr
abstract
accent-color
accept
accesskey
acronym
action
actuate
add
address
@ -647,6 +649,9 @@ apply
arcrole
area
arguments
aria-describedby
aria-labelledby
aria-owns
article
as
aside
@ -660,6 +665,7 @@ attributename
attributetype
audio
auto
autocomplete
await
azimuth
b
@ -685,6 +691,7 @@ baseprofile
bdi
bdo
before
begin
bgsound
big
bigint
@ -778,6 +785,7 @@ charset
circle
cite
class
classid
clear
clip
clip-path
@ -787,12 +795,15 @@ clippath
clippathunits
cm
code
codebase
col
colgroup
color
color-mix
color-profile
color-scheme
cols
colspan
column-count
column-gap
column-rule-color
@ -827,6 +838,7 @@ currentColor
currentcolor
cursor
custom-media
d
data
datalist
dd
@ -997,6 +1009,7 @@ forced-color-adjust
foreignObject
foreignobject
form
formaction
frame
frameset
from
@ -1094,6 +1107,7 @@ intrinsic
is
isindex
isolation
itemid
itemprop
itemref
itemtype
@ -1158,6 +1172,7 @@ list-style-image
list-style-type
listing
local
longdesc
lr
lr-tb
ltr
@ -1227,6 +1242,7 @@ max-height
max-inline-size
max-lines
max-width
maxlength
media
medium
menu
@ -1285,7 +1301,106 @@ offset-rotate
oklab
oklch
ol
onabort
onafterprint
onautocomplete
onautocompleteerror
onauxclick
onbeforematch
onbeforeprint
onbeforeunload
onbegin
onblur
oncancel
oncanplay
oncanplaythrough
onchange
onclick
onclose
oncontextlost
oncontextmenu
oncontextrestored
oncopy
oncuechange
oncut
ondblclick
ondrag
ondragend
ondragenter
ondragexit
ondragleave
ondragover
ondragstart
ondrop
ondurationchange
onemptied
onend
onended
onerror
onfocus
onformdata
onhashchange
oninput
oninvalid
onkeydown
onkeypress
onkeyup
onlanguagechange
onload
onloadeddata
onloadedmetadata
onloadstart
only
onmessage
onmessageerror
onmousedown
onmouseenter
onmouseleave
onmousemove
onmouseout
onmouseover
onmouseup
onmousewheel
onoffline
ononline
onpagehide
onpageshow
onpaste
onpause
onplay
onplaying
onpopstate
onprogress
onratechange
onreadystatechange
onrejectionhandled
onrepeat
onreset
onresize
onscroll
onsecuritypolicyviolation
onseeked
onseeking
onselect
onshow
onslotchange
onsort
onstalled
onstorage
onsubmit
onsuspend
ontimeupdate
ontoggle
onunhandledrejection
onunload
onvisibilitychange
onvolumechange
onwaiting
onwebkitanimationend
onwebkitanimationiteration
onwebkitanimationstart
onwebkittransitionend
onwheel
opacity
optgroup
option
@ -1331,6 +1446,7 @@ page-break-after
page-break-before
page-break-inside
paint-order
panose-1
param
part
path
@ -1346,6 +1462,7 @@ patternunits
pc
perspective
picture
ping
place-content
place-items
place-self
@ -1362,6 +1479,7 @@ pointsatz
polygon
polyline
position
poster
pre
preload
preserveAlpha
@ -1372,6 +1490,7 @@ primitiveUnits
primitiveunits
private
process
profile
progress
property
protected
@ -1432,6 +1551,8 @@ rotatez
round
row
row-gap
rows
rowspan
rp
rt
rtc
@ -1525,6 +1646,7 @@ spreadMethod
spreadmethod
src
srcdoc
srcset
start
startOffset
startoffset
@ -1565,6 +1687,7 @@ symbol
systemLanguage
systemlanguage
tab-size
tabindex
table
table-layout
tableValues
@ -1660,7 +1783,9 @@ unknown
unset
url
use
usemap
user-select
values
var
vb
vertical-align

View File

@ -17,12 +17,6 @@
"name": "__local__c"
}
],
"d": [
{
"type": "local",
"name": "__local__d"
}
],
"y": [
{
"type": "local",
@ -46,5 +40,11 @@
"type": "local",
"name": "__local__x"
}
],
"d": [
{
"type": "local",
"name": "__local__d"
}
]
}

View File

@ -222,7 +222,7 @@
4 | }
`----
x Ident { value: Atom('d' type=inline), raw: "d" }
x Ident { value: Atom('d' type=static), raw: "d" }
,-[$DIR/tests/fixture/vendor/esbuild/misc/L0mEf41IMkWcP7NotllkAg/input.css:2:1]
2 | a: b;
3 | c: d;

View File

@ -1,7 +1,7 @@
#![deny(clippy::all)]
#![feature(box_patterns)]
use std::{cmp::Ordering, mem::take};
use std::{borrow::Cow, cmp::Ordering, mem::take};
use once_cell::sync::Lazy;
use serde_json::Value;
@ -23,262 +23,145 @@ use crate::option::{
pub mod option;
// Global attributes
static EVENT_HANDLER_ATTRIBUTES: &[&str] = &[
"onabort",
"onautocomplete",
"onautocompleteerror",
"onauxclick",
"onbeforematch",
"oncancel",
"oncanplay",
"oncanplaythrough",
"onchange",
"onclick",
"onclose",
"oncontextlost",
"oncontextmenu",
"oncontextrestored",
"oncuechange",
"ondblclick",
"ondrag",
"ondragend",
"ondragenter",
"ondragexit",
"ondragleave",
"ondragover",
"ondragstart",
"ondrop",
"ondurationchange",
"onemptied",
"onended",
"onformdata",
"oninput",
"oninvalid",
"onkeydown",
"onkeypress",
"onkeyup",
"onmousewheel",
"onmousedown",
"onmouseenter",
"onmouseleave",
"onmousemove",
"onmouseout",
"onmouseover",
"onmouseup",
"onpause",
"onplay",
"onplaying",
"onprogress",
"onratechange",
"onreset",
"onsecuritypolicyviolation",
"onseeked",
"onseeking",
"onselect",
"onslotchange",
"onstalled",
"onsubmit",
"onsuspend",
"ontimeupdate",
"ontoggle",
"onvolumechange",
"onwaiting",
"onwebkitanimationend",
"onwebkitanimationiteration",
"onwebkitanimationstart",
"onwebkittransitionend",
"onwheel",
"onblur",
"onerror",
"onfocus",
"onload",
"onloadeddata",
"onloadedmetadata",
"onloadstart",
"onresize",
"onscroll",
"onafterprint",
"onbeforeprint",
"onbeforeunload",
"onhashchange",
"onlanguagechange",
"onmessage",
"onmessageerror",
"onoffline",
"ononline",
"onpagehide",
"onpageshow",
"onpopstate",
"onrejectionhandled",
"onstorage",
"onunhandledrejection",
"onunload",
"oncut",
"oncopy",
"onpaste",
"onreadystatechange",
"onvisibilitychange",
"onshow",
"onsort",
"onbegin",
"onend",
"onrepeat",
static ALLOW_TO_TRIM_HTML_ATTRIBUTES: &[(&JsWord, &JsWord)] = &[
(&js_word!("head"), &js_word!("profile")),
(&js_word!("audio"), &js_word!("src")),
(&js_word!("embed"), &js_word!("src")),
(&js_word!("iframe"), &js_word!("src")),
(&js_word!("img"), &js_word!("src")),
(&js_word!("input"), &js_word!("src")),
(&js_word!("input"), &js_word!("usemap")),
(&js_word!("input"), &js_word!("longdesc")),
(&js_word!("script"), &js_word!("src")),
(&js_word!("source"), &js_word!("src")),
(&js_word!("track"), &js_word!("src")),
(&js_word!("video"), &js_word!("src")),
(&js_word!("video"), &js_word!("poster")),
(&js_word!("td"), &js_word!("colspan")),
(&js_word!("td"), &js_word!("rowspan")),
(&js_word!("th"), &js_word!("colspan")),
(&js_word!("th"), &js_word!("rowspan")),
(&js_word!("col"), &js_word!("span")),
(&js_word!("colgroup"), &js_word!("span")),
(&js_word!("textarea"), &js_word!("cols")),
(&js_word!("textarea"), &js_word!("rows")),
(&js_word!("textarea"), &js_word!("maxlength")),
(&js_word!("input"), &js_word!("size")),
(&js_word!("input"), &js_word!("formaction")),
(&js_word!("input"), &js_word!("maxlength")),
(&js_word!("button"), &js_word!("formaction")),
(&js_word!("select"), &js_word!("size")),
(&js_word!("form"), &js_word!("action")),
(&js_word!("object"), &js_word!("data")),
(&js_word!("object"), &js_word!("codebase")),
(&js_word!("object"), &js_word!("classid")),
(&js_word!("applet"), &js_word!("codebase")),
(&js_word!("a"), &js_word!("href")),
(&js_word!("area"), &js_word!("href")),
(&js_word!("link"), &js_word!("href")),
(&js_word!("base"), &js_word!("href")),
(&js_word!("q"), &js_word!("cite")),
(&js_word!("blockquote"), &js_word!("cite")),
(&js_word!("del"), &js_word!("cite")),
(&js_word!("ins"), &js_word!("cite")),
(&js_word!("img"), &js_word!("usemap")),
(&js_word!("object"), &js_word!("usemap")),
];
static ALLOW_TO_TRIM_GLOBAL_ATTRIBUTES: &[&str] = &["style", "tabindex", "itemid"];
static ALLOW_TO_TRIM_SVG_ATTRIBUTES: &[(&JsWord, &JsWord)] = &[(&js_word!("a"), &js_word!("href"))];
static ALLOW_TO_TRIM_HTML_ATTRIBUTES: &[(&str, &str)] = &[
("head", "profile"),
("audio", "src"),
("embed", "src"),
("iframe", "src"),
("img", "src"),
("input", "src"),
("input", "usemap"),
("input", "longdesc"),
("script", "src"),
("source", "src"),
("track", "src"),
("video", "src"),
("video", "poster"),
("td", "colspan"),
("td", "rowspan"),
("th", "colspan"),
("th", "rowspan"),
("col", "span"),
("colgroup", "span"),
("textarea", "cols"),
("textarea", "rows"),
("textarea", "maxlength"),
("input", "size"),
("input", "formaction"),
("input", "maxlength"),
("button", "formaction"),
("select", "size"),
("form", "action"),
("object", "data"),
("object", "codebase"),
("object", "classid"),
("applet", "codebase"),
("a", "href"),
("area", "href"),
("link", "href"),
("base", "href"),
("q", "cite"),
("blockquote", "cite"),
("del", "cite"),
("ins", "cite"),
("img", "usemap"),
("object", "usemap"),
static COMMA_SEPARATED_HTML_ATTRIBUTES: &[(&JsWord, &JsWord)] = &[
(&js_word!("img"), &js_word!("srcset")),
(&js_word!("source"), &js_word!("srcset")),
(&js_word!("img"), &js_word!("sizes")),
(&js_word!("source"), &js_word!("sizes")),
(&js_word!("link"), &js_word!("media")),
(&js_word!("source"), &js_word!("media")),
(&js_word!("style"), &js_word!("media")),
];
static ALLOW_TO_TRIM_SVG_ATTRIBUTES: &[(&str, &str)] = &[("a", "href")];
static COMMA_SEPARATED_HTML_ATTRIBUTES: &[(&str, &str)] = &[
("img", "srcset"),
("source", "srcset"),
("img", "sizes"),
("source", "sizes"),
("link", "media"),
("source", "media"),
("style", "media"),
static COMMA_SEPARATED_SVG_ATTRIBUTES: &[(&JsWord, &JsWord)] = &[
(&js_word!("style"), &js_word!("media")),
(&js_word!("polyline"), &js_word!("points")),
(&js_word!("polygon"), &js_word!("points")),
];
static COMMA_SEPARATED_SVG_ATTRIBUTES: &[(&str, &str)] = &[
("style", "media"),
("polyline", "points"),
("polygon", "points"),
static SPACE_SEPARATED_HTML_ATTRIBUTES: &[(&JsWord, &JsWord)] = &[
(&js_word!("a"), &js_word!("rel")),
(&js_word!("a"), &js_word!("ping")),
(&js_word!("area"), &js_word!("rel")),
(&js_word!("area"), &js_word!("ping")),
(&js_word!("link"), &js_word!("rel")),
(&js_word!("link"), &js_word!("sizes")),
(&js_word!("link"), &js_word!("blocking")),
(&js_word!("iframe"), &js_word!("sandbox")),
(&js_word!("td"), &js_word!("headers")),
(&js_word!("th"), &js_word!("headers")),
(&js_word!("output"), &js_word!("for")),
(&js_word!("script"), &js_word!("blocking")),
(&js_word!("style"), &js_word!("blocking")),
(&js_word!("input"), &js_word!("autocomplete")),
(&js_word!("form"), &js_word!("rel")),
(&js_word!("form"), &js_word!("autocomplete")),
];
static SPACE_SEPARATED_GLOBAL_ATTRIBUTES: &[&str] = &[
"class",
"itemprop",
"itemref",
"itemtype",
"part",
"accesskey",
"aria-describedby",
"aria-labelledby",
"aria-owns",
];
static SPACE_SEPARATED_HTML_ATTRIBUTES: &[(&str, &str)] = &[
("a", "rel"),
("a", "ping"),
("area", "rel"),
("area", "ping"),
("link", "rel"),
("link", "sizes"),
("link", "blocking"),
("iframe", "sandbox"),
("td", "headers"),
("th", "headers"),
("output", "for"),
("script", "blocking"),
("style", "blocking"),
("input", "autocomplete"),
("form", "rel"),
("form", "autocomplete"),
];
static SPACE_SEPARATED_SVG_ATTRIBUTES: &[(&str, &str)] = &[
("svg", "preserveAspectRatio"),
("svg", "viewBox"),
("symbol", "preserveAspectRatio"),
("symbol", "viewBox"),
("image", "preserveAspectRatio"),
("feImage", "preserveAspectRatio"),
("marker", "preserveAspectRatio"),
("pattern", "preserveAspectRatio"),
("pattern", "viewBox"),
("pattern", "patternTransform"),
("view", "preserveAspectRatio"),
("view", "viewBox"),
("path", "d"),
static SPACE_SEPARATED_SVG_ATTRIBUTES: &[(&JsWord, &JsWord)] = &[
(&js_word!("svg"), &js_word!("preserveAspectRatio")),
(&js_word!("svg"), &js_word!("viewBox")),
(&js_word!("symbol"), &js_word!("preserveAspectRatio")),
(&js_word!("symbol"), &js_word!("viewBox")),
(&js_word!("image"), &js_word!("preserveAspectRatio")),
(&js_word!("feImage"), &js_word!("preserveAspectRatio")),
(&js_word!("marker"), &js_word!("preserveAspectRatio")),
(&js_word!("pattern"), &js_word!("preserveAspectRatio")),
(&js_word!("pattern"), &js_word!("viewBox")),
(&js_word!("pattern"), &js_word!("patternTransform")),
(&js_word!("view"), &js_word!("preserveAspectRatio")),
(&js_word!("view"), &js_word!("viewBox")),
(&js_word!("path"), &js_word!("d")),
// TODO improve me more
("textPath", "path"),
("animateMotion", "path"),
("glyph", "d"),
("missing-glyph", "d"),
("feColorMatrix", "values"),
("feConvolveMatrix", "kernelMatrix"),
("text", "rotate"),
("tspan", "rotate"),
("feFuncA", "tableValues"),
("feFuncB", "tableValues"),
("feFuncG", "tableValues"),
("feFuncR", "tableValues"),
("linearGradient", "gradientTransform"),
("radialGradient", "gradientTransform"),
("font-face", "panose-1"),
("a", "rel"),
(&js_word!("textPath"), &js_word!("path")),
(&js_word!("animateMotion"), &js_word!("path")),
(&js_word!("glyph"), &js_word!("d")),
(&js_word!("missing-glyph"), &js_word!("d")),
(&js_word!("feColorMatrix"), &js_word!("values")),
(&js_word!("feConvolveMatrix"), &js_word!("kernelMatrix")),
(&js_word!("text"), &js_word!("rotate")),
(&js_word!("tspan"), &js_word!("rotate")),
(&js_word!("feFuncA"), &js_word!("tableValues")),
(&js_word!("feFuncB"), &js_word!("tableValues")),
(&js_word!("feFuncG"), &js_word!("tableValues")),
(&js_word!("feFuncR"), &js_word!("tableValues")),
(&js_word!("linearGradient"), &js_word!("gradientTransform")),
(&js_word!("radialGradient"), &js_word!("gradientTransform")),
(&js_word!("font-face"), &js_word!("panose-1")),
(&js_word!("a"), &js_word!("rel")),
];
static SEMICOLON_SEPARATED_SVG_ATTRIBUTES: &[(&str, &str)] = &[
("animate", "keyTimes"),
("animate", "keySplines"),
("animate", "values"),
("animate", "begin"),
("animate", "end"),
("animateColor", "keyTimes"),
("animateColor", "keySplines"),
("animateColor", "values"),
("animateColor", "begin"),
("animateColor", "end"),
("animateMotion", "keyTimes"),
("animateMotion", "keySplines"),
("animateMotion", "values"),
("animateMotion", "values"),
("animateMotion", "end"),
("animateTransform", "keyTimes"),
("animateTransform", "keySplines"),
("animateTransform", "values"),
("animateTransform", "begin"),
("animateTransform", "end"),
("discard", "begin"),
("set", "begin"),
("set", "end"),
static SEMICOLON_SEPARATED_SVG_ATTRIBUTES: &[(&JsWord, &JsWord)] = &[
(&js_word!("animate"), &js_word!("keyTimes")),
(&js_word!("animate"), &js_word!("keySplines")),
(&js_word!("animate"), &js_word!("values")),
(&js_word!("animate"), &js_word!("begin")),
(&js_word!("animate"), &js_word!("end")),
(&js_word!("animateColor"), &js_word!("keyTimes")),
(&js_word!("animateColor"), &js_word!("keySplines")),
(&js_word!("animateColor"), &js_word!("values")),
(&js_word!("animateColor"), &js_word!("begin")),
(&js_word!("animateColor"), &js_word!("end")),
(&js_word!("animateMotion"), &js_word!("keyTimes")),
(&js_word!("animateMotion"), &js_word!("keySplines")),
(&js_word!("animateMotion"), &js_word!("values")),
(&js_word!("animateMotion"), &js_word!("values")),
(&js_word!("animateMotion"), &js_word!("end")),
(&js_word!("animateTransform"), &js_word!("keyTimes")),
(&js_word!("animateTransform"), &js_word!("keySplines")),
(&js_word!("animateTransform"), &js_word!("values")),
(&js_word!("animateTransform"), &js_word!("begin")),
(&js_word!("animateTransform"), &js_word!("end")),
(&js_word!("discard"), &js_word!("begin")),
(&js_word!("set"), &js_word!("begin")),
(&js_word!("set"), &js_word!("end")),
];
enum CssMinificationMode {
@ -368,7 +251,108 @@ fn get_white_space(namespace: Namespace, tag_name: &JsWord) -> WhiteSpace {
impl Minifier<'_> {
fn is_event_handler_attribute(&self, attribute: &Attribute) -> bool {
EVENT_HANDLER_ATTRIBUTES.contains(&&*attribute.name)
matches!(
attribute.name,
js_word!("onabort")
| js_word!("onautocomplete")
| js_word!("onautocompleteerror")
| js_word!("onauxclick")
| js_word!("onbeforematch")
| js_word!("oncancel")
| js_word!("oncanplay")
| js_word!("oncanplaythrough")
| js_word!("onchange")
| js_word!("onclick")
| js_word!("onclose")
| js_word!("oncontextlost")
| js_word!("oncontextmenu")
| js_word!("oncontextrestored")
| js_word!("oncuechange")
| js_word!("ondblclick")
| js_word!("ondrag")
| js_word!("ondragend")
| js_word!("ondragenter")
| js_word!("ondragexit")
| js_word!("ondragleave")
| js_word!("ondragover")
| js_word!("ondragstart")
| js_word!("ondrop")
| js_word!("ondurationchange")
| js_word!("onemptied")
| js_word!("onended")
| js_word!("onformdata")
| js_word!("oninput")
| js_word!("oninvalid")
| js_word!("onkeydown")
| js_word!("onkeypress")
| js_word!("onkeyup")
| js_word!("onmousewheel")
| js_word!("onmousedown")
| js_word!("onmouseenter")
| js_word!("onmouseleave")
| js_word!("onmousemove")
| js_word!("onmouseout")
| js_word!("onmouseover")
| js_word!("onmouseup")
| js_word!("onpause")
| js_word!("onplay")
| js_word!("onplaying")
| js_word!("onprogress")
| js_word!("onratechange")
| js_word!("onreset")
| js_word!("onsecuritypolicyviolation")
| js_word!("onseeked")
| js_word!("onseeking")
| js_word!("onselect")
| js_word!("onslotchange")
| js_word!("onstalled")
| js_word!("onsubmit")
| js_word!("onsuspend")
| js_word!("ontimeupdate")
| js_word!("ontoggle")
| js_word!("onvolumechange")
| js_word!("onwaiting")
| js_word!("onwebkitanimationend")
| js_word!("onwebkitanimationiteration")
| js_word!("onwebkitanimationstart")
| js_word!("onwebkittransitionend")
| js_word!("onwheel")
| js_word!("onblur")
| js_word!("onerror")
| js_word!("onfocus")
| js_word!("onload")
| js_word!("onloadeddata")
| js_word!("onloadedmetadata")
| js_word!("onloadstart")
| js_word!("onresize")
| js_word!("onscroll")
| js_word!("onafterprint")
| js_word!("onbeforeprint")
| js_word!("onbeforeunload")
| js_word!("onhashchange")
| js_word!("onlanguagechange")
| js_word!("onmessage")
| js_word!("onmessageerror")
| js_word!("onoffline")
| js_word!("ononline")
| js_word!("onpagehide")
| js_word!("onpageshow")
| js_word!("onpopstate")
| js_word!("onrejectionhandled")
| js_word!("onstorage")
| js_word!("onunhandledrejection")
| js_word!("onunload")
| js_word!("oncut")
| js_word!("oncopy")
| js_word!("onpaste")
| js_word!("onreadystatechange")
| js_word!("onvisibilitychange")
| js_word!("onshow")
| js_word!("onsort")
| js_word!("onbegin")
| js_word!("onend")
| js_word!("onrepeat")
)
}
fn is_boolean_attribute(&self, element: &Element, attribute: &Attribute) -> bool {
@ -396,16 +380,17 @@ impl Minifier<'_> {
}
fn is_trimable_separated_attribute(&self, element: &Element, attribute: &Attribute) -> bool {
if ALLOW_TO_TRIM_GLOBAL_ATTRIBUTES.contains(&&*attribute.name) {
return true;
match attribute.name {
js_word!("style") | js_word!("tabindex") | js_word!("itemid") => return true,
_ => {}
}
match element.namespace {
Namespace::HTML => {
ALLOW_TO_TRIM_HTML_ATTRIBUTES.contains(&(&element.tag_name, &*attribute.name))
ALLOW_TO_TRIM_HTML_ATTRIBUTES.contains(&(&element.tag_name, &attribute.name))
}
Namespace::SVG => {
ALLOW_TO_TRIM_SVG_ATTRIBUTES.contains(&(&element.tag_name, &*attribute.name))
ALLOW_TO_TRIM_SVG_ATTRIBUTES.contains(&(&element.tag_name, &attribute.name))
}
_ => false,
}
@ -456,24 +441,33 @@ impl Minifier<'_> {
}
_ if attribute.name == js_word!("exportparts") => true,
_ => {
COMMA_SEPARATED_HTML_ATTRIBUTES.contains(&(&element.tag_name, &*attribute.name))
COMMA_SEPARATED_HTML_ATTRIBUTES.contains(&(&element.tag_name, &attribute.name))
}
},
Namespace::SVG => {
COMMA_SEPARATED_SVG_ATTRIBUTES.contains(&(&element.tag_name, &*attribute.name))
COMMA_SEPARATED_SVG_ATTRIBUTES.contains(&(&element.tag_name, &attribute.name))
}
_ => false,
}
}
fn is_space_separated_attribute(&self, element: &Element, attribute: &Attribute) -> bool {
if SPACE_SEPARATED_GLOBAL_ATTRIBUTES.contains(&&*attribute.name) {
return true;
match attribute.name {
js_word!("class")
| js_word!("itemprop")
| js_word!("itemref")
| js_word!("itemtype")
| js_word!("part")
| js_word!("accesskey")
| js_word!("aria-describedby")
| js_word!("aria-labelledby")
| js_word!("aria-owns") => return true,
_ => {}
}
match element.namespace {
Namespace::HTML => {
SPACE_SEPARATED_HTML_ATTRIBUTES.contains(&(&element.tag_name, &*attribute.name))
SPACE_SEPARATED_HTML_ATTRIBUTES.contains(&(&element.tag_name, &attribute.name))
}
Namespace::SVG => {
match attribute.name {
@ -484,7 +478,7 @@ impl Minifier<'_> {
_ => {}
}
SPACE_SEPARATED_SVG_ATTRIBUTES.contains(&(&element.tag_name, &*attribute.name))
SPACE_SEPARATED_SVG_ATTRIBUTES.contains(&(&element.tag_name, &attribute.name))
}
_ => false,
}
@ -493,7 +487,7 @@ impl Minifier<'_> {
fn is_semicolon_separated_attribute(&self, element: &Element, attribute: &Attribute) -> bool {
match element.namespace {
Namespace::SVG => {
SEMICOLON_SEPARATED_SVG_ATTRIBUTES.contains(&(&element.tag_name, &*attribute.name))
SEMICOLON_SEPARATED_SVG_ATTRIBUTES.contains(&(&element.tag_name, &attribute.name))
}
_ => false,
}
@ -681,7 +675,12 @@ impl Minifier<'_> {
&SVG_ELEMENTS_AND_ATTRIBUTES
};
let attribute_name = if let Some(prefix) = &attribute.prefix {
let attributes = match default_attributes.get(&element.tag_name) {
Some(element) => element,
None => return false,
};
let attribute_info = if let Some(prefix) = &attribute.prefix {
let mut with_namespace =
String::with_capacity(prefix.len() + 1 + attribute.name.len());
@ -689,24 +688,20 @@ impl Minifier<'_> {
with_namespace.push(':');
with_namespace.push_str(&attribute.name);
with_namespace.into()
attributes.other.get(&JsWord::from(with_namespace))
} else {
attribute.name.clone()
};
let normalized_value = attribute_value.trim();
let attributes = match default_attributes.get(&element.tag_name) {
Some(element) => element,
None => return false,
attributes.other.get(&attribute.name)
};
let attribute_info = match attributes.other.get(&attribute_name) {
let attribute_info = match attribute_info {
Some(attribute_info) => attribute_info,
None => return false,
};
match (attribute_info.inherited, &attribute_info.initial) {
(None, Some(initial)) | (Some(false), Some(initial)) => {
let normalized_value = attribute_value.trim();
match self.options.remove_redundant_attributes {
RemoveRedundantAttributes::None => false,
RemoveRedundantAttributes::Smart => {
@ -782,7 +777,7 @@ impl Minifier<'_> {
false
}
fn is_preserved_comment(&self, data: &str) -> bool {
fn is_preserved_comment(&self, data: &JsWord) -> bool {
if let Some(preserve_comments) = &self.options.preserve_comments {
return preserve_comments.iter().any(|regex| regex.is_match(data));
}
@ -790,7 +785,7 @@ impl Minifier<'_> {
false
}
fn is_conditional_comment(&self, data: &str) -> bool {
fn is_conditional_comment(&self, data: &JsWord) -> bool {
if CONDITIONAL_COMMENT_START.is_match(data) || CONDITIONAL_COMMENT_END.is_match(data) {
return true;
}
@ -1273,7 +1268,15 @@ impl Minifier<'_> {
}
}
fn collapse_whitespace(&self, data: &str) -> String {
fn collapse_whitespace<'a>(&self, data: &'a str) -> Cow<'a, str> {
if data.is_empty() {
return Cow::Borrowed(data);
}
if data.chars().all(|c| !matches!(c, c if is_whitespace(c))) {
return Cow::Borrowed(data);
}
let mut collapsed = String::with_capacity(data.len());
let mut in_whitespace = false;
@ -1294,10 +1297,10 @@ impl Minifier<'_> {
};
}
collapsed
Cow::Owned(collapsed)
}
fn is_additional_minifier_attribute(&self, name: &str) -> Option<MinifierType> {
fn is_additional_minifier_attribute(&self, name: &JsWord) -> Option<MinifierType> {
if let Some(minify_additional_attributes) = &self.options.minify_additional_attributes {
for item in minify_additional_attributes {
if item.0.is_match(name) {
@ -1912,7 +1915,7 @@ impl Minifier<'_> {
type_attribute_value
}
fn is_additional_scripts_content(&self, name: &str) -> Option<MinifierType> {
fn is_additional_scripts_content(&self, name: &JsWord) -> Option<MinifierType> {
if let Some(minify_additional_scripts_content) =
&self.options.minify_additional_scripts_content
{
@ -2713,7 +2716,7 @@ impl Minifier<'_> {
_ => trimmed.to_string(),
}
} else if matches!(n.name, js_word!("points")) {
self.collapse_whitespace(value.trim())
self.collapse_whitespace(value.trim()).to_string()
} else if matches!(n.name, js_word!("exportparts")) {
value.chars().filter(|c| !c.is_whitespace()).collect()
} else {