Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci: check for API changes in @digdir/designsystemet #2750

Draft
wants to merge 4 commits into
base: next
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ jobs:
- name: Test CLI (create tokens, then build the theme)
run: yarn test:cli

- name: CLI - Check for changes in the API
run: yarn report:cli-api

- name: Install Playwright
run: npx playwright install --with-deps
- name: Build storybook
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@
},
"[html]": {
"editor.defaultFormatter": "biomejs.biome"
}
},
"files.associations": { "api-extractor.json": "jsonc" }
}
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@
"types:storefront": "yarn workspace storefront types",
"version-packages": "changeset version",
"publish": "yarn build && changeset publish",
"chromatic": "yarn workspace @designsystemet/storybook chromatic"
"chromatic": "yarn workspace @designsystemet/storybook chromatic",
"report:cli-api": "yarn workspace @digdir/designsystemet api-report"
},
"devDependencies": {
"@biomejs/biome": "1.9.3",
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.7",
"@microsoft/api-extractor": "^7.47.11",
"@svitejs/changesets-changelog-github-compact": "^1.1.0",
"@types/node": "^22.1.0",
"@vitejs/plugin-react-swc": "^3.7.0",
Expand Down
1 change: 1 addition & 0 deletions packages/cli/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
test-tokens-create
test-tokens-build
temp
458 changes: 458 additions & 0 deletions packages/cli/api-extractor.json

Large diffs are not rendered by default.

195 changes: 195 additions & 0 deletions packages/cli/api-report/designsystemet.api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
## API Report File for "@digdir/designsystemet"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

import { Command } from '@commander-js/extra-typings';
import type { CssColor } from '@adobe/leonardo-contrast-colors';

// @public
export const areColorsContrasting: (color1: CssColor, color2: CssColor, type?: "decorative" | "aa" | "aaa") => boolean;

// @public (undocumented)
export const baseColors: Record<GlobalColors, CssColor>;

// @public
export const calculateContrastOneColor: (baseColor: CssColor) => "#000000" | "#ffffff";

// @public
export const calculateContrastTwoColor: (color: CssColor) => CssColor;

// @public
export const canTextBeUsedOnColors: (baseDefaultColor: CssColor, baseActiveColor: CssColor) => boolean;

// @public (undocumented)
export type ColorError = 'none' | 'decorative' | 'interaction';

// @public (undocumented)
export type ColorInfo = {
hex: CssColor;
number: ColorNumber;
name: string;
};

// @public (undocumented)
export type ColorMode = 'light' | 'dark' | 'contrast';

// @public (undocumented)
export type ColorNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15;

// @public (undocumented)
export type ContrastMode = 'aa' | 'aaa';

// @public (undocumented)
export const convertToHex: (color?: string) => CssColor;

// @public
export const createColorWithLightness: (color: CssColor, lightness: number) => CssColor;

// Warning: (ae-forgotten-export) The symbol "Tokens" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
export const createTokens: (opts: CreateTokensOptions) => Tokens;

// @public (undocumented)
export type CreateTokensOptions = {
colors: Colors_2;
typography: Typography;
themeName: string;
};

// Warning: (ae-forgotten-export) The symbol "ThemeGenType" needs to be exported by the entry point index.d.ts
//
// @public
export const generateColorTheme: ({ colors, contrastMode }: ThemeGenType) => Record<ThemeColors, ThemeInfo>;

// Warning: (ae-forgotten-export) The symbol "GlobalGenType" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
export const generateGlobalColors: ({ contrastMode }: GlobalGenType) => Record<GlobalColors, ThemeInfo>;

// @public
export const generateScaleForColor: (color: CssColor, mode: ColorMode, contrastMode?: "aa" | "aaa") => ColorInfo[];

// @public
export const generateThemeForColor: (color: CssColor, contrastMode?: "aa" | "aaa") => ThemeInfo;

// @public (undocumented)
export const getApcaContrastLc: (textColor: CssColor, backgroundColor: CssColor) => string | number;

// @public (undocumented)
export const getBaseColor: (color: CssColor) => CssColor;

// @public
export const getColorNameFromNumber: (number: ColorNumber) => string;

// @public
export const getColorNumberFromName: (name: string) => ColorNumber;

// @public
export const getContrastFromHex: (color1: CssColor, color2: CssColor) => number;

// @public
export const getContrastFromLightness: (lightness: number, mainColor: CssColor, backgroundColor: CssColor) => number;

// @public (undocumented)
export const getCssVariable: (colorType: string, colorNumber: ColorNumber) => string;

// @public
export const getHslLightessFromHex: (hex: CssColor) => number;

// @public (undocumented)
export const getHslSaturationFromHex: (hex: CssColor) => number;

// @public
export const getLightnessFromHex: (hex: string) => number;

// @public
export const getRatioFromLum: (lum1: number, lum2: number) => number;

// @public (undocumented)
export type GlobalColors = 'red' | 'blue' | 'green' | 'orange' | 'purple' | 'yellow';

// @public
export const hexToCssHsl: (hex: string, valuesOnly?: boolean) => string;

// @public
export const hexToHSL: (H: string) => number[];

// @public
export const hexToHsluv: (hex: string) => number[];

// @public
export const hexToRgb: (hex: string, type?: "255" | "1") => {
r: number;
g: number;
b: number;
} | null;

// @public
export const hslArrToCss: (HSL: number[]) => string;

// @public
export const HSLToHex: (h: number, s: number, l: number) => string;

// @public
export const isHexColor: (hex: string) => boolean;

// @public
export const luminanceFromHex: (hex: CssColor) => number;

// @public
export const luminanceFromRgb: (r: string, g: string, b: string) => number;

// @public (undocumented)
export const migrateCmd: Command<[string | undefined], {
list?: true | undefined;
glob: string;
}>;

// @public (undocumented)
export const rgbToHex: (rgb: {
r: number;
g: number;
b: number;
}) => string;

// @public (undocumented)
export type ThemeColors = 'accent' | 'neutral' | 'brand1' | 'brand2' | 'brand3';

// @public (undocumented)
export type ThemeInfo = {
light: ColorInfo[];
dark: ColorInfo[];
contrast: ColorInfo[];
};

// @public (undocumented)
export const tokensBuildCmd: Command<[], {
tokens: string;
out: string;
preview: boolean;
verbose: boolean;
}>;

// @public (undocumented)
export const tokensCreateCmd: Command<[], {
accent: string;
neutral: string;
brand1: string;
brand2: string;
brand3: string;
write: string | true;
fontFamily: string;
theme: string;
}>;

// Warnings were encountered during analysis:
//
// src/tokens/create.ts:6:3 - (ae-forgotten-export) The symbol "Colors_2" needs to be exported by the entry point index.d.ts
// src/tokens/create.ts:7:3 - (ae-forgotten-export) The symbol "Typography" needs to be exported by the entry point index.d.ts

// (No @packageDocumentation comment for this package)

```
121 changes: 65 additions & 56 deletions packages/cli/bin/designsystemet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,71 +10,80 @@ import { writeTokens } from '../src/tokens/write.js';

program.name('Designsystemet').description('CLI for working with Designsystemet').showHelpAfterError();

function makeTokenCommands() {
const tokenCmd = createCommand('tokens');
const DEFAULT_TOKENSDIR = './design-tokens';
/*
* designsystemet tokens
*/
const DEFAULT_TOKENSDIR = './design-tokens';

tokenCmd
.command('build')
.description('Build Designsystemet tokens')
.option('-t, --tokens <string>', `Path to ${chalk.blue('design-tokens')}`, DEFAULT_TOKENSDIR)
.option('-o, --out <string>', `Output directory for built ${chalk.blue('design-tokens')}`, './dist/tokens')
.option('-p, --preview', 'Generate preview token.ts files', false)
.option('--verbose', 'Enable verbose output', false)
.action((opts) => {
const tokens = typeof opts.tokens === 'string' ? opts.tokens : DEFAULT_TOKENSDIR;
const out = typeof opts.out === 'string' ? opts.out : './dist/tokens';
const preview = opts.preview;
const verbose = opts.verbose;
console.log(`Building tokens in ${chalk.green(tokens)}`);
return buildTokens({ tokens, out, preview, verbose, accentColor: 'accent' });
});
const tokensCmd = createCommand('tokens');

tokenCmd
.command('create')
.description('Create Designsystemet tokens')
.requiredOption('-a, --accent <number>', `Accent hex color`)
.requiredOption('-n, --neutral <number>', `Neutral hex color`)
.requiredOption('-b1, --brand1 <number>', `Brand1 hex color`)
.requiredOption('-b2, --brand2 <number>', `Brand2 hex color`)
.requiredOption('-b3, --brand3 <number>', `Brand3 hex color`)
.option('-w, --write [string]', `Output directory for created ${chalk.blue('design-tokens')}`, DEFAULT_TOKENSDIR)
.option('-f, --font-family <string>', `Font family`, 'Inter')
.option('--theme <string>', `Theme name`, 'theme')
.action(async (opts) => {
const { theme, fontFamily } = opts;
console.log(`Creating tokens with options ${chalk.green(JSON.stringify(opts, null, 2))}`);
const write = typeof opts.write === 'boolean' ? DEFAULT_TOKENSDIR : opts.write;
/*
* designsystemet tokens create
*/
export const tokensCreateCmd = tokensCmd
.command('create')
.description('Create Designsystemet tokens')
.requiredOption('-a, --accent <number>', `Accent hex color`)
.requiredOption('-n, --neutral <number>', `Neutral hex color`)
.requiredOption('-b1, --brand1 <number>', `Brand1 hex color`)
.requiredOption('-b2, --brand2 <number>', `Brand2 hex color`)
.requiredOption('-b3, --brand3 <number>', `Brand3 hex color`)
.option('-w, --write [string]', `Output directory for created ${chalk.blue('design-tokens')}`, DEFAULT_TOKENSDIR)
.option('-f, --font-family <string>', `Font family`, 'Inter')
.option('--theme <string>', `Theme name`, 'theme')
.action(async (opts) => {
const { theme, fontFamily } = opts;
console.log(`Creating tokens with options ${chalk.green(JSON.stringify(opts, null, 2))}`);
const write = typeof opts.write === 'boolean' ? DEFAULT_TOKENSDIR : opts.write;

const props = {
themeName: theme,
colors: {
accent: convertToHex(opts.accent),
neutral: convertToHex(opts.neutral),
brand1: convertToHex(opts.brand1),
brand2: convertToHex(opts.brand2),
brand3: convertToHex(opts.brand3),
},
typography: {
fontFamily: fontFamily,
},
};
const props = {
themeName: theme,
colors: {
accent: convertToHex(opts.accent),
neutral: convertToHex(opts.neutral),
brand1: convertToHex(opts.brand1),
brand2: convertToHex(opts.brand2),
brand3: convertToHex(opts.brand3),
},
typography: {
fontFamily: fontFamily,
},
};

const tokens = createTokens(props);
const tokens = createTokens(props);

if (write) {
await writeTokens({ writeDir: write, tokens, themeName: theme });
}
if (write) {
await writeTokens({ writeDir: write, tokens, themeName: theme });
}

return Promise.resolve();
});
return Promise.resolve();
});

return tokenCmd;
}
/*
* designsystemet tokens build
*/
export const tokensBuildCmd = tokensCmd
.command('build')
.description('Build Designsystemet tokens')
.option('-t, --tokens <string>', `Path to ${chalk.blue('design-tokens')}`, DEFAULT_TOKENSDIR)
.option('-o, --out <string>', `Output directory for built ${chalk.blue('design-tokens')}`, './dist/tokens')
.option('-p, --preview', 'Generate preview token.ts files', false)
.option('--verbose', 'Enable verbose output', false)
.action((opts) => {
const tokens = typeof opts.tokens === 'string' ? opts.tokens : DEFAULT_TOKENSDIR;
const out = typeof opts.out === 'string' ? opts.out : './dist/tokens';
const preview = opts.preview;
const verbose = opts.verbose;
console.log(`Building tokens in ${chalk.green(tokens)}`);
return buildTokens({ tokens, out, preview, verbose, accentColor: 'accent' });
});

program.addCommand(makeTokenCommands());
program.addCommand(tokensCmd);

program
/*
* designsystemet migrate
*/
export const migrateCmd = program
.command('migrate')
.description('run a Designsystemet migration')
.addArgument(new Argument('[migration]', 'Available migrations').choices(Object.keys(migrations)))
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './bin/designsystemet';
export * from './src';
3 changes: 2 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
"test": "yarn test:tokens-create-and-build",
"clean": "rimraf dist",
"clean:theme": "yarn workspace @digdir/designsystemet-theme clean",
"update:template": "tsx ./src/tokens/template.ts"
"update:template": "tsx ./src/tokens/template.ts",
"api-report": "api-extractor run"
},
"dependencies": {
"@adobe/leonardo-contrast-colors": "^1.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
"sourceMap": false,
"incremental": false
},
"include": ["./src", "./bin/", "./declarations.d.ts"]
"include": ["./index.ts", "./src", "./bin/", "./declarations.d.ts"]
}
Loading
Loading