Skip to content

Commit

Permalink
feat: better typescript types, js modules (#92)
Browse files Browse the repository at this point in the history
* chore: update typescript version

* feat: better typescript types, js modules
  • Loading branch information
bennypowers authored Mar 30, 2023
1 parent 57f30b5 commit cde3ef0
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 41 deletions.
6 changes: 6 additions & 0 deletions .changeset/better-ts-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@rhds/tokens": minor
---

Improved exported typescript types, use string references in media tokens'
javascript module representation
1 change: 1 addition & 0 deletions build.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export function build() {
.registerFormat(Formats.hexokinase)
.registerFormat(Formats.docsPage)
.registerAction(Actions.copyAssets)
.registerAction(Actions.copyTypes)
.registerAction(Actions.writeEsMapDeclaration)
.registerAction(Actions.writeVSIXManifest)
.registerAction(Actions.descriptionFile)
Expand Down
26 changes: 25 additions & 1 deletion lib/actions.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { readFileSync, copyFileSync, mkdirSync, rmSync, writeFileSync, rmdirSync, readdirSync } from 'node:fs';
import {
readFileSync,
copyFileSync,
mkdirSync,
rmSync,
writeFileSync,
rmdirSync,
readdirSync,
} from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

Expand All @@ -7,6 +15,8 @@ import { fileURLToPath } from 'node:url';
const rel = path => new URL(path, import.meta.url);
const DOCS_STYLES_IN = fileURLToPath(rel('../docs/styles.css'));
const DOCS_STYLES_OUT = fileURLToPath(rel('../build/styles.css'));
const TYPES_IN = fileURLToPath(rel('./types.ts'));
const TYPES_OUT = fileURLToPath(rel('../js/types.ts'));
const ASSETS_IN_DIR = rel('../docs/assets/');
const ASSETS_OUT_DIR = rel('../build/assets/');
const PACKAGE_JSON_URL = rel('../package.json');
Expand Down Expand Up @@ -48,6 +58,20 @@ export const copyAssets = {
}
};

/**
* Copy base TS types
* @type {Action}
*/
export const copyTypes = {
name: 'copyTypes',
do() {
copyFileSync(TYPES_IN, TYPES_OUT);
},
undo() {
rmSync(TYPES_OUT, { force: true });
}
};

/**
* Write declaration file for JS token map
* @type {Action}
Expand Down
58 changes: 45 additions & 13 deletions lib/formats/modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,31 @@ import { colorFormats } from '../transforms.js';
const { fileHeader } = StyleDictionary.formatHelpers;

function deserializeShadow(x) {
const [offsetX, offsetY, blur, spread, color] = x.split(' ');
return { offsetX, offsetY, blur, spread, color };
const [offsetX, offsetY, blur, spread, color] = x.$value.split(' ');
return JSON.stringify({ offsetX, offsetY, blur, spread, color });
}

const capitalize = x => `${x.at(0).toUpperCase()}${x.slice(1)}`;

function colorRef(x) {
const r = JSON.stringify(colorFormats.transformer({ ...x }));
return r;
}

function mediaRef(x) {
const values = [];
const stringified = JSON.stringify(x.original.$value, (_, value) => {
const [, inner] = value?.match?.(/^\{(.*)\}$/) ?? [];
if (inner) {
const v = inner.split('.').map(capitalize).join('');
values.push(v);
return v.replace(/"(.*)"/, '$1');
} else {
return value;
}
});
const r = `${stringified.replace(new RegExp(`"(${values.join('|')})"`), '$1')} as const`;
return r;
}

/**
Expand All @@ -23,19 +46,28 @@ export const modules = {
formatter({ file, dictionary, platform }) {
const categories = new Set(dictionary.allTokens.map(x => x.attributes.category));
for (const name of categories) {
const category = dictionary.allTokens.filter(x => x.attributes?.category === name);
const outpath = join(process.cwd(), platform.buildPath, `${name}.js`);
const content = category
.filter(x => !Predicates.isColor(x) || !x.name.match(/(rgb|hsl)$/i))
const outpath = join(process.cwd(), platform.buildPath, `${name}.ts`);
const category = dictionary
.allTokens
.filter(x => x.attributes?.category === name)
// don't output -rgb and -hsl tokens, because colours here are structured data which includes hsl and rgb values
.filter(x => !Predicates.isColor(x) || !x.name.match(/(rgb|hsl)$/i));
const defs = category
.map(x => {
const value =
Predicates.isColor(x) ? colorFormats.transformer({ ...x })
: Predicates.isShadow(x) ? deserializeShadow(x.$value)
: x.$value;
return `export const ${x.name} = ${JSON.stringify(value)};`;
})
.join('\n');
writeFileSync(outpath, content, 'utf8');
Predicates.isColor(x) ? colorRef(x)
: Predicates.isShadow(x) ? deserializeShadow(x)
: Predicates.isMediaQuery(x) ? mediaRef(x)
: JSON.stringify(x.$value);
return `export const ${x.name}${Predicates.isColor(x) ? ': Color' : ''} = ${value};`;
});
const hasColors = category.some(x => Predicates.isColor(x));
const contents = [
fileHeader({ file }),
...!hasColors ? [] : ['import type { Color } from "./types.js";'],
...defs
].join('\n');
writeFileSync(outpath, contents, 'utf8');
}
return [
fileHeader({ file }),
Expand Down
22 changes: 22 additions & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export interface Color {
isLight: boolean;
hex: string;
rgb: {
r: number;
g: number;
b: number;
a: number;
};
hsl: {
h: number;
s: number;
l: number;
a: number;
};
hsv: {
h: number;
s: number;
v: number;
a: number;
};
}
23 changes: 11 additions & 12 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 54 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,65 @@
"exports": {
".": {
"import": "./js/tokens.js",
"require": "./js/tokens.cjs"
"require": "./js/tokens.cjs",
"types": "./js/tokens.d.ts"
},
"./json/*": {
"require": "./json/*"
},
"./plugins/11ty.cjs": "./plugins/11ty.cjs",
"./plugins/stylelint.cjs": "./plugins/stylelint.cjs",
"./css/*": "./css/*",
"./values.js": {
"import": "./js/values.js",
"require": "./js/values.cjs"
},
"./animation.js": "./js/animation.js",
"./border.js": "./js/border.js",
"./box-shadow.js": "./js/box-shadow.js",
"./color.js": "./js/color.js",
"./icon.js": "./js/icon.js",
"./length.js": "./js/length.js",
"./media.js": "./js/media.js",
"./opacity.js": "./js/opacity.js",
"./space.js": "./js/space.js",
"./typography.js": "./js/typography.js"
"require": "./js/values.cjs",
"types": "./js/values.d.ts"
},
"./animation.js": {
"import": "./js/animation.js",
"types": "./js/animation.d.ts"
},
"./border.js": {
"import": "./js/border.js",
"types": "./js/border.d.ts"
},
"./box-shadow.js": {
"import": "./js/box-shadow.js",
"types": "./js/box-shadow.d.ts"
},
"./color.js": {
"import": "./js/color.js",
"types": "./js/color.d.ts"
},
"./icon.js": {
"import": "./js/icon.js",
"types": "./js/icon.d.ts"
},
"./length.js": {
"import": "./js/length.js",
"types": "./js/length.d.ts"
},
"./media.js": {
"import": "./js/media.js",
"types": "./js/media.d.ts"
},
"./opacity.js": {
"import": "./js/opacity.js",
"types": "./js/opacity.d.ts"
},
"./space.js": {
"import": "./js/space.js",
"types": "./js/space.d.ts"
},
"./typography.js": {
"import": "./js/typography.js",
"types": "./js/typography.d.ts"
}
},
"files": [
"css",
"editor",
"plugins",
"js",
"js/**/*.{js,d.ts}",
"json",
"scss"
],
Expand All @@ -57,6 +88,7 @@
"build": {
"dependencies": [
"style-dictionary",
"types",
"package",
"11ty"
]
Expand Down Expand Up @@ -97,6 +129,12 @@
"style-dictionary"
]
},
"types": {
"command": "tsc -m es2022 --target es2022 --moduleResolution nodenext -d ./js/*.ts",
"dependencies": [
"style-dictionary"
]
},
"package": {
"command": "cd editor/vscode && vsce package",
"dependencies": [
Expand Down Expand Up @@ -124,6 +162,7 @@
"tap-difflet": "^0.7.2",
"tape-describe": "^1.0.3",
"tape-es": "^1.2.17",
"typescript": "^5.0.2",
"vsce": "^2.15.0",
"wireit": "^0.9.5",
"yaml": "^2.2.1"
Expand Down
2 changes: 2 additions & 0 deletions platforms.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ map:
js:
transformGroup: js
buildPath: js/
actions:
- copyTypes
files:
- destination: values.js
format: javascript/modules
Expand Down

0 comments on commit cde3ef0

Please sign in to comment.