Skip to content

Commit 81ee010

Browse files
committed
Serialize @function return type like parameter types
type(*) or * are omitted. A single <syntax-component> is always unwrapped from type(). A chain of <syntax-component> is unwrapped from type except in the output of CSSFunctionRule.cssText.
1 parent 14e0f20 commit 81ee010

File tree

3 files changed

+38
-10
lines changed

3 files changed

+38
-10
lines changed

__tests__/stylesheet.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ describe('CSSFunctionRule, CSSFunctionDeclarations', () => {
512512
['--parameter-4 <number> : 1'],
513513
['--parameter-5 type(<number>)', '--parameter-5 <number>'],
514514
['--parameter-6 type(<number> | <percentage>)'],
515+
['--parameter-7 type("<number>")', '--parameter-7 <number>'],
515516
]
516517
const styleSheet = createStyleSheet(`
517518
@function --name(${parameters.map(([input]) => input).join(', ')}) returns type(*) {

lib/cssom/CSSFunctionRule-impl.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ class CSSFunctionRuleImpl extends CSSGroupingRuleImpl {
2020
super(globalObject, args, privateData)
2121
const { parentStyleSheet } = this
2222
const { prelude: [{ name, value: parameters }, returnType], value } = privateData
23-
const type = isOmitted(returnType) ? '*' : serializeCSSComponentValue(returnType[1])
2423
const rules = parseBlockContents(value, this).map(rule => {
2524
if (Array.isArray(rule)) {
2625
return CSSFunctionDeclarations.createImpl(globalObject, undefined, {
@@ -32,8 +31,8 @@ class CSSFunctionRuleImpl extends CSSGroupingRuleImpl {
3231
return rule
3332
})
3433
this._parameters = parameters
34+
this._returnType = returnType
3535
this.name = serializeIdentifier({ value: name })
36-
this.returnType = type === 'type(*)' ? '*' : type
3736
this.cssRules = CSSRuleList.createImpl(globalObject, undefined, { rules })
3837
}
3938

@@ -42,24 +41,39 @@ class CSSFunctionRuleImpl extends CSSGroupingRuleImpl {
4241
* @see {@link https://drafts.csswg.org/cssom-1/#dom-cssrule-csstext}
4342
*/
4443
get cssText() {
45-
const { _parameters, cssRules, name, returnType } = this
44+
const { _parameters, _returnType, cssRules, returnType, name } = this
4645
const rules = cssRules._rules.map(rule => rule.cssText).join(' ')
4746
let string = `@function ${name}(${serializeCSSComponentValue(_parameters)}) `
4847
if (returnType !== '*') {
49-
string += `returns ${returnType} `
48+
string += `returns ${serializeCSSComponentValue(_returnType[1])} `
5049
}
5150
string += rules ? `{ ${rules} }` : '{}'
5251
return string
5352
}
5453

54+
/**
55+
* @returns {string}
56+
* @see {@link https://drafts.csswg.org/css-mixins-1/#dom-cssfunctionrule-returntype}
57+
*/
58+
get returnType() {
59+
const { _returnType } = this
60+
if (isOmitted(_returnType)) {
61+
return '*'
62+
}
63+
const type = _returnType[1]
64+
if (type.types[0] === '<function>') {
65+
return serializeCSSComponentValue(type.value)
66+
}
67+
return serializeCSSComponentValue(type)
68+
}
69+
5570
/**
5671
* @returns {FunctionParameter[]}
5772
* @see {@link https://drafts.csswg.org/css-mixins-1/#dom-cssfunctionrule-getparameters}
5873
*/
5974
getParameters() {
6075
const parameters = []
6176
this._parameters.forEach(([name, type, defaultValue]) => {
62-
defaultValue = isOmitted(defaultValue) ? null : serializeCSSComponentValue(defaultValue[1]),
6377
name = serializeIdentifier(name)
6478
if (isOmitted(type)) {
6579
type = '*'
@@ -68,6 +82,7 @@ class CSSFunctionRuleImpl extends CSSGroupingRuleImpl {
6882
} else {
6983
type = serializeCSSComponentValue(type)
7084
}
85+
defaultValue = isOmitted(defaultValue) ? null : serializeCSSComponentValue(defaultValue[1])
7186
parameters.push({ defaultValue, name, type })
7287
})
7388
return parameters

lib/parse/postprocess.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,21 @@ function postParseCounterStyleName(name, node) {
377377
return name
378378
}
379379

380+
/**
381+
* @param {object} type
382+
* @returns {object}
383+
* @see {@link https://drafts.csswg.org/css-mixins-1/#typedef-css-type}
384+
*
385+
* It represents a single <syntax-component> type without a type() wrapper.
386+
*/
387+
function postParseCSSType(type) {
388+
const { types, value } = type
389+
if (types[0] === '<function>' && isList(value) && isOmitted(value[1])) {
390+
return value[0]
391+
}
392+
return type
393+
}
394+
380395
/**
381396
* @param {object[]} definition
382397
* @param {object} node
@@ -592,7 +607,7 @@ function postParseForgivingSelectorList(selectors, node) {
592607
* It aborts parsing when the parameter has the same name as a preceding one,
593608
* or when its default value is invalid according to its type.
594609
*
595-
* It represents the parameter without a default type.
610+
* It represents the parameter without the default type.
596611
*/
597612
function postParseFunctionParameter(parameter, node, parser) {
598613
const { context, parent } = node
@@ -612,10 +627,6 @@ function postParseFunctionParameter(parameter, node, parser) {
612627
if (syntax.value === '*') {
613628
return list([name, omitted, defaultValue])
614629
}
615-
const [head, combined] = syntax
616-
if (isOmitted(combined)) {
617-
return list([name, head, defaultValue])
618-
}
619630
}
620631
}
621632
return parameter
@@ -1767,6 +1778,7 @@ module.exports = {
17671778
'<container-name>': postParseContainerNameType,
17681779
'<counter-name>': postParseCounterName,
17691780
'<counter-style-name>': postParseCounterStyleName,
1781+
'<css-type>': postParseCSSType,
17701782
'<custom-function-definition>': postParseCustomFunctionDefinition,
17711783
'<custom-ident>': postParseCustomIdentifier,
17721784
'<custom-property-name>': postParseCustomPropertyName,

0 commit comments

Comments
 (0)