diff --git a/.changeset/stupid-deers-call.md b/.changeset/stupid-deers-call.md new file mode 100644 index 000000000..0cc80a631 --- /dev/null +++ b/.changeset/stupid-deers-call.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': minor +--- + +Allow specifying a function for outputReferences, conditionally outputting a ref or not per token. Also exposes outputReferencesFilter utility function which will determine whether a token should be outputting refs based on whether those referenced tokens were filtered out or not. diff --git a/.eslintrc.json b/.eslintrc.json index 406b05c1b..c897b1813 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,4 +1,5 @@ { + "ignorePatterns": ["/docs/dist/**/*"], "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" diff --git a/.prettierignore b/.prettierignore index 0e03cbe42..d0fb38c52 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,2 +1,3 @@ .changeset/ **/*.snap.js +/docs/dist diff --git a/__integration__/__snapshots__/outputReferences.test.snap.js b/__integration__/__snapshots__/outputReferences.test.snap.js index bf48f8073..eb0639244 100644 --- a/__integration__/__snapshots__/outputReferences.test.snap.js +++ b/__integration__/__snapshots__/outputReferences.test.snap.js @@ -4,7 +4,6 @@ export const snapshots = {}; snapshots["integration output references should warn the user if filters out references briefly"] = `⚠️ __integration__/build/filteredVariables.css While building filteredVariables.css, filtered out token references were found; output may be unexpected. Ignore this warning if intentional. -Here are the references that are used but not defined in the file: Use log.verbosity "verbose" or use CLI option --verbose for more details.`; /* end snapshot integration output references should warn the user if filters out references briefly */ @@ -23,3 +22,9 @@ color.core.blue.0 This is caused when combining a filter and \`outputReferences\`.`; /* end snapshot integration output references should warn the user if filters out references with a detailed message when using verbose logging */ +snapshots["integration output references should not warn the user if filters out references is prevented with outputReferencesFilter"] = +` +css +✔︎ __integration__/build/filteredVariables.css`; +/* end snapshot integration output references should not warn the user if filters out references is prevented with outputReferencesFilter */ + diff --git a/__integration__/logging/__snapshots__/file.test.snap.js b/__integration__/logging/__snapshots__/file.test.snap.js index 9ad997022..b7dd01229 100644 --- a/__integration__/logging/__snapshots__/file.test.snap.js +++ b/__integration__/logging/__snapshots__/file.test.snap.js @@ -391,7 +391,6 @@ snapshots["integration logging file filtered references should warn users briefl css ⚠️ __integration__/build/filteredReferences.css While building filteredReferences.css, filtered out token references were found; output may be unexpected. Ignore this warning if intentional. -Here are the references that are used but not defined in the file: Use log.verbosity "verbose" or use CLI option --verbose for more details.`; /* end snapshot integration logging file filtered references should warn users briefly of filtered references by default */ @@ -399,7 +398,6 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details.`; snapshots["integration logging file filtered references should throw a brief error of filtered references with log level set to error"] = `⚠️ __integration__/build/filteredReferences.css While building filteredReferences.css, filtered out token references were found; output may be unexpected. Ignore this warning if intentional. -Here are the references that are used but not defined in the file: Use log.verbosity "verbose" or use CLI option --verbose for more details.`; /* end snapshot integration logging file filtered references should throw a brief error of filtered references with log level set to error */ @@ -407,7 +405,6 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details.`; snapshots["integration logging file filtered references should throw a brief error of filtered references with log level set to error on platform level"] = `⚠️ __integration__/build/filteredReferences.css While building filteredReferences.css, filtered out token references were found; output may be unexpected. Ignore this warning if intentional. -Here are the references that are used but not defined in the file: Use log.verbosity "verbose" or use CLI option --verbose for more details.`; /* end snapshot integration logging file filtered references should throw a brief error of filtered references with log level set to error on platform level */ diff --git a/__integration__/outputReferences.test.js b/__integration__/outputReferences.test.js index ba29fad83..f0d44ac46 100644 --- a/__integration__/outputReferences.test.js +++ b/__integration__/outputReferences.test.js @@ -15,6 +15,7 @@ import StyleDictionary from 'style-dictionary'; import { restore, stubMethod } from 'hanbi'; import { buildPath, cleanConsoleOutput } from './_constants.js'; import { clearOutput } from '../__tests__/__helpers.js'; +import { outputReferencesFilter } from '../lib/utils/references/outputReferencesFilter.js'; describe('integration', async () => { let stub; @@ -57,6 +58,38 @@ describe('integration', async () => { await expect(stub.lastCall.args.map(cleanConsoleOutput).join('\n')).to.matchSnapshot(); }); + it('should not warn the user if filters out references is prevented with outputReferencesFilter', async () => { + const sd = new StyleDictionary({ + // we are only testing showFileHeader options so we don't need + // the full source. + log: { verbosity: 'verbose' }, + source: [`__integration__/tokens/**/[!_]*.json?(c)`], + platforms: { + css: { + transformGroup: 'css', + buildPath, + files: [ + { + destination: 'filteredVariables.css', + format: 'css/variables', + // filter tokens and use outputReferences + // Style Dictionary should build this file ok + // but warn the user + filter: (token) => token.attributes.type === 'background', + options: { + outputReferences: outputReferencesFilter, + }, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + await expect( + [...stub.calls].map((cal) => cal.args.map(cleanConsoleOutput)).join('\n'), + ).to.matchSnapshot(); + }); + it('should warn the user if filters out references with a detailed message when using verbose logging', async () => { const sd = new StyleDictionary({ log: { verbosity: 'verbose' }, diff --git a/__tests__/common/formatHelpers/createPropertyFormatter.test.js b/__tests__/common/formatHelpers/createPropertyFormatter.test.js index 5842c243e..7086504d8 100644 --- a/__tests__/common/formatHelpers/createPropertyFormatter.test.js +++ b/__tests__/common/formatHelpers/createPropertyFormatter.test.js @@ -12,6 +12,8 @@ */ import { expect } from 'chai'; import createPropertyFormatter from '../../../lib/common/formatHelpers/createPropertyFormatter.js'; +import flattenTokens from '../../../lib/utils/flattenTokens.js'; +import { outputReferencesFilter } from '../../../lib/utils/references/outputReferencesFilter.js'; const dictionary = { foo: { @@ -221,6 +223,178 @@ describe('common', () => { ); }); + it('should support conditionally outputting references', () => { + const unfilteredTokens = { + foo: { + value: '5px', + original: { + value: '5px', + type: 'spacing', + }, + name: 'foo', + path: ['foo'], + type: 'spacing', + }, + bar: { + value: '5px', + original: { + value: '{foo}', + type: 'spacing', + }, + name: 'bar', + path: ['bar'], + type: 'spacing', + }, + qux: { + value: '5px', + original: { + value: '{foo}', + type: 'spacing', + }, + name: 'qux', + path: ['qux'], + type: 'spacing', + }, + }; + const tokens = { ...unfilteredTokens }; + const allTokens = flattenTokens(tokens); + const propFormatter = createPropertyFormatter({ + dictionary: { + tokens, + unfilteredTokens, + allTokens, + }, + format: 'css', + // outputReferences function that only outputs the refs if the token name is "bar" + outputReferences: (token) => token.name === 'bar', + }); + expect(propFormatter(tokens.bar)).to.equal(' --bar: var(--foo);'); + expect(propFormatter(tokens.qux)).to.equal(' --qux: 5px;'); + }); + + it('should make it easy to not output refs for tokens that contains refs that are filtered out', () => { + const unfilteredTokens = { + foo: { + value: '5px', + original: { + value: '5px', + type: 'spacing', + }, + name: 'foo', + path: ['foo'], + type: 'spacing', + }, + bar: { + value: '10px', + original: { + value: '10px', + type: 'spacing', + }, + name: 'bar', + path: ['bar'], + type: 'spacing', + }, + 'ref foo': { + value: '5px', + original: { + value: '{foo}', + type: 'spacing', + }, + name: 'ref-foo', + path: ['ref foo'], + type: 'spacing', + }, + 'ref bar': { + value: '10px', + original: { + value: '{bar}', + type: 'spacing', + }, + name: 'ref-bar', + path: ['ref bar'], + type: 'spacing', + }, + }; + const tokens = { ...unfilteredTokens }; + delete tokens.foo; + const allTokens = flattenTokens(tokens); + const propFormatter = createPropertyFormatter({ + dictionary: { + tokens, + unfilteredTokens, + allTokens, + }, + format: 'css', + // outputReferences function that only outputs the refs if the referred tokens are not filtered out + outputReferences: outputReferencesFilter, + }); + + expect(propFormatter(tokens['ref foo'])).to.equal(' --ref-foo: 5px;'); + expect(propFormatter(tokens['ref bar'])).to.equal(' --ref-bar: var(--bar);'); + }); + + it('DTCG: should make it easy to not output refs for tokens that contains refs that are filtered out', () => { + const unfilteredTokens = { + foo: { + $value: '5px', + original: { + $value: '5px', + type: 'spacing', + }, + name: 'foo', + path: ['foo'], + $type: 'spacing', + }, + bar: { + $value: '10px', + original: { + $value: '10px', + $type: 'spacing', + }, + name: 'bar', + path: ['bar'], + $type: 'spacing', + }, + 'ref foo': { + $value: '5px', + original: { + $value: '{foo}', + $type: 'spacing', + }, + name: 'ref-foo', + path: ['ref foo'], + $type: 'spacing', + }, + 'ref bar': { + $value: '10px', + original: { + $value: '{bar}', + $type: 'spacing', + }, + name: 'ref-bar', + path: ['ref bar'], + $type: 'spacing', + }, + }; + const tokens = { ...unfilteredTokens }; + delete tokens.foo; + const allTokens = flattenTokens(tokens, true); + const propFormatter = createPropertyFormatter({ + dictionary: { + tokens, + unfilteredTokens, + allTokens, + }, + format: 'css', + usesDtcg: true, + // outputReferences function that only outputs the refs if the referred tokens are not filtered out + outputReferences: outputReferencesFilter, + }); + + expect(propFormatter(tokens['ref foo'])).to.equal(' --ref-foo: 5px;'); + expect(propFormatter(tokens['ref bar'])).to.equal(' --ref-bar: var(--bar);'); + }); + it('should support object value references for outputReferences', () => { // The ref is an object type value, which means there will usually be some kind of transform (e.g. a CSS shorthand transform) // to change it from an object to a string. In our example, we use a border CSS shorthand for border token. diff --git a/__tests__/utils/groupMessages.test.js b/__tests__/utils/groupMessages.test.js new file mode 100644 index 000000000..b14b49328 --- /dev/null +++ b/__tests__/utils/groupMessages.test.js @@ -0,0 +1,31 @@ +/* + * 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 { GroupMessages } from '../../lib/utils/groupMessages.js'; + +// TODO: add more tests + +describe('groupMessage', () => { + it('should allow removing messages', () => { + const grpMessages = new GroupMessages(); + const FILTER_WARNINGS = grpMessages.GROUP.FilteredOutputReferences; + grpMessages.add(FILTER_WARNINGS, '{foo.bar}'); + grpMessages.add(FILTER_WARNINGS, '{baz.qux}'); + grpMessages.add(FILTER_WARNINGS, '{another.one}'); + + expect(grpMessages.count(FILTER_WARNINGS)).to.equal(3); + grpMessages.remove(FILTER_WARNINGS, '{baz.qux}'); + expect(grpMessages.count(FILTER_WARNINGS)).to.equal(2); + expect(grpMessages.fetchMessages(FILTER_WARNINGS)).to.eql(['{foo.bar}', '{another.one}']); + }); +}); diff --git a/docs/src/content/docs/reference/Hooks/Formats/index.md b/docs/src/content/docs/reference/Hooks/Formats/index.md index 8f2969ab5..e3bd130cd 100644 --- a/docs/src/content/docs/reference/Hooks/Formats/index.md +++ b/docs/src/content/docs/reference/Hooks/Formats/index.md @@ -81,7 +81,7 @@ The design token that is passed to the filter function has already been [transfo ## References in output files -Starting with version 3.0, some formats can keep the references in the output. This is a bit hard to explain, so let's look at an example. Say you have this very basic set of design tokens: +Some formats can keep the references in the output. This is a bit hard to explain, so let's look at an example. Say you have this very basic set of design tokens: ```json // tokens.json @@ -152,6 +152,11 @@ Not all formats use the `outputReferences` option because that file format might You can create custom formats that output references as well. See the [Custom format with output references](#custom-format-with-output-references) section. +### Filters + +When combining [`filters`](/reference/hooks/filters) with `outputReferences`, it could happen that a token is referencing another token that is getting filtered out. +When that happens, Style Dictionary will throw a warning. However, it is possible to configure `outputReferences` to use [our `outputReferencesFilter` utility function](/reference/utils/references/#outputreferencesfilter), which will prevent tokens that reference other tokens that are filtered out from outputting references, they will output the resolved values instead. + ## File headers By default Style Dictionary adds a file header comment in the top of files built using built-in formats like this: diff --git a/docs/src/content/docs/reference/Utils/references.md b/docs/src/content/docs/reference/Utils/references.md index 05beba639..e8f474340 100644 --- a/docs/src/content/docs/reference/Utils/references.md +++ b/docs/src/content/docs/reference/Utils/references.md @@ -60,7 +60,7 @@ Most notable option for public usage is `usesDtcg`, if set to true, the `resolve ## getReferences -Whether or not a token value contains references +(Whether or not a token value contains references ```javascript title="build-tokens.js" import StyleDictionary from 'style-dictionary'; @@ -100,7 +100,7 @@ getReferences('solid {spacing.2} {colors.black}', sd.tokens, { usesDtcg: true }) :::note You can pass a third `options` argument where you can pass some configuration options for how references are resolved Most notable option for public usage is `usesDtcg`, if set to true, the `resolveReferences` utility will assume DTCG syntax (`$value` props) -::: +:::) ### Complicated example @@ -236,3 +236,126 @@ export const Border = `solid ${Spacing2} ${SemanticBgPrimary}`; The above example does not support DTCG syntax, but this could be quite easily added, since you can query `sd.usesDtcg` or inside a formatter functions `dictionary.options.usesDtcg`. ::: + +## outputReferencesFilter + +An `OutputReferences` function that filters for tokens containing references to other tokens that are filtered out in the output. +Usually Style Dictionary will throw a warning when you're using `outputReferences: true` and are about to have a broken reference in your output because the token you're referencing is filtered out. +What that means is that you usually have to either adjust your filter or disable `outputReferences` altogether, but supplying a function instead [allows you to conditionally output references on a per token basis](/reference/hooks/formats#references-in-output-files). + +```javascript title="build-tokens.js" +import StyleDictionary from 'style-dictionary'; +import { outputReferencesFilter } from 'style-dictionary/utils'; + +const sd = new StyleDictionary({ + tokens: { + colors: { + black: { + value: '#000', + type: 'color', + }, + grey: { + // filtering this one out + value: '#ccc', + type: 'color', + }, + }, + spacing: { + 2: { + value: '2px', + type: 'dimension', + }, + }, + border: { + value: 'solid {spacing.2} {colors.black}', + }, + shadow: { + // danger: references a filtered out token! + value: '0 4px 2px {colors.grey}', + }, + }, + platforms: { + css: { + transformGroup: 'css', + files: [ + { + destination: 'vars.css', + format: 'css/variables', + filter: (token) => token.name !== 'colors-grey', + options: { + // returns false for the shadow token because it refs color-grey which is filtered out + outputReferences: outputReferencesFilter, + }, + }, + ], + }, + }, +}); +``` + +Output: + +```css title="vars.css" +:root { + --spacing-2: 2rem; + --colors-black: #000000; + --shadow: 0 4px 2px #cccccc; + --border: solid var(--spacing-2) var(--colors-black); +} +``` + +Note that `--colors-grey` was filtered out and therefore the shadow does not contain a CSS custom property (reference) but rather the resolved value. + +Live Demo: + +~ sd-playground + +```json tokens +{ + "colors": { + "black": { + "value": "#000", + "type": "color" + }, + "grey": { + "value": "#ccc", + "type": "color" + } + }, + "spacing": { + "2": { + "value": "2px", + "type": "dimension" + } + }, + "border": { + "value": "solid {spacing.2} {colors.black}" + }, + "shadow": { + "value": "0 4px 2px {colors.grey}" + } +} +``` + +```js config +import { outputReferencesFilter } from 'style-dictionary/utils'; + +export default { + platforms: { + css: { + transformGroup: 'css', + files: [ + { + destination: 'vars.css', + format: 'css/variables', + filter: (token) => token.name !== 'colors-grey', + options: { + // returns false for the shadow token because it refs color-grey which is filtered out + outputReferences: outputReferencesFilter, + }, + }, + ], + }, + }, +}; +``` diff --git a/lib/buildFile.js b/lib/buildFile.js index 6d7e09d2f..485ca3b47 100644 --- a/lib/buildFile.js +++ b/lib/buildFile.js @@ -189,8 +189,7 @@ export default async function buildFile(file, platform = {}, dictionary, options .rgb(255, 69, 0) .bold( destination, - )}, filtered out token references were found; output may be unexpected. Ignore this warning if intentional. -Here are the references that are used but not defined in the file:`; + )}, filtered out token references were found; output may be unexpected. Ignore this warning if intentional.`; const help = chalk.rgb( 255, 165, @@ -198,7 +197,7 @@ Here are the references that are used but not defined in the file:`; )(['This is caused when combining a filter and `outputReferences`.'].join('\n ')); const warn = platform.log?.verbosity === 'verbose' - ? `${warnHeader}\n${title}\n ${filteredReferencesWarnings}\n${help}` + ? `${warnHeader}\n${title}\nHere are the references that are used but not defined in the file:\n ${filteredReferencesWarnings}\n${help}` : `${warnHeader}\n${title}\n\n${verbosityInfo}`; if (platform?.log?.warnings === 'error') { throw new Error(warn); diff --git a/lib/cleanFile.js b/lib/cleanFile.js index 0a2b6ff47..157aa9240 100644 --- a/lib/cleanFile.js +++ b/lib/cleanFile.js @@ -40,7 +40,6 @@ export default async function cleanFile(file, platform = {}, vol = fs) { destination = platform.buildPath + destination; } - // console.log(fs); if (!vol.existsSync(destination)) { consoleLog(chalk.bold.red('!') + ' ' + destination + ', does not exist'); return; diff --git a/lib/common/formatHelpers/createPropertyFormatter.js b/lib/common/formatHelpers/createPropertyFormatter.js index a956c2eb2..3ed0e8318 100644 --- a/lib/common/formatHelpers/createPropertyFormatter.js +++ b/lib/common/formatHelpers/createPropertyFormatter.js @@ -14,8 +14,10 @@ import { _getReferences } from '../../utils/references/getReferences.js'; import usesReferences from '../../utils/references/usesReferences.js'; /** + * @typedef {import('../../../types/DesignToken.d.ts').TransformedToken} TransformedToken * @typedef {import('../../../types/DesignToken.d.ts').Dictionary} Dictionary * @typedef {import('../../../types/File.d.ts').FormattingOptions} Formatting + * @typedef {import('../../../types/Format.d.ts').OutputReferences} OutputReferences */ /** @@ -107,7 +109,7 @@ function addComment(to_ret_token, comment, options) { * }); * ``` * @param {Object} options - * @param {boolean} [options.outputReferences] - Whether or not to output references. You will want to pass this from the `options` object sent to the formatter function. + * @param {OutputReferences} [options.outputReferences] - Whether or not to output references. You will want to pass this from the `options` object sent to the formatter function. * @param {boolean} [options.outputReferenceFallbacks] - Whether or not to output css variable fallback values when using output references. You will want to pass this from the `options` object sent to the formatter function. * @param {Dictionary} options.dictionary - The dictionary object sent to the formatter function * @param {string} [options.format] - Available formats are: 'css', 'sass', 'less', and 'stylus'. If you want to customize the format and can't use one of those predefined formats, use the `formatting` option @@ -164,6 +166,11 @@ export default function createPropertyFormatter({ let value = usesDtcg ? token.$value : token.value; const originalValue = usesDtcg ? token.original.$value : token.original.value; + const shouldOutputRef = + usesReferences(originalValue) && + (typeof outputReferences === 'function' + ? outputReferences(token, { dictionary, usesDtcg }) + : outputReferences); /** * A single value can have multiple references either by interpolation: * "value": "{size.border.width.value} solid {color.border.primary.value}" @@ -176,7 +183,7 @@ export default function createPropertyFormatter({ * This will see if there are references and if there are, replace * the resolved value with the reference's name. */ - if (outputReferences && usesReferences(originalValue)) { + if (shouldOutputRef) { // Formats that use this function expect `value` to be a string // or else you will get '[object Object]' in the output const refs = _getReferences(originalValue, tokens, { unfilteredTokens }, []); diff --git a/lib/utils/groupMessages.js b/lib/utils/groupMessages.js index 28691b482..413ba9224 100644 --- a/lib/utils/groupMessages.js +++ b/lib/utils/groupMessages.js @@ -13,7 +13,7 @@ export const verbosityInfo = `Use log.verbosity "verbose" or use CLI option --verbose for more details.`; -class GroupMessages { +export class GroupMessages { constructor() { /** @type {{[key: string]: string[]}} */ this.groupedMessages = {}; @@ -55,6 +55,19 @@ class GroupMessages { } } + /** + * @param {string} messageGroup + * @param {string} message + */ + remove(messageGroup, message) { + if (messageGroup && this.groupedMessages[messageGroup]?.length > 0) { + const index = this.groupedMessages[messageGroup].indexOf(message); + if (index !== -1) { + this.groupedMessages[messageGroup].splice(index, 1); + } + } + } + /** * * @param {string} messageGroup diff --git a/lib/utils/index.js b/lib/utils/index.js index 6132365be..eaad6cc77 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -14,8 +14,16 @@ import usesReferences from './references/usesReferences.js'; import { getReferences } from './references/getReferences.js'; import { resolveReferences } from './references/resolveReferences.js'; +import { outputReferencesFilter } from './references/outputReferencesFilter.js'; import flattenTokens from './flattenTokens.js'; import { typeDtcgDelegate } from './preprocess.js'; // Public style-dictionary/utils API -export { usesReferences, getReferences, resolveReferences, flattenTokens, typeDtcgDelegate }; +export { + usesReferences, + getReferences, + resolveReferences, + outputReferencesFilter, + flattenTokens, + typeDtcgDelegate, +}; diff --git a/lib/utils/references/outputReferencesFilter.js b/lib/utils/references/outputReferencesFilter.js new file mode 100644 index 000000000..cc14ecdb0 --- /dev/null +++ b/lib/utils/references/outputReferencesFilter.js @@ -0,0 +1,31 @@ +import GroupMessages from '../groupMessages.js'; +import { getReferences } from './getReferences.js'; + +const FILTER_WARNINGS = GroupMessages.GROUP.FilteredOutputReferences; + +/** + * @typedef {import('../../../types/DesignToken.d.ts').TransformedToken} TransformedToken + * @typedef {import('../../../types/DesignToken.d.ts').Dictionary} Dictionary + * + * @param {TransformedToken} token + * @param {{ dictionary: Dictionary, usesDtcg?: boolean }} dictionary + * @returns + */ +export function outputReferencesFilter(token, { dictionary, usesDtcg }) { + const originalValue = usesDtcg ? token.original.$value : token.original.value; + // get refs, pass unfilteredTokens to ensure we find the refs even if they are filtered out + const refs = getReferences(originalValue, dictionary.tokens, { + unfilteredTokens: dictionary.unfilteredTokens, + usesDtcg, + }); + return refs.every((ref) => { + // check whether every ref can be found in the filtered set of tokens + const foundToken = dictionary.allTokens.find((token) => token.name === ref.name); + if (!foundToken) { + // remove the warning about this ref being filtered out, since we now prevent it from outputting it as a ref + GroupMessages.remove(FILTER_WARNINGS, ref.path.join('.')); + } + + return !!foundToken; + }); +} diff --git a/scripts/clearDocCache.cjs b/scripts/clearDocCache.cjs deleted file mode 100644 index 21eceed26..000000000 --- a/scripts/clearDocCache.cjs +++ /dev/null @@ -1,7 +0,0 @@ -const jsdoc2md = require('jsdoc-to-markdown'); - -async function clear() { - await jsdoc2md.clear(); -} - -clear(); diff --git a/scripts/generateDocs.cjs b/scripts/generateDocs.cjs deleted file mode 100644 index 55a0d18b6..000000000 --- a/scripts/generateDocs.cjs +++ /dev/null @@ -1,95 +0,0 @@ -const jsdoc2md = require('jsdoc-to-markdown'); -const fs = require('fs-extra'); -const execSync = require('child_process').execSync; - -function prependWarning(input, source) { - return ` -${input}`; -} - -// TODO: re-enable automatic generation of API docs via template and JSDocs -// const DOCS_PATH = './docs/api.md'; -// const docs = jsdoc2md.renderSync({ -// files: ['lib/**/*.js'], -// template: fs.readFileSync('scripts/handlebars/templates/api.hbs').toString(), -// // 'no-gfm': true, -// separators: true, -// partial: [ -// 'scripts/handlebars/header.hbs', -// 'scripts/handlebars/sig-name.hbs', -// 'scripts/handlebars/body.hbs', -// ], -// configure: '.jsdoc.json', -// }); - -// fs.ensureFileSync(DOCS_PATH); -// fs.writeFileSync(DOCS_PATH, prependWarning(docs, 'scripts/handlebars/templates/api.hbs')); -// console.log(DOCS_PATH + ' generated.'); - -const TRANSFORMS_PATH = './docs/transforms.md'; -const transforms = jsdoc2md.renderSync({ - files: ['lib/common/transforms.js'], - template: fs.readFileSync('scripts/handlebars/templates/transforms.hbs').toString(), - 'no-gfm': true, - separators: true, - partial: ['scripts/handlebars/header.hbs', 'scripts/handlebars/body.hbs'], - configure: '.jsdoc.json', -}); - -fs.ensureFileSync(TRANSFORMS_PATH); -fs.writeFileSync( - TRANSFORMS_PATH, - prependWarning(transforms, 'scripts/handlebars/templates/api.hbs'), -); -console.log(TRANSFORMS_PATH + ' generated.'); - -const TRANSFORM_GROUPS_PATH = './docs/transform_groups.md'; -const transform_groups = jsdoc2md.renderSync({ - files: ['lib/common/transformGroups.js'], - template: fs.readFileSync('scripts/handlebars/templates/transform_groups.hbs').toString(), - 'no-gfm': true, - separators: true, - partial: ['scripts/handlebars/header.hbs', 'scripts/handlebars/body.hbs'], - configure: '.jsdoc.json', -}); - -fs.ensureFileSync(TRANSFORM_GROUPS_PATH); -fs.writeFileSync( - TRANSFORM_GROUPS_PATH, - prependWarning(transform_groups, 'scripts/handlebars/templates/api.hbs'), -); -console.log(TRANSFORM_GROUPS_PATH + ' generated.'); - -const ACTIONS_PATH = './docs/actions.md'; -const actions = jsdoc2md.renderSync({ - files: ['lib/common/actions.js'], - template: fs.readFileSync('scripts/handlebars/templates/actions.hbs').toString(), - 'no-gfm': true, - separators: true, - partial: ['scripts/handlebars/header.hbs', 'scripts/handlebars/body.hbs'], - configure: '.jsdoc.json', -}); - -fs.ensureFileSync(ACTIONS_PATH); -fs.writeFileSync(ACTIONS_PATH, prependWarning(actions, 'scripts/handlebars/templates/api.hbs')); -console.log(ACTIONS_PATH + ' generated.'); - -const FORMATS_PATH = './docs/formats.md'; -const formats = jsdoc2md.renderSync({ - files: ['lib/common/formats.js', 'lib/register/format.js', 'lib/common/formatHelpers/*.js'], - template: fs.readFileSync('scripts/handlebars/templates/formats.hbs').toString(), - 'no-gfm': true, - separators: true, - partial: ['scripts/handlebars/header.hbs', 'scripts/handlebars/body.hbs'], - configure: '.jsdoc.json', -}); - -fs.ensureFileSync(FORMATS_PATH); -fs.writeFileSync(FORMATS_PATH, prependWarning(formats, 'scripts/handlebars/templates/api.hbs')); -console.log(FORMATS_PATH + ' generated.'); - -execSync(`npm run format:prettier`); -execSync(`git add ./docs/`); diff --git a/scripts/handlebars/body.hbs b/scripts/handlebars/body.hbs deleted file mode 100644 index 5800bd636..000000000 --- a/scripts/handlebars/body.hbs +++ /dev/null @@ -1,28 +0,0 @@ -{{#if (equal kind "function")}}> {{>sig-name}}{{/if}} - -{{>deprecated~}} -{{>description~}} -{{>summary~}} -{{>augments~}} -{{>implements~}} -{{>mixes~}} -{{>default~}} -{{>chainable~}} -{{>overrides~}} -{{>returns~}} -{{>throws~}} -{{>fires~}} -{{>this~}} -{{>readOnly~}} -{{>requires~}} -{{>customTags~}} -{{>see~}} -{{>since~}} -{{>version~}} -{{>authors~}} -{{>license~}} -{{>copyright~}} -{{>todo~}} -{{>params~}} -{{>properties~}} -{{>examples~}} diff --git a/scripts/handlebars/header.hbs b/scripts/handlebars/header.hbs deleted file mode 100644 index 559372a5b..000000000 --- a/scripts/handlebars/header.hbs +++ /dev/null @@ -1,2 +0,0 @@ -{{>heading-indent}} -{{#if typicalname}}{{{typicalname}}}{{else}}{{{name}}} {{/if}} diff --git a/scripts/handlebars/sig-name.hbs b/scripts/handlebars/sig-name.hbs deleted file mode 100644 index c36857eab..000000000 --- a/scripts/handlebars/sig-name.hbs +++ /dev/null @@ -1,19 +0,0 @@ -{{#if virtual}}*{{/if}}{{#with (parentObject)}}{{#if virtual}}*{{/if~}}{{/with~}} -{{#if name}}{{#sig~}} -{{{@depOpen}~}} -{{{@codeOpen}~}} -{{#if @prefix}}{{@prefix}} {{/if~}} -{{@parent~}} -{{@accessSymbol}}{{#if (isEvent)}}"{{{name}}}"{{else}}{{{name}}}{{/if~}} -{{#if @methodSign}}{{#if (isEvent)}} {{@methodSign}}{{else}}{{@methodSign}}{{/if}}{{/if~}} -{{{@codeClose}~}} -{{#if @returnSymbol}} {{@returnSymbol}}{{/if~}} -{{#if @returnTypes}} {{>linked-type-list types=@returnTypes delimiter=" \| " }}{{/if~}} -{{#if @suffix}} {{@suffix}}{{/if~}} -{{{@depClose}~}} -{{~/sig}} - -{{/if}} -{{#if virtual}}*{{/if}}{{#with (parentObject)}}{{#if virtual}}*{{/if}} - -{{/with}} diff --git a/scripts/handlebars/templates/actions.hbs b/scripts/handlebars/templates/actions.hbs deleted file mode 100644 index 3eccc0e51..000000000 --- a/scripts/handlebars/templates/actions.hbs +++ /dev/null @@ -1,31 +0,0 @@ -# Actions - -Actions provide a way to run custom build code such as generating binary assets like images. - -Here are all the actions that come with the Style Dictionary build system. We try to include what most people might need. If you think we are missing some things, take a look at our [contributing docs](https://github.com/amzn/style-dictionary/blob/main/CONTRIBUTING.md) and send us a pull request! If you have a specific need for your project, you can always create your own custom action with [`registerAction`](api.md?id=registeraction). - -You use actions in your config file under platforms > [platform] > actions - -```json -{ - "source": ["tokens/**/*.json"], - "platforms": { - "android": { - "transformGroup": "android", - "files": [], - "actions": ["copy_assets"] - } - } -} -``` - - ----- - -## Pre-defined Actions - -[lib/common/actions.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/actions.js) - -{{#namespace name="Actions"}} -{{>members~}} -{{/namespace}} \ No newline at end of file diff --git a/scripts/handlebars/templates/api.hbs b/scripts/handlebars/templates/api.hbs deleted file mode 100644 index ea7fde106..000000000 --- a/scripts/handlebars/templates/api.hbs +++ /dev/null @@ -1,5 +0,0 @@ -# API - -{{#module name="style-dictionary"}} -{{>members}} -{{/module}} diff --git a/scripts/handlebars/templates/formats.hbs b/scripts/handlebars/templates/formats.hbs deleted file mode 100644 index 95967fa09..000000000 --- a/scripts/handlebars/templates/formats.hbs +++ /dev/null @@ -1,361 +0,0 @@ -# Formats - -Formats define the output of your created files. For example, to use your styles in CSS -you use the `css/variables` format. This will create a CSS file containing the variables from -your style dictionary. - -## Using formats - -You use formats in your config file under platforms > [platform] > files > [file] > format - -```json -{ - "source": ["tokens/**/*.json"], - "platforms": { - "css": { - "transformGroup": "css", - "files": [ - { - "format": "css/variables", - "destination": "variables.css" - } - ] - } - } -} -``` - -There is an extensive (but not exhaustive) list of [included formats](#pre-defined-formats) available in Style Dictionary. - -## Format configuration - -Formats can take configuration to make them more flexible. This allows you to re-use the same format multiple times with different configurations or to allow the format to use data not defined in the tokens themselves. To configure a format, add extra attributes on the file object in your configuration like the following: - -```json -{ - "source": ["tokens/**/*.json"], - "platforms": { - "scss": { - "transformGroup": "scss", - "files": [{ - "destination": "map.scss", - "format": "scss/map-deep", - "mapName": "my-tokens" - }] - } - } -} -``` - -In this example we are adding the `mapName` configuration to the `scss/map-deep` format. This will change the name of the SCSS map in the output. Not all formats have the configuration options; format configuration is defined by the format itself. To see the configuration options of a format, take a look at the documentation of the [specific format](#pre-defined-formats) - -## Filtering tokens - -A special file configuration is `filter`, which will filter the tokens before they get to the format. This allows you to re-use the same format to generate multiple files with different sets of tokens. Filtering tokens works by adding a `filter` attribute on the file object, where `filter` is: - -* An object which gets passed to [Lodash's filter method](https://lodash.com/docs/4.17.14#filter). -* A string that references the name of a registered filter, using the [`registerFilter`](api.md#registerfilter) method -* A function that takes a token and returns a boolean if the token should be included (true) or excluded (false). **This is only available if you are defining your configuration in Javascript.** - -```javascript -{ - "destination": "destination", - "format": "myCustomFormat", - "filter": "myCustomFilter", // a named filter defined with .registerFilter - "filter": function(token) {}, // an inline function - "filter": {} // an object pass to lodash's filter method -} -``` - -The design token that is passed to the filter function has already been [transformed](transforms.md) and has [default metadata](tokens.md?id=default-design-token-metadata) added by Style Dictionary. - -## References in output files - -Starting with version 3.0, some formats can keep the references in the output. This is a bit hard to explain, so let's look at an example. Say you have this very basic set of design tokens: - -```json5 -// tokens.json -{ - "color": { - "red": { "value": "#ff0000" }, - "danger": { "value": "{color.red.value}" }, - "error": { "value": "{color.danger.value}" } - } -} -``` - -With this configuration: - -```json5 -// config.json -{ - "source": ["tokens.json"] - "platforms": { - "css": { - "transformGroup": "css", - "files": [{ - "destination": "variables.css", - "format": "css/variables", - "options": { - // Look here 👇 - "outputReferences": true - } - }] - } - } -} -``` - -This would be the output: - -```css -:root { - --color-red: #ff0000; - --color-danger: var(--color-red); - --color-error: var(--color-danger); -} -``` - -The css variables file now keeps the references you have in your Style Dictionary! This is useful for outputting themeable and dynamic code. - -Without `outputReferences: true` Style Dictionary would resolve all references and the output would be: - -```css -:root { - --color-red: #ff0000; - --color-danger: #ff0000; - --color-error: #ff0000; -} -``` - -Not all formats use the `outputReferences` option because that file format might not support it (like JSON for example). The current list of formats that handle `outputReferences`: - -* [css/variables](#cssvariables) -* [scss/variables](#scssvariables) -* [less/variables](#lessvariables) -* [android/resources](#androidresources) -* [compose/object](#composeobject) -* [ios-swift/class.swift](#ios-swiftclassswift) -* [flutter/class.dart](#flutterclassdart) - -You can create custom formats that output references as well. See the [Custom format with output references](#custom-format-with-output-references) section. - -## File headers - -By default Style Dictionary adds a file header comment in the top of files built using built-in formats like this: - -```js -// Do not edit directly -// Generated on Sat, 01 Jan 2000 00:00:00 GMT -``` - -You can remove these comments with the option: `showFileHeader: false` if you do not want them in your generated files. You can also create your own file header or extend the default one. This could be useful if you want to put a version number or hash of the source files rather than a timestamp. - -Custom file headers can be added the same way you would add a custom format, either by using the [`registerFileHeader`](api.md#registerfileheader) function or adding the fileHeader object directly in the Style Dictionary [configuration](config.md). Your custom file header can be used in built-in formats as well as custom formats. To use a custom file header in a custom format see the [`fileHeader`](formats.md#fileheader) format helper method. - -```js -const StyleDictionary = require('style-dictionary'); -StyleDictionary.registerFileHeader({ - name: 'myCustomHeader', - fileHeader: (defaultMessage) => { - // defaultMessage are the 2 lines above that appear in the default file header - // you can use this to add a message before or after the default message 👇 - - // the fileHeader function should return an array of strings - // which will be formatted in the proper comment style for a given format - return [ - ...defaultMessage, - `hello?`, - `is it me you're looking for?`, - ] - } -}); -``` - -Then you can use your custom file header in a file similar to a custom format: - -```json5 -{ - source: ['tokens/**/*.json'], - platforms: { - css: { - transformGroup: 'css', - files: [{ - destination: 'variables.css', - format: 'css/variables', - options: { - fileHeader: 'myCustomHeader' - } - }] - } - } -} -``` - -Which should output a file that will start like this: - -```css -/** - * Do not edit directly - * Generated on Thu, 18 Mar 2021 21:30:47 GMT - * hello? - * is it me you're looking for? - */ -``` - -For an in-depth example see the [custom-file-header](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/custom-file-header) example. - -## Custom formats - -You can create custom formats using the [`registerFormat`](api.md#registerformat) function or by directly including them in your [configuration](config.md). A format has a name and a formatter function, which takes an object as the argument and should return a string which is then written to a file. - -{{#module name="format"}} -{{>members}} -{{/module}} - -To use your custom format, you call it by name in the file configuration object: - -```json -{ - "source": ["tokens/**/*.json"], - "platforms": { - "css": { - "options": { - "showFileHeader": true - }, - "transformGroup": "css", - "files": [{ - "destination": "destination", - "format": "myCustomFormat", - "options": { - "showFileHeader": false - } - }] - } - } -} -``` - -It is recommended for any configuration needed for your custom format to use the `options` object. Style Dictionary will merge platform and file options so that in your Style Dictionary configuration you can specify options at a platform or file level. In the configuration above, the `options` object passed to the formatter would have `showFileHeader: false`. - -
-Note: to support legacy ways of defining custom formats, this in the formatter function is bound to the file object and when Style Dictionary calls the formatter function it passes 3 arguments: dictionary, platform, and file. Starting in 3.0 all data the formatter needs is in the first argument as shown above to make it easier to grab the arguments by name rather than by position. We recommend not using this or the positional arguments in your custom format. -
- -## Custom format with output references - -To take advantage of outputting references in your custom formats there are 2 helper methods available: `usesReferences(value)` and `getReferences(value, tokens)`. Here is an example using those: - -```javascript -import { getReferences, usesReferences } from 'style-dictionary/utils'; - -StyleDictionary.registerFormat({ - name: `es6WithReferences`, - formatter: function({dictionary}) { - return dictionary.allTokens.map(token => { - let value = JSON.stringify(token.value); - // the `dictionary` object now has `usesReferences()` and - // `getReferences()` methods. `usesReferences()` will return true if - // the value has a reference in it. `getReferences()` will return - // an array of references to the whole tokens so that you can access their - // names or any other attributes. - if (usesReferences(token.original.value)) { - // Note: make sure to use `token.original.value` because - // `token.value` is already resolved at this point. - const refs = getReferences(token.original.value, dictionary.tokens); - refs.forEach(ref => { - value = value.replace(ref.value, function() { - return `${ref.name}`; - }); - }); - } - return `export const ${token.name} = ${value};` - }).join(`\n`) - } -}); -``` - -## Custom format helpers - -We provide some helper methods we use internally in some of the built-in formats to make building custom formats a bit easier. They are accessible at `StyleDictionary.formatHelpers`. - -```javascript -const StyleDictionary = require('style-dictionary'); - -const { fileHeader, formattedVariables } = StyleDictionary.formatHelpers; - -StyleDictionary.registerFormat({ - name: 'myCustomFormat', - formatter: function({dictionary, file, options}) { - const { outputReferences } = options; - return fileHeader({file}) + - ':root {\n' + - formattedVariables({format: 'css', dictionary, outputReferences}) + - '\n}\n'; - } -}); -``` - -Here are the available format helper methods: - -{{#module name="formatHelpers"}} -{{>members}} -{{/module}} - -## Using a template / templating engine to create a format - -Formatters are functions and created easily with most templating engines. Formats can be built using templates if there is a lot of boilerplate code to insert (e.g. ObjectiveC files). If the output consists of only the values (e.g. a flat SCSS variables file), writing a formatter function directly may be easier. - -Any templating language can work as long as there is a node module for it. All you need to do is register a format that calls your template and returns a string. - -Here is a quick example for Lodash. - -```js -import StyleDictionary from 'style-dictionary'; -const sd = await StyleDictionary.extend('config.json'); -const _ = require('lodash'); - -const template = _.template( fs.readFileSync('templates/myFormat.template') ); - -sd.registerFormat({ - name: 'my/format', - formatter: template -}); - -// format: 'my/format' is now available for use... -``` - -And another example for Handlebars. - -```js -import StyleDictionary from 'style-dictionary'; -const sd = await StyleDictionary.extend('config.json'); -const Handlebars = require('handlebars'); - -const template = Handlebars.compile( fs.readFileSync('templates/MyTemplate.hbs').toString() ); - -sd.registerFormat({ - name: 'my/format', - formatter: function({dictionary, platform}) { - return template({ - tokens: dictionary.tokens, - options: platform - }); - } -}); - -// format: 'my/format' is now available for use... -``` - ----- - -## Pre-defined Formats - -These are the formats included in Style Dictionary by default, pulled from [lib/common/formats.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/formats.js) - -Want a format? [You can request it here](https://github.com/amzn/style-dictionary/issues). - -You created a format and think it should be included? [Send us a PR](https://github.com/amzn/style-dictionary/pulls). - - -{{#namespace name="Formats"}}{{>members~}}{{/namespace}} diff --git a/scripts/handlebars/templates/transform_groups.hbs b/scripts/handlebars/templates/transform_groups.hbs deleted file mode 100644 index ad38050aa..000000000 --- a/scripts/handlebars/templates/transform_groups.hbs +++ /dev/null @@ -1,26 +0,0 @@ -# Transform Groups - -Transform Groups are a way to easily use multiple transforms at once. They are an array of transforms. You can define a custom transform group with the [`registerTransformGroup`](api.md#registertransformgroup). - -You use transformGroups in your config file under platforms > [platform] > transformGroup - -```json -{ - "source": ["tokens/**/*.json"], - "platforms": { - "android": { - "transformGroup": "android" - } - } -} -``` - ----- - -## Pre-defined Transform groups - -[lib/common/transformGroups.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/transformGroups.js) - -{{#namespace name="TransformGroups"}} -{{>members~}} -{{/namespace}} diff --git a/scripts/handlebars/templates/transforms.hbs b/scripts/handlebars/templates/transforms.hbs deleted file mode 100644 index 9e7295ea9..000000000 --- a/scripts/handlebars/templates/transforms.hbs +++ /dev/null @@ -1,95 +0,0 @@ -# Transforms - -Transforms are functions that modify a [token](tokens.md) so that it can be understood by a specific platform. It can modify the name, value, or attributes of a token - enabling each platform to use the design token in different ways. A simple example is changing pixel values to point values for iOS and dp or sp for Android. - -Transforms are isolated per platform; each platform begins with the same design token and makes the modifications it needs without affecting other platforms. The order you use transforms matters because transforms are performed sequentially. Transforms are used in your [configuration](config.md), and can be either [pre-defined transforms](transforms.md?id=pre-defined-transforms) supplied by Style Dictionary or [custom transforms](transforms.md?id=defining-custom-transforms). - -Some platform configuration attributes apply a broader effect over the transforms applied. For example, the `size/remToDp` transform will scale a number by 16, or by the value of `options.basePxFontSize` if it is present. Check individual transform documentation to see where this is applicable. - - - -## Using Transforms -You use transforms in your config file under platforms > [platform] > transforms - -```json -{ - "source": ["tokens/**/*.json"], - "platforms": { - "android": { - "transforms": ["attribute/cti", "name/kebab", "color/hex", "size/rem"] - } - } -} -``` - -A transform consists of 4 parts: type, name, matcher, and transformer. Transforms are run on all design tokens where the matcher returns true. *NOTE: if you don't provide a matcher function, it will match all tokens.* - -## Transform Types -There are 3 types of transforms: attribute, name, and value. - -**Attribute:** An attribute transform adds to the attributes object on a design token. This is for including any meta-data about a design token such as it's CTI or other information. - -**Name:** A name transform transforms the name of a design token. You should really only be applying one name transformer because they will override each other if you use more than one. - -**Value:** The value transform is the most important as this is the one that changes the representation of the value. Colors can be turned into hex values, rgb, hsl, hsv, etc. Value transforms have a matcher function that filter which tokens that transform runs on. This allows us to only run a color transform on only the colors and not every design token. - -## Defining Custom Transforms -You can define custom transforms with the [`registerTransform`](api.md#registertransform). Style Dictionary adds some [default metadata](tokens.md?id=default-design-token-metadata) to each design token to provide context that may be useful for some transforms. - -## Transitive Transforms -Starting in version 3.0, you can define transitive transforms which allow you to transform a referenced value. Normally, value transforms only transform non-referenced values and because transforms happen before references are resolved, the transformed value is then used to resolve references. - -```javascript -const StyleDictionary = require('style-dictionary'); - -StyleDictionary.registerTransform({ - type: `value`, - transitive: true, - name: `myTransitiveTransform`, - matcher: (token) => {}, - transformer: (token) => { - // token.value will be resolved and transformed at this point - } -}) -``` - -There is one thing to be mindful of with transitive transforms. The token's value will be resolved and *transformed* already at the time the transitive transform. What happens is Style Dictionary will transform and resolve values iteratively. First it will transform any non-referenced values, then it will resolve any references to non-referenced values, then it will try to transform any non-referenced values, and so on. Let's take a look at an example: - -```json -{ - "color": { - "red": { "value": "#f00" }, - "danger": { "value": "{color.red}" }, - "error": { "value": "{color.danger}" } - } -} -``` - -Style dictionary will first transform the value of `color.red`, then resolve `color.danger` to the transformed `color.red` value. Then it will transform `color.danger` and resolve `color.error` to the transformed `color.danger`. Finally, it will transform `color.error` and see that there is nothing left to transform or resolve. - -This allows you to modify a reference that modifies another reference. For example: - -```json -{ - "color": { - "red": { "value": "#f00" }, - "danger": { "value": "{color.red}", "darken": 0.75 }, - "error": { "value": "{color.danger}", "darken": 0.5 } - } -} -``` - -Using a custom transitive transform you could have `color.danger` darken `color.red` and `color.error` darken `color.danger`. The pre-defined transforms are *not transitive* to be backwards compatible with Style Dictionary v2 - an upgrade should not cause breaking changes. - -If you want to learn more about transitive transforms, take a look at the [transitive transforms example](https://github.com/amzn/style-dictionary/tree/main/examples/advanced/transitive-transforms). - - -## Pre-defined Transforms - -[lib/common/transforms.js](https://github.com/amzn/style-dictionary/blob/main/lib/common/transforms.js) - -> All the pre-defined transforms included use the [CTI structure](tokens.md?id=category-type-item) for matching tokens. If you structure your design tokens differently you will need to write [custom transforms](transforms.md?id=defining-custom-transforms) or make sure the proper CTIs are on the attributes of your design tokens. - -{{#namespace name="Transforms"}} -{{>members~}} -{{/namespace}} diff --git a/types/Format.d.ts b/types/Format.d.ts index 835b84969..44f7abd92 100644 --- a/types/Format.d.ts +++ b/types/Format.d.ts @@ -11,7 +11,7 @@ * and limitations under the License. */ -import type { Dictionary } from './DesignToken.d.ts'; +import type { Dictionary, TransformedToken } from './DesignToken.d.ts'; import type { File } from './File.d.ts'; import type { LocalOptions, Config, PlatformConfig } from './Config.d.ts'; @@ -46,3 +46,7 @@ export interface Format { name: string; formatter: Formatter; } + +export type OutputReferences = + | ((token: TransformedToken, options: { dictionary: Dictionary; usesDtcg?: boolean }) => boolean) + | boolean; diff --git a/types/index.d.ts b/types/index.d.ts index 2499aefa9..8c3872a75 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -7,14 +7,14 @@ export type { DesignTokens, TransformedToken, TransformedTokens, - Dictionary + Dictionary, } from './DesignToken.d.ts'; export type { FileHeader, File, FormattingOptions } from './File.d.ts'; export type { Filter, Matcher } from './Filter.d.ts'; -export type { Format, FormatterArguments, Formatter } from './Format.d.ts'; +export type { Format, FormatterArguments, Formatter, OutputReferences } from './Format.d.ts'; export type { Parser, ParserOptions } from './Parser.d.ts';