diff --git a/.changeset/yellow-zoos-camp.md b/.changeset/yellow-zoos-camp.md new file mode 100644 index 0000000000..55cc68f9b2 --- /dev/null +++ b/.changeset/yellow-zoos-camp.md @@ -0,0 +1,5 @@ +--- +'@digdir/designsystemet': patch +--- + +Make sure the internal order of sections in the CSS generated by the CLI is deterministic, to avoid unnecessary git diffs diff --git a/packages/cli/src/tokens/build/utils/entryfile.ts b/packages/cli/src/tokens/build/utils/entryfile.ts index 78cbb0bdc3..3f316ad1b8 100644 --- a/packages/cli/src/tokens/build/utils/entryfile.ts +++ b/packages/cli/src/tokens/build/utils/entryfile.ts @@ -4,16 +4,49 @@ import glob from 'fast-glob'; import fs from 'fs-extra'; import * as R from 'ramda'; -const sortLightmodeFirst = R.sortWith([R.descend(R.includes('light')), R.descend(R.includes('secondary'))]); +/** + * Defines a sort order for the sections of the entry CSS file. + * This ensures a deterministic order, whereas earlier this was nondeterministic + */ +// biome-ignore format: keep array as one line per item +const sortOrder = [ + 'color-mode/light', + 'typography/secondary', + 'semantic', + 'color-mode/dark', + 'color-mode/contrast', + 'typography/primary', +]; + +const sortByDefinedOrder = R.sortBy((fileName) => { + const sortIndex = sortOrder.findIndex((sortElement) => fileName.includes(`${sortElement}.css`)); + if (sortIndex === -1) { + // Ensure file names that don't have a specified sort order appear last + console.error( + chalk.yellow('WARNING: CSS section does not have a defined sort order:', fileName.replace('.css', '')), + ); + console.log( + chalk.dim( + ` +A Digdir developer should define its order in the sortOrder array in entryfile.ts. +The section will currently be added to the end of the entry file, but the exact +order may change due to nondeterminism.`.trim(), + ), + ); + console.log(); + + return Infinity; + } + return sortIndex; +}); const header = `@charset "UTF-8"; @layer ds.reset, ds.theme, ds.base, ds.utilities, ds.components; \n`; -const sortAndConcat = R.pipe( - sortLightmodeFirst, - R.map((file): string => { +const concat = R.pipe( + R.map((file: string): string => { try { const content = fs.readFileSync(file, 'utf-8').toString(); return content; @@ -38,7 +71,8 @@ export const makeEntryFile: EntryFile = async ({ outPath, buildPath, theme }) => const writePath = `${outPath}/${theme}.css`; const files = await glob(`**/*`, { cwd: buildPath }); - const content = header + sortAndConcat(files.map((file) => `${buildPath}/${file}`)); + const sortedFileNames = sortByDefinedOrder(files); + const content = header + concat(sortedFileNames.map((file) => `${buildPath}/${file}`)); await fs.writeFile(writePath, content); };