feat(css/parser): Normalize and improve function name (#6667)

This commit is contained in:
Alexander Akait 2022-12-20 15:43:58 +03:00 committed by GitHub
parent 65c2ab32ab
commit 2571070148
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 1481 additions and 751 deletions

View File

@ -42,7 +42,7 @@
), ),
ctxt: #0, ctxt: #0,
}, },
value: Atom('constant' type=dynamic), value: Atom('constant' type=static),
}, },
tag: Const( tag: Const(
ConstTag { ConstTag {

0
crates/swc_atoms/scripts/add-from-cargo-check.sh Normal file → Executable file
View File

View File

@ -85,6 +85,57 @@
-ms-high-contrast-adjust -ms-high-contrast-adjust
-ms-hyphens -ms-hyphens
-ms-interpolation-mode -ms-interpolation-mode
-moz-any
-moz-calc
-moz-document
-moz-keyframes
*
-infinity
-moz-activehyperlinktext
-moz-any
-moz-buttondefault
-moz-buttonhoverface
-moz-buttonhovertext
-moz-calc
-moz-cellhighlight
-moz-cellhighlighttext
-moz-combobox
-moz-comboboxtext
-moz-default-background-color
-moz-default-color
-moz-dialog
-moz-dialogtext
-moz-document
-moz-dragtargetzone
-moz-eventreerow
-moz-html-cellhighlight
-moz-html-cellhighlighttext
-moz-hyperlinktext
-moz-keyframes
-moz-mac-accentdarkestshadow
-moz-mac-accentdarkshadow
-moz-mac-accentface
-moz-mac-accentlightesthighlight
-moz-mac-accentlightshadow
-moz-mac-accentregularhighlight
-moz-mac-accentregularshadow
-moz-mac-chrome-active
-moz-mac-chrome-inactive
-moz-mac-focusring
-moz-mac-menuselect
-moz-mac-menushadow
-moz-mac-menutextselect
-moz-menubarhovertext
-moz-menubartext
-moz-menuhover
-moz-menuhovertext
-moz-nativehyperlinktext
-moz-oddtreerow
-moz-visitedhyperlinktext
-moz-win-accentcolor
-moz-win-accentcolortext
-moz-win-communicationstext
-moz-win-mediatext
-ms-keyframes -ms-keyframes
-ms-region-fragment -ms-region-fragment
-ms-scroll-chaining -ms-scroll-chaining
@ -832,16 +883,22 @@ _extends
_toConsumableArray _toConsumableArray
a a
abbr abbr
abs
abstract abstract
accent-color accent-color
accept accept
accesskey accesskey
acos
acronym acronym
action action
activeborder
activecaption
activetext
actuate actuate
add add
address address
after after
aliceblue
align-content align-content
align-items align-items
align-self align-self
@ -877,7 +934,9 @@ animation-timing-function
annotation annotation
annotation-xml annotation-xml
anonymous anonymous
antiquewhite
any any
appWorkspace
appearance appearance
apple-touch-icon apple-touch-icon
apple-touch-icon-precomposed apple-touch-icon-precomposed
@ -889,6 +948,8 @@ application/ld+json
application/x-javascript application/x-javascript
application/xhtml+xml application/xhtml+xml
apply apply
aqua
aquamarine
arcrole arcrole
area area
arguments arguments
@ -898,10 +959,13 @@ aria-owns
article article
as as
aside aside
asin
aspect-ratio aspect-ratio
assert assert
asserts asserts
async async
atan
atan2
attributeName attributeName
attributeType attributeType
attributename attributename
@ -912,9 +976,11 @@ autocomplete
avoid avoid
await await
azimuth azimuth
azure
b b
backdrop-filter backdrop-filter
backface-visibility backface-visibility
background
background-attachment background-attachment
background-blend-mode background-blend-mode
background-clip background-clip
@ -937,15 +1003,21 @@ bdi
bdo bdo
before before
begin begin
beige
bgsound bgsound
big big
bigint bigint
bisque
black
blanchedalmond
blink blink
block block
block-overflow block-overflow
block-size block-size
blocking blocking
blockquote blockquote
blue
blueviolet
body body
bold bold
boolean boolean
@ -1017,24 +1089,38 @@ break
break-after break-after
break-before break-before
break-inside break-inside
brown
burlywood
button button
buttonborder
buttonface
buttonhighlight
buttonshadow
buttontext
cadetblue
calc calc
calcMode calcMode
calcmode calcmode
call call
canvas canvas
canvastext canvastext
cap
caption caption
caption-side caption-side
captiontext
caret-color caret-color
caret-shape caret-shape
case case
catch catch
center center
ch
character-variant character-variant
charset charset
chartreuse
chocolate
circle circle
cite cite
clamp
class class
classid classid
clear clear
@ -1052,6 +1138,7 @@ colgroup
collection collection
color color
color-adjust color-adjust
color-contrast
color-index color-index
color-mix color-mix
color-profile color-profile
@ -1073,6 +1160,7 @@ columns
command command
concat concat
const const
constant
constructor constructor
contain contain
contain-intrinsic-block-size contain-intrinsic-block-size
@ -1085,12 +1173,23 @@ content-box
content-security-policy content-security-policy
contenteditable contenteditable
continue continue
coral
cornflowerblue
cornsilk
cos
counter-increment counter-increment
counter-reset counter-reset
counter-set counter-set
counter-style counter-style
cqb
cqh
cqi
cqmax
cqmin
cqw
createClass createClass
createReactClass createReactClass
crimson
crossorigin crossorigin
cubic-bezier cubic-bezier
cue cue
@ -1100,12 +1199,34 @@ currentColor
currentcolor currentcolor
cursor cursor
custom-media custom-media
cyan
d d
darkblue
darkcyan
darkgoldenrod
darkgray
darkgreen
darkgrey
darkkhaki
darkmagenta
darkolivegreen
darkorange
darkorchid
darkred
darksalmon
darkseagreen
darkslateblue
darkslategray
darkslategrey
darkturquoise
darkviolet
data data
datalist datalist
dd dd
debugger debugger
declare declare
deeppink
deepskyblue
default default
definitionURL definitionURL
definitionurl definitionurl
@ -1123,6 +1244,8 @@ dfn
dialog dialog
diffuseConstant diffuseConstant
diffuseconstant diffuseconstant
dimgray
dimgrey
dir dir
direction direction
discard discard
@ -1133,6 +1256,7 @@ div
dl dl
do do
document document
dodgerblue
dpcm dpcm
dpi dpi
dppx dppx
@ -1143,6 +1267,7 @@ dvi
dvmax dvmax
dvmin dvmin
dvw dvw
e
ease ease
ease-in ease-in
ease-in-out ease-in-out
@ -1163,6 +1288,7 @@ env
eval eval
even even
ex ex
exp
export export
exportparts exportparts
extends extends
@ -1218,7 +1344,9 @@ fespecularlighting
fespotlight fespotlight
fetile fetile
feturbulence feturbulence
field
fieldset fieldset
fieldtext
figcaption figcaption
figure figure
file file
@ -1229,6 +1357,7 @@ filter
filterUnits filterUnits
filterunits filterunits
finally finally
firebrick
first-child first-child
first-letter first-letter
first-line first-line
@ -1242,6 +1371,7 @@ flex-grow
flex-shrink flex-shrink
flex-wrap flex-wrap
float float
floralwhite
flow flow
flow-from flow-from
flow-into flow-into
@ -1277,26 +1407,38 @@ for
forced-color-adjust forced-color-adjust
foreignObject foreignObject
foreignobject foreignobject
forestgreen
form form
formaction formaction
format format
fr
frame frame
frameset frameset
from from
from-image from-image
fuchsia
function function
future future
g g
gainsboro
get get
ghostwhite
global global
glyph glyph
glyphRef glyphRef
glyphref glyphref
gold
goldenrod
grad grad
gradientTransform gradientTransform
gradientUnits gradientUnits
gradienttransform gradienttransform
gradientunits gradientunits
gray
graytext
green
greenyellow
grey
grid grid
grid-auto-columns grid-auto-columns
grid-auto-flow grid-auto-flow
@ -1325,11 +1467,14 @@ headers
height height
hgroup hgroup
highlight highlight
highlighttext
historical-forms historical-forms
hkern hkern
honeydew
horizontal-tb horizontal-tb
host host
host-context host-context
hotpink
hr hr
href href
hsl hsl
@ -1339,6 +1484,7 @@ http-equiv
hwb hwb
hyphenate-character hyphenate-character
hyphens hyphens
hypot
hz hz
i i
ic ic
@ -1359,7 +1505,15 @@ import
important important
importmap importmap
in in
inactiveborder
inactivecaption
inactivecaptiontext
indianred
indigo
infer infer
infinity
infobackground
infotext
inherit inherit
initial initial
initial-letter initial-letter
@ -1388,6 +1542,7 @@ itemprop
itemref itemref
itemtype itemtype
iterator iterator
ivory
jump-end jump-end
jump-start jump-start
justify-content justify-content
@ -1411,12 +1566,17 @@ keypoints
keysplines keysplines
keytimes keytimes
keywords keywords
khaki
khz khz
lab
label label
lang lang
language language
last-child last-child
last-of-type last-of-type
lavender
lavenderblush
lawngreen
layer layer
lch lch
left left
@ -1425,6 +1585,7 @@ left-middle
left-top left-top
legacy legacy
legend legend
lemonchiffon
length length
lengthAdjust lengthAdjust
lengthadjust lengthadjust
@ -1432,6 +1593,23 @@ let
letter-spacing letter-spacing
lh lh
li li
lightblue
lightcoral
lightcyan
lightgoldenrodyellow
lightgray
lightgreen
lightgrey
lightpink
lightsalmon
lightseagreen
lightskyblue
lightslategray
lightslategrey
lightsteelblue
lightyellow
lime
limegreen
limitingConeAngle limitingConeAngle
limitingconeangle limitingconeangle
line line
@ -1443,12 +1621,15 @@ line-through
linear linear
linearGradient linearGradient
lineargradient lineargradient
linen
link link
linktext
list-item list-item
list-style-image list-style-image
list-style-type list-style-type
listing listing
local local
log
longdesc longdesc
lr lr
lr-tb lr-tb
@ -1460,6 +1641,7 @@ lvi
lvmax lvmax
lvmin lvmin
lvw lvw
magenta
main main
malignmark malignmark
manual manual
@ -1484,6 +1666,8 @@ markerWidth
markerheight markerheight
markerunits markerunits
markerwidth markerwidth
marktext
maroon
marquee marquee
mask mask
mask-border mask-border
@ -1515,6 +1699,7 @@ math-shift
math-style math-style
matrix matrix
matrix3d matrix3d
max
max-aspect-ratio max-aspect-ratio
max-block-size max-block-size
max-color max-color
@ -1531,12 +1716,24 @@ max-width
maxlength maxlength
media media
medium medium
mediumaquamarine
mediumblue
mediumorchid
mediumpurple
mediumseagreen
mediumslateblue
mediumspringgreen
mediumturquoise
mediumvioletred
menu menu
menutext
meta meta
metadata metadata
meter meter
mglyph mglyph
mi mi
midnightblue
min
min-aspect-ratio min-aspect-ratio
min-block-size min-block-size
min-color min-color
@ -1549,12 +1746,16 @@ min-inline-size
min-monochrome min-monochrome
min-resolution min-resolution
min-width min-width
mintcream
missing-glyph missing-glyph
mistyrose
mix-blend-mode mix-blend-mode
mixed mixed
mm mm
mn mn
mo mo
moccasin
mod
module module
monochrome monochrome
mozmm mozmm
@ -1563,7 +1764,10 @@ ms
mtext mtext
name name
namespace namespace
nan
nav nav
navajowhite
navy
nest nest
never never
new new
@ -1599,6 +1803,9 @@ offset-rotate
oklab oklab
oklch oklch
ol ol
oldlace
olive
olivedrab
onabort onabort
onafterprint onafterprint
onautocomplete onautocomplete
@ -1704,6 +1911,9 @@ opentype
optgroup optgroup
option option
or or
orange
orangered
orchid
order order
ornaments ornaments
orphans orphans
@ -1746,7 +1956,12 @@ page-break-after
page-break-before page-break-before
page-break-inside page-break-inside
paint-order paint-order
palegoldenrod
palegreen
paleturquoise
palevioletred
panose-1 panose-1
papayawhip
param param
part part
past past
@ -1761,15 +1976,20 @@ patterncontentunits
patterntransform patterntransform
patternunits patternunits
pc pc
peachpuff
perspective perspective
perspective-origin perspective-origin
peru
pi
picture picture
ping ping
pink
place-content place-content
place-items place-items
place-self place-self
placeholder placeholder
plaintext plaintext
plum
pointer-events pointer-events
points points
pointsAtX pointsAtX
@ -1782,6 +2002,8 @@ polygon
polyline polyline
position position
poster poster
pow
powderblue
pre pre
preload preload
preserveAlpha preserveAlpha
@ -1799,6 +2021,7 @@ property
protected protected
pt pt
public public
purple
px px
q q
rad rad
@ -1809,7 +2032,9 @@ rbc
rcap rcap
rch rch
readonly readonly
rebeccapurple
rect rect
red
refX refX
refY refY
refx refx
@ -1846,6 +2071,7 @@ right-top
rl rl
rlh rlh
role role
rosybrown
rotate rotate
rotate3d rotate3d
rotateX rotateX
@ -1860,6 +2086,7 @@ row-gap
row-reverse row-reverse
rows rows
rowspan rowspan
royalblue
rp rp
rt rt
rtc rtc
@ -1872,14 +2099,20 @@ ruby-position
ruby-text ruby-text
run-in run-in
s s
saddlebrown
salmon
samp samp
sandbox sandbox
sandybrown
satisfies satisfies
scale scale
scale3d scale3d
scaleX scaleX
scaleY scaleY
scaleZ scaleZ
scalex
scaley
scalez
script script
scroll scroll
scroll-behavior scroll-behavior
@ -1916,11 +2149,17 @@ scroll-snap-type-x
scroll-snap-type-y scroll-snap-type-y
scroll-timeline-axis scroll-timeline-axis
scroll-timeline-name scroll-timeline-name
scrollbar
scrollbar-color scrollbar-color
scrollbar-gutter scrollbar-gutter
scrollbar-width scrollbar-width
seagreen
seashell
section section
select select
selecteditem
selecteditemtext
selector
separate separate
set set
shadow shadow
@ -1930,6 +2169,10 @@ shape-outside
show show
sideways-lr sideways-lr
sideways-rl sideways-rl
sienna
sign
silver
sin
size size
sizes sizes
skew skew
@ -1937,10 +2180,15 @@ skewX
skewY skewY
skewx skewx
skewy skewy
skyblue
slateblue
slategray
slategrey
slice slice
slot slot
slotted slotted
small small
snow
solid solid
solidColor solidColor
source source
@ -1955,6 +2203,8 @@ specularexponent
speculationrules speculationrules
spreadMethod spreadMethod
spreadmethod spreadmethod
springgreen
sqrt
src src
srcdoc srcdoc
srcset srcset
@ -1964,6 +2214,7 @@ startoffset
static static
stdDeviation stdDeviation
stddeviation stddeviation
steelblue
step-end step-end
step-start step-start
steps steps
@ -1986,6 +2237,7 @@ super
supports supports
surfaceScale surfaceScale
surfacescale surfacescale
svb
svg svg
svh svh
svi svi
@ -2005,6 +2257,7 @@ table-cell
table-layout table-layout
tableValues tableValues
tablevalues tablevalues
tan
target target
targetX targetX
targetY targetY
@ -2015,6 +2268,7 @@ tb-lr
tb-rl tb-rl
tbody tbody
td td
teal
template template
text text
text-align-last text-align-last
@ -2055,11 +2309,18 @@ tfoot
th th
thead thead
this this
thistle
threeddarkshadow
threedface
threedhighlight
threedlightshadow
threedshadow
throw throw
time time
title title
to to
toString toString
tomato
top top
top-center top-center
top-left top-left
@ -2083,6 +2344,8 @@ translate3d
translateX translateX
translateY translateY
translateZ translateZ
translatey
translatez
transparent transparent
tref tref
true true
@ -2091,6 +2354,7 @@ try
tspan tspan
tt tt
turn turn
turquoise
type type
typeof typeof
u u
@ -2122,6 +2386,8 @@ viewTarget
viewbox viewbox
viewport viewport
viewtarget viewtarget
violet
visitedtext
vkern vkern
vmax vmax
vmin vmin
@ -2129,12 +2395,18 @@ void
vw vw
wbr wbr
weight weight
wheat
where where
while while
white
white-space white-space
whitesmoke
widows widows
width width
will-change will-change
window
windowframe
windowtext
with with
woff woff
woff2 woff2
@ -2161,8 +2433,13 @@ xml:space
xmlns xmlns
xmlns:xlink xmlns:xlink
xmp xmp
xyz
xyz-d50
xyz-d65
yChannelSelector yChannelSelector
ychannelselector ychannelselector
yellow
yellowgreen
yield yield
z-index z-index
zoom zoom

View File

@ -36,6 +36,15 @@ impl PartialEq<str> for AtRuleName {
} }
} }
impl PartialEq<JsWord> for AtRuleName {
fn eq(&self, other: &JsWord) -> bool {
match self {
AtRuleName::DashedIdent(v) => v.value == *other,
AtRuleName::Ident(v) => v.value == *other,
}
}
}
#[ast_node] #[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)] #[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum AtRulePrelude { pub enum AtRulePrelude {

View File

@ -1,4 +1,5 @@
use is_macro::Is; use is_macro::Is;
use swc_atoms::JsWord;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span}; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span};
use crate::{ use crate::{
@ -100,12 +101,39 @@ impl Take for SimpleBlock {
} }
} }
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum FunctionName {
#[tag("Ident")]
Ident(Ident),
#[tag("DashedIdent")]
DashedIdent(DashedIdent),
}
impl PartialEq<str> for FunctionName {
fn eq(&self, other: &str) -> bool {
match self {
FunctionName::DashedIdent(v) => *v == *other,
FunctionName::Ident(v) => *v == *other,
}
}
}
impl PartialEq<JsWord> for FunctionName {
fn eq(&self, other: &JsWord) -> bool {
match self {
FunctionName::DashedIdent(v) => v.value == *other,
FunctionName::Ident(v) => v.value == *other,
}
}
}
#[ast_node("Function")] #[ast_node("Function")]
#[derive(Eq, Hash, EqIgnoreSpan)] #[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Function { pub struct Function {
/// Span starting from the `lo` of identifier and to the end of `)`. /// Span starting from the `lo` of identifier and to the end of `)`.
pub span: Span, pub span: Span,
pub name: Ident, pub name: FunctionName,
pub value: Vec<ComponentValue>, pub value: Vec<ComponentValue>,
} }
@ -267,6 +295,24 @@ pub enum DeclarationName {
DashedIdent(DashedIdent), DashedIdent(DashedIdent),
} }
impl PartialEq<str> for DeclarationName {
fn eq(&self, other: &str) -> bool {
match self {
DeclarationName::DashedIdent(v) => *v == *other,
DeclarationName::Ident(v) => *v == *other,
}
}
}
impl PartialEq<JsWord> for DeclarationName {
fn eq(&self, other: &JsWord) -> bool {
match self {
DeclarationName::DashedIdent(v) => v.value == *other,
DeclarationName::Ident(v) => v.value == *other,
}
}
}
#[ast_node("ImportantFlag")] #[ast_node("ImportantFlag")]
#[derive(Eq, Hash, EqIgnoreSpan)] #[derive(Eq, Hash, EqIgnoreSpan)]
pub struct ImportantFlag { pub struct ImportantFlag {

View File

@ -32,3 +32,26 @@ macro_rules! matches_eq_ignore_ascii_case {
)* false )* false
}}; }};
} }
/// Returns true if the given value matches one of the given patterns.
///
/// The type of value and patterns should be identical.
///
/// # Examples
///
/// ```
/// use swc_atoms::JsWord;
/// use swc_atoms::js_word;
/// use swc_css_ast::*;
///
/// assert!(matches_eq!(JsWord::from("a"), js_word!("a")));
/// assert!(matches_eq!("a", "a"));
/// ```
#[macro_export]
macro_rules! matches_eq {
($value:expr, $($pat:expr),*) => {{
$(
$value == $pat ||
)* false
}};
}

View File

@ -1315,6 +1315,14 @@ where
write_raw!(self, ")"); write_raw!(self, ")");
} }
#[emitter]
fn emit_function_name(&mut self, n: &FunctionName) -> Result {
match n {
FunctionName::Ident(n) => emit!(self, n),
FunctionName::DashedIdent(n) => emit!(self, n),
}
}
#[emitter] #[emitter]
fn emit_color_profile_name(&mut self, n: &ColorProfileName) -> Result { fn emit_color_profile_name(&mut self, n: &ColorProfileName) -> Result {
match n { match n {

View File

@ -286,12 +286,6 @@ impl VisitMut for NormalizeTest {
} }
} }
fn visit_mut_function(&mut self, n: &mut Function) {
n.visit_mut_children_with(self);
n.name.value = n.name.value.to_lowercase().into();
}
fn visit_mut_pseudo_class_selector(&mut self, n: &mut PseudoClassSelector) { fn visit_mut_pseudo_class_selector(&mut self, n: &mut PseudoClassSelector) {
n.visit_mut_children_with(self); n.visit_mut_children_with(self);

View File

@ -1,45 +1,42 @@
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_css_ast::{AbsoluteColorBase, ComponentValue}; use swc_css_ast::{AbsoluteColorBase, ComponentValue, FunctionName};
use crate::compiler::Compiler; use crate::compiler::Compiler;
impl Compiler { impl Compiler {
pub(crate) fn process_color_alpha_parameter(&mut self, n: &mut AbsoluteColorBase) { pub(crate) fn process_color_alpha_parameter(&mut self, n: &mut AbsoluteColorBase) {
if let AbsoluteColorBase::Function(function) = n { if let AbsoluteColorBase::Function(function) = n {
let name = function.name.value.to_ascii_lowercase();
if let Some(ComponentValue::AlphaValue(_) | ComponentValue::Function(_)) = if let Some(ComponentValue::AlphaValue(_) | ComponentValue::Function(_)) =
function.value.last() function.value.last()
{ {
if !matches!( let name = match &mut function.name {
name, FunctionName::Ident(name) => name,
js_word!("rgb") | js_word!("rgba") | js_word!("hsl") | js_word!("hsla") _ => {
) { return;
return; }
} };
match name { if name.value == js_word!("rgb") {
js_word!("rgb") => { name.value = js_word!("rgba");
function.name.value = js_word!("rgba"); name.raw = None;
function.name.raw = None; } else if name.value == js_word!("hsl") {
} name.value = js_word!("hsla");
js_word!("hsl") => { name.raw = None;
function.name.value = js_word!("hsla");
function.name.raw = None;
}
_ => {}
} }
} else { } else {
match name { let name = match &mut function.name {
js_word!("rgba") => { FunctionName::Ident(name) => name,
function.name.value = js_word!("rgb"); _ => {
function.name.raw = None; return;
} }
js_word!("hsla") => { };
function.name.value = js_word!("hsl");
function.name.raw = None; if name.value == js_word!("rgba") {
} name.value = js_word!("rgb");
_ => {} name.raw = None;
} else if name.value == js_word!("hsla") {
name.value = js_word!("hsl");
name.raw = None;
} }
} }
} }

View File

@ -2,7 +2,7 @@ use swc_atoms::js_word;
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_css_ast::{ use swc_css_ast::{
AbsoluteColorBase, AlphaValue, Color, ComponentValue, Delimiter, DelimiterValue, Function, AbsoluteColorBase, AlphaValue, Color, ComponentValue, Delimiter, DelimiterValue, Function,
Ident, Number, FunctionName, Ident, Number,
}; };
use swc_css_utils::{hex_to_rgba, round_alpha}; use swc_css_utils::{hex_to_rgba, round_alpha};
@ -43,11 +43,11 @@ impl Compiler {
*n = ComponentValue::Color(Box::new(Color::AbsoluteColorBase( *n = ComponentValue::Color(Box::new(Color::AbsoluteColorBase(
AbsoluteColorBase::Function(Function { AbsoluteColorBase::Function(Function {
span: hex_color.span, span: hex_color.span,
name: Ident { name: FunctionName::Ident(Ident {
span: DUMMY_SP, span: DUMMY_SP,
value: js_word!("rgba"), value: js_word!("rgba"),
raw: None, raw: None,
}, }),
value: vec![ value: vec![
ComponentValue::Number(Box::new(Number { ComponentValue::Number(Box::new(Number {
span: DUMMY_SP, span: DUMMY_SP,

View File

@ -1,7 +1,7 @@
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_css_ast::{ use swc_css_ast::{
AbsoluteColorBase, AlphaValue, Angle, ComponentValue, Delimiter, DelimiterValue, Hue, Ident, AbsoluteColorBase, AlphaValue, Angle, ComponentValue, Delimiter, DelimiterValue, FunctionName,
Number, Percentage, Hue, Ident, Number, Percentage,
}; };
use swc_css_utils::{angle_to_deg, hwb_to_rgb, to_rgb255}; use swc_css_utils::{angle_to_deg, hwb_to_rgb, to_rgb255};
@ -95,7 +95,7 @@ impl Compiler {
pub(crate) fn process_color_hwb(&mut self, n: &mut AbsoluteColorBase) { pub(crate) fn process_color_hwb(&mut self, n: &mut AbsoluteColorBase) {
if let AbsoluteColorBase::Function(function) = n { if let AbsoluteColorBase::Function(function) = n {
if function.name.value != js_word!("hwb") { if function.name != js_word!("hwb") {
return; return;
} }
@ -120,11 +120,11 @@ impl Compiler {
if a == 1.0 { if a == 1.0 {
*n = AbsoluteColorBase::Function(swc_css_ast::Function { *n = AbsoluteColorBase::Function(swc_css_ast::Function {
name: Ident { name: FunctionName::Ident(Ident {
value: js_word!("rgb"), value: js_word!("rgb"),
span: Default::default(), span: Default::default(),
raw: None, raw: None,
}, }),
value: vec![ value: vec![
ComponentValue::Number(Box::new(Number { ComponentValue::Number(Box::new(Number {
value: rgb[0].round(), value: rgb[0].round(),
@ -154,11 +154,11 @@ impl Compiler {
}); });
} else { } else {
*n = AbsoluteColorBase::Function(swc_css_ast::Function { *n = AbsoluteColorBase::Function(swc_css_ast::Function {
name: Ident { name: FunctionName::Ident(Ident {
value: js_word!("rgba"), value: js_word!("rgba"),
span: Default::default(), span: Default::default(),
raw: None, raw: None,
}, }),
value: vec![ value: vec![
ComponentValue::Number(Box::new(Number { ComponentValue::Number(Box::new(Number {
value: rgb[0].round(), value: rgb[0].round(),

View File

@ -2,7 +2,7 @@ use std::mem::take;
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::DUMMY_SP; use swc_common::DUMMY_SP;
use swc_css_ast::{AbsoluteColorBase, ComponentValue, Delimiter, DelimiterValue}; use swc_css_ast::{matches_eq, AbsoluteColorBase, ComponentValue, Delimiter, DelimiterValue};
use crate::compiler::Compiler; use crate::compiler::Compiler;
@ -12,11 +12,12 @@ impl Compiler {
n: &mut AbsoluteColorBase, n: &mut AbsoluteColorBase,
) { ) {
if let AbsoluteColorBase::Function(function) = n { if let AbsoluteColorBase::Function(function) = n {
let name = function.name.value.to_ascii_lowercase(); if !matches_eq!(
function.name,
if !matches!( js_word!("rgb"),
name, js_word!("rgba"),
js_word!("rgb") | js_word!("rgba") | js_word!("hsl") | js_word!("hsla") js_word!("hsl"),
js_word!("hsla")
) { ) {
return; return;
} }

View File

@ -1,7 +1,9 @@
use std::f64::consts::PI; use std::f64::consts::PI;
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_css_ast::{AbsoluteColorBase, AlphaValue, Angle, ComponentValue, Hue, Number, Percentage}; use swc_css_ast::{
matches_eq, AbsoluteColorBase, AlphaValue, Angle, ComponentValue, Hue, Number, Percentage,
};
use swc_css_utils::{clamp_unit_f64, round_alpha}; use swc_css_utils::{clamp_unit_f64, round_alpha};
use crate::compiler::Compiler; use crate::compiler::Compiler;
@ -9,10 +11,8 @@ use crate::compiler::Compiler;
impl Compiler { impl Compiler {
pub(crate) fn process_rgb_and_hsl(&mut self, n: &mut AbsoluteColorBase) { pub(crate) fn process_rgb_and_hsl(&mut self, n: &mut AbsoluteColorBase) {
if let AbsoluteColorBase::Function(function) = n { if let AbsoluteColorBase::Function(function) = n {
let name = function.name.value.to_ascii_lowercase(); let is_rgb = matches_eq!(function.name, js_word!("rgb"), js_word!("rgba"));
let is_hsl = matches_eq!(function.name, js_word!("hsl"), js_word!("hsla"));
let is_rgb = matches!(name, js_word!("rgb") | js_word!("rgba"));
let is_hsl = matches!(name, js_word!("hsl") | js_word!("hsla"));
if is_rgb { if is_rgb {
function.value = function function.value = function

View File

@ -1,3 +1,4 @@
use swc_atoms::js_word;
use swc_css_ast::*; use swc_css_ast::*;
use swc_css_visit::{Visit, VisitWith}; use swc_css_visit::{Visit, VisitWith};
@ -37,8 +38,7 @@ impl Visit for CustomPropertyNoMissingVarFunction {
} }
fn visit_function(&mut self, function: &Function) { fn visit_function(&mut self, function: &Function) {
self.in_var_function self.in_var_function.push(function.name == js_word!("var"));
.push(function.name.value.eq_str_ignore_ascii_case("var"));
function.visit_children_with(self); function.visit_children_with(self);
self.in_var_function.pop(); self.in_var_function.pop();
} }

View File

@ -46,9 +46,9 @@
7 | :root { --bar: 0; } a { color: --foo(--bar); } 7 | :root { --bar: 0; } a { color: --foo(--bar); }
`---- `----
x Unexpected missing var function for '--bar'. x Unexpected missing var function for '--foo'.
,-[$DIR/tests/rules/fail/custom-property-no-missing-var-function/input.css:6:1] ,-[$DIR/tests/rules/fail/custom-property-no-missing-var-function/input.css:6:1]
6 | :root { --foo: pink; } a { color: --foo, red; } 6 | :root { --foo: pink; } a { color: --foo, red; }
7 | :root { --bar: 0; } a { color: --foo(--bar); } 7 | :root { --bar: 0; } a { color: --foo(--bar); }
: ^^^^^ : ^^^^^
`---- `----

View File

@ -119,11 +119,11 @@ macro_rules! make_color {
Color::AbsoluteColorBase(AbsoluteColorBase::Function(Function { Color::AbsoluteColorBase(AbsoluteColorBase::Function(Function {
span: $span, span: $span,
name: Ident { name: FunctionName::Ident(Ident {
span: DUMMY_SP, span: DUMMY_SP,
value: js_word!("rgba"), value: js_word!("rgba"),
raw: None, raw: None,
}, }),
value: vec![ value: vec![
ComponentValue::Number(Box::new(Number { ComponentValue::Number(Box::new(Number {
span: DUMMY_SP, span: DUMMY_SP,
@ -387,7 +387,7 @@ impl Compressor {
name, name,
value, value,
.. ..
})) if matches!(&*name.value, "rgb" | "rgba") => { })) if name == &js_word!("rgb") || name == &js_word!("rgba") => {
let rgba: Vec<_> = value let rgba: Vec<_> = value
.iter() .iter()
.filter(|n| { .filter(|n| {
@ -425,7 +425,7 @@ impl Compressor {
name, name,
value, value,
.. ..
})) if matches!(&*name.value, "hsl" | "hsla") => { })) if name == &js_word!("hsl") || name == &js_word!("hsla") => {
let hsla: Vec<_> = value let hsla: Vec<_> = value
.iter() .iter()
.filter(|n| { .filter(|n| {
@ -465,7 +465,7 @@ impl Compressor {
name, name,
value, value,
.. ..
})) if matches!(&*name.value, "hwb") => { })) if name == &js_word!("hwb") => {
let h = match self.get_hue(value.get(0).as_ref()) { let h = match self.get_hue(value.get(0).as_ref()) {
Some(value) => value, Some(value) => value,
_ => return, _ => return,

View File

@ -10,9 +10,7 @@ impl Compressor {
name, name,
value: function_value, value: function_value,
span, span,
}) if name.value.eq_ignore_ascii_case(&js_word!("cubic-bezier")) }) if name == &js_word!("cubic-bezier") && function_value.len() == 7 => {
&& function_value.len() == 7 =>
{
if let ( if let (
first, first,
second, second,
@ -81,9 +79,7 @@ impl Compressor {
name, name,
value: function_value, value: function_value,
span, span,
}) if name.value.eq_ignore_ascii_case(&js_word!("steps")) }) if name == &js_word!("steps") && function_value.len() == 3 => {
&& function_value.len() == 3 =>
{
match (&function_value[0], &function_value[2]) { match (&function_value[0], &function_value[2]) {
( (
ComponentValue::Integer(box Integer { ComponentValue::Integer(box Integer {

View File

@ -1,13 +1,10 @@
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_css_ast::*; use swc_css_ast::*;
pub fn is_calc_function_name(ident: &Ident) -> bool { pub fn is_calc_function_name(function_name: &FunctionName) -> bool {
matches_eq_ignore_ascii_case!( *function_name == js_word!("calc")
ident.value, || *function_name == js_word!("-webkit-calc")
js_word!("calc"), || *function_name == js_word!("-moz-calc")
js_word!("-webkit-calc"),
js_word!("-moz-calc")
)
} }
pub fn transform_calc_value_into_component_value(calc_value: &CalcValue) -> Option<ComponentValue> { pub fn transform_calc_value_into_component_value(calc_value: &CalcValue) -> Option<ComponentValue> {

View File

@ -341,8 +341,8 @@ impl VisitMut for Compressor {
} }
fn visit_mut_function(&mut self, n: &mut Function) { fn visit_mut_function(&mut self, n: &mut Function) {
if matches_eq_ignore_ascii_case!( if matches_eq!(
n.name.value, n.name,
js_word!("rotate"), js_word!("rotate"),
js_word!("skew"), js_word!("skew"),
js_word!("skewx"), js_word!("skewx"),

View File

@ -1,4 +1,5 @@
use swc_atoms::js_word; use swc_atoms::js_word;
use swc_common::Spanned;
use swc_css_ast::*; use swc_css_ast::*;
use super::Compressor; use super::Compressor;
@ -10,9 +11,7 @@ impl Compressor {
name, name,
value: function_value, value: function_value,
.. ..
}) if name.value.eq_ignore_ascii_case(&js_word!("translate")) }) if name == &js_word!("translate") && function_value.len() == 3 => {
&& function_value.len() == 3 =>
{
match (function_value.get(0), function_value.get(2)) { match (function_value.get(0), function_value.get(2)) {
( (
Some(first), Some(first),
@ -30,11 +29,11 @@ impl Compressor {
})), })),
Some(second), Some(second),
) if *first_number == 0 => { ) if *first_number == 0 => {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("translateY"), value: js_word!("translatey"),
raw: None, raw: None,
}; });
*function_value = vec![second.clone()]; *function_value = vec![second.clone()];
} }
_ => {} _ => {}
@ -44,9 +43,7 @@ impl Compressor {
name, name,
value: function_value, value: function_value,
.. ..
}) if name.value.eq_ignore_ascii_case(&js_word!("translate3d")) }) if name == &js_word!("translate3d") && function_value.len() == 5 => {
&& function_value.len() == 5 =>
{
match ( match (
function_value.get(0), function_value.get(0),
function_value.get(2), function_value.get(2),
@ -63,11 +60,11 @@ impl Compressor {
})), })),
Some(third), Some(third),
) if *first_number == 0 && *second_number == 0 => { ) if *first_number == 0 && *second_number == 0 => {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("translateZ"), value: js_word!("translatez"),
raw: None, raw: None,
}; });
*function_value = vec![third.clone()]; *function_value = vec![third.clone()];
} }
_ => {} _ => {}
@ -77,9 +74,7 @@ impl Compressor {
name, name,
value: function_value, value: function_value,
.. ..
}) if name.value.eq_ignore_ascii_case(&js_word!("scale")) }) if name == &js_word!("scale") && function_value.len() == 3 => {
&& function_value.len() == 3 =>
{
match (function_value.get(0), function_value.get(2)) { match (function_value.get(0), function_value.get(2)) {
( (
Some( Some(
@ -102,11 +97,11 @@ impl Compressor {
.. ..
})), })),
) if *second_number == 1 => { ) if *second_number == 1 => {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("scaleX"), value: js_word!("scalex"),
raw: None, raw: None,
}; });
*function_value = vec![first.clone()]; *function_value = vec![first.clone()];
} }
( (
@ -116,11 +111,11 @@ impl Compressor {
})), })),
Some(second), Some(second),
) if *first_number == 1 => { ) if *first_number == 1 => {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("scaleY"), value: js_word!("scaley"),
raw: None, raw: None,
}; });
*function_value = vec![second.clone()]; *function_value = vec![second.clone()];
} }
_ => {} _ => {}
@ -130,9 +125,7 @@ impl Compressor {
name, name,
value: function_value, value: function_value,
.. ..
}) if name.value.eq_ignore_ascii_case(&js_word!("scale3d")) }) if name == &js_word!("scale3d") && function_value.len() == 5 => {
&& function_value.len() == 5 =>
{
match ( match (
function_value.get(0), function_value.get(0),
function_value.get(2), function_value.get(2),
@ -149,11 +142,11 @@ impl Compressor {
.. ..
})), })),
) if *second_number == 1 && *third_number == 1 => { ) if *second_number == 1 && *third_number == 1 => {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("scaleX"), value: js_word!("scalex"),
raw: None, raw: None,
}; });
*function_value = vec![first.clone()]; *function_value = vec![first.clone()];
} }
( (
@ -167,11 +160,11 @@ impl Compressor {
.. ..
})), })),
) if *first_number == 1 && *third_number == 1 => { ) if *first_number == 1 && *third_number == 1 => {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("scaleY"), value: js_word!("scaley"),
raw: None, raw: None,
}; });
*function_value = vec![second.clone()]; *function_value = vec![second.clone()];
} }
( (
@ -185,11 +178,11 @@ impl Compressor {
})), })),
Some(third), Some(third),
) if *first_number == 1 && *second_number == 1 => { ) if *first_number == 1 && *second_number == 1 => {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("scaleZ"), value: js_word!("scalez"),
raw: None, raw: None,
}; });
*function_value = vec![third.clone()]; *function_value = vec![third.clone()];
} }
_ => {} _ => {}
@ -199,9 +192,7 @@ impl Compressor {
name, name,
value: function_value, value: function_value,
.. ..
}) if name.value.eq_ignore_ascii_case(&js_word!("matrix3d")) }) if name == &js_word!("matrix3d") && function_value.len() == 31 => {
&& function_value.len() == 31 =>
{
match ( match (
function_value.get(0), function_value.get(0),
function_value.get(1), function_value.get(1),
@ -288,11 +279,11 @@ impl Compressor {
&& *fifteenth_number == 0 && *fifteenth_number == 0
&& *sixteenth_number == 1 => && *sixteenth_number == 1 =>
{ {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("matrix"), value: js_word!("matrix"),
raw: None, raw: None,
}; });
*function_value = vec![ *function_value = vec![
first.clone(), first.clone(),
first_comma.clone(), first_comma.clone(),
@ -314,9 +305,7 @@ impl Compressor {
name, name,
value: function_value, value: function_value,
.. ..
}) if name.value.eq_ignore_ascii_case(&js_word!("rotate3d")) }) if name == &js_word!("rotate3d") && function_value.len() == 7 => {
&& function_value.len() == 7 =>
{
match ( match (
function_value.get(0), function_value.get(0),
function_value.get(2), function_value.get(2),
@ -338,11 +327,11 @@ impl Compressor {
})), })),
Some(fourth_value), Some(fourth_value),
) if *first_number == 1 && *second_number == 0 && *third_number == 0 => { ) if *first_number == 1 && *second_number == 0 && *third_number == 0 => {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("rotateX"), value: js_word!("rotatex"),
raw: None, raw: None,
}; });
*function_value = vec![fourth_value.clone()]; *function_value = vec![fourth_value.clone()];
} }
( (
@ -360,11 +349,11 @@ impl Compressor {
})), })),
Some(fourth_value), Some(fourth_value),
) if *first_number == 0 && *second_number == 1 && *third_number == 0 => { ) if *first_number == 0 && *second_number == 1 && *third_number == 0 => {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("rotateY"), value: js_word!("rotatey"),
raw: None, raw: None,
}; });
*function_value = vec![fourth_value.clone()]; *function_value = vec![fourth_value.clone()];
} }
( (
@ -382,11 +371,11 @@ impl Compressor {
})), })),
Some(fourth_value), Some(fourth_value),
) if *first_number == 0 && *second_number == 0 && *third_number == 1 => { ) if *first_number == 0 && *second_number == 0 && *third_number == 1 => {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("rotate"), value: js_word!("rotate"),
raw: None, raw: None,
}; });
*function_value = vec![fourth_value.clone()]; *function_value = vec![fourth_value.clone()];
} }
_ => {} _ => {}
@ -396,23 +385,19 @@ impl Compressor {
name, name,
value: function_value, value: function_value,
.. ..
}) if name.value.eq_ignore_ascii_case(&js_word!("rotatez")) }) if name == &js_word!("rotatez") && function_value.len() == 1 => {
&& function_value.len() == 1 => *name = FunctionName::Ident(Ident {
{ span: name.span(),
*name = Ident {
span: name.span,
value: js_word!("rotate"), value: js_word!("rotate"),
raw: None, raw: None,
}; });
} }
ComponentValue::Function(box Function { ComponentValue::Function(box Function {
name, name,
value: function_value, value: function_value,
.. ..
}) if name.value.eq_ignore_ascii_case(&js_word!("skew")) }) if name == &js_word!("skew") && function_value.len() == 3 => {
&& function_value.len() == 3 =>
{
match (function_value.get(0), function_value.get(2)) { match (function_value.get(0), function_value.get(2)) {
( (
Some(first), Some(first),
@ -421,11 +406,11 @@ impl Compressor {
.. ..
})), })),
) if *second_number == 0 => { ) if *second_number == 0 => {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("skewX"), value: js_word!("skewx"),
raw: None, raw: None,
}; });
*function_value = vec![first.clone()]; *function_value = vec![first.clone()];
} }
@ -436,11 +421,11 @@ impl Compressor {
})), })),
Some(second), Some(second),
) if *first_number == 0 => { ) if *first_number == 0 => {
*name = Ident { *name = FunctionName::Ident(Ident {
span: name.span, span: name.span(),
value: js_word!("skewY"), value: js_word!("skewy"),
raw: None, raw: None,
}; });
*function_value = vec![second.clone()]; *function_value = vec![second.clone()];
} }
_ => {} _ => {}

View File

@ -1 +1 @@
.deg{transform:rotate(0);transform:rotate(9deg);transform:rotate(-9deg);transform:rotate(10deg);transform:rotate(180deg);transform:rotate(0);transform:rotate(350deg);transform:rotate(-9deg);transform:rotate(0);transform:rotate(360.5deg);transform:rotate(-360.5deg);transform:rotate(1deg);transform:rotate(-1deg)}.grad{transform:rotate(0);transform:rotate(9grad);transform:rotate(-9grad);transform:rotate(9deg);transform:rotate(180deg);transform:rotate(0);transform:rotate(800.5grad);transform:rotate(-800.5grad);transform:rotate(821grad);transform:rotate(-821grad)}.rad{transform:rotate(0);transform:rotate(1rad);transform:rotate(1.5rad);transform:rotate(-1.5rad)}.turn{transform:rotate(0);transform:rotate(180deg);transform:rotate(0);transform:rotate(180deg);transform:rotate(0);transform:rotate(180deg);transform:rotate(0)}.cross{transform:rotate(90deg);transform:rotate(1.57rad);transform:rotate(3.1416rad)}.class1{transform:rotate(0)}.class2{transform:skew(0,0)}.class3{transform:skewx(0)}.class4{transform:skewy(0)}.class5{transform:rotate3d(10,10,10,0)}.class6{transform:rotatex(0)}.class7{transform:rotatey(0)}.class8{transform:rotate(0)}.class9,.class10{transform:rotate(0)}.class11{transform:rotate(0)}@keyframes spinner-border{to{transform:rotate(360deg)}} .deg{transform:rotate(0);transform:rotate(9deg);transform:rotate(-9deg);transform:rotate(10deg);transform:rotate(180deg);transform:rotate(0);transform:rotate(350deg);transform:rotate(-9deg);transform:rotate(0);transform:rotate(360.5deg);transform:rotate(-360.5deg);transform:rotate(1deg);transform:rotate(-1deg)}.grad{transform:rotate(0);transform:rotate(9grad);transform:rotate(-9grad);transform:rotate(9deg);transform:rotate(180deg);transform:rotate(0);transform:rotate(800.5grad);transform:rotate(-800.5grad);transform:rotate(821grad);transform:rotate(-821grad)}.rad{transform:rotate(0);transform:rotate(1rad);transform:rotate(1.5rad);transform:rotate(-1.5rad)}.turn{transform:rotate(0);transform:rotate(180deg);transform:rotate(0);transform:rotate(180deg);transform:rotate(0);transform:rotate(180deg);transform:rotate(0)}.cross{transform:rotate(90deg);transform:rotate(1.57rad);transform:rotate(3.1416rad)}.class1{transform:rotate(0)}.class2{transform:skew(0,0)}.class3{transform:skewx(0)}.class4{transform:skewy(0)}.class5{transform:rotate3d(10,10,10,0)}.class6{transform:rotatex(0)}.class7{transform:rotatey(0)}.class8,.class9,.class10,.class11{transform:rotate(0)}@keyframes spinner-border{to{transform:rotate(360deg)}}

View File

@ -1,14 +1,14 @@
{ {
"blue": [
{
"type": "local",
"name": "__local__blue"
}
],
"foo": [ "foo": [
{ {
"type": "local", "type": "local",
"name": "__local__foo" "name": "__local__foo"
} }
],
"blue": [
{
"type": "local",
"name": "__local__blue"
}
] ]
} }

View File

@ -1,8 +1,8 @@
use std::{borrow::Cow, fmt::Debug, mem::take}; use std::{borrow::Cow, fmt::Debug, mem::take};
use swc_atoms::{Atom, JsWord}; use swc_atoms::Atom;
use swc_common::{BytePos, Span, Spanned, SyntaxContext}; use swc_common::{BytePos, Span, Spanned, SyntaxContext};
use swc_css_ast::{ComponentValue, ListOfComponentValues, Token, TokenAndSpan}; use swc_css_ast::{ComponentValue, FunctionName, ListOfComponentValues, Token, TokenAndSpan};
use super::PResult; use super::PResult;
use crate::error::{Error, ErrorKind}; use crate::error::{Error, ErrorKind};
@ -224,7 +224,7 @@ type SpanLike = (BytePos, BytePos);
#[derive(Debug)] #[derive(Debug)]
enum TokenOrBlock<'a> { enum TokenOrBlock<'a> {
Token(&'a TokenAndSpan), Token(&'a TokenAndSpan),
Function(Box<(Span, JsWord, Atom)>), Function(Box<(Span, FunctionName)>),
LBracket(SpanLike), LBracket(SpanLike),
LParen(SpanLike), LParen(SpanLike),
LBrace(SpanLike), LBrace(SpanLike),
@ -279,11 +279,7 @@ impl<'a> Input<'a> {
function.name.span_hi() + BytePos(1), function.name.span_hi() + BytePos(1),
Default::default(), Default::default(),
), ),
function.name.value.clone(), function.name.clone(),
match &function.name.raw {
Some(raw) => raw.clone(),
_ => Atom::from(function.name.value.clone()),
},
)))); ))));
} }
@ -381,13 +377,26 @@ impl<'a> Input<'a> {
TokenOrBlock::Token(token_and_span) => { TokenOrBlock::Token(token_and_span) => {
return Ok(Cow::Borrowed(token_and_span)) return Ok(Cow::Borrowed(token_and_span))
} }
TokenOrBlock::Function(function) => TokenAndSpan { TokenOrBlock::Function(function) => {
span: function.0, let name = match function.1 {
token: Token::Function { FunctionName::Ident(name) => match name.raw {
value: function.1, Some(raw) => (name.value, raw),
raw: function.2, _ => (name.value.clone(), Atom::from(name.value)),
}, },
}, FunctionName::DashedIdent(name) => match name.raw {
Some(raw) => (format!("--{}", name.value).into(), raw),
_ => (name.value.clone(), Atom::from(name.value)),
},
};
TokenAndSpan {
span: function.0,
token: Token::Function {
value: name.0,
raw: name.1,
},
}
}
TokenOrBlock::LBracket(span) => TokenAndSpan { TokenOrBlock::LBracket(span) => TokenAndSpan {
span: Span::new(span.0, span.1, Default::default()), span: Span::new(span.0, span.1, Default::default()),
token: Token::LBracket, token: Token::LBracket,

View File

@ -196,7 +196,7 @@ where
at_rule.span = span!(self, span.lo); at_rule.span = span!(self, span.lo);
// Canonicalization against a grammar // Canonicalization against a grammar
if self.ctx.need_canonicalize { if !is_dashed_ident && self.ctx.need_canonicalize {
at_rule = self.canonicalize_at_rule_prelude(at_rule)?; at_rule = self.canonicalize_at_rule_prelude(at_rule)?;
} }
@ -214,7 +214,7 @@ where
at_rule.span = span!(self, span.lo); at_rule.span = span!(self, span.lo);
// Canonicalization against a grammar // Canonicalization against a grammar
if self.ctx.need_canonicalize { if !is_dashed_ident && self.ctx.need_canonicalize {
at_rule = self.canonicalize_at_rule_prelude(at_rule)?; at_rule = self.canonicalize_at_rule_prelude(at_rule)?;
at_rule = self.canonicalize_at_rule_block(at_rule)?; at_rule = self.canonicalize_at_rule_block(at_rule)?;
} }
@ -605,14 +605,17 @@ where
// //
// Return nothing. // Return nothing.
let span = self.input.cur_span(); let span = self.input.cur_span();
let is_dashed_ident = match cur!(self) { let declaration_name = match cur!(self) {
Token::Ident { value, .. } => value.starts_with("--"), Token::Ident { value, .. } => value,
_ => { _ => {
return Err(Error::new(span, ErrorKind::Expected("ident"))); return Err(Error::new(span, ErrorKind::Expected("ident")));
} }
}; };
let is_dashed_ident = declaration_name.starts_with("--");
let name = if is_dashed_ident { let name = if is_dashed_ident {
DeclarationName::DashedIdent(self.parse()?) let ident = self.parse()?;
DeclarationName::DashedIdent(ident)
} else { } else {
let mut ident: Ident = self.parse()?; let mut ident: Ident = self.parse()?;
@ -923,16 +926,25 @@ where
// Create a function with its name equal to the value of the current input token // Create a function with its name equal to the value of the current input token
// and with its value initially set to an empty list. // and with its value initially set to an empty list.
let span = self.input.cur_span(); let span = self.input.cur_span();
let ident = match bump!(self) { let function_name = match bump!(self) {
Token::Function { value, raw } => (value, raw), Token::Function { value, raw } => (value, raw),
_ => { _ => {
unreachable!() unreachable!()
} }
}; };
let name = Ident { let is_dashed_ident = function_name.0.starts_with("--");
span: Span::new(span.lo, span.hi - BytePos(1), Default::default()), let name = if is_dashed_ident {
value: ident.0, FunctionName::DashedIdent(DashedIdent {
raw: Some(ident.1), span: Span::new(span.lo, span.hi - BytePos(1), Default::default()),
value: function_name.0[2..].into(),
raw: Some(function_name.1),
})
} else {
FunctionName::Ident(Ident {
span: Span::new(span.lo, span.hi - BytePos(1), Default::default()),
value: function_name.0.to_ascii_lowercase(),
raw: Some(function_name.1),
})
}; };
let mut function = Function { let mut function = Function {
span: Default::default(), span: Default::default(),
@ -975,7 +987,7 @@ where
function.span = span!(self, span.lo); function.span = span!(self, span.lo);
// Canonicalization against a grammar // Canonicalization against a grammar
if self.ctx.need_canonicalize { if !is_dashed_ident && self.ctx.need_canonicalize {
function = self.canonicalize_function_value(function)?; function = self.canonicalize_function_value(function)?;
} }

View File

@ -267,11 +267,10 @@ where
&mut self, &mut self,
mut function: Function, mut function: Function,
) -> PResult<Function> { ) -> PResult<Function> {
let function_name = function.name.value.to_ascii_lowercase();
let locv = self.create_locv(function.value); let locv = self.create_locv(function.value);
function.value = match self.parse_according_to_grammar(&locv, |parser| { function.value = match self.parse_according_to_grammar(&locv, |parser| {
parser.parse_function_values(&function_name) parser.parse_function_values(&function.name)
}) { }) {
Ok(values) => values, Ok(values) => values,
Err(err) => { Err(err) => {

File diff suppressed because it is too large Load Diff

View File

@ -1057,7 +1057,7 @@
"end": 494, "end": 494,
"ctxt": 0 "ctxt": 0
}, },
"value": "LAYER", "value": "layer",
"raw": "LAYER" "raw": "LAYER"
}, },
"value": [ "value": [
@ -1547,7 +1547,7 @@
"end": 709, "end": 709,
"ctxt": 0 "ctxt": 0
}, },
"value": "SUPPORTS", "value": "supports",
"raw": "SUPPORTS" "raw": "SUPPORTS"
}, },
"value": [ "value": [
@ -9192,7 +9192,7 @@
"end": 4755, "end": 4755,
"ctxt": 0 "ctxt": 0
}, },
"value": "LAYER", "value": "layer",
"raw": "LAYER" "raw": "LAYER"
}, },
"value": [ "value": [
@ -9239,7 +9239,7 @@
"end": 4773, "end": 4773,
"ctxt": 0 "ctxt": 0
}, },
"value": "SUPPORTS", "value": "supports",
"raw": "SUPPORTS" "raw": "SUPPORTS"
}, },
"value": [ "value": [

View File

@ -256,7 +256,7 @@
"end": 158, "end": 158,
"ctxt": 0 "ctxt": 0
}, },
"value": "translateX", "value": "translatex",
"raw": "translateX" "raw": "translateX"
}, },
"value": [ "value": [
@ -354,7 +354,7 @@
"end": 209, "end": 209,
"ctxt": 0 "ctxt": 0
}, },
"value": "translateX", "value": "translatex",
"raw": "translateX" "raw": "translateX"
}, },
"value": [ "value": [
@ -1566,7 +1566,7 @@
"end": 718, "end": 718,
"ctxt": 0 "ctxt": 0
}, },
"value": "translateX", "value": "translatex",
"raw": "translateX" "raw": "translateX"
}, },
"value": [ "value": [
@ -1664,7 +1664,7 @@
"end": 769, "end": 769,
"ctxt": 0 "ctxt": 0
}, },
"value": "translateX", "value": "translatex",
"raw": "translateX" "raw": "translateX"
}, },
"value": [ "value": [

View File

@ -4161,13 +4161,13 @@
"ctxt": 0 "ctxt": 0
}, },
"name": { "name": {
"type": "Ident", "type": "DashedIdent",
"span": { "span": {
"start": 1709, "start": 1709,
"end": 1718, "end": 1718,
"ctxt": 0 "ctxt": 0
}, },
"value": "--element", "value": "element",
"raw": "--element" "raw": "--element"
}, },
"value": [ "value": [

View File

@ -6331,7 +6331,7 @@
52 | [--self] { 52 | [--self] {
`---- `----
x Ident x DashedIdent
,-[$DIR/tests/fixture/at-rule/supports/input.css:50:1] ,-[$DIR/tests/fixture/at-rule/supports/input.css:50:1]
50 | 50 |
51 | @supports (--element(".minwidth")) { 51 | @supports (--element(".minwidth")) {
@ -8977,7 +8977,7 @@
89 | } 89 | }
`---- `----
x Ident { value: Atom('black' type=inline), raw: "black" } x Ident { value: Atom('black' type=static), raw: "black" }
,-[$DIR/tests/fixture/at-rule/supports/input.css:87:1] ,-[$DIR/tests/fixture/at-rule/supports/input.css:87:1]
87 | from { 87 | from {
88 | color: black; 88 | color: black;
@ -9163,7 +9163,7 @@
92 | } 92 | }
`---- `----
x Ident { value: Atom('white' type=inline), raw: "white" } x Ident { value: Atom('white' type=static), raw: "white" }
,-[$DIR/tests/fixture/at-rule/supports/input.css:90:1] ,-[$DIR/tests/fixture/at-rule/supports/input.css:90:1]
90 | to { 90 | to {
91 | color: white 91 | color: white
@ -9527,7 +9527,7 @@
101 | body { 101 | body {
`---- `----
x Ident { value: Atom('green' type=inline), raw: "green" } x Ident { value: Atom('green' type=static), raw: "green" }
,-[$DIR/tests/fixture/at-rule/supports/input.css:99:1] ,-[$DIR/tests/fixture/at-rule/supports/input.css:99:1]
99 | 99 |
100 | @supports (--foo: green) { 100 | @supports (--foo: green) {
@ -11493,7 +11493,7 @@
126 | } 126 | }
`---- `----
x Ident { value: Atom('black' type=inline), raw: "black" } x Ident { value: Atom('black' type=static), raw: "black" }
,-[$DIR/tests/fixture/at-rule/supports/input.css:124:1] ,-[$DIR/tests/fixture/at-rule/supports/input.css:124:1]
124 | from { 124 | from {
125 | color: black; 125 | color: black;
@ -11679,7 +11679,7 @@
129 | } 129 | }
`---- `----
x Ident { value: Atom('white' type=inline), raw: "white" } x Ident { value: Atom('white' type=static), raw: "white" }
,-[$DIR/tests/fixture/at-rule/supports/input.css:127:1] ,-[$DIR/tests/fixture/at-rule/supports/input.css:127:1]
127 | to { 127 | to {
128 | color: white 128 | color: white

View File

@ -6686,7 +6686,7 @@
50 | } 50 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/fixture/at-rule/unknown/input.css:48:1] ,-[$DIR/tests/fixture/at-rule/unknown/input.css:48:1]
48 | 48 |
49 | color: red; 49 | color: red;

View File

@ -13,3 +13,7 @@
@--custom {} @--custom {}
@--library1-custom {} @--library1-custom {}
.class {
--vendor-property: --vendor-function("test");
}

View File

@ -2,7 +2,7 @@
"type": "Stylesheet", "type": "Stylesheet",
"span": { "span": {
"start": 1, "start": 1,
"end": 172, "end": 234,
"ctxt": 0 "ctxt": 0
}, },
"rules": [ "rules": [
@ -559,6 +559,138 @@
}, },
"value": [] "value": []
} }
},
{
"type": "QualifiedRule",
"span": {
"start": 173,
"end": 233,
"ctxt": 0
},
"prelude": {
"type": "SelectorList",
"span": {
"start": 173,
"end": 179,
"ctxt": 0
},
"children": [
{
"type": "ComplexSelector",
"span": {
"start": 173,
"end": 179,
"ctxt": 0
},
"children": [
{
"type": "CompoundSelector",
"span": {
"start": 173,
"end": 179,
"ctxt": 0
},
"nestingSelector": null,
"typeSelector": null,
"subclassSelectors": [
{
"type": "ClassSelector",
"span": {
"start": 173,
"end": 179,
"ctxt": 0
},
"text": {
"type": "Ident",
"span": {
"start": 174,
"end": 179,
"ctxt": 0
},
"value": "class",
"raw": "class"
}
}
]
}
]
}
]
},
"block": {
"type": "SimpleBlock",
"span": {
"start": 180,
"end": 233,
"ctxt": 0
},
"name": {
"type": "PreservedToken",
"span": {
"start": 180,
"end": 181,
"ctxt": 0
},
"token": "LBrace"
},
"value": [
{
"type": "Declaration",
"span": {
"start": 186,
"end": 230,
"ctxt": 0
},
"name": {
"type": "DashedIdent",
"span": {
"start": 186,
"end": 203,
"ctxt": 0
},
"value": "vendor-property",
"raw": "--vendor-property"
},
"value": [
{
"type": "Function",
"span": {
"start": 205,
"end": 230,
"ctxt": 0
},
"name": {
"type": "DashedIdent",
"span": {
"start": 205,
"end": 222,
"ctxt": 0
},
"value": "vendor-function",
"raw": "--vendor-function"
},
"value": [
{
"type": "PreservedToken",
"span": {
"start": 223,
"end": 229,
"ctxt": 0
},
"token": {
"String": {
"value": "test",
"raw": "\"test\""
}
}
}
]
}
],
"important": null
}
]
}
} }
] ]
} }

View File

@ -15,7 +15,11 @@
12 | | } 12 | | }
13 | | 13 | |
14 | | @--custom {} 14 | | @--custom {}
15 | `-> @--library1-custom {} 15 | | @--library1-custom {}
16 | |
17 | | .class {
18 | | --vendor-property: --vendor-function("test");
19 | `-> }
`---- `----
x Rule x Rule
@ -307,7 +311,7 @@
8 | } 8 | }
`---- `----
x Ident { value: Atom('blue' type=inline), raw: "blue" } x Ident { value: Atom('blue' type=static), raw: "blue" }
,-[$DIR/tests/fixture/dashed-ident/input.css:6:1] ,-[$DIR/tests/fixture/dashed-ident/input.css:6:1]
6 | .foo { 6 | .foo {
7 | --fg-color: blue; 7 | --fg-color: blue;
@ -634,3 +638,155 @@
15 | @--library1-custom {} 15 | @--library1-custom {}
: ^ : ^
`---- `----
x Rule
,-[$DIR/tests/fixture/dashed-ident/input.css:16:1]
16 |
17 | ,-> .class {
18 | | --vendor-property: --vendor-function("test");
19 | `-> }
`----
x QualifiedRule
,-[$DIR/tests/fixture/dashed-ident/input.css:16:1]
16 |
17 | ,-> .class {
18 | | --vendor-property: --vendor-function("test");
19 | `-> }
`----
x SelectorList
,-[$DIR/tests/fixture/dashed-ident/input.css:16:1]
16 |
17 | .class {
: ^^^^^^
18 | --vendor-property: --vendor-function("test");
`----
x ComplexSelector
,-[$DIR/tests/fixture/dashed-ident/input.css:16:1]
16 |
17 | .class {
: ^^^^^^
18 | --vendor-property: --vendor-function("test");
`----
x CompoundSelector
,-[$DIR/tests/fixture/dashed-ident/input.css:16:1]
16 |
17 | .class {
: ^^^^^^
18 | --vendor-property: --vendor-function("test");
`----
x SubclassSelector
,-[$DIR/tests/fixture/dashed-ident/input.css:16:1]
16 |
17 | .class {
: ^^^^^^
18 | --vendor-property: --vendor-function("test");
`----
x ClassSelector
,-[$DIR/tests/fixture/dashed-ident/input.css:16:1]
16 |
17 | .class {
: ^^^^^^
18 | --vendor-property: --vendor-function("test");
`----
x Ident
,-[$DIR/tests/fixture/dashed-ident/input.css:16:1]
16 |
17 | .class {
: ^^^^^
18 | --vendor-property: --vendor-function("test");
`----
x SimpleBlock
,-[$DIR/tests/fixture/dashed-ident/input.css:16:1]
16 |
17 | ,-> .class {
18 | | --vendor-property: --vendor-function("test");
19 | `-> }
`----
x LBrace
,-[$DIR/tests/fixture/dashed-ident/input.css:16:1]
16 |
17 | .class {
: ^
18 | --vendor-property: --vendor-function("test");
`----
x ComponentValue
,-[$DIR/tests/fixture/dashed-ident/input.css:17:1]
17 | .class {
18 | --vendor-property: --vendor-function("test");
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19 | }
`----
x Declaration
,-[$DIR/tests/fixture/dashed-ident/input.css:17:1]
17 | .class {
18 | --vendor-property: --vendor-function("test");
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19 | }
`----
x DeclarationName
,-[$DIR/tests/fixture/dashed-ident/input.css:17:1]
17 | .class {
18 | --vendor-property: --vendor-function("test");
: ^^^^^^^^^^^^^^^^^
19 | }
`----
x DashedIdent
,-[$DIR/tests/fixture/dashed-ident/input.css:17:1]
17 | .class {
18 | --vendor-property: --vendor-function("test");
: ^^^^^^^^^^^^^^^^^
19 | }
`----
x ComponentValue
,-[$DIR/tests/fixture/dashed-ident/input.css:17:1]
17 | .class {
18 | --vendor-property: --vendor-function("test");
: ^^^^^^^^^^^^^^^^^^^^^^^^^
19 | }
`----
x Function
,-[$DIR/tests/fixture/dashed-ident/input.css:17:1]
17 | .class {
18 | --vendor-property: --vendor-function("test");
: ^^^^^^^^^^^^^^^^^^^^^^^^^
19 | }
`----
x DashedIdent
,-[$DIR/tests/fixture/dashed-ident/input.css:17:1]
17 | .class {
18 | --vendor-property: --vendor-function("test");
: ^^^^^^^^^^^^^^^^^
19 | }
`----
x ComponentValue
,-[$DIR/tests/fixture/dashed-ident/input.css:17:1]
17 | .class {
18 | --vendor-property: --vendor-function("test");
: ^^^^^^
19 | }
`----
x String { value: Atom('test' type=inline), raw: "\"test\"" }
,-[$DIR/tests/fixture/dashed-ident/input.css:17:1]
17 | .class {
18 | --vendor-property: --vendor-function("test");
: ^^^^^^
19 | }
`----

View File

@ -182,42 +182,31 @@
"ctxt": 0 "ctxt": 0
}, },
"name": { "name": {
"type": "Ident", "type": "DashedIdent",
"span": { "span": {
"start": 38, "start": 38,
"end": 42, "end": 42,
"ctxt": 0 "ctxt": 0
}, },
"value": "--fn", "value": "fn",
"raw": "--fn" "raw": "--fn"
}, },
"value": [ "value": [
{ {
"type": "Length", "type": "PreservedToken",
"span": { "span": {
"start": 43, "start": 43,
"end": 48, "end": 48,
"ctxt": 0 "ctxt": 0
}, },
"value": { "token": {
"type": "Number", "Dimension": {
"span": { "value": 100.0,
"start": 43, "raw_value": "100",
"end": 46, "unit": "px",
"ctxt": 0 "type": "integer",
}, "raw_unit": "px"
"value": 100.0, }
"raw": "100"
},
"unit": {
"type": "Ident",
"span": {
"start": 46,
"end": 48,
"ctxt": 0
},
"value": "px",
"raw": "px"
} }
} }
] ]
@ -251,42 +240,31 @@
"ctxt": 0 "ctxt": 0
}, },
"name": { "name": {
"type": "Ident", "type": "DashedIdent",
"span": { "span": {
"start": 61, "start": 61,
"end": 69, "end": 69,
"ctxt": 0 "ctxt": 0
}, },
"value": "--fn--fn", "value": "fn--fn",
"raw": "--fn--fn" "raw": "--fn--fn"
}, },
"value": [ "value": [
{ {
"type": "Length", "type": "PreservedToken",
"span": { "span": {
"start": 70, "start": 70,
"end": 75, "end": 75,
"ctxt": 0 "ctxt": 0
}, },
"value": { "token": {
"type": "Number", "Dimension": {
"span": { "value": 100.0,
"start": 70, "raw_value": "100",
"end": 73, "unit": "px",
"ctxt": 0 "type": "integer",
}, "raw_unit": "px"
"value": 100.0, }
"raw": "100"
},
"unit": {
"type": "Ident",
"span": {
"start": 73,
"end": 75,
"ctxt": 0
},
"value": "px",
"raw": "px"
} }
} }
] ]

View File

@ -235,7 +235,7 @@
4 | prod: --fn--fn(100px); 4 | prod: --fn--fn(100px);
`---- `----
x Ident x DashedIdent
,-[$DIR/tests/fixture/function/unknown/input.css:2:1] ,-[$DIR/tests/fixture/function/unknown/input.css:2:1]
2 | prod: fn(100px); 2 | prod: fn(100px);
3 | prod: --fn(100px); 3 | prod: --fn(100px);
@ -251,7 +251,7 @@
4 | prod: --fn--fn(100px); 4 | prod: --fn--fn(100px);
`---- `----
x Dimension x Dimension(DimensionToken { value: 100.0, raw_value: "100", unit: Atom('px' type=static), type_flag: Integer, raw_unit: "px" })
,-[$DIR/tests/fixture/function/unknown/input.css:2:1] ,-[$DIR/tests/fixture/function/unknown/input.css:2:1]
2 | prod: fn(100px); 2 | prod: fn(100px);
3 | prod: --fn(100px); 3 | prod: --fn(100px);
@ -259,30 +259,6 @@
4 | prod: --fn--fn(100px); 4 | prod: --fn--fn(100px);
`---- `----
x Length
,-[$DIR/tests/fixture/function/unknown/input.css:2:1]
2 | prod: fn(100px);
3 | prod: --fn(100px);
: ^^^^^
4 | prod: --fn--fn(100px);
`----
x Number
,-[$DIR/tests/fixture/function/unknown/input.css:2:1]
2 | prod: fn(100px);
3 | prod: --fn(100px);
: ^^^
4 | prod: --fn--fn(100px);
`----
x Ident
,-[$DIR/tests/fixture/function/unknown/input.css:2:1]
2 | prod: fn(100px);
3 | prod: --fn(100px);
: ^^
4 | prod: --fn--fn(100px);
`----
x ComponentValue x ComponentValue
,-[$DIR/tests/fixture/function/unknown/input.css:3:1] ,-[$DIR/tests/fixture/function/unknown/input.css:3:1]
3 | prod: --fn(100px); 3 | prod: --fn(100px);
@ -331,7 +307,7 @@
5 | } 5 | }
`---- `----
x Ident x DashedIdent
,-[$DIR/tests/fixture/function/unknown/input.css:3:1] ,-[$DIR/tests/fixture/function/unknown/input.css:3:1]
3 | prod: --fn(100px); 3 | prod: --fn(100px);
4 | prod: --fn--fn(100px); 4 | prod: --fn--fn(100px);
@ -347,34 +323,10 @@
5 | } 5 | }
`---- `----
x Dimension x Dimension(DimensionToken { value: 100.0, raw_value: "100", unit: Atom('px' type=static), type_flag: Integer, raw_unit: "px" })
,-[$DIR/tests/fixture/function/unknown/input.css:3:1] ,-[$DIR/tests/fixture/function/unknown/input.css:3:1]
3 | prod: --fn(100px); 3 | prod: --fn(100px);
4 | prod: --fn--fn(100px); 4 | prod: --fn--fn(100px);
: ^^^^^ : ^^^^^
5 | } 5 | }
`---- `----
x Length
,-[$DIR/tests/fixture/function/unknown/input.css:3:1]
3 | prod: --fn(100px);
4 | prod: --fn--fn(100px);
: ^^^^^
5 | }
`----
x Number
,-[$DIR/tests/fixture/function/unknown/input.css:3:1]
3 | prod: --fn(100px);
4 | prod: --fn--fn(100px);
: ^^^
5 | }
`----
x Ident
,-[$DIR/tests/fixture/function/unknown/input.css:3:1]
3 | prod: --fn(100px);
4 | prod: --fn--fn(100px);
: ^^
5 | }
`----

View File

@ -491,7 +491,7 @@
"end": 171, "end": 171,
"ctxt": 0 "ctxt": 0
}, },
"value": "rGb", "value": "rgb",
"raw": "rGb" "raw": "rGb"
}, },
"value": [ "value": [
@ -2419,7 +2419,7 @@
"end": 812, "end": 812,
"ctxt": 0 "ctxt": 0
}, },
"value": "rGbA", "value": "rgba",
"raw": "rGbA" "raw": "rGbA"
}, },
"value": [ "value": [
@ -3850,7 +3850,7 @@
"end": 1299, "end": 1299,
"ctxt": 0 "ctxt": 0
}, },
"value": "HsL", "value": "hsl",
"raw": "HsL" "raw": "HsL"
}, },
"value": [ "value": [

View File

@ -164,7 +164,7 @@
3 | main { 3 | main {
`---- `----
x Ident { value: Atom('teal' type=inline), raw: "teal" } x Ident { value: Atom('teal' type=static), raw: "teal" }
,-[$DIR/tests/recovery/at-rule/media/wrong-stylesheet/input.css:1:1] ,-[$DIR/tests/recovery/at-rule/media/wrong-stylesheet/input.css:1:1]
1 | @media print { 1 | @media print {
2 | color: teal; 2 | color: teal;

View File

@ -232,7 +232,7 @@
4 | } 4 | }
`---- `----
x Ident { value: Atom('blue' type=inline), raw: "blue" } x Ident { value: Atom('blue' type=static), raw: "blue" }
,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:1] ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:1]
2 | content: "foo"; 2 | content: "foo";
3 | color: blue; 3 | color: blue;

View File

@ -47,13 +47,13 @@
"ctxt": 0 "ctxt": 0
}, },
"name": { "name": {
"type": "Ident", "type": "DashedIdent",
"span": { "span": {
"start": 12, "start": 12,
"end": 21, "end": 21,
"ctxt": 0 "ctxt": 0
}, },
"value": "--element", "value": "element",
"raw": "--element" "raw": "--element"
}, },
"value": [ "value": [
@ -1496,13 +1496,13 @@
"ctxt": 0 "ctxt": 0
}, },
"name": { "name": {
"type": "Ident", "type": "DashedIdent",
"span": { "span": {
"start": 356, "start": 356,
"end": 362, "end": 362,
"ctxt": 0 "ctxt": 0
}, },
"value": "--func", "value": "func",
"raw": "--func" "raw": "--func"
}, },
"value": [ "value": [

View File

@ -95,7 +95,7 @@
2 | [--self] { 2 | [--self] {
`---- `----
x Ident x DashedIdent
,-[$DIR/tests/recovery/at-rule/supports/non-standard-prelude/input.css:1:1] ,-[$DIR/tests/recovery/at-rule/supports/non-standard-prelude/input.css:1:1]
1 | @supports (--element(".minwidth", { "minWidth": 300 })) { 1 | @supports (--element(".minwidth", { "minWidth": 300 })) {
: ^^^^^^^^^ : ^^^^^^^^^
@ -1428,7 +1428,7 @@
20 | * { background: red; } 20 | * { background: red; }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/at-rule/supports/non-standard-prelude/input.css:18:1] ,-[$DIR/tests/recovery/at-rule/supports/non-standard-prelude/input.css:18:1]
18 | 18 |
19 | @supports ([color: red]) { 19 | @supports ([color: red]) {
@ -1836,7 +1836,7 @@
24 | * { background: red; } 24 | * { background: red; }
`---- `----
x Ident x DashedIdent
,-[$DIR/tests/recovery/at-rule/supports/non-standard-prelude/input.css:22:1] ,-[$DIR/tests/recovery/at-rule/supports/non-standard-prelude/input.css:22:1]
22 | 22 |
23 | @supports ([[[[[{ --func(color: { red }) }]]]]]) { 23 | @supports ([[[[[{ --func(color: { red }) }]]]]]) {
@ -1940,7 +1940,7 @@
24 | * { background: red; } 24 | * { background: red; }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/at-rule/supports/non-standard-prelude/input.css:22:1] ,-[$DIR/tests/recovery/at-rule/supports/non-standard-prelude/input.css:22:1]
22 | 22 |
23 | @supports ([[[[[{ --func(color: { red }) }]]]]]) { 23 | @supports ([[[[[{ --func(color: { red }) }]]]]]) {

View File

@ -651,7 +651,7 @@
21 | } 21 | }
`---- `----
x Ident { value: Atom('blue' type=inline), raw: "blue" } x Ident { value: Atom('blue' type=static), raw: "blue" }
,-[$DIR/tests/recovery/cdo-and-cdc/input.css:19:1] ,-[$DIR/tests/recovery/cdo-and-cdc/input.css:19:1]
19 | 19 |
20 | color: blue; 20 | color: blue;

View File

@ -123,7 +123,7 @@
3 | } 3 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important-1/input.css:1:1] ,-[$DIR/tests/recovery/declaration/important-1/input.css:1:1]
1 | a { 1 | a {
2 | color: red !importan; 2 | color: red !importan;

View File

@ -136,7 +136,7 @@
3 | } 3 | }
`---- `----
x Ident { value: Atom('white' type=inline), raw: "white" } x Ident { value: Atom('white' type=static), raw: "white" }
,-[$DIR/tests/recovery/declaration/important/input.css:1:1] ,-[$DIR/tests/recovery/declaration/important/input.css:1:1]
1 | .a { 1 | .a {
2 | color: white !!important; 2 | color: white !!important;
@ -312,7 +312,7 @@
7 | } 7 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:5:1] ,-[$DIR/tests/recovery/declaration/important/input.css:5:1]
5 | .class { 5 | .class {
6 | color: red red red !important !important; 6 | color: red red red !important !important;
@ -344,7 +344,7 @@
7 | } 7 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:5:1] ,-[$DIR/tests/recovery/declaration/important/input.css:5:1]
5 | .class { 5 | .class {
6 | color: red red red !important !important; 6 | color: red red red !important !important;
@ -376,7 +376,7 @@
7 | } 7 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:5:1] ,-[$DIR/tests/recovery/declaration/important/input.css:5:1]
5 | .class { 5 | .class {
6 | color: red red red !important !important; 6 | color: red red red !important !important;
@ -568,7 +568,7 @@
11 | } 11 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:9:1] ,-[$DIR/tests/recovery/declaration/important/input.css:9:1]
9 | .class { 9 | .class {
10 | color: red red red !important!important ; 10 | color: red red red !important!important ;
@ -600,7 +600,7 @@
11 | } 11 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:9:1] ,-[$DIR/tests/recovery/declaration/important/input.css:9:1]
9 | .class { 9 | .class {
10 | color: red red red !important!important ; 10 | color: red red red !important!important ;
@ -632,7 +632,7 @@
11 | } 11 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:9:1] ,-[$DIR/tests/recovery/declaration/important/input.css:9:1]
9 | .class { 9 | .class {
10 | color: red red red !important!important ; 10 | color: red red red !important!important ;
@ -824,7 +824,7 @@
15 | } 15 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:13:1] ,-[$DIR/tests/recovery/declaration/important/input.css:13:1]
13 | .class { 13 | .class {
14 | color: red red red /* test*/ !important /*test*/ !important /*test*/ ; 14 | color: red red red /* test*/ !important /*test*/ !important /*test*/ ;
@ -856,7 +856,7 @@
15 | } 15 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:13:1] ,-[$DIR/tests/recovery/declaration/important/input.css:13:1]
13 | .class { 13 | .class {
14 | color: red red red /* test*/ !important /*test*/ !important /*test*/ ; 14 | color: red red red /* test*/ !important /*test*/ !important /*test*/ ;
@ -888,7 +888,7 @@
15 | } 15 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:13:1] ,-[$DIR/tests/recovery/declaration/important/input.css:13:1]
13 | .class { 13 | .class {
14 | color: red red red /* test*/ !important /*test*/ !important /*test*/ ; 14 | color: red red red /* test*/ !important /*test*/ !important /*test*/ ;
@ -1096,7 +1096,7 @@
19 | } 19 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:17:1] ,-[$DIR/tests/recovery/declaration/important/input.css:17:1]
17 | .class { 17 | .class {
18 | color: red red red !important !important!important; 18 | color: red red red !important !important!important;
@ -1128,7 +1128,7 @@
19 | } 19 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:17:1] ,-[$DIR/tests/recovery/declaration/important/input.css:17:1]
17 | .class { 17 | .class {
18 | color: red red red !important !important!important; 18 | color: red red red !important !important!important;
@ -1160,7 +1160,7 @@
19 | } 19 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:17:1] ,-[$DIR/tests/recovery/declaration/important/input.css:17:1]
17 | .class { 17 | .class {
18 | color: red red red !important !important!important; 18 | color: red red red !important !important!important;
@ -1400,7 +1400,7 @@
23 | } 23 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:21:1] ,-[$DIR/tests/recovery/declaration/important/input.css:21:1]
21 | .class { 21 | .class {
22 | color: red red red /* test */ ! /*test */ important /* test */ ! /* test */ important /* test */; 22 | color: red red red /* test */ ! /*test */ important /* test */ ! /* test */ important /* test */;
@ -1432,7 +1432,7 @@
23 | } 23 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:21:1] ,-[$DIR/tests/recovery/declaration/important/input.css:21:1]
21 | .class { 21 | .class {
22 | color: red red red /* test */ ! /*test */ important /* test */ ! /* test */ important /* test */; 22 | color: red red red /* test */ ! /*test */ important /* test */ ! /* test */ important /* test */;
@ -1464,7 +1464,7 @@
23 | } 23 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/important/input.css:21:1] ,-[$DIR/tests/recovery/declaration/important/input.css:21:1]
21 | .class { 21 | .class {
22 | color: red red red /* test */ ! /*test */ important /* test */ ! /* test */ important /* test */; 22 | color: red red red /* test */ ! /*test */ important /* test */ ! /* test */ important /* test */;

View File

@ -147,7 +147,7 @@
3 | } 3 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/declaration/wrong-name/input.css:1:1] ,-[$DIR/tests/recovery/declaration/wrong-name/input.css:1:1]
1 | a { 1 | a {
2 | 20: red; 2 | 20: red;

View File

@ -155,7 +155,7 @@
3 | } 3 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/delim-token/at-sign/input.css:1:1] ,-[$DIR/tests/recovery/delim-token/at-sign/input.css:1:1]
1 | a { 1 | a {
2 | color: @ red; 2 | color: @ red;

View File

@ -19316,7 +19316,7 @@
245 | _background: white; 245 | _background: white;
`---- `----
x Ident { value: Atom('black' type=inline), raw: "black" } x Ident { value: Atom('black' type=static), raw: "black" }
,-[$DIR/tests/recovery/hacks/input.css:243:1] ,-[$DIR/tests/recovery/hacks/input.css:243:1]
243 | a { 243 | a {
244 | *color : black; 244 | *color : black;

View File

@ -456,7 +456,7 @@
"end": 172, "end": 172,
"ctxt": 0 "ctxt": 0
}, },
"value": "Blur", "value": "blur",
"raw": "Blur" "raw": "Blur"
}, },
"value": [ "value": [
@ -608,7 +608,7 @@
"end": 227, "end": 227,
"ctxt": 0 "ctxt": 0
}, },
"value": "Wheel", "value": "wheel",
"raw": "Wheel" "raw": "Wheel"
}, },
"value": [ "value": [

View File

@ -285,7 +285,7 @@
: ^^^ : ^^^
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:4:1] ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:4:1]
4 | 4 |
5 | .class { color: red } 5 | .class { color: red }
@ -448,7 +448,7 @@
: ^^^^ : ^^^^
`---- `----
x Ident { value: Atom('blue' type=inline), raw: "blue" } x Ident { value: Atom('blue' type=static), raw: "blue" }
,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:6:1] ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:6:1]
6 | 6 |
7 | .class { color: blue } 7 | .class { color: blue }

View File

@ -399,7 +399,7 @@
7 | } 7 | }
`---- `----
x Ident { value: Atom('green' type=inline), raw: "green" } x Ident { value: Atom('green' type=static), raw: "green" }
,-[$DIR/tests/recovery/style-blocks-contents/basic/input.css:5:1] ,-[$DIR/tests/recovery/style-blocks-contents/basic/input.css:5:1]
5 | ident 5 | ident
6 | color: green; 6 | color: green;
@ -834,7 +834,7 @@
15 | } 15 | }
`---- `----
x Ident { value: Atom('red' type=inline), raw: "red" } x Ident { value: Atom('red' type=static), raw: "red" }
,-[$DIR/tests/recovery/style-blocks-contents/basic/input.css:13:1] ,-[$DIR/tests/recovery/style-blocks-contents/basic/input.css:13:1]
13 | ident 13 | ident
14 | color: red 14 | color: red

View File

@ -127,7 +127,7 @@ impl VisitMut for CrossFadeFunctionReplacerOnLegacyVariant<'_> {
fn visit_mut_function(&mut self, n: &mut Function) { fn visit_mut_function(&mut self, n: &mut Function) {
n.visit_mut_children_with(self); n.visit_mut_children_with(self);
if n.name.value.eq_str_ignore_ascii_case(self.from) { if n.name == *self.from {
let mut transparency_values = vec![]; let mut transparency_values = vec![];
for group in n.value.split_mut(|n| { for group in n.value.split_mut(|n| {
@ -217,8 +217,16 @@ impl VisitMut for CrossFadeFunctionReplacerOnLegacyVariant<'_> {
n.value = new_value; n.value = new_value;
n.name.value = self.to.into(); match &mut n.name {
n.name.raw = None; FunctionName::Ident(name) => {
name.value = self.to.into();
name.raw = None;
}
FunctionName::DashedIdent(name) => {
name.value = self.to.into();
name.raw = None;
}
}
} }
} }
} }
@ -265,13 +273,21 @@ impl VisitMut for ImageSetFunctionReplacerOnLegacyVariant<'_> {
fn visit_mut_function(&mut self, n: &mut Function) { fn visit_mut_function(&mut self, n: &mut Function) {
let old_in_function = self.in_function; let old_in_function = self.in_function;
self.in_function = n.name.value.eq_str_ignore_ascii_case(self.from); self.in_function = n.name == *self.from;
n.visit_mut_children_with(self); n.visit_mut_children_with(self);
if n.name.value.eq_str_ignore_ascii_case(self.from) { if n.name == *self.from {
n.name.value = self.to.into(); match &mut n.name {
n.name.raw = None; FunctionName::Ident(name) => {
name.value = self.to.into();
name.raw = None;
}
FunctionName::DashedIdent(name) => {
name.value = self.to.into();
name.raw = None;
}
}
} }
self.in_function = old_in_function; self.in_function = old_in_function;
@ -300,9 +316,17 @@ impl VisitMut for LinearGradientFunctionReplacerOnLegacyVariant<'_> {
fn visit_mut_function(&mut self, n: &mut Function) { fn visit_mut_function(&mut self, n: &mut Function) {
n.visit_mut_children_with(self); n.visit_mut_children_with(self);
if &*n.name.value.to_ascii_lowercase() == self.from { if n.name == *self.from {
n.name.value = self.to.into(); match &mut n.name {
n.name.raw = None; FunctionName::Ident(name) => {
name.value = self.to.into();
name.raw = None;
}
FunctionName::DashedIdent(name) => {
name.value = self.to.into();
name.raw = None;
}
}
let first = n.value.get(0); let first = n.value.get(0);
@ -526,10 +550,8 @@ impl VisitMut for CalcReplacer<'_> {
fn visit_mut_function(&mut self, n: &mut Function) { fn visit_mut_function(&mut self, n: &mut Function) {
let old_inside_calc = self.inside_calc; let old_inside_calc = self.inside_calc;
let name = n.name.value.to_ascii_lowercase(); let is_webkit_calc = n.name == js_word!("-webkit-calc");
let is_moz_calc = n.name == js_word!("-moz-calc");
let is_webkit_calc = matches!(name, js_word!("-webkit-calc"));
let is_moz_calc = matches!(name, js_word!("-moz-calc"));
if self.to.is_none() && (is_webkit_calc || is_moz_calc) { if self.to.is_none() && (is_webkit_calc || is_moz_calc) {
return; return;
@ -541,14 +563,24 @@ impl VisitMut for CalcReplacer<'_> {
return; return;
} }
self.inside_calc = matches!(name, js_word!("calc")) || is_webkit_calc || is_moz_calc; let is_calc = n.name == js_word!("calc");
self.inside_calc = is_calc || is_webkit_calc || is_moz_calc;
n.visit_mut_children_with(self); n.visit_mut_children_with(self);
if matches!(name, js_word!("calc")) { if is_calc {
if let Some(to) = self.to { if let Some(to) = self.to {
n.name.value = to.clone(); match &mut n.name {
n.name.raw = None; FunctionName::Ident(name) => {
name.value = to.into();
name.raw = None;
}
FunctionName::DashedIdent(name) => {
name.value = to.into();
name.raw = None;
}
}
} }
} }
@ -563,11 +595,11 @@ impl VisitMut for CalcReplacer<'_> {
} }
if let CalcValue::Function(function) = n { if let CalcValue::Function(function) = n {
let name = function.name.value.to_ascii_lowercase(); if matches_eq!(
function.name,
if matches!( js_word!("calc"),
name, js_word!("-webkit-calc"),
js_word!("calc") | js_word!("-webkit-calc") | js_word!("-moz-calc") js_word!("-moz-calc")
) { ) {
let calc_sum = match function.value.get(0) { let calc_sum = match function.value.get(0) {
Some(ComponentValue::CalcSum(calc_sum)) => *calc_sum.clone(), Some(ComponentValue::CalcSum(calc_sum)) => *calc_sum.clone(),
@ -599,7 +631,7 @@ impl VisitMut for FontFaceFormatOldSyntax {
fn visit_mut_function(&mut self, n: &mut Function) { fn visit_mut_function(&mut self, n: &mut Function) {
n.visit_mut_children_with(self); n.visit_mut_children_with(self);
if !n.name.value.eq_ignore_ascii_case(&js_word!("format")) { if !(n.name == js_word!("format")) {
return; return;
} }
@ -2524,10 +2556,10 @@ impl VisitMut for Prefixer {
} }
} }
js_word!("filter") => match &n.value[0] { js_word!("filter") => match &n.value.get(0) {
ComponentValue::PreservedToken(_) => {} Some(ComponentValue::PreservedToken(_)) => {}
ComponentValue::Function(function) Some(ComponentValue::Function(function)) if function.name == js_word!("alpha") => {}
if function.name.value.eq_ignore_ascii_case(&js_word!("alpha")) => {} None => {}
_ => { _ => {
add_declaration!(Prefix::Webkit, js_word!("-webkit-filter"), None); add_declaration!(Prefix::Webkit, js_word!("-webkit-filter"), None);
} }
@ -2708,18 +2740,18 @@ impl VisitMut for Prefixer {
let has_3d_function = n.value.iter().any(|n| match n { let has_3d_function = n.value.iter().any(|n| match n {
ComponentValue::Function(function) ComponentValue::Function(function)
if matches_eq_ignore_ascii_case!( if matches_eq!(
&*function.name.value, function.name,
"matrix3d", js_word!("matrix3d"),
"translate3d", js_word!("translate3d"),
"translatez", js_word!("translatez"),
"scale3d", js_word!("scale3d"),
"scalez", js_word!("scalez"),
"rotate3d", js_word!("rotate3d"),
"rotatex", js_word!("rotatex"),
"rotatey", js_word!("rotatey"),
"rotatez", js_word!("rotatez"),
"perspective" js_word!("perspective")
) => ) =>
{ {
true true

View File

@ -41,9 +41,16 @@ impl VisitMut for FunctionNameReplacer<'_> {
fn visit_mut_function(&mut self, n: &mut Function) { fn visit_mut_function(&mut self, n: &mut Function) {
n.visit_mut_children_with(self); n.visit_mut_children_with(self);
if n.name.value.eq_str_ignore_ascii_case(self.from) { match &mut n.name {
n.name.value = self.to.into(); FunctionName::Ident(name) if name.value.eq_str_ignore_ascii_case(self.from) => {
n.name.raw = None; name.value = self.to.into();
name.raw = None;
}
FunctionName::DashedIdent(name) if name.value.eq_str_ignore_ascii_case(self.from) => {
name.value = self.to.into();
name.raw = None;
}
_ => {}
} }
} }
} }

View File

@ -154,9 +154,14 @@ define!({
pub value: DelimiterValue, pub value: DelimiterValue,
} }
pub enum FunctionName {
Ident(Ident),
DashedIdent(DashedIdent),
}
pub struct Function { pub struct Function {
pub span: Span, pub span: Span,
pub name: Ident, pub name: FunctionName,
pub value: Vec<ComponentValue>, pub value: Vec<ComponentValue>,
} }