-
Notifications
You must be signed in to change notification settings - Fork 567
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(references): value object references now work (#623)
Fixes #615 Token values that are objects as opposed to simple strings were not working with `outputReferences` and throwing an error. These changes fix some behavior and make sure certain scenarios don't fail. This makes explicit what `outputReferences` can and can't do: * The `value` must be a string at time of formatting. This should be the case anyways, if not you will get `[object Object]` in output files. With `outputReferences` this was failing because an object does not have the `.replace` function. * The `value` must have the referenced values in it for `outputReferences` to replace the resolved values with the reference's name. For example if you define a color using an HSL object and transform it to a hex value, we cannot undo that transform to understand which parts of the value to use the reference's name. * References to non-token's will not work with `outputReferences` because the references will not have a `name` attribute. Just like the previous point, it will build fine, but just won't output the reference and instead output the transformed and resolved value. Changes: * In `createPropertyFormatter`, rather than looking at the *original* value and replacing references with the referenced token's name, we are now looking at the *transformed* value and replacing any referenced *values* with the reference's name. This allows us to still use `outputReferences` with a value object. * Updated `getReferences` to mirror `usesReference` with respect to object values. `usesReference` checks the object values, whereas `getReferences` did not.
- Loading branch information
1 parent
f6a9fc0
commit 23de306
Showing
6 changed files
with
435 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`integration object values css/variables border should match snapshot 1`] = ` | ||
"/** | ||
* Do not edit directly | ||
* Generated on Sat, 01 Jan 2000 00:00:00 GMT | ||
*/ | ||
:root { | ||
--border-primary: 0.125rem solid #ff0000; | ||
} | ||
" | ||
`; | ||
|
||
exports[`integration object values css/variables border with references should match snapshot 1`] = ` | ||
"/** | ||
* Do not edit directly | ||
* Generated on Sat, 01 Jan 2000 00:00:00 GMT | ||
*/ | ||
:root { | ||
--border-primary: var(--size-border) solid var(--color-red); | ||
} | ||
" | ||
`; | ||
|
||
exports[`integration object values css/variables hex syntax should match snapshot 1`] = ` | ||
"/** | ||
* Do not edit directly | ||
* Generated on Sat, 01 Jan 2000 00:00:00 GMT | ||
*/ | ||
:root { | ||
--color-red: #ff0000; | ||
--color-green: #40bf40; | ||
} | ||
" | ||
`; | ||
|
||
exports[`integration object values css/variables hex syntax with references should match snapshot 1`] = ` | ||
"/** | ||
* Do not edit directly | ||
* Generated on Sat, 01 Jan 2000 00:00:00 GMT | ||
*/ | ||
:root { | ||
--color-red: #ff0000; | ||
--color-green: #40bf40; | ||
} | ||
" | ||
`; | ||
|
||
exports[`integration object values css/variables hsl syntax should match snapshot 1`] = ` | ||
"/** | ||
* Do not edit directly | ||
* Generated on Sat, 01 Jan 2000 00:00:00 GMT | ||
*/ | ||
:root { | ||
--color-red: #ff0000; | ||
--color-green: hsl(120, 50%, 50%); | ||
} | ||
" | ||
`; | ||
|
||
exports[`integration object values css/variables hsl syntax with references should match snapshot 1`] = ` | ||
"/** | ||
* Do not edit directly | ||
* Generated on Sat, 01 Jan 2000 00:00:00 GMT | ||
*/ | ||
:root { | ||
--color-red: #ff0000; | ||
--color-green: hsl(120, 50%, 50%); | ||
} | ||
" | ||
`; | ||
|
||
exports[`integration object values scss/variables should match snapshot 1`] = ` | ||
" | ||
// Do not edit directly | ||
// Generated on Sat, 01 Jan 2000 00:00:00 GMT | ||
$border-primary: 0.125rem solid #ff0000;" | ||
`; | ||
|
||
exports[`integration object values scss/variables with references should match snapshot 1`] = ` | ||
" | ||
// Do not edit directly | ||
// Generated on Sat, 01 Jan 2000 00:00:00 GMT | ||
$border-primary: $size-border solid $color-red;" | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
const fs = require('fs-extra'); | ||
const Color = require('tinycolor2'); | ||
const StyleDictionary = require('../index'); | ||
const {buildPath} = require('./_constants'); | ||
|
||
const options = { | ||
outputReferences: true | ||
} | ||
|
||
describe('integration', () => { | ||
describe('object values', () => { | ||
StyleDictionary.extend({ | ||
properties: { | ||
hue: `120`, | ||
saturation: `50%`, | ||
lightness: `50%`, | ||
color: { | ||
red: { value: "#f00" }, | ||
green: { | ||
value: { | ||
h: "{hue}", | ||
s: "{saturation}", | ||
l: "{lightness}" | ||
} | ||
} | ||
}, | ||
size: { | ||
border: { value: 0.125 } | ||
}, | ||
border: { | ||
primary: { | ||
// getReferences should work on objects like this: | ||
value: { | ||
color: "{color.red.value}", | ||
width: "{size.border.value}", | ||
style: "solid" | ||
} | ||
}, | ||
} | ||
}, | ||
transform: { | ||
hsl: { | ||
type: 'value', | ||
transitive: true, | ||
matcher: (token) => token.original.value.h, | ||
transformer: (token) => { | ||
return `hsl(${token.value.h}, ${token.value.s}, ${token.value.l})` | ||
} | ||
}, | ||
hslToHex: { | ||
type: 'value', | ||
transitive: true, | ||
matcher: (token) => token.original.value.h, | ||
transformer: (token) => { | ||
return Color(`hsl(${token.value.h}, ${token.value.s}, ${token.value.l})`).toHexString(); | ||
} | ||
}, | ||
cssBorder: { | ||
type: 'value', | ||
transitive: true, | ||
matcher: (token) => token.path[0] === `border`, | ||
transformer: (token) => { | ||
return `${token.value.width} ${token.value.style} ${token.value.color}` | ||
} | ||
} | ||
}, | ||
platforms: { | ||
// This will test to see if a value object for an hsl color works | ||
// with and without `outputReferences` | ||
cssHsl: { | ||
buildPath, | ||
transforms: StyleDictionary.transformGroup.css.concat([`hsl`]), | ||
files: [{ | ||
destination: `hsl.css`, | ||
format: `css/variables`, | ||
filter: (token) => token.attributes.category === `color` | ||
},{ | ||
destination: `hslWithReferences.css`, | ||
format: `css/variables`, | ||
filter: (token) => token.attributes.category === `color`, | ||
options | ||
}] | ||
}, | ||
|
||
// This will test to see if a value object for an hsl that has been | ||
// transformed to a hex color works with and without `outputReferences` | ||
cssHex: { | ||
buildPath, | ||
transforms: StyleDictionary.transformGroup.css.concat([`cssBorder`,`hslToHex`]), | ||
files: [{ | ||
destination: 'hex.css', | ||
format: 'css/variables', | ||
filter: (token) => token.attributes.category === `color`, | ||
},{ | ||
destination: 'hexWithReferences.css', | ||
format: 'css/variables', | ||
filter: (token) => token.attributes.category === `color`, | ||
options | ||
}] | ||
}, | ||
|
||
// This will test to see if a value object for a border | ||
// works with and without `outputReferences` | ||
cssBorder: { | ||
buildPath, | ||
transforms: StyleDictionary.transformGroup.css.concat([`cssBorder`]), | ||
files: [{ | ||
destination: 'border.css', | ||
format: 'css/variables', | ||
filter: (token) => token.attributes.category === `border`, | ||
},{ | ||
destination: 'borderWithReferences.css', | ||
format: 'css/variables', | ||
filter: (token) => token.attributes.category === `border`, | ||
options | ||
}] | ||
}, | ||
|
||
scss: { | ||
buildPath, | ||
transforms: StyleDictionary.transformGroup.css.concat([`cssBorder`,`hslToHex`]), | ||
files: [{ | ||
destination: 'border.scss', | ||
format: 'scss/variables', | ||
filter: (token) => token.attributes.category === `border`, | ||
},{ | ||
destination: 'borderWithReferences.scss', | ||
format: 'scss/variables', | ||
filter: (token) => token.attributes.category === `border`, | ||
options | ||
}] | ||
}, | ||
} | ||
}).buildAllPlatforms(); | ||
|
||
describe('css/variables', () => { | ||
describe(`hsl syntax`, () => { | ||
const output = fs.readFileSync(`${buildPath}hsl.css`, {encoding:'UTF-8'}); | ||
it(`should match snapshot`, () => { | ||
expect(output).toMatchSnapshot(); | ||
}); | ||
|
||
describe(`with references`, () => { | ||
const output = fs.readFileSync(`${buildPath}hslWithReferences.css`, {encoding:'UTF-8'}); | ||
it(`should match snapshot`, () => { | ||
expect(output).toMatchSnapshot(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe(`hex syntax`, () => { | ||
const output = fs.readFileSync(`${buildPath}hex.css`, {encoding:'UTF-8'}); | ||
it(`should match snapshot`, () => { | ||
expect(output).toMatchSnapshot(); | ||
}); | ||
|
||
describe(`with references`, () => { | ||
const output = fs.readFileSync(`${buildPath}hexWithReferences.css`, {encoding:'UTF-8'}); | ||
it(`should match snapshot`, () => { | ||
expect(output).toMatchSnapshot(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe(`border`, () => { | ||
const output = fs.readFileSync(`${buildPath}border.css`, {encoding:'UTF-8'}); | ||
it(`should match snapshot`, () => { | ||
expect(output).toMatchSnapshot(); | ||
}); | ||
|
||
describe(`with references`, () => { | ||
const output = fs.readFileSync(`${buildPath}borderWithReferences.css`, {encoding:'UTF-8'}); | ||
it(`should match snapshot`, () => { | ||
expect(output).toMatchSnapshot(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('scss/variables', () => { | ||
const output = fs.readFileSync(`${buildPath}border.scss`, {encoding:'UTF-8'}); | ||
it(`should match snapshot`, () => { | ||
expect(output).toMatchSnapshot(); | ||
}); | ||
|
||
describe(`with references`, () => { | ||
const output = fs.readFileSync(`${buildPath}borderWithReferences.scss`, {encoding:'UTF-8'}); | ||
it(`should match snapshot`, () => { | ||
expect(output).toMatchSnapshot(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
||
afterAll(() => { | ||
fs.emptyDirSync(buildPath); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
// `.getReferences` is bound to a dictionary object, so to test it we will | ||
// create a dictionary object and then call `.getReferences` on it. | ||
const createDictionary = require('../../../lib/utils/createDictionary'); | ||
|
||
const properties = { | ||
color: { | ||
red: { value: "#f00" }, | ||
danger: { value: "{color.red.value}" } | ||
}, | ||
size: { | ||
border: { value: "2px" } | ||
}, | ||
border: { | ||
primary: { | ||
// getReferences should work on objects like this: | ||
value: { | ||
color: "{color.red.value}", | ||
width: "{size.border.value}", | ||
style: "solid" | ||
} | ||
}, | ||
secondary: { | ||
// getReferences should work on interpolated values like this: | ||
value: "{size.border.value} solid {color.red.value}" | ||
} | ||
} | ||
} | ||
|
||
const dictionary = createDictionary({ properties }); | ||
|
||
describe('utils', () => { | ||
describe('reference', () => { | ||
describe('getReferences()', () => { | ||
it(`should return an empty array if the value has no references`, () => { | ||
expect(dictionary.getReferences(properties.color.red.value)).toEqual([]); | ||
}); | ||
|
||
it(`should work with a single reference`, () => { | ||
expect(dictionary.getReferences(properties.color.danger.value)).toEqual( | ||
expect.arrayContaining([ | ||
{value: "#f00"} | ||
]) | ||
); | ||
}); | ||
|
||
it(`should work with object values`, () => { | ||
expect(dictionary.getReferences(properties.border.primary.value)).toEqual( | ||
expect.arrayContaining([ | ||
{value: "2px"}, | ||
{value: "#f00"} | ||
]) | ||
); | ||
}); | ||
|
||
it(`should work with interpolated values`, () => { | ||
expect(dictionary.getReferences(properties.border.secondary.value)).toEqual( | ||
expect.arrayContaining([ | ||
{value: "2px"}, | ||
{value: "#f00"} | ||
]) | ||
); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.