Skip to content

Commit 5fa290c

Browse files
committed
Add tests of shorthand values with / separated longhand values
... and fix those for "mask" and "offset".
1 parent 9cc8637 commit 5fa290c

File tree

3 files changed

+91
-9
lines changed

3 files changed

+91
-9
lines changed

__tests__/style.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,6 +2237,16 @@ describe('border-image', () => {
22372237
longhands.forEach(longhand => expect(style[longhand]).toBe(initial(longhand)))
22382238
expect(style.borderImage).toBe('none')
22392239
expect(style.cssText).toBe('border-image: none;')
2240+
style.borderImage = '100% / 0'
2241+
longhands.forEach(longhand =>
2242+
expect(style[longhand]).toBe(longhand === 'border-image-width' ? '0' : initial(longhand)))
2243+
expect(style.borderImage).toBe('100% / 0')
2244+
expect(style.cssText).toBe('border-image: 100% / 0;')
2245+
style.borderImage = '100% / / 1'
2246+
longhands.forEach(longhand =>
2247+
expect(style[longhand]).toBe(longhand === 'border-image-outset' ? '1' : initial(longhand)))
2248+
expect(style.borderImage).toBe('100% / 1 / 1')
2249+
expect(style.cssText).toBe('border-image: 100% / 1 / 1;')
22402250
})
22412251
test('shorthand reification', () => {
22422252

@@ -2793,6 +2803,11 @@ describe('font', () => {
27932803
longhands.forEach(longhand => expect(style[longhand]).toBe(initial(longhand)))
27942804
expect(style.font).toBe('medium monospace')
27952805
expect(style.cssText).toBe('font: medium monospace;')
2806+
style.font = 'medium / 1 monospace'
2807+
longhands.forEach(longhand =>
2808+
expect(style[longhand]).toBe(longhand === 'line-height' ? '1' : initial(longhand)))
2809+
expect(style.font).toBe('medium / 1 monospace')
2810+
expect(style.cssText).toBe('font: medium / 1 monospace;')
27962811

27972812
// System font
27982813
style.font = 'caption'
@@ -3589,6 +3604,13 @@ describe('mask', () => {
35893604
expect(style.mask).toBe('no-clip')
35903605
expect(style.cssText).toBe('mask: no-clip;')
35913606

3607+
// mask-position mask-size
3608+
style.mask = '0% 0% / cover'
3609+
longhands.forEach(longhand =>
3610+
expect(style[longhand]).toBe(longhand === 'mask-size' ? 'cover' : initial(longhand)))
3611+
expect(style.mask).toBe('0% 0% / cover')
3612+
expect(style.cssText).toBe('mask: 0% 0% / cover;')
3613+
35923614
// mask-origin mask-clip
35933615
style.mask = 'fill-box'
35943616
longhands.forEach(longhand =>
@@ -3651,6 +3673,16 @@ describe('mask-border', () => {
36513673
longhands.forEach(longhand => expect(style[longhand]).toBe(initial(longhand)))
36523674
expect(style.maskBorder).toBe('none')
36533675
expect(style.cssText).toBe('mask-border: none;')
3676+
style.maskBorder = '0 / 1'
3677+
longhands.forEach(longhand =>
3678+
expect(style[longhand]).toBe(longhand === 'mask-border-width' ? '1' : initial(longhand)))
3679+
expect(style.maskBorder).toBe('0 / 1')
3680+
expect(style.cssText).toBe('mask-border: 0 / 1;')
3681+
style.maskBorder = '0 / / 1'
3682+
longhands.forEach(longhand =>
3683+
expect(style[longhand]).toBe(longhand === 'mask-border-outset' ? '1' : initial(longhand)))
3684+
expect(style.maskBorder).toBe('0 / auto / 1')
3685+
expect(style.cssText).toBe('mask-border: 0 / auto / 1;')
36543686
})
36553687
test('shorthand reification', () => {
36563688

@@ -3682,6 +3714,21 @@ describe('offset', () => {
36823714
longhands.forEach(longhand => expect(style[longhand]).toBe(initial(longhand)))
36833715
expect(style.offset).toBe('normal')
36843716
expect(style.cssText).toBe('offset: normal;')
3717+
style.offset = 'circle()'
3718+
longhands.forEach(longhand =>
3719+
expect(style[longhand]).toBe(longhand === 'offset-path' ? 'circle()' : initial(longhand)))
3720+
expect(style.offset).toBe('circle()')
3721+
expect(style.cssText).toBe('offset: circle();')
3722+
style.offset = 'none 1px'
3723+
longhands.forEach(longhand =>
3724+
expect(style[longhand]).toBe(longhand === 'offset-distance' ? '1px' : initial(longhand)))
3725+
expect(style.offset).toBe('none 1px')
3726+
expect(style.cssText).toBe('offset: none 1px;')
3727+
style.offset = 'none reverse'
3728+
longhands.forEach(longhand =>
3729+
expect(style[longhand]).toBe(longhand === 'offset-rotate' ? 'reverse' : initial(longhand)))
3730+
expect(style.offset).toBe('none reverse')
3731+
expect(style.cssText).toBe('offset: none reverse;')
36853732
style.offset = 'normal / left'
36863733
longhands.forEach(longhand =>
36873734
expect(style[longhand]).toBe(longhand === 'offset-anchor' ? 'left center' : initial(longhand)))

lib/parse/shorthand.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -728,8 +728,27 @@ function parseMaskBorder(values, longhands) {
728728
* @returns {Map}
729729
* @see {@link https://drafts.fxtf.org/motion-1/#propdef-offset}
730730
*/
731-
function parseOffset([head, anchor], longhands) {
732-
return parseLonghandsByIndex(isOmitted(anchor) ? head.flat(3) : [head, anchor[1]].flat(3), longhands)
731+
function parseOffset([[position, center], anchor], longhands) {
732+
const declarations = getInitialLonghandDeclarations(longhands)
733+
if (!isOmitted(anchor)) {
734+
declarations.set('offset-anchor', anchor[1])
735+
}
736+
if (isOmitted(position)) {
737+
const [path, tail] = center
738+
declarations.set('offset-path', path)
739+
if (isOmitted(tail)) {
740+
return declarations
741+
}
742+
const [distance, rotate] = tail
743+
if (isOmitted(distance)) {
744+
declarations.set('offset-rotate', rotate)
745+
} else {
746+
declarations.set('offset-distance', distance)
747+
}
748+
} else {
749+
declarations.set('offset-position', position)
750+
}
751+
return declarations
733752
}
734753

735754
/**

lib/serialize.js

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2704,9 +2704,15 @@ function representMask(declarations) {
27042704
while (0 < index-- && 1 < mask.length) {
27052705
const { [index]: { name } } = declarations
27062706
const value = mask[index]
2707-
if (value === properties[name].initial.serialized || (name === 'mask-origin' && value === mask[index + 1])) {
2707+
const next = mask[index + 1]
2708+
if (name === 'mask-position' && next?.startsWith('/')) {
2709+
continue
2710+
}
2711+
if (value === properties[name].initial.serialized || (name === 'mask-origin' && value === next)) {
27082712
mask.splice(index, 1)
2709-
} else if (name === 'mask-size') {
2713+
continue
2714+
}
2715+
if (name === 'mask-size') {
27102716
mask.splice(index, 1, `/ ${value}`)
27112717
}
27122718
}
@@ -2753,14 +2759,24 @@ function representObjectFit(value) {
27532759

27542760
/**
27552761
* @param {object[]} declarations
2756-
* @param {string[]} longhands
27572762
* @returns {string[]}
27582763
* @see {@link https://drafts.fxtf.org/motion-1/#propdef-offset}
27592764
*/
2760-
function representOffset(declarations, longhands) {
2761-
let values = declarations.map(serializeValue)
2765+
function representOffset(declarations) {
2766+
const values = declarations.map(serializeValue)
27622767
const anchor = values.pop()
2763-
values = representWithoutInitialValues(values, longhands)
2768+
const [position, path, distance, rotate] = values
2769+
if (rotate === properties['offset-rotate'].initial.serialized) {
2770+
values.pop()
2771+
}
2772+
if (distance === properties['offset-distance'].initial.serialized) {
2773+
values.splice(2, 1)
2774+
}
2775+
if (values.length === 2 && path === properties['offset-path'].initial.serialized) {
2776+
values.pop()
2777+
} else if (position === properties['offset-position'].initial.serialized) {
2778+
values.shift()
2779+
}
27642780
if (anchor === properties['offset-anchor'].initial.serialized) {
27652781
return values
27662782
}
@@ -3389,7 +3405,7 @@ function representDeclarationValue({ name, pending, source, value }) {
33893405
case 'mask-border':
33903406
return representMaskBorder(declarations)
33913407
case 'offset':
3392-
return representOffset(declarations, longhands)
3408+
return representOffset(declarations)
33933409
case 'page-break-after':
33943410
case 'page-break-before':
33953411
case 'page-break-inside':

0 commit comments

Comments
 (0)