diff --git a/.changeset/dirty-grapes-deliver.md b/.changeset/dirty-grapes-deliver.md new file mode 100644 index 000000000..4b9183e21 --- /dev/null +++ b/.changeset/dirty-grapes-deliver.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Make `defaultMessage` param in FileHeader type optional. diff --git a/.changeset/tall-comics-grow.md b/.changeset/tall-comics-grow.md new file mode 100644 index 000000000..9cc75213d --- /dev/null +++ b/.changeset/tall-comics-grow.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +(#1305): fix reference sorting in `sortByReference` function for DTCG token format, ensuring token references are declared after their targets diff --git a/.changeset/wicked-pears-eat.md b/.changeset/wicked-pears-eat.md new file mode 100644 index 000000000..5d69e1754 --- /dev/null +++ b/.changeset/wicked-pears-eat.md @@ -0,0 +1,5 @@ +--- +'style-dictionary': patch +--- + +Fix `filterTokens` utility to deal with random metadata properties throughout token groups, without throwing errors. diff --git a/__integration__/__snapshots__/outputReferences.test.snap.js b/__integration__/__snapshots__/outputReferences.test.snap.js index 03ff1092d..5e6a8dc65 100644 --- a/__integration__/__snapshots__/outputReferences.test.snap.js +++ b/__integration__/__snapshots__/outputReferences.test.snap.js @@ -1,7 +1,7 @@ /* @web/test-runner snapshot v1 */ export const snapshots = {}; -snapshots["integration output references should warn the user if filters out references briefly"] = +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. @@ -9,7 +9,7 @@ Use log.verbosity "verbose" or use CLI option --verbose for more details. Refer to: https://styledictionary.com/reference/logging/`; /* end snapshot integration output references should warn the user if filters out references briefly */ -snapshots["integration output references should warn the user if filters out references with a detailed message when using verbose logging"] = +snapshots["integration output references should warn the user if filters out references with a detailed message when using verbose logging"] = `⚠️ __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: @@ -23,13 +23,13 @@ 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"] = +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 */ -snapshots["integration output references should allow using outputReferencesTransformed to not output refs when value has been transitively transformed"] = +snapshots["integration output references should allow using outputReferencesTransformed to not output refs when value has been transitively transformed"] = `/** * Do not edit directly, this file was auto-generated. */ @@ -41,3 +41,15 @@ snapshots["integration output references should allow using outputReferencesTran `; /* end snapshot integration output references should allow using outputReferencesTransformed to not output refs when value has been transitively transformed */ +snapshots["integration output references should properly reference tokens in dtcg format"] = +`/** + * Do not edit directly, this file was auto-generated. + */ + +:root { + --base: #ff0000; + --referred: var(--base); +} +`; +/* end snapshot integration output references should properly reference tokens in dtcg format */ + diff --git a/__integration__/outputReferences.test.js b/__integration__/outputReferences.test.js index 1fde83684..0013f63c7 100644 --- a/__integration__/outputReferences.test.js +++ b/__integration__/outputReferences.test.js @@ -176,5 +176,41 @@ describe('integration', async () => { await sd.buildAllPlatforms(); await expect(stub.lastCall.args.map(cleanConsoleOutput).join('\n')).to.matchSnapshot(); }); + + it('should properly reference tokens in dtcg format', async () => { + const sd = new StyleDictionary({ + tokens: { + base: { + $value: '#FF0000', + $type: 'color', + }, + referred: { + $value: '{base}', + $type: 'color', + }, + }, + platforms: { + css: { + transformGroup: 'css', + buildPath, + files: [ + { + destination: 'dtcgOutputRef.css', + format: 'css/variables', + options: { + outputReferences: true, + usesDtcg: true, + }, + }, + ], + }, + }, + }); + await sd.buildAllPlatforms(); + const output = fs.readFileSync(resolve(`${buildPath}dtcgOutputRef.css`), { + encoding: 'UTF-8', + }); + await expect(output).to.matchSnapshot(); + }); }); }); diff --git a/__tests__/common/formatHelpers/sortByReference.test.js b/__tests__/common/formatHelpers/sortByReference.test.js new file mode 100644 index 000000000..5da5e75c6 --- /dev/null +++ b/__tests__/common/formatHelpers/sortByReference.test.js @@ -0,0 +1,110 @@ +/* + * 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 sortByReference from '../../../lib/common/formatHelpers/sortByReference.js'; + +const TRANSFORMED_TOKENS = (usesDtcg) => { + const valueKey = usesDtcg ? '$value' : 'value'; + const typeKey = usesDtcg ? '$type' : 'type'; + + return { + color: { + primary: { + [valueKey]: '#FF0000', + [typeKey]: 'color', + original: { + [valueKey]: '{color.red}', + [typeKey]: 'color', + }, + }, + red: { + [valueKey]: '#FF0000', + [typeKey]: 'color', + original: { + [valueKey]: '#FF0000', + [typeKey]: 'color', + }, + }, + }, + }; +}; + +describe('common', () => { + describe('formatHelpers', () => { + describe('sortByReference', () => { + [ + ['default', false, TRANSFORMED_TOKENS(false)], + ['dtcg', true, TRANSFORMED_TOKENS(true)], + ].forEach(([tokenFormat, usesDtcg, tokens]) => { + it(`should keep order when idx0 has no reference(${tokenFormat})`, () => { + const allTokens = [tokens.color.red, tokens.color.primary]; + + const sorted = [...allTokens].sort( + sortByReference(tokens, { + usesDtcg, + }), + ); + + expect(sorted).to.eql([tokens.color.red, tokens.color.primary]); + }); + it(`should reorder, if idx0 references idx1 (${tokenFormat})`, () => { + const allTokens = [tokens.color.primary, tokens.color.red]; + + const sorted = [...allTokens].sort( + sortByReference(tokens, { + usesDtcg, + }), + ); + + expect(sorted).to.eql([tokens.color.red, tokens.color.primary]); + }); + }); + it('should reorder when idx0 is undefined', () => { + const tokens = TRANSFORMED_TOKENS(false); + const tokensWithAnUndefinedValue = { + ...tokens, + color: { ...tokens.color, primary: undefined }, + }; + const allTokens = [ + tokensWithAnUndefinedValue.color.primary, + tokensWithAnUndefinedValue.color.red, + ]; + + const sorted = [...allTokens].sort(sortByReference(tokensWithAnUndefinedValue)); + + expect(sorted).to.eql([ + tokensWithAnUndefinedValue.color.red, + tokensWithAnUndefinedValue.color.primary, + ]); + }); + it('should keep order when idx1 is undefined', () => { + const tokens = TRANSFORMED_TOKENS(false); + const tokensWithUndefinedValue = { + ...tokens, + color: { ...tokens.color, primary: undefined }, + }; + const allTokens = [ + tokensWithUndefinedValue.color.red, + tokensWithUndefinedValue.color.primary, + ]; + + const sorted = [...allTokens].sort(sortByReference(tokensWithUndefinedValue)); + + expect(sorted).to.eql([ + tokensWithUndefinedValue.color.red, + tokensWithUndefinedValue.color.primary, + ]); + }); + }); + }); +}); diff --git a/__tests__/filterTokens.test.js b/__tests__/filterTokens.test.js index 1d3ef4820..c643b7f8e 100644 --- a/__tests__/filterTokens.test.js +++ b/__tests__/filterTokens.test.js @@ -86,6 +86,46 @@ const tokens = { }, }; +const random_meta_tokens = { + description: null, + meta: undefined, + more_meta: [], + foo: { + description: null, + meta: undefined, + more_meta: [], + bar: { + description: null, + meta: undefined, + more_meta: [], + value: 0, + type: 'number', + original: { + value: 0, + }, + name: 'foo-bar', + path: ['foo', 'bar'], + }, + }, + qux: { + description: null, + meta: undefined, + more_meta: [], + value: 0, + type: 'number', + original: { + value: 0, + }, + name: 'qux', + path: ['qux'], + }, +}; + +const random_meta_dictionary = { + tokens: random_meta_tokens, + allTokens: flattenTokens(random_meta_tokens), +}; + const falsy_values = { kept: kept, not_kept: not_kept, @@ -115,11 +155,11 @@ describe('filterTokens', () => { }); it('should work with a filter function', async () => { - const filter = (property) => property.path.includes('size'); + const filter = (token) => token.path.includes('size'); const filteredDictionary = await filterTokens(dictionary, filter); - filteredDictionary.allTokens.forEach((property) => { - expect(property).to.not.equal(colorRed); - expect(property).not.to.not.equal(colorBlue); + filteredDictionary.allTokens.forEach((token) => { + expect(token).to.not.equal(colorRed); + expect(token).not.to.not.equal(colorBlue); }); expect(filteredDictionary.allTokens).to.eql([sizeSmall, sizeLarge]); expect(filteredDictionary.tokens).to.have.property('size'); @@ -127,17 +167,28 @@ describe('filterTokens', () => { }); it('should work with falsy values and a filter function', async () => { - const filter = (property) => property.path.includes('kept'); + const filter = (token) => token.path.includes('kept'); const filteredDictionary = await filterTokens(falsy_dictionary, filter); - filteredDictionary.allTokens.forEach((property) => { - expect(property).to.not.equal(not_kept); + filteredDictionary.allTokens.forEach((token) => { + expect(token).to.not.equal(not_kept); }); expect(filteredDictionary.allTokens).to.eql([kept]); expect(filteredDictionary.tokens).to.have.property('kept'); expect(filteredDictionary.tokens).to.not.have.property('not_kept'); }); + it('should work with random metadata props inside tokens / token groups', async () => { + const filter = (token) => { + return token.path.includes('bar'); + }; + + const filteredDictionary = await filterTokens(random_meta_dictionary, filter); + expect(filteredDictionary.allTokens).to.eql([random_meta_tokens.foo.bar]); + expect(filteredDictionary.tokens).to.have.nested.property('foo.bar'); + expect(filteredDictionary.tokens).to.not.have.property('qux'); + }); + it('should work with async filters', async () => { const filtered = await filterTokens(dictionary, async (token) => { await new Promise((resolve) => setTimeout(resolve, 100)); diff --git a/__tests__/utils/reference/resolveReferences.test.js b/__tests__/utils/reference/resolveReferences.test.js index 819af33aa..552c33a14 100644 --- a/__tests__/utils/reference/resolveReferences.test.js +++ b/__tests__/utils/reference/resolveReferences.test.js @@ -197,7 +197,7 @@ describe('utils', () => { }); describe('ignorePaths', () => { - it('should not resolve values containing constiables in ignored paths', () => { + it('should not resolve values containing variables in ignored paths', () => { const obj = { foo: { value: 'bar' }, bar: { diff --git a/__tests__/utils/resolveObject.test.js b/__tests__/utils/resolveObject.test.js index 0df0ca8bc..030d46d66 100644 --- a/__tests__/utils/resolveObject.test.js +++ b/__tests__/utils/resolveObject.test.js @@ -187,7 +187,7 @@ describe('utils', () => { }); describe('ignorePaths', () => { - it('should not resolve values containing constiables in ignored paths', () => { + it('should not resolve values containing variables in ignored paths', () => { const test = resolveObject( { foo: { value: 'bar' }, diff --git a/lib/common/formatHelpers/fileHeader.js b/lib/common/formatHelpers/fileHeader.js index 048cf58c7..8bb397bdd 100644 --- a/lib/common/formatHelpers/fileHeader.js +++ b/lib/common/formatHelpers/fileHeader.js @@ -67,7 +67,7 @@ export default async function fileHeader({ file, commentStyle, formatting = {}, /** * @type {FileHeader} */ - let fn = (arr) => arr; + let fn = (arr) => arr ?? []; if (file?.options?.fileHeader && typeof file?.options?.fileHeader !== 'string') { fn = file.options.fileHeader; } diff --git a/lib/common/formatHelpers/formattedVariables.js b/lib/common/formatHelpers/formattedVariables.js index f37397915..60d3d5521 100644 --- a/lib/common/formatHelpers/formattedVariables.js +++ b/lib/common/formatHelpers/formattedVariables.js @@ -80,7 +80,7 @@ export default function formattedVariables({ // note: using the spread operator here so we get a new array rather than // mutating the original allTokens = [...allTokens].sort( - sortByReference(tokens, { unfilteredTokens: dictionary.unfilteredTokens }), + sortByReference(tokens, { unfilteredTokens: dictionary.unfilteredTokens, usesDtcg }), ); } diff --git a/lib/common/formatHelpers/sortByReference.js b/lib/common/formatHelpers/sortByReference.js index ef04c94e4..732eb08bd 100644 --- a/lib/common/formatHelpers/sortByReference.js +++ b/lib/common/formatHelpers/sortByReference.js @@ -19,6 +19,9 @@ import { getReferences } from '../../utils/references/getReferences.js'; * @typedef {import('../../../types/DesignToken.ts').TransformedToken} Token */ +const A_COMES_FIRST = -1; +const B_COMES_FIRST = 1; + /** * A function that returns a sorting function to be used with Array.sort that * will sort the allTokens array based on references. This is to make sure @@ -31,66 +34,62 @@ import { getReferences } from '../../utils/references/getReferences.js'; * dictionary.allTokens.sort(sortByReference(dictionary)) * ``` * @param {Tokens} tokens - * @param {{unfilteredTokens?: Tokens}} [opts] + * @param {{unfilteredTokens?: Tokens, usesDtcg?: boolean}} [opts] * @returns {(a: Token, b: Token) => number} */ -export default function sortByReference(tokens, opts) { +export default function sortByReference(tokens, { unfilteredTokens, usesDtcg } = {}) { + const valueKey = usesDtcg ? '$value' : 'value'; + /** * The sorter function is recursive to account for multiple levels of nesting * @param {Token} a * @param {Token} b - * @returns + * @returns {number} */ function sorter(a, b) { - const aComesFirst = -1; - const bComesFirst = 1; - - // return early if a or b ar undefined if (typeof a === 'undefined') { - return aComesFirst; - } else if (typeof b === 'undefined') { - return bComesFirst; + return A_COMES_FIRST; + } + if (typeof b === 'undefined') { + return B_COMES_FIRST; } - // If token a uses a reference and token b doesn't, b might come before a - // read on.. - if (a.original && usesReferences(a.original.value)) { - // Both a and b have references, we need to see if they reference each other - if (b.original && usesReferences(b.original.value)) { - const aRefs = getReferences(a.original.value, tokens, { - unfilteredTokens: opts?.unfilteredTokens, - warnImmediately: false, - }); - const bRefs = getReferences(b.original.value, tokens, { - unfilteredTokens: opts?.unfilteredTokens, - warnImmediately: false, - }); - - aRefs.forEach((aRef) => { - // a references b, we want b to come first - if (aRef.name === b.name) { - return bComesFirst; - } - }); + const aUsesRefs = a.original && usesReferences(a.original[valueKey]); + const bUsesRefs = b.original && usesReferences(b.original[valueKey]); - bRefs.forEach((bRef) => { - // ditto but opposite - if (bRef.name === a.name) { - return aComesFirst; - } - }); + // -----BOTH REFERENCE----- + if (aUsesRefs && bUsesRefs) { + // Collect references for 'a' and 'b' + const aRefs = getReferences(a.original[valueKey], tokens, { + unfilteredTokens, + warnImmediately: false, + }); + const bRefs = getReferences(b.original[valueKey], tokens, { + unfilteredTokens, + warnImmediately: false, + }); - // both a and b have references and don't reference each other - // we go further down the rabbit hole (reference chain) - return sorter(aRefs[0], bRefs[0]); - } else { - // a has a reference and b does not: - return bComesFirst; + // 'a' references 'b' -> 'b' should come first + if (aRefs.some((aRef) => aRef.name === b.name)) { + return B_COMES_FIRST; } - // a does not have a reference it should come first regardless if b has one - } else { - return aComesFirst; + // 'b' references 'a' -> 'a' should come first + if (bRefs.some((bRef) => bRef.name === a.name)) { + return A_COMES_FIRST; + } + + // 'a' and 'b' reference, but not each other. Recurse to next level + return sorter(aRefs[0], bRefs[0]); } + + // ----- ONLY ONE REFERENCES ----- + // 'a' references, 'b' doesn't -> 'b' should come first + if (aUsesRefs) { + return B_COMES_FIRST; + } + + // 'a' doesn't reference. It should come first regardless of 'b' + return A_COMES_FIRST; } return sorter; diff --git a/lib/common/formats.js b/lib/common/formats.js index 080b736ea..88f95345b 100644 --- a/lib/common/formats.js +++ b/lib/common/formats.js @@ -1190,7 +1190,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul let sortedTokens; if (outputReferences) { - sortedTokens = [...allTokens].sort(sortByReference(tokens, { unfilteredTokens })); + sortedTokens = [...allTokens].sort(sortByReference(tokens, { unfilteredTokens, usesDtcg })); } else { sortedTokens = [...allTokens].sort(sortByName); } @@ -1238,7 +1238,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul let sortedTokens; if (outputReferences) { - sortedTokens = [...allTokens].sort(sortByReference(tokens, { unfilteredTokens })); + sortedTokens = [...allTokens].sort(sortByReference(tokens, { unfilteredTokens, usesDtcg })); } else { sortedTokens = [...allTokens].sort(sortByName); } @@ -1297,7 +1297,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul let sortedTokens; if (outputReferences) { - sortedTokens = [...allTokens].sort(sortByReference(tokens, { unfilteredTokens })); + sortedTokens = [...allTokens].sort(sortByReference(tokens, { unfilteredTokens, usesDtcg })); } else { sortedTokens = [...allTokens].sort(sortByName); } @@ -1520,7 +1520,7 @@ declare const ${moduleName}: ${JSON.stringify(treeWalker(dictionary.tokens), nul let sortedTokens; if (outputReferences) { - sortedTokens = [...allTokens].sort(sortByReference(tokens, { unfilteredTokens })); + sortedTokens = [...allTokens].sort(sortByReference(tokens, { unfilteredTokens, usesDtcg })); } else { sortedTokens = [...allTokens].sort(sortByName); } diff --git a/lib/filterTokens.js b/lib/filterTokens.js index 93de1dc0b..966594c6a 100644 --- a/lib/filterTokens.js +++ b/lib/filterTokens.js @@ -48,25 +48,27 @@ async function filterTokenObject(tokens, filter, options) { // out const result = await Object.entries(tokens ?? []).reduce(async (_acc, [key, token]) => { const acc = await _acc; - const tokenValue = options.usesDtcg ? token.$value : token.value; // If the token is not an object, we don't know what it is. We return it as-is. if (!isPlainObject(token)) { return acc; - // If the token has a `value` member we know it's a property, pass it to - // the filter function and either include it in the final `acc` object or - // exclude it (by returning the `acc` object without it added). - } else if (typeof tokenValue !== 'undefined') { - const filtered = await asyncFilter(/** @type {Token[]} */ ([token]), filter, options); - return filtered.length === 0 ? acc : { ...acc, [key]: token }; - // If we got here we have an object that is not a property. We'll assume - // it's an object containing multiple tokens and recursively filter it - // using the `filterTokenObject` function. } else { - const filtered = await filterTokenObject(token, filter, options); - // If the filtered object is not empty then add it to the final `acc` - // object. If it is empty then every property inside of it was filtered - // out, then exclude it entirely from the final `acc` object. - return Object.entries(filtered || {}).length < 1 ? acc : { ...acc, [key]: filtered }; + const tokenValue = options.usesDtcg ? token.$value : token.value; + if (typeof tokenValue === 'undefined') { + // If we got here we have an object that is not a token. We'll assume + // it's token group containing multiple tokens and recursively filter it + // using the `filterTokenObject` function. + const filtered = await filterTokenObject(token, filter, options); + // If the filtered object is not empty then add it to the final `acc` + // object. If it is empty then every token inside of it was filtered + // out, then exclude it entirely from the final `acc` object. + return Object.entries(filtered || {}).length < 1 ? acc : { ...acc, [key]: filtered }; + } else { + // If the token has a `value` member we know it's a token, pass it to + // the filter function and either include it in the final `acc` object or + // exclude it (by returning the `acc` object without it added). + const filtered = await asyncFilter(/** @type {Token[]} */ ([token]), filter, options); + return filtered.length === 0 ? acc : { ...acc, [key]: token }; + } } }, {}); return result; diff --git a/package-lock.json b/package-lock.json index f3c841465..93f892fcc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "style-dictionary", - "version": "4.1.0", + "version": "4.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "style-dictionary", - "version": "4.1.0", + "version": "4.1.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -5388,9 +5388,9 @@ "dev": true }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", - "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.3.tgz", + "integrity": "sha512-MmKSfaB9GX+zXl6E8z4koOr/xU63AMVleLEa64v7R0QF/ZloMs5vcD1sHgM64GXXS1csaJutG+ddtzcueI/BLg==", "cpu": [ "arm" ], @@ -5401,9 +5401,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", - "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.3.tgz", + "integrity": "sha512-zrt8ecH07PE3sB4jPOggweBjJMzI1JG5xI2DIsUbkA+7K+Gkjys6eV7i9pOenNSDJH3eOr/jLb/PzqtmdwDq5g==", "cpu": [ "arm64" ], @@ -5414,9 +5414,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", - "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.3.tgz", + "integrity": "sha512-P0UxIOrKNBFTQaXTxOH4RxuEBVCgEA5UTNV6Yz7z9QHnUJ7eLX9reOd/NYMO3+XZO2cco19mXTxDMXxit4R/eQ==", "cpu": [ "arm64" ], @@ -5427,9 +5427,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", - "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.3.tgz", + "integrity": "sha512-L1M0vKGO5ASKntqtsFEjTq/fD91vAqnzeaF6sfNAy55aD+Hi2pBI5DKwCO+UNDQHWsDViJLqshxOahXyLSh3EA==", "cpu": [ "x64" ], @@ -5440,9 +5440,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", - "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.3.tgz", + "integrity": "sha512-btVgIsCjuYFKUjopPoWiDqmoUXQDiW2A4C3Mtmp5vACm7/GnyuprqIDPNczeyR5W8rTXEbkmrJux7cJmD99D2g==", "cpu": [ "arm" ], @@ -5453,9 +5453,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", - "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.3.tgz", + "integrity": "sha512-zmjbSphplZlau6ZTkxd3+NMtE4UKVy7U4aVFMmHcgO5CUbw17ZP6QCgyxhzGaU/wFFdTfiojjbLG3/0p9HhAqA==", "cpu": [ "arm" ], @@ -5466,9 +5466,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", - "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.3.tgz", + "integrity": "sha512-nSZfcZtAnQPRZmUkUQwZq2OjQciR6tEoJaZVFvLHsj0MF6QhNMg0fQ6mUOsiCUpTqxTx0/O6gX0V/nYc7LrgPw==", "cpu": [ "arm64" ], @@ -5479,9 +5479,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", - "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.3.tgz", + "integrity": "sha512-MnvSPGO8KJXIMGlQDYfvYS3IosFN2rKsvxRpPO2l2cum+Z3exiExLwVU+GExL96pn8IP+GdH8Tz70EpBhO0sIQ==", "cpu": [ "arm64" ], @@ -5492,9 +5492,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", - "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.3.tgz", + "integrity": "sha512-+W+p/9QNDr2vE2AXU0qIy0qQE75E8RTwTwgqS2G5CRQ11vzq0tbnfBd6brWhS9bCRjAjepJe2fvvkvS3dno+iw==", "cpu": [ "ppc64" ], @@ -5505,9 +5505,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", - "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.3.tgz", + "integrity": "sha512-yXH6K6KfqGXaxHrtr+Uoy+JpNlUlI46BKVyonGiaD74ravdnF9BUNC+vV+SIuB96hUMGShhKV693rF9QDfO6nQ==", "cpu": [ "riscv64" ], @@ -5518,9 +5518,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", - "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.3.tgz", + "integrity": "sha512-R8cwY9wcnApN/KDYWTH4gV/ypvy9yZUHlbJvfaiXSB48JO3KpwSpjOGqO4jnGkLDSk1hgjYkTbTt6Q7uvPf8eg==", "cpu": [ "s390x" ], @@ -5531,9 +5531,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", - "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.3.tgz", + "integrity": "sha512-kZPbX/NOPh0vhS5sI+dR8L1bU2cSO9FgxwM8r7wHzGydzfSjLRCFAT87GR5U9scj2rhzN3JPYVC7NoBbl4FZ0g==", "cpu": [ "x64" ], @@ -5544,9 +5544,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", - "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.3.tgz", + "integrity": "sha512-S0Yq+xA1VEH66uiMNhijsWAafffydd2X5b77eLHfRmfLsRSpbiAWiRHV6DEpz6aOToPsgid7TI9rGd6zB1rhbg==", "cpu": [ "x64" ], @@ -5557,9 +5557,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", - "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.3.tgz", + "integrity": "sha512-9isNzeL34yquCPyerog+IMCNxKR8XYmGd0tHSV+OVx0TmE0aJOo9uw4fZfUuk2qxobP5sug6vNdZR6u7Mw7Q+Q==", "cpu": [ "arm64" ], @@ -5570,9 +5570,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", - "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.3.tgz", + "integrity": "sha512-nMIdKnfZfzn1Vsk+RuOvl43ONTZXoAPUUxgcU0tXooqg4YrAqzfKzVenqqk2g5efWh46/D28cKFrOzDSW28gTA==", "cpu": [ "ia32" ], @@ -5583,9 +5583,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", - "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.3.tgz", + "integrity": "sha512-fOvu7PCQjAj4eWDEuD8Xz5gpzFqXzGlxHZozHP4b9Jxv9APtdxL6STqztDzMLuRXEc4UpXGGhx029Xgm91QBeA==", "cpu": [ "x64" ], @@ -19005,9 +19005,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true }, "node_modules/picomatch": { @@ -19179,9 +19179,9 @@ } }, "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -19199,8 +19199,8 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -20527,9 +20527,9 @@ "dev": true }, "node_modules/rollup": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", - "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.3.tgz", + "integrity": "sha512-7sqRtBNnEbcBtMeRVc6VRsJMmpI+JU1z9VTvW8D4gXIYQFz0aLcsE6rRkyghZkLfEgUZgVvOG7A5CVz/VW5GIA==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -20542,22 +20542,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.18.0", - "@rollup/rollup-android-arm64": "4.18.0", - "@rollup/rollup-darwin-arm64": "4.18.0", - "@rollup/rollup-darwin-x64": "4.18.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", - "@rollup/rollup-linux-arm-musleabihf": "4.18.0", - "@rollup/rollup-linux-arm64-gnu": "4.18.0", - "@rollup/rollup-linux-arm64-musl": "4.18.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", - "@rollup/rollup-linux-riscv64-gnu": "4.18.0", - "@rollup/rollup-linux-s390x-gnu": "4.18.0", - "@rollup/rollup-linux-x64-gnu": "4.18.0", - "@rollup/rollup-linux-x64-musl": "4.18.0", - "@rollup/rollup-win32-arm64-msvc": "4.18.0", - "@rollup/rollup-win32-ia32-msvc": "4.18.0", - "@rollup/rollup-win32-x64-msvc": "4.18.0", + "@rollup/rollup-android-arm-eabi": "4.21.3", + "@rollup/rollup-android-arm64": "4.21.3", + "@rollup/rollup-darwin-arm64": "4.21.3", + "@rollup/rollup-darwin-x64": "4.21.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.21.3", + "@rollup/rollup-linux-arm-musleabihf": "4.21.3", + "@rollup/rollup-linux-arm64-gnu": "4.21.3", + "@rollup/rollup-linux-arm64-musl": "4.21.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.21.3", + "@rollup/rollup-linux-riscv64-gnu": "4.21.3", + "@rollup/rollup-linux-s390x-gnu": "4.21.3", + "@rollup/rollup-linux-x64-gnu": "4.21.3", + "@rollup/rollup-linux-x64-musl": "4.21.3", + "@rollup/rollup-win32-arm64-msvc": "4.21.3", + "@rollup/rollup-win32-ia32-msvc": "4.21.3", + "@rollup/rollup-win32-x64-msvc": "4.21.3", "fsevents": "~2.3.2" } }, @@ -21064,9 +21064,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -22701,14 +22701,14 @@ } }, "node_modules/vite": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.2.tgz", - "integrity": "sha512-6lA7OBHBlXUxiJxbO5aAY2fsHHzDr1q7DvXYnyZycRs2Dz+dXBWuhpWHvmljTRTpQC2uvGmUFFkSHF2vGo90MA==", + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz", + "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==", "dev": true, "dependencies": { "esbuild": "^0.21.3", - "postcss": "^8.4.38", - "rollup": "^4.13.0" + "postcss": "^8.4.43", + "rollup": "^4.20.0" }, "bin": { "vite": "bin/vite.js" @@ -22727,6 +22727,7 @@ "less": "*", "lightningcss": "^1.21.0", "sass": "*", + "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" @@ -22744,6 +22745,9 @@ "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, diff --git a/types/File.ts b/types/File.ts index f2b7df30e..bc40d55a2 100644 --- a/types/File.ts +++ b/types/File.ts @@ -25,7 +25,7 @@ export interface FormattingOverrides { } export type FileHeader = ( - defaultMessage: string[], + defaultMessage?: string[], options?: Config, ) => Promise | string[];