Skip to content

Commit 972f8c0

Browse files
committed
Fix parsing gradients and linear()
Gradient color stops specified with two positions, or linear() control points specified with two input progress values, should be normalized into two two color stops or control points (w3c/csswg-drafts#9288).
1 parent 81992ac commit 972f8c0

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

__tests__/value.js

+16
Original file line numberDiff line numberDiff line change
@@ -3574,6 +3574,10 @@ describe('<gradient>', () => {
35743574
['radial-gradient(at center, red)', 'radial-gradient(at center center, red)'],
35753575
['radial-gradient(at center center, red)'],
35763576
['radial-gradient(in oklab, red)', 'radial-gradient(red)'],
3577+
// Implicit color stops
3578+
['conic-gradient(red 0deg 180deg)', 'conic-gradient(red 0deg, red 180deg)'],
3579+
['linear-gradient(red 0% 50%)', 'linear-gradient(red 0%, red 50%)'],
3580+
['radial-gradient(red 0% 50%)', 'radial-gradient(red 0%, red 50%)'],
35773581
]
35783582
valid.forEach(([input, expected = input]) => expect(parse('<gradient>', input)).toBe(expected))
35793583
})
@@ -3733,6 +3737,18 @@ describe('<line-names>', () => {
37333737
})
37343738
})
37353739
})
3740+
describe('<linear()>', () => {
3741+
test('representation', () => {
3742+
expect(parse('<linear()>', 'linear(1)', false)).toMatchObject({
3743+
name: 'linear',
3744+
types: ['<function>', '<linear()>'],
3745+
value: list([list([number(1), list()])], ','),
3746+
})
3747+
})
3748+
test('valid', () => {
3749+
expect(parse('<linear()>', 'linear(0 0% 50%)')).toBe('linear(0 0%, 0 50%)')
3750+
})
3751+
})
37363752
describe('<media-type>', () => {
37373753
test('invalid', () => {
37383754
const invalid = [

lib/serialize.js

+46
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,25 @@ function serializeColor({ name, types, value }, mixed = false) {
391391
return `${name}(${value.join(' ')})`
392392
}
393393

394+
/**
395+
* @param {object[]} stop
396+
* @param {object} node
397+
* @returns {object[]}
398+
* @see {@link https://drafts.csswg.org/css-images-4/#typedef-angular-color-stop}
399+
* @see {@link https://drafts.csswg.org/css-images-4/#typedef-linear-color-stop}
400+
*/
401+
function serializeColorStop([color, position]) {
402+
color = serializeCSSComponentValue(color)
403+
if (isOmitted(position)) {
404+
return color
405+
}
406+
if (position.length === 2) {
407+
const [p1, p2] = position.map(serializeCSSComponentValue)
408+
return `${color} ${p1}, ${color} ${p2}`
409+
}
410+
return `${color} ${serializeCSSComponentValue(position)}`
411+
}
412+
394413
/**
395414
* @param {object[]} stripe
396415
* @returns {string}
@@ -780,6 +799,28 @@ function serializeLineNameList(list) {
780799
}).join(' ')
781800
}
782801

802+
/**
803+
* @param {object} linear
804+
* @returns {string}
805+
* @see {@link https://drafts.csswg.org/css-easing-2/#funcdef-linear}
806+
*/
807+
function serializeLinear({ value }) {
808+
let string = 'linear('
809+
for (const [output, input] of value) {
810+
const [x, x2] = input.map(serializeCSSComponentValue)
811+
const y = serializeCSSComponentValue(output)
812+
string += y
813+
if (x) {
814+
string += ` ${x}`
815+
if(x2) {
816+
string += `, ${y} ${x2}`
817+
}
818+
}
819+
}
820+
string += ')'
821+
return string
822+
}
823+
783824
/**
784825
* @param {object[]} gradient
785826
* @returns {string}
@@ -1427,6 +1468,9 @@ function serializeCSSComponentValue(component) {
14271468
return serializeAlpha(component)
14281469
case '<an+b>':
14291470
return serializeAnB(component)
1471+
case '<angular-color-stop>':
1472+
case '<linear-color-stop>':
1473+
return serializeColorStop(component)
14301474
case '<attr()>':
14311475
return serializeAttribute(component)
14321476
case '<arc-command>':
@@ -1496,6 +1540,8 @@ function serializeCSSComponentValue(component) {
14961540
return serializeLineNames(component)
14971541
case '<line-name-list>':
14981542
return serializeLineNameList(component)
1543+
case '<linear()>':
1544+
return serializeLinear(component)
14991545
case '<linear-gradient-syntax>':
15001546
return serializeLinearGradientSyntax(component)
15011547
case '<math-function>':

0 commit comments

Comments
 (0)