Skip to content

Commit

Permalink
feat: support w3c special properties (#1081)
Browse files Browse the repository at this point in the history
  • Loading branch information
jorenbroekema authored Jan 23, 2024
1 parent 3138313 commit 294fd0e
Show file tree
Hide file tree
Showing 55 changed files with 879 additions and 431 deletions.
5 changes: 5 additions & 0 deletions .changeset/rich-pianos-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'style-dictionary': minor
---

Support W3C Draft specification for Design Tokens, by adding support for $value, $type and $description properties.
23 changes: 14 additions & 9 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,21 @@
"mocha": true,
"es6": true
},
"globals": {
"Buffer": true,
"escape": true
},
"extends": ["eslint:recommended"],
"plugins": ["mocha"],
"rules": {
"no-console": 0,
"no-unused-vars": 1,
"no-control-regex": 0,
"comma-dangle": 0,
"no-prototype-builtins": 0
}
"no-console": ["error", { "allow": ["warn", "error"] }],
"mocha/no-skipped-tests": "warn",
"mocha/no-exclusive-tests": "error",
"no-var": "error"
},
"overrides": [
{
"files": ["examples/**/*.js"],
"rules": {
"no-console": 0
}
}
]
}
16 changes: 16 additions & 0 deletions __integration__/__snapshots__/w3c-forward-compat.test.snap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* @web/test-runner snapshot v1 */
export const snapshots = {};

snapshots["should match snapshot"] =
`/**
* Do not edit directly
* Generated on Sat, 01 Jan 2000 00:00:00 GMT
*/
:root {
--colors-black-500: rgb(0, 0, 0);
--colors-black-dimension: 5px; /* Some description */
}
`;
/* end snapshot should match snapshot */

1 change: 1 addition & 0 deletions __integration__/_constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const cleanConsoleOutput = (str) => {
// https://github.com/chalk/ansi-regex/blob/main/index.js#L3
.map((s) =>
s
// eslint-disable-next-line no-control-regex
.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '')
.trim(),
);
Expand Down
92 changes: 92 additions & 0 deletions __integration__/w3c-forward-compat.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
import { expect } from 'chai';
import StyleDictionary from 'style-dictionary';
import { fs } from 'style-dictionary/fs';
import Color from 'tinycolor2';
import { resolve } from '../lib/resolve.js';
import { buildPath } from './_constants.js';
import { clearOutput } from '../__tests__/__helpers.js';

describe('integration', () => {
afterEach(() => {
clearOutput(buildPath);
});

/**
* Integration test for forward compatibility with https://design-tokens.github.io/community-group/format/
* - $value special property
* - $type special property & inherits from ancestors
* - $description special property
*/
describe('W3C DTCG draft spec forward compatibility', async () => {
const sd = new StyleDictionary({
tokens: {
colors: {
$type: 'color', // $type should be inherited by the children
black: {
500: {
$value: '#000000', // $value should work
value: {}, // should be allowed as $ prop takes precedence -> bad practice though
type: 'dimension', // should be allowed as the inherited $type takes precedence -> bad practice though
},
dimension: {
$value: '5',
value: 'something else', // should be allowed as $ prop takes precedence -> bad practice though
$type: 'dimension',
type: 'color', // should be allowed as $ prop takes precedence -> bad practice though
$description: 'Some description',
},
},
},
},
transform: {
'custom/css/color': {
type: 'value',
matcher: (token) => token.$type === 'color',
transformer: (token) => {
return Color(token.$value).toRgbString();
},
},
'custom/add/px': {
type: 'value',
matcher: (token) => token.$type === 'dimension',
transformer: (token) => {
return `${token.$value}px`;
},
},
},
platforms: {
css: {
transforms: ['name/cti/kebab', 'custom/css/color', 'custom/add/px'],
buildPath,
files: [
{
destination: 'vars.css',
format: 'css/variables',
},
],
},
},
});
await sd.buildAllPlatforms();

const output = fs.readFileSync(resolve(`${buildPath}vars.css`), {
encoding: `UTF-8`,
});

it(`should match snapshot`, async () => {
await expect(output).to.matchSnapshot();
});
});
});
50 changes: 44 additions & 6 deletions __tests__/StyleDictionary.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ describe('StyleDictionary class + extend method', () => {
});
const output = fileToJSON('__tests__/__tokens/paddings.json');
traverseObj(output, (obj) => {
if (obj.hasOwnProperty('value') && !obj.filePath) {
if (Object.hasOwn(obj, 'value') && !obj.filePath) {
obj.filePath = '__tests__/__tokens/paddings.json';
obj.isSource = false;
}
Expand All @@ -98,7 +98,7 @@ describe('StyleDictionary class + extend method', () => {
});
const output = fileToJSON('__tests__/__tokens/paddings.json');
traverseObj(output, (obj) => {
if (obj.hasOwnProperty('value') && !obj.filePath) {
if (Object.hasOwn(obj, 'value') && !obj.filePath) {
obj.filePath = '__tests__/__tokens/paddings.json';
obj.isSource = false;
}
Expand Down Expand Up @@ -148,7 +148,7 @@ describe('StyleDictionary class + extend method', () => {
});
const output = fileToJSON('__tests__/__tokens/paddings.json');
traverseObj(output, (obj) => {
if (obj.hasOwnProperty('value') && !obj.filePath) {
if (Object.hasOwn(obj, 'value') && !obj.filePath) {
obj.filePath = '__tests__/__tokens/paddings.json';
obj.isSource = true;
}
Expand All @@ -164,7 +164,7 @@ describe('StyleDictionary class + extend method', () => {
});
const output = fileToJSON('__tests__/__tokens/paddings.json');
traverseObj(output, (obj) => {
if (obj.hasOwnProperty('value') && !obj.filePath) {
if (Object.hasOwn(obj, 'value') && !obj.filePath) {
obj.filePath = filePath;
obj.isSource = true;
}
Expand All @@ -180,7 +180,7 @@ describe('StyleDictionary class + extend method', () => {
});
const output = fileToJSON('__tests__/__tokens/paddings.json');
traverseObj(output, (obj) => {
if (obj.hasOwnProperty('value') && !obj.filePath) {
if (Object.hasOwn(obj, 'value') && !obj.filePath) {
obj.filePath = '__tests__/__tokens/paddings.json';
obj.isSource = true;
}
Expand All @@ -200,7 +200,7 @@ describe('StyleDictionary class + extend method', () => {
});
const output = fileToJSON('__tests__/__tokens/paddings.json');
traverseObj(output, (obj) => {
if (obj.hasOwnProperty('value') && !obj.filePath) {
if (Object.hasOwn(obj, 'value') && !obj.filePath) {
obj.filePath = '__tests__/__tokens/paddings.json';
obj.isSource = true;
}
Expand Down Expand Up @@ -288,4 +288,42 @@ describe('StyleDictionary class + extend method', () => {

expect(obj.polluted).to.be.undefined;
});

it('should allow using $type value on a token group, children inherit, local overrides take precedence', async () => {
const sd = new StyleDictionary({
tokens: {
dimensions: {
$type: 'dimension',
sm: {
$value: '5',
},
md: {
$value: '10',
},
nested: {
deep: {
lg: {
$value: '15',
},
},
},
nope: {
$value: '20',
$type: 'spacing',
},
},
},
platforms: {
css: {
transformGroup: 'css',
},
},
});
await sd.hasInitialized;

expect(sd.tokens.dimensions.sm.$type).to.equal('dimension');
expect(sd.tokens.dimensions.md.$type).to.equal('dimension');
expect(sd.tokens.dimensions.nested.deep.lg.$type).to.equal('dimension');
expect(sd.tokens.dimensions.nope.$type).to.equal('spacing');
});
});
6 changes: 3 additions & 3 deletions __tests__/common/filters.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('common', () => {
describe('filters', () => {
describe('removePrivate', () => {
it('should keep a regular token in for distribution', () => {
var regularToken = {
const regularToken = {
name: 'color-border',
value: '#1a1aed',
};
Expand All @@ -26,7 +26,7 @@ describe('common', () => {
});

it('should keep an unfiltered token in for distribution', () => {
var unfilteredToken = {
const unfilteredToken = {
name: 'color-border',
value: '#1a1aed',
private: false,
Expand All @@ -36,7 +36,7 @@ describe('common', () => {
});

it('should remove a filtered token from the distribution output', () => {
var filteredToken = {
const filteredToken = {
name: 'color-border',
value: '#1a1aed',
private: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,21 @@ snapshots["common formatHelpers createPropertyFormatter commentStyle allows over
$color-green: #00FF00;`;
/* end snapshot common formatHelpers createPropertyFormatter commentStyle allows overriding formatting commentStyle 2 */

snapshots["common formatHelpers createPropertyFormatter commentStyle supports W3C spec $description property for comments 1"] =
` --color-red: #FF0000; /* Foo bar qux red */`;
/* end snapshot common formatHelpers createPropertyFormatter commentStyle supports W3C spec $description property for comments 1 */

snapshots["common formatHelpers createPropertyFormatter commentStyle supports W3C spec $description property for comments 2"] =
` --color-green: #00FF00; /* Foo bar qux green */`;
/* end snapshot common formatHelpers createPropertyFormatter commentStyle supports W3C spec $description property for comments 2 */

snapshots["common formatHelpers createPropertyFormatter commentStyle supports W3C spec $description property for comments 3"] =
` /**
* Foo
* bar
* qux
* blue
*/
--color-blue: #0000FF;`;
/* end snapshot common formatHelpers createPropertyFormatter commentStyle supports W3C spec $description property for comments 3 */

71 changes: 60 additions & 11 deletions __tests__/common/formatHelpers/createPropertyFormatter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,16 +290,6 @@ describe('common', () => {
},
path: ['color', 'red'],
},
blue: {
name: 'color-blue',
value: '#0000FF',
comment: 'Foo\nbar\nqux',
attributes: {
category: 'color',
type: 'blue',
},
path: ['color', 'blue'],
},
green: {
name: 'color-green',
value: '#00FF00',
Expand All @@ -310,6 +300,16 @@ describe('common', () => {
},
path: ['color', 'green'],
},
blue: {
name: 'color-blue',
value: '#0000FF',
comment: 'Foo\nbar\nqux',
attributes: {
category: 'color',
type: 'blue',
},
path: ['color', 'blue'],
},
},
};

Expand Down Expand Up @@ -356,9 +356,58 @@ describe('common', () => {
const sassRed = sassFormatter(commentDictionary.color.green);

await expect(cssRed).to.matchSnapshot(1);

await expect(sassRed).to.matchSnapshot(2);
});

it('supports W3C spec $description property for comments', async () => {
const descriptionDictionary = {
color: {
red: {
name: 'color-red',
value: '#FF0000',
$description: 'Foo bar qux red',
attributes: {
category: 'color',
type: 'red',
},
path: ['color', 'red'],
},
green: {
name: 'color-green',
value: '#00FF00',
$description: 'Foo bar qux green',
attributes: {
category: 'color',
type: 'green',
},
path: ['color', 'green'],
},
blue: {
name: 'color-blue',
value: '#0000FF',
$description: 'Foo\nbar\nqux\nblue',
attributes: {
category: 'color',
type: 'blue',
},
path: ['color', 'blue'],
},
},
};
// long commentStyle
const cssFormatter = createPropertyFormatter({
format: 'css',
dictionary: { tokens: descriptionDictionary },
});

const cssRed = cssFormatter(descriptionDictionary.color.red);
const cssGreen = cssFormatter(descriptionDictionary.color.green);
const cssBlue = cssFormatter(descriptionDictionary.color.blue);

await expect(cssRed).to.matchSnapshot(1);
await expect(cssGreen).to.matchSnapshot(2);
await expect(cssBlue).to.matchSnapshot(3);
});
});
});
});
Expand Down
Loading

0 comments on commit 294fd0e

Please sign in to comment.