@terrazzo/cli 2.0.0-beta.4 → 2.0.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +8 -4
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +8 -9
package/bin/cli.js
CHANGED
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
* SOFTWARE.
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
+
import fs from 'node:fs';
|
|
28
29
|
import { createRequire } from 'node:module';
|
|
29
30
|
import { parseArgs } from 'node:util';
|
|
30
31
|
import { Logger } from '@terrazzo/parser';
|
|
31
|
-
import dotenv from 'dotenv';
|
|
32
32
|
import {
|
|
33
33
|
buildCmd,
|
|
34
34
|
checkCmd,
|
|
@@ -43,9 +43,13 @@ import {
|
|
|
43
43
|
|
|
44
44
|
const require = createRequire(process.cwd());
|
|
45
45
|
|
|
46
|
-
// Load env
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
// Load .env file into process.env
|
|
47
|
+
for (const envFile of ['.env', 'production.env', 'development.env']) {
|
|
48
|
+
if (fs.existsSync(envFile)) {
|
|
49
|
+
process.loadEnvFile(envFile);
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
49
53
|
|
|
50
54
|
const [, , ...argsRaw] = process.argv;
|
|
51
55
|
const { values: flags, positionals } = parseArgs({
|
package/dist/index.js
CHANGED
|
@@ -851,7 +851,7 @@ async function getVariables(fileKey, { logger, unpublished, matchers }) {
|
|
|
851
851
|
|
|
852
852
|
//#endregion
|
|
853
853
|
//#region src/import/figma/index.ts
|
|
854
|
-
async function importFromFigma({ url, logger, unpublished, skipStyles, skipVariables, fontFamilyNames, fontWeightNames, numberNames }) {
|
|
854
|
+
async function importFromFigma({ url, logger, unpublished, skipStyles, skipVariables, fontFamilyNames = "/fontFamily$", fontWeightNames = "/fontWeight$", numberNames }) {
|
|
855
855
|
const fileKey = getFileID(url);
|
|
856
856
|
if (!fileKey) logger.error({
|
|
857
857
|
group: "import",
|
|
@@ -873,8 +873,8 @@ async function importFromFigma({ url, logger, unpublished, skipStyles, skipVaria
|
|
|
873
873
|
logger,
|
|
874
874
|
unpublished,
|
|
875
875
|
matchers: {
|
|
876
|
-
fontFamily: new RegExp(fontFamilyNames
|
|
877
|
-
fontWeight: new RegExp(fontWeightNames
|
|
876
|
+
fontFamily: fontFamilyNames ? new RegExp(fontFamilyNames) : void 0,
|
|
877
|
+
fontWeight: fontWeightNames ? new RegExp(fontWeightNames) : void 0,
|
|
878
878
|
number: numberNames ? new RegExp(numberNames) : void 0
|
|
879
879
|
}
|
|
880
880
|
}) : null]);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["defineConfig","sculeCamelCase","fsSync","fs","fsSync","fs","fs","fsSync","defineConfig","defineConfigCore"],"sources":["../src/shared.ts","../src/build.ts","../src/check.ts","../src/help.ts","../src/import/figma/lib.ts","../src/import/figma/styles.ts","../src/import/figma/variables.ts","../src/import/figma/index.ts","../src/import/index.ts","../src/init.ts","../src/lab.ts","../src/normalize.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { type ConfigInit, defineConfig, type Logger } from '@terrazzo/parser';\nimport pc from 'picocolors';\nimport { createServer, type ViteDevServer } from 'vite';\nimport { ViteNodeRunner } from 'vite-node/client';\nimport { ViteNodeServer } from 'vite-node/server';\n\nexport const cwd = new URL(`${pathToFileURL(process.cwd())}/`); // trailing slash needed to interpret as directory\nexport const DEFAULT_CONFIG_PATH = new URL('./terrazzo.config.ts', cwd);\nexport const DEFAULT_TOKENS_PATH = new URL('./tokens.json', cwd);\n\nexport type Command = 'build' | 'check' | 'help' | 'init' | 'version';\n\nexport const GREEN_CHECK = pc.green('✔');\n\nexport interface Flags {\n /** --config, -c */\n config?: string;\n /** --out, -o */\n out?: string;\n /** --help */\n help?: boolean;\n /** --watch, -w */\n watch?: boolean;\n /** --version */\n version?: boolean;\n}\n\nexport interface LoadConfigOptions {\n cmd: Command;\n flags: Flags;\n logger: Logger;\n}\n\n/** Load config */\nexport async function loadConfig({ cmd, flags, logger }: LoadConfigOptions) {\n /**\n * Vite server for loading .ts config files\n * TODO: remove me when Node 24 is the oldest-supported Node version\n */\n let viteServer: ViteDevServer | undefined;\n try {\n let config: ConfigInit = {\n tokens: [DEFAULT_TOKENS_PATH],\n outDir: new URL('./tokens/', cwd),\n plugins: [],\n lint: {\n build: { enabled: true },\n rules: {},\n },\n alphabetize: false,\n ignore: { tokens: [], deprecated: false },\n };\n let configPath: string | undefined;\n\n if (typeof flags.config === 'string') {\n if (flags.config === '') {\n logger.error({ group: 'config', message: 'Missing path after --config flag' });\n process.exit(1);\n }\n configPath = resolveConfig(flags.config);\n if (!configPath) {\n logger.error({ group: 'config', message: `Could not locate ${flags.config}` });\n }\n }\n\n const resolvedConfigPath = resolveConfig(configPath);\n if (resolvedConfigPath) {\n try {\n // Note: we create a vite-node instance only when resolving the config,\n // because in most scenarios we only ever need this once and never again.\n // even in watch mode we don’t reload the config, so keeping a vite-node\n // “hot” instance doesn’t provide obvious benefits (only potential memory leaks)\n viteServer = await createServer({ mode: 'development' });\n const viteNodeServer = new ViteNodeServer(viteServer);\n const viteNodeRunner = new ViteNodeRunner({\n root: viteServer.config.root,\n base: viteServer.config.base,\n fetchModule(...args) {\n return viteNodeServer.fetchModule(...args);\n },\n resolveId(...args) {\n return viteNodeServer.resolveId(...args);\n },\n });\n const mod = await viteNodeRunner.executeFile(resolvedConfigPath);\n if (!mod.default) {\n // we format it immediately below\n throw new Error(\n `No default export found in ${resolvedConfigPath.replace(fileURLToPath(cwd), '')}. See https://terrazzo.dev/docs for instructions.`,\n );\n }\n config = defineConfig(mod.default, { cwd, logger });\n } catch (err) {\n logger.error({ group: 'config', message: (err as Error).message || (err as string) });\n }\n } else if (cmd !== 'init' && cmd !== 'check') {\n logger.error({ group: 'config', message: 'No config file found. Create one with `npx terrazzo init`.' });\n }\n\n // clean up\n if (viteServer) {\n await viteServer?.close();\n }\n\n return {\n config,\n configPath: resolvedConfigPath,\n };\n } catch (err) {\n printError((err as Error).message);\n\n // clean up\n if (viteServer) {\n await viteServer.close();\n }\n\n process.exit(1);\n }\n}\n\n/** load tokens */\nexport async function loadTokens(tokenPaths: URL[], { logger }: { logger: Logger }) {\n try {\n const allTokens = [];\n\n if (!Array.isArray(tokenPaths)) {\n logger.error({ group: 'config', message: `loadTokens: Expected array, received ${typeof tokenPaths}` });\n }\n\n // if this is the default value, also check for tokens.yaml\n if (tokenPaths.length === 1 && tokenPaths[0]!.href === DEFAULT_TOKENS_PATH.href) {\n if (!fs.existsSync(tokenPaths[0]!)) {\n const yamlPath = new URL('./tokens.yaml', cwd);\n if (fs.existsSync(yamlPath)) {\n tokenPaths[0] = yamlPath;\n } else {\n logger.error({\n group: 'config',\n message: `Could not locate ${path.relative(cwd.href, tokenPaths[0]!.href)}. To create one, run \\`npx tz init\\`.`,\n });\n return;\n }\n }\n }\n\n // download/read\n for (let i = 0; i < tokenPaths.length; i++) {\n const filename = tokenPaths[i];\n\n if (!(filename instanceof URL)) {\n logger.error({ group: 'config', message: `Expected URL, received ${filename}`, label: `loadTokens[${i}]` });\n return;\n } else if (filename.protocol === 'http:' || filename.protocol === 'https:') {\n try {\n // if Figma URL\n if (filename.host === 'figma.com' || filename.host === 'www.figma.com') {\n const [_, fileKeyword, fileKey] = filename.pathname.split('/');\n if (fileKeyword !== 'file' || !fileKey) {\n logger.error({\n group: 'config',\n message: `Unexpected Figma URL. Expected \"https://www.figma.com/file/:file_key/:file_name?…\", received \"${filename.href}\"`,\n });\n }\n const headers = new Headers({\n Accept: '*/*',\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:123.0) Gecko/20100101 Firefox/123.0',\n });\n if (process.env.FIGMA_ACCESS_TOKEN) {\n headers.set('X-FIGMA-TOKEN', process.env.FIGMA_ACCESS_TOKEN);\n } else {\n logger.warn({ group: 'config', message: 'FIGMA_ACCESS_TOKEN not set' });\n }\n const res = await fetch(`https://api.figma.com/v1/files/${fileKey}/variables/local`, {\n method: 'GET',\n headers,\n });\n if (res.ok) {\n allTokens.push({ filename, src: await res.text() });\n }\n const message = res.status !== 404 ? JSON.stringify(await res.json(), undefined, 2) : '';\n logger.error({\n group: 'config',\n message: `Figma responded with ${res.status}${message ? `:\\n${message}` : ''}`,\n });\n break;\n }\n\n // otherwise, expect YAML/JSON\n const res = await fetch(filename, {\n method: 'GET',\n headers: { Accept: '*/*', 'User-Agent': 'Mozilla/5.0 Gecko/20100101 Firefox/123.0' },\n });\n allTokens.push({ filename, src: await res.text() });\n } catch (err) {\n logger.error({ group: 'config', message: `${filename.href}: ${err}` });\n return;\n }\n } else {\n if (fs.existsSync(filename)) {\n allTokens.push({ filename, src: fs.readFileSync(filename, 'utf8') });\n } else {\n logger.error({\n group: 'config',\n message: `Could not locate ${path.relative(cwd.href, filename.href)}. To create one, run \\`npx tz init\\`.`,\n });\n return;\n }\n }\n }\n\n return allTokens;\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** Print error */\nexport function printError(message: string) {\n // biome-ignore lint/suspicious/noConsole: this is its job\n console.error(pc.red(`✗ ${message}`));\n}\n\n/** Print success */\nexport function printSuccess(message: string, startTime?: number) {\n // biome-ignore lint/suspicious/noConsole: this is its job\n console.log(`${GREEN_CHECK} ${message}${startTime ? ` ${time(startTime)}` : ''}`);\n}\n\n/** Resolve config */\nexport function resolveConfig(filename?: string): string | undefined {\n // --config [configpath]\n if (filename && fs.existsSync(new URL(filename, cwd))) {\n return filename;\n }\n // note: the order isn’t significant; just try for most-common first.\n // if a user has multiple config files with different extensions that’s their fault\n for (const ext of ['.ts', '.js', '.mts', '.cts', '.mjs', '.cjs']) {\n const maybeFilename = `terrazzo.config${ext}`;\n if (fs.existsSync(new URL(maybeFilename, cwd))) {\n return fileURLToPath(new URL(maybeFilename, cwd));\n }\n }\n}\n\n/** Resolve tokens.json path (for lint command) */\nexport function resolveTokenPath(filename: string, { logger }: { logger: Logger }) {\n const tokensPath = new URL(filename, cwd);\n if (!fs.existsSync(tokensPath)) {\n logger.error({ group: 'config', message: `Could not locate ${filename}. Does the file exist?` });\n } else if (!fs.statSync(tokensPath).isFile()) {\n logger.error({ group: 'config', message: `Expected JSON or YAML file, received ${filename}.` });\n }\n return tokensPath;\n}\n\n/** Print time elapsed */\nexport function time(start: number) {\n const diff = performance.now() - start;\n return pc.dim(diff < 750 ? `${Math.round(diff)}ms` : `${(diff / 1000).toFixed(1)}s`);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { type BuildRunnerResult, build, type ConfigInit, type Logger, parse } from '@terrazzo/parser';\nimport chokidar from 'chokidar';\nimport pc from 'picocolors';\nimport yamlToMomoa from 'yaml-to-momoa';\nimport {\n cwd,\n DEFAULT_TOKENS_PATH,\n type Flags,\n GREEN_CHECK,\n loadTokens,\n printError,\n printSuccess,\n resolveConfig,\n} from './shared.js';\n\nexport interface BuildOptions {\n flags: Flags;\n config: ConfigInit;\n configPath: string;\n logger: Logger;\n}\n\n/** tz build */\nexport async function buildCmd({ config, configPath, flags, logger }: BuildOptions) {\n try {\n const startTime = performance.now();\n if (!Array.isArray(config.plugins) || !config.plugins.length) {\n logger.error({\n group: 'config',\n message: `No plugins defined! Add some in ${configPath || 'terrazzo.config.ts'}`,\n });\n }\n\n // first build\n let rawSchemas = await loadTokens(config.tokens, { logger });\n if (!rawSchemas) {\n logger.error({\n group: 'config',\n message: `Error loading ${path.relative(fileURLToPath(cwd), fileURLToPath(config.tokens[0] || DEFAULT_TOKENS_PATH))}`,\n });\n return;\n }\n let { tokens, resolver, sources } = await parse(rawSchemas, { config, logger, yamlToMomoa });\n let result = await build(tokens, { resolver, sources, config, logger });\n writeFiles(result, { config, logger });\n\n // --watch (handle rebuild)\n if (flags.watch) {\n const dt = new Intl.DateTimeFormat('en-us', {\n hour: '2-digit',\n minute: '2-digit',\n });\n\n async function rebuild({ messageBefore, messageAfter }: { messageBefore?: string; messageAfter?: string } = {}) {\n try {\n if (messageBefore) {\n logger.info({ group: 'plugin', label: 'watch', message: messageBefore });\n }\n rawSchemas = await loadTokens(config.tokens, { logger });\n if (!rawSchemas) {\n throw new Error(\n `Error loading ${path.relative(fileURLToPath(cwd), fileURLToPath(config.tokens[0] || DEFAULT_TOKENS_PATH))}`,\n );\n }\n const parseResult = await parse(rawSchemas, { config, logger, yamlToMomoa });\n tokens = parseResult.tokens;\n sources = parseResult.sources;\n resolver = parseResult.resolver;\n result = await build(tokens, { resolver, sources, config, logger });\n if (messageAfter) {\n logger.info({ group: 'plugin', label: 'watch', message: messageAfter });\n }\n writeFiles(result, { config, logger });\n } catch (err) {\n // biome-ignore lint/suspicious/noConsole: this is its job\n console.error(pc.red(`✗ ${(err as Error).message || (err as string)}`));\n // don’t exit! we’re watching, so continue as long as possible\n }\n }\n\n const tokenWatcher = chokidar.watch(config.tokens.map((filename) => fileURLToPath(filename)));\n tokenWatcher.on('change', async (filename) => {\n await rebuild({\n messageBefore: `${pc.dim(dt.format(new Date()))} ${pc.green('tz')}} ${pc.yellow(filename)} updated ${GREEN_CHECK}`,\n });\n });\n const configWatcher = chokidar.watch(resolveConfig(configPath)!);\n configWatcher.on('change', async () => {\n await rebuild({\n messageBefore: `${pc.dim(dt.format(new Date()))} ${pc.green('tz')} ${pc.yellow('Config updated. Reloading…')}`,\n });\n });\n\n // keep process occupied\n await new Promise(() => {});\n } else {\n printSuccess(\n `${Object.keys(tokens).length} token${Object.keys(tokens).length !== 1 ? 's' : ''} built`,\n startTime,\n );\n }\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** Write files */\nexport function writeFiles(result: BuildRunnerResult, { config, logger }: { config: ConfigInit; logger: Logger }) {\n for (const { filename, contents } of result.outputFiles) {\n const output = new URL(filename, config.outDir);\n fs.mkdirSync(new URL('.', output), { recursive: true });\n fs.writeFileSync(output, contents);\n logger.debug({ group: 'parser', label: 'buildEnd', message: `Wrote file ${fileURLToPath(output)}` });\n }\n}\n","import { type ConfigInit, type Logger, parse } from '@terrazzo/parser';\nimport yamlToMomoa from 'yaml-to-momoa';\nimport { loadTokens, printError, printSuccess, resolveTokenPath } from './shared.js';\n\nexport interface CheckOptions {\n /** positional CLI args */\n positionals: string[];\n config: ConfigInit;\n logger: Logger;\n}\n\n/** tz check */\nexport async function checkCmd({ config, logger, positionals }: CheckOptions) {\n try {\n const startTime = performance.now();\n const tokenPaths = positionals.slice(1).length\n ? positionals.slice(1).map((tokenPath) => resolveTokenPath(tokenPath, { logger }))\n : config.tokens;\n const sources = await loadTokens(tokenPaths, { logger });\n if (!sources?.length) {\n logger.error({ group: 'config', message: 'Couldn’t find any tokens. Run `npx tz init` to create some.' });\n return;\n }\n await parse(sources, { config, continueOnError: true, logger, yamlToMomoa }); // will throw if errors\n printSuccess('No errors', startTime);\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n","/** Show help */\nexport function helpCmd() {\n // biome-ignore lint/suspicious/noConsole: this is its job\n console.log(`tz\n [commands]\n build Build token artifacts from tokens.json\n --watch, -w Watch tokens.json for changes and recompile\n --no-lint Disable linters running on build\n check [path] Check tokens.json for errors and run linters\n lint [path] (alias of check)\n init Create a starter tokens.json file\n lab Manage your tokens with a web interface\n import [path] Import from a Figma Design file\n --o [file] Save imported JSON\n --unpublished Include unpublished Variables\n --skip-styles Don’t import styles\n --skip-variables\n Don’t import variables\n\n [options]\n --help Show this message\n --config, -c Path to config (default: ./terrazzo.config.ts)\n --quiet Suppress warnings\n`);\n}\n","import type {\n GetFileNodesResponse,\n GetFileResponse,\n GetFileStylesResponse,\n GetLocalVariablesResponse,\n GetPublishedVariablesResponse,\n} from '@figma/rest-api-spec';\nimport type { Logger } from '@terrazzo/parser';\nimport { camelCase as sculeCamelCase } from 'scule';\n\nexport const KEY = ':key';\nexport const FILE_KEY = ':file_key';\nexport const API = {\n file: `https://api.figma.com/v1/files/${FILE_KEY}`,\n fileNodes: `https://api.figma.com/v1/files/${FILE_KEY}/nodes`,\n fileStyles: `https://api.figma.com/v1/files/${FILE_KEY}/styles`,\n localVariables: `https://api.figma.com/v1/files/${FILE_KEY}/variables/local`,\n publishedVariables: `https://api.figma.com/v1/files/${FILE_KEY}/variables/published`,\n styles: `https://api.figma.com/v1/styles/${KEY}`,\n};\n\n/** Wrapper around camelCase to handle more cases */\nexport function formatName(name: string): string {\n return sculeCamelCase(name.replace(/\\s+/g, '-'));\n}\n\nconst nf = new Intl.NumberFormat('en-us');\n\n/** Wrapper around camelCase to handle more cases */\nexport function formatNumber(number: number): string {\n return nf.format(number);\n}\n\n/** Get File ID from design URL */\nexport function getFileID(url: string) {\n return url.match(/^https:\\/\\/(www\\.)?figma\\.com\\/design\\/([^/]+)/)?.[2];\n}\n\n/** /v1/files/:file_key */\nexport async function getFile(fileKey: string, { logger }: { logger: Logger }) {\n const res = await fetch(API.file.replace(FILE_KEY, fileKey), {\n method: 'GET',\n headers: { 'X-Figma-Token': process.env.FIGMA_ACCESS_TOKEN! },\n });\n if (!res.ok) {\n logger.error({ group: 'import', message: `${res.status} ${await res.text()}` });\n }\n return (await res.json()) as GetFileResponse;\n}\n\n/** /v1/files/:file_key/nodes */\nexport async function getFileNodes(fileKey: string, { ids, logger }: { logger: Logger; ids?: string[] }) {\n let url = API.fileNodes.replace(FILE_KEY, fileKey);\n if (ids?.length) {\n url += `?ids=${ids.join(',')}`;\n }\n const res = await fetch(url, {\n method: 'GET',\n headers: { 'X-Figma-Token': process.env.FIGMA_ACCESS_TOKEN! },\n });\n if (!res.ok) {\n logger.error({ group: 'import', message: `${res.status} ${await res.text()}` });\n }\n return (await res.json()) as GetFileNodesResponse;\n}\n\n/** /v1/files/:file_key/styles */\nexport async function getFileStyles(fileKey: string, { logger }: { logger: Logger }) {\n const res = await fetch(API.fileStyles.replace(FILE_KEY, fileKey), {\n method: 'GET',\n headers: { 'X-Figma-Token': process.env.FIGMA_ACCESS_TOKEN! },\n });\n if (!res.ok) {\n logger.error({ group: 'import', message: `${res.status} ${await res.text()}` });\n }\n return (await res.json()) as GetFileStylesResponse;\n}\n\n/** /v1/files/:file_key/variables/local */\nexport async function getFileLocalVariables(fileKey: string, { logger }: { logger: Logger }) {\n const res = await fetch(API.localVariables.replace(FILE_KEY, fileKey), {\n method: 'GET',\n headers: { 'X-Figma-Token': process.env.FIGMA_ACCESS_TOKEN! },\n });\n if (!res.ok) {\n logger.error({ group: 'import', message: `${res.status} ${await res.text}` });\n }\n return (await res.json()) as GetLocalVariablesResponse;\n}\n\n/** /v1/files/:file_key/variables/published */\nexport async function getFilePublishedVariables(fileKey: string, { logger }: { logger: Logger }) {\n const res = await fetch(API.publishedVariables.replace(FILE_KEY, fileKey), {\n method: 'GET',\n headers: { 'X-Figma-Token': process.env.FIGMA_ACCESS_TOKEN! },\n });\n if (!res.ok) {\n logger.error({ group: 'import', message: `${res.status} ${await res.text}` });\n }\n return (await res.json()) as GetPublishedVariablesResponse;\n}\n","import type { DropShadowEffect, InnerShadowEffect, Node, PublishedStyle, Style } from '@figma/rest-api-spec';\nimport type {\n ColorValue,\n DimensionToken,\n GradientValue,\n Logger,\n NumberToken,\n ShadowValue,\n TypographyValue,\n} from '@terrazzo/parser';\nimport { formatName, getFile, getFileNodes, getFileStyles } from './lib.js';\n\n/** /v1/files/:file_key/styles */\nexport async function getStyles(\n fileKey: string,\n { logger, unpublished }: { logger: Logger; unpublished?: boolean },\n): Promise<{ count: number; code: any }> {\n const result: { count: number; code: any } = {\n count: 0,\n code: {\n sets: {\n styles: {\n sources: [{}],\n },\n },\n },\n };\n\n const styleNodeIDs = new Set<string>();\n const stylesByID = new Map<string, Style | PublishedStyle>();\n\n if (unpublished) {\n const styles = await getFile(fileKey, { logger });\n for (const [id, style] of Object.entries(styles.styles)) {\n styleNodeIDs.add(id);\n stylesByID.set(id, style);\n }\n } else {\n const styles = await getFileStyles(fileKey, { logger });\n for (const style of styles.meta.styles) {\n styleNodeIDs.add(style.node_id);\n stylesByID.set(style.node_id, style);\n }\n }\n\n const fileNodes = await getFileNodes(fileKey, { ids: [...styleNodeIDs], logger });\n\n result.count += styleNodeIDs.size;\n for (const [id, s] of stylesByID) {\n const styleNode = fileNodes.nodes[id];\n if (!styleNode) {\n logger.warn({\n group: 'import',\n message: `Style ${s.name} not found in file nodes. Does it need to be published?`,\n });\n continue;\n }\n\n const styleType = 'style_type' in s ? s.style_type : s.styleType;\n const tokenBase = {\n $type: undefined as any,\n $description: s.description || undefined,\n $value: undefined as any,\n $extensions: {\n 'figma.com': {\n name: s.name,\n node_id: id,\n created_at: 'created_at' in s ? s.created_at : undefined,\n updated_at: 'updated_at' in s ? s.updated_at : undefined,\n },\n },\n };\n\n switch (styleType) {\n case 'FILL': {\n const $value = fillStyle(styleNode.document);\n if (!$value) {\n logger.error({ group: 'import', message: `Could not parse fill for ${s.name}`, continueOnError: true });\n }\n if (Array.isArray($value)) {\n tokenBase.$type = 'gradient';\n } else {\n tokenBase.$type = 'color';\n }\n tokenBase.$value = $value;\n break;\n }\n case 'TEXT': {\n const $value = textStyle(styleNode.document);\n if (!$value) {\n logger.error({ group: 'import', message: `Could not parse text for ${s.name}`, continueOnError: true });\n }\n tokenBase.$type = 'typography';\n tokenBase.$value = $value;\n break;\n }\n case 'EFFECT': {\n const $value = effectStyle(styleNode.document);\n if (!$value) {\n logger.error({ group: 'import', message: `Could not parse effect for ${s.name}`, continueOnError: true });\n }\n tokenBase.$type = 'shadow';\n tokenBase.$value = $value;\n break;\n }\n case 'GRID': {\n const layoutGrids = gridStyles(styleNode.document);\n if (!layoutGrids) {\n logger.error({ group: 'import', message: `Could not parse grid for ${s.name}`, continueOnError: true });\n }\n // Note: Grids scaffold out multiple sub-components, so we need to “cheat” a little here\n let node = result.code.sets.styles.sources[0];\n const path = s.name.split('/').map(formatName);\n const name = path.pop()!;\n for (const key of path) {\n if (!(key in node)) {\n node[key] = {};\n }\n node = node[key];\n }\n node[name] = layoutGrids;\n break;\n }\n }\n\n // Only place in tree if we got a value for it\n if (tokenBase.$type !== undefined) {\n let node = result.code.sets.styles.sources[0];\n const path = s.name.split('/').map(formatName);\n const name = path.pop()!;\n for (const key of path) {\n if (!(key in node)) {\n node[key] = {};\n }\n node = node[key];\n }\n node[name] = tokenBase;\n }\n }\n\n return result;\n}\n\n/** Return a shadow token from an effect */\nexport function effectStyle(node: Node): ShadowValue[] | undefined {\n if ('effects' in node) {\n const shadows = node.effects.filter((e) => e.type === 'DROP_SHADOW' || e.type === 'INNER_SHADOW') as (\n | DropShadowEffect\n | InnerShadowEffect\n )[];\n if (shadows.length) {\n return shadows.map((s) => ({\n inset: s.type === 'INNER_SHADOW',\n offsetX: { value: s.offset.x, unit: 'px' },\n offsetY: { value: s.offset.y, unit: 'px' },\n blur: { value: s.radius, unit: 'px' },\n spread: { value: s.spread ?? 0, unit: 'px' },\n color: { colorSpace: 'srgb', components: [s.color.r, s.color.g, s.color.b], alpha: s.color.a },\n }));\n }\n }\n}\n\n/** Return a color or gradient token from a fill */\nexport function fillStyle(node: Node): ColorValue | GradientValue | undefined {\n if ('fills' in node) {\n for (const fill of node.fills) {\n switch (fill.type) {\n case 'SOLID': {\n return { colorSpace: 'srgb', components: [fill.color.r, fill.color.g, fill.color.b], alpha: fill.color.a };\n }\n case 'GRADIENT_LINEAR':\n case 'GRADIENT_RADIAL':\n case 'GRADIENT_ANGULAR':\n case 'GRADIENT_DIAMOND': {\n return fill.gradientStops.map((stop) => ({\n position: stop.position,\n color: { colorSpace: 'srgb', components: [stop.color.r, stop.color.g, stop.color.b], alpha: stop.color.a },\n }));\n }\n }\n }\n }\n}\n\n/** Return a dimension token from grid */\nexport function gridStyles(node: Node): Record<string, Record<string, DimensionToken | NumberToken>> | undefined {\n if (!('layoutGrids' in node) || !node.layoutGrids?.length) {\n return;\n }\n const values: Record<string, Record<string, DimensionToken | NumberToken>> = {};\n for (const grid of node.layoutGrids!) {\n const pattern = grid.pattern.toLowerCase();\n if (values[pattern]) {\n continue;\n }\n values[pattern] = {\n sectionSize: { $type: 'dimension', $value: { value: grid.sectionSize, unit: 'px' } },\n gutterSize: { $type: 'dimension', $value: { value: grid.sectionSize, unit: 'px' } },\n };\n if (grid.count > 0) {\n values[pattern].count = { $type: 'number', $value: grid.count };\n }\n }\n return values;\n}\n\n/** Return a typography token from text */\nexport function textStyle(node: Node): TypographyValue | undefined {\n if (!('style' in node)) {\n return;\n }\n return {\n fontFamily: [node.style.fontFamily!],\n fontWeight: node.style.fontWeight,\n fontStyle: node.style.fontStyle,\n fontSize: node.style.fontSize ? { value: node.style.fontSize, unit: 'px' } : { value: 1, unit: 'em' },\n letterSpacing: { value: node.style.letterSpacing ?? 0, unit: 'px' },\n lineHeight:\n 'lineHeightPercentFontSize' in node.style\n ? node.style.lineHeightPercentFontSize!\n : 'lineHeightPx' in node.style\n ? { value: node.style.lineHeightPx!, unit: 'px' }\n : 1,\n };\n}\n","import type { LocalVariable, LocalVariableCollection, RGBA } from '@figma/rest-api-spec';\nimport type { Logger } from '@terrazzo/parser';\nimport { formatName, getFileLocalVariables, getFilePublishedVariables } from './lib.js';\n\n/** /v1/files/:file_key/variables/published | /v1/files/:file_key/variables/local */\nexport async function getVariables(\n fileKey: string,\n {\n logger,\n unpublished,\n matchers,\n }: {\n logger: Logger;\n unpublished?: boolean;\n matchers: Record<'fontFamily' | 'fontWeight' | 'number', RegExp | undefined>;\n },\n): Promise<{ count: number; remoteCount: number; code: any }> {\n const result: { count: number; remoteCount: number; code: any } = {\n count: 0,\n remoteCount: 0,\n code: {\n sets: {},\n modifiers: {},\n },\n };\n\n const allVariables: Record<string, LocalVariable> = {};\n const variableCollections: Record<string, LocalVariableCollection> = {};\n let finalVariables: Record<string, LocalVariable> = {};\n const modeIDToName: Record<string, string> = {}; // Note: this can have duplicate values; they’ll be scoped in separate modifier contexts\n\n // We must always fetch local variables, no matter what, to get the data we need\n const local = await getFileLocalVariables(fileKey, { logger });\n for (const id of Object.keys(local.meta.variables)) {\n if (local.meta.variables[id]!.hiddenFromPublishing) {\n continue;\n }\n allVariables[id] = local.meta.variables[id]!;\n }\n for (const id of Object.keys(local.meta.variableCollections)) {\n variableCollections[id] = local.meta.variableCollections[id]!;\n for (const mode of local.meta.variableCollections[id]!.modes) {\n modeIDToName[mode.modeId] = formatName(mode.name);\n }\n }\n\n // If --unpublished is set, we’re ready to transform; otherwise, filter set from latest publish\n if (unpublished) {\n finalVariables = allVariables;\n } else {\n const published = await getFilePublishedVariables(fileKey, { logger });\n for (const id of Object.keys(published.meta.variables)) {\n finalVariables[id] = allVariables[id]!;\n }\n }\n\n const remoteIDs = new Set<string>();\n\n for (const id of Object.keys(finalVariables)) {\n const variable = finalVariables[id]!;\n const collection = variableCollections[variable.variableCollectionId]!;\n const collectionName = formatName(collection.name);\n const hasMultipleModes = collection.modes.length > 1;\n if (hasMultipleModes) {\n if (!(collectionName in result.code.modifiers)) {\n result.code.modifiers[collectionName] = {\n contexts: Object.fromEntries(collection.modes.map((m) => [formatName(m.name), [{}]])),\n default: modeIDToName[collection.defaultModeId],\n };\n }\n } else {\n if (!(collectionName in result.code.sets)) {\n result.code.sets[collectionName] = { sources: [{}] };\n }\n }\n\n const matches =\n (matchers.fontFamily?.test(variable.name) && 'fontFamily') ||\n (matchers.fontWeight?.test(variable.name) && 'fontWeight') ||\n (matchers.number?.test(variable.name) && 'number') ||\n undefined;\n\n for (const [modeID, value] of Object.entries(variable.valuesByMode)) {\n const modeName = modeIDToName[modeID]!;\n let node = result.code;\n if (hasMultipleModes) {\n if (!(modeName in result.code.modifiers[collectionName].contexts)) {\n // TODO: why did this happen? Why did we miss this? Is this a hidden conflict?\n result.code.modifiers[collectionName].contexts[modeName] = [{}];\n }\n node = result.code.modifiers[collectionName].contexts[modeName][0]!;\n } else {\n node = result.code.sets[collectionName].sources[0];\n }\n\n const tokenBase = {\n $type: undefined as any,\n $description: (variable as LocalVariable).description || undefined,\n $value: undefined as any,\n $extensions: {\n 'figma.com': {\n name: variable.name,\n id: variable.id,\n variableCollectionId: variable.variableCollectionId,\n codeSyntax: Object.keys(variable.codeSyntax).length ? variable.codeSyntax : undefined,\n },\n },\n };\n\n // If this token is an alias of another, keep this as a value override\n const isAliasOfID =\n (typeof value === 'object' && 'type' in value && value.type === 'VARIABLE_ALIAS' && value.id) || undefined;\n if (isAliasOfID) {\n if (allVariables[isAliasOfID]) {\n tokenBase.$type =\n matches ||\n { COLOR: 'color', BOOLEAN: 'boolean', STRING: 'string', FLOAT: 'dimension' }[variable.resolvedType];\n tokenBase.$value = `{${allVariables[isAliasOfID].name.split('/').map(formatName).join('.')}}`;\n } else {\n remoteIDs.add(isAliasOfID);\n continue;\n }\n } else if (matches === 'fontFamily') {\n tokenBase.$type = 'fontFamily';\n tokenBase.$value = String(value).split(',');\n } else if (matches === 'fontWeight') {\n tokenBase.$type = 'fontWeight';\n tokenBase.$value = value;\n } else if (matches === 'number') {\n if (typeof value === 'object') {\n throw new Error(`Can’t coerce ${variable.name} into number type.`);\n }\n tokenBase.$type = 'number';\n tokenBase.$value = Number(value); // fun fact: this coerces booleans correctly\n } else {\n switch (variable.resolvedType) {\n case 'BOOLEAN':\n case 'STRING': {\n tokenBase.$type = variable.resolvedType.toLowerCase();\n tokenBase.$value = value;\n break;\n }\n case 'FLOAT': {\n tokenBase.$type = 'dimension';\n tokenBase.$value = { value, unit: 'px' };\n break;\n }\n case 'COLOR': {\n const { r, g, b, a } = value as RGBA;\n tokenBase.$type = 'color';\n tokenBase.$value = { colorSpace: 'srgb', components: [r, g, b], alpha: a };\n break;\n }\n }\n }\n\n // Only place in tree if we got a value for it\n if (tokenBase.$value !== undefined) {\n const path = variable.name.split('/').map(formatName);\n const name = path.pop()!;\n for (const key of path) {\n if (!(key in node)) {\n node[key] = {};\n }\n node = node[key];\n }\n node[name] = tokenBase;\n }\n }\n }\n\n // Update counts\n result.count = Object.keys(finalVariables).length;\n result.remoteCount = remoteIDs.size;\n\n return result;\n}\n","import type { Logger } from '@terrazzo/parser';\nimport { pluralize } from '@terrazzo/token-tools';\nimport { merge } from 'merge-anything';\nimport { formatNumber, getFileID } from './lib.js';\nimport { getStyles } from './styles.js';\nimport { getVariables } from './variables.js';\n\nexport interface importFromFigmaOptions {\n url: string;\n logger: Logger;\n /** Grab unpublished Styles/Variables @default false */\n unpublished?: boolean;\n skipStyles?: boolean;\n skipVariables?: boolean;\n /** RegEx for overriding Variable types with fontFamily tokens */\n fontFamilyNames?: string;\n /** RegEx for overriding Variable types with fontWeight tokens */\n fontWeightNames?: string;\n /** RegEx for overriding Variable types with number tokens */\n numberNames?: string;\n}\n\nexport interface FigmaOutput {\n variableCount: number;\n styleCount: number;\n /** The Resolver JSON, in object format (could be any shape) */\n code: Record<string, any>;\n}\n\nexport async function importFromFigma({\n url,\n logger,\n unpublished,\n skipStyles,\n skipVariables,\n fontFamilyNames,\n fontWeightNames,\n numberNames,\n}: importFromFigmaOptions): Promise<FigmaOutput> {\n const fileKey = getFileID(url);\n if (!fileKey) {\n logger.error({ group: 'import', message: `Invalid Figma URL: ${url}` });\n }\n\n const result: FigmaOutput = {\n variableCount: 0,\n styleCount: 0,\n code: {\n $schema: 'https://www.designtokens.org/schemas/2025.10/resolver.json',\n version: '2025.10',\n resolutionOrder: [],\n sets: {},\n modifiers: {},\n },\n };\n\n try {\n const [styles, vars] = await Promise.all([\n !skipStyles ? getStyles(fileKey!, { logger }) : null,\n !skipVariables\n ? getVariables(fileKey!, {\n logger,\n unpublished,\n matchers: {\n fontFamily: new RegExp(fontFamilyNames || '/fontFamily$'),\n fontWeight: new RegExp(fontWeightNames || '/fontWeight$'),\n number: numberNames ? new RegExp(numberNames) : undefined,\n },\n })\n : null,\n ]);\n if (styles) {\n result.styleCount += styles.count;\n result.code = merge(result.code, styles.code);\n }\n if (vars) {\n result.variableCount += vars.count;\n result.code = merge(result.code, vars.code);\n if (vars.remoteCount) {\n logger.warn({\n group: 'import',\n message: `${formatNumber(vars.remoteCount)} ${pluralize(vars.remoteCount, 'Variable', 'Variables')} were remote and could not be accessed. Try importing from other files to grab them.`,\n });\n }\n }\n } catch (err) {\n logger.error({ group: 'import', message: (err as Error).message });\n }\n\n // Arbitrarily guess on resolutionOrder\n for (const group of ['sets', 'modifiers'] as const) {\n for (const name of Object.keys(result.code[group])) {\n result.code.resolutionOrder.push({ $ref: `#/${group}/${name}` });\n }\n }\n\n return result;\n}\n\n/** Is this a valid URL, and one belonging to a Figma file? */\nexport function isFigmaPath(url: string) {\n try {\n new URL(url);\n return /^https:\\/\\/(www\\.)?figma\\.com\\/design\\/[A-Za-z0-9]+/.test(url);\n } catch {\n return false;\n }\n}\n","import fsSync from 'node:fs';\nimport fs from 'node:fs/promises';\nimport type { Logger } from '@terrazzo/parser';\nimport { pluralize } from '@terrazzo/token-tools';\nimport { importFromFigma, isFigmaPath } from './figma/index.js';\nimport { formatNumber } from './figma/lib.js';\n\nexport * from './figma/index.js';\n\nexport interface ImportCmdOptions {\n flags: {\n /** The output file @default stdout */\n output?: string;\n } & Record<string, any>;\n positionals: string[];\n logger: Logger;\n}\n\nexport async function importCmd({ flags, positionals, logger }: ImportCmdOptions) {\n const [_cmd, url] = positionals;\n if (!url) {\n logger.error({\n group: 'import',\n message: 'Missing import path. Expected `tz import [file]`.',\n });\n }\n\n if (isFigmaPath(url!)) {\n const { FIGMA_ACCESS_TOKEN } = process.env;\n if (!FIGMA_ACCESS_TOKEN) {\n logger.error({\n group: 'import',\n message: `FIGMA_ACCESS_TOKEN not set! See https://terrazzo.app/docs/guides/import-from-figma`,\n });\n }\n\n const start = performance.now();\n const result = await importFromFigma({\n url: url!,\n logger,\n unpublished: flags.unpublished,\n skipStyles: flags['skip-styles'],\n skipVariables: flags['skip-variables'],\n fontFamilyNames: flags['font-family-names'],\n fontWeightNames: flags['font-weight-names'],\n numberNames: flags['number-names'],\n });\n const end = performance.now() - start;\n\n if (flags.output) {\n const oldFile = fsSync.existsSync(flags.output) ? JSON.parse(await fs.readFile(flags.output, 'utf8')) : {};\n // merge with old file, if any\n const code = {\n $schema: result.code.$schema, // Reset $schema\n version: result.code.version, // Reset version\n // Note: it’s important to have resolutionOrder higher up, since sets and modifiers will be a mess\n resolutionOrder: oldFile.resolutionOrder?.length ? oldFile.resolutionOrder : result.code.resolutionOrder, // Rely on old file, since the Figma file won’t understand resolutionOrder\n sets: result.code.sets, // Overwrite old sets\n modifiers: result.code.modifiers, // Overwrite old modifiers\n $defs: oldFile.$defs, // Just in case\n $extensions: oldFile.$extensions, // Just in case\n };\n await fs.writeFile(flags.output, `${JSON.stringify(code, undefined, 2)}\\n`);\n logger.info({\n group: 'import',\n message: `Imported ${formatNumber(result.variableCount)} ${pluralize(result.variableCount, 'Variable', 'Variables')}, ${formatNumber(result.styleCount)} ${pluralize(result.styleCount, 'Style', 'Styles')} → ${flags.output}`,\n timing: end,\n });\n } else {\n process.stdout.write(JSON.stringify(result.code));\n }\n\n return;\n }\n\n // Other imports here\n}\n","import { spawn } from 'node:child_process';\nimport fsSync from 'node:fs';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { confirm, intro, multiselect, outro, select, spinner } from '@clack/prompts';\nimport type { Logger } from '@terrazzo/parser';\nimport { pluralize } from '@terrazzo/token-tools';\nimport { detect } from 'detect-package-manager';\nimport { generate } from 'escodegen';\nimport { type ESTree, parseModule } from 'meriyah';\nimport { cwd, loadConfig, printError } from './shared.js';\n\nconst INSTALL_COMMAND = {\n npm: 'install -D --silent',\n yarn: 'add -D --silent',\n pnpm: 'add -D --silent',\n bun: 'install -D --silent',\n};\n\nconst SYNTAX_SETTINGS = {\n format: {\n indent: { style: ' ' },\n quotes: 'single',\n semicolons: true,\n },\n};\n\nconst EXAMPLE_TOKENS_PATH = 'my-tokens.tokens.json';\n\ninterface ImportSpec {\n specifier: string;\n path: string;\n}\n\n// Local copy of dtcg-examples/index.json. Copied partially for security (no\n// arbitrary injection of URL fetches), but also efficiency (saves a\n// round-trip).\ntype DesignSystem =\n | 'adobe-spectrum'\n | 'apple-hig'\n | 'figma-sds'\n | 'github-primer'\n | 'ibm-carbon'\n | 'microsoft-fluent'\n | 'shopify-polaris';\n\nconst DESIGN_SYSTEMS: Record<DesignSystem, { name: string; author: string; tokens: string[] }> = {\n 'adobe-spectrum': {\n name: 'Spectrum',\n author: 'Adobe',\n tokens: ['dtcg-examples/adobe-spectrum.resolver.json'],\n },\n 'apple-hig': {\n name: 'Human Interface Guidelines',\n author: 'Apple',\n tokens: ['dtcg-examples/apple-hig.resolver.json'],\n },\n 'figma-sds': {\n name: 'Simple Design System',\n author: 'Figma',\n tokens: ['dtcg-examples/figma-sds.resolver.json'],\n },\n 'github-primer': {\n name: 'Primer',\n author: 'GitHub',\n tokens: ['dtcg-examples/github-primer.resolver.json'],\n },\n 'ibm-carbon': {\n name: 'Carbon',\n author: 'IBM',\n tokens: ['dtcg-examples/ibm-carbon.resolver.json'],\n },\n 'microsoft-fluent': {\n name: 'Fluent',\n author: 'Microsoft',\n tokens: ['dtcg-examples/microsoft-fluent.resolver.json'],\n },\n 'shopify-polaris': {\n name: 'Polaris',\n author: 'Shopify',\n tokens: ['dtcg-examples/shopify-polaris.resolver.json'],\n },\n};\n\nexport interface InitOptions {\n logger: Logger;\n}\n\nexport async function initCmd({ logger }: InitOptions) {\n try {\n intro('⛋ Welcome to Terrazzo');\n const packageManager = await detect({ cwd: fileURLToPath(cwd) });\n\n // TODO: pass in CLI flags?\n const { config, configPath = 'terrazzo.config.ts' } = await loadConfig({ cmd: 'init', flags: {}, logger });\n const tokensPath = config.tokens[0]!;\n const hasExistingConfig = fsSync.existsSync(configPath);\n let startFromDS = !(tokensPath && fsSync.existsSync(tokensPath));\n\n // 1. tokens\n if (tokensPath && fsSync.existsSync(tokensPath)) {\n if (\n await confirm({\n message: `Found tokens at ${path.relative(fileURLToPath(cwd), fileURLToPath(tokensPath))}. Overwrite with a new design system?`,\n })\n ) {\n startFromDS = true;\n }\n }\n\n if (startFromDS) {\n const ds = DESIGN_SYSTEMS[\n (await select({\n message: 'Start from existing design system?',\n options: [\n ...Object.entries(DESIGN_SYSTEMS).map(([id, { author, name }]) => ({\n value: id,\n label: `${author} ${name}`,\n })),\n { value: 'none', label: 'None' },\n ],\n })) as keyof typeof DESIGN_SYSTEMS\n ] as (typeof DESIGN_SYSTEMS)[DesignSystem] | undefined;\n\n if (ds) {\n const s = spinner();\n s.start('Downloading');\n await new Promise((resolve, reject) => {\n // security: spawn() is much safer than exec()\n const subprocess = spawn(packageManager, [INSTALL_COMMAND[packageManager], 'dtcg-examples'], { cwd });\n subprocess.on('error', reject);\n subprocess.on('exit', resolve);\n });\n s.stop('Download complete');\n\n if (hasExistingConfig) {\n await updateConfigTokens(configPath, ds.tokens);\n } else {\n await newConfigFile(configPath, ds.tokens);\n }\n } else {\n startFromDS = false; // we’ll use this later in the final check\n }\n }\n\n // 2. If a user selected no DS, and doesn’t have a config file, create one\n if (!hasExistingConfig) {\n await newConfigFile(configPath, [EXAMPLE_TOKENS_PATH]);\n await fs.writeFile(EXAMPLE_TOKENS_PATH, JSON.stringify(EXAMPLE_TOKENS, undefined, 2));\n }\n\n // 3. plugins\n const existingPlugins = config.plugins.map((p) => p.name);\n const pluginSelection = await multiselect({\n message: 'Install plugins?',\n options: [\n { value: ['@terrazzo/plugin-css'], label: 'CSS' },\n { value: ['@terrazzo/plugin-js'], label: 'JS + TS' },\n { value: ['@terrazzo/plugin-css', '@terrazzo/plugin-sass'], label: 'Sass' },\n { value: ['@terrazzo/plugin-tailwind'], label: 'Tailwind' },\n ],\n required: false,\n });\n const newPlugins = Array.isArray(pluginSelection)\n ? Array.from(new Set(pluginSelection.flat().filter((p) => !existingPlugins.includes(p))))\n : [];\n if (newPlugins?.length) {\n const plugins: ImportSpec[] = newPlugins.map((p) => ({ specifier: p.replace('@terrazzo/plugin-', ''), path: p }));\n const pluginCount = `${newPlugins.length} ${pluralize(newPlugins.length, 'plugin', 'plugins')}`;\n const s = spinner();\n s.start(`Installing ${pluginCount}`);\n // note: this is async to show the spinner\n await new Promise((resolve, reject) => {\n // security: spawn() is much safer than exec()\n const subprocess = spawn(packageManager, [INSTALL_COMMAND[packageManager], newPlugins.join(' ')], { cwd });\n subprocess.on('error', reject);\n subprocess.on('exit', resolve);\n });\n s.message('Updating config');\n\n await updateConfigPlugins(configPath, plugins);\n\n s.stop(`Installed ${pluginCount}`);\n }\n\n // 4. No tokens, no plugins\n if (!startFromDS && !newPlugins?.length) {\n outro('Nothing to do. Exiting.');\n return;\n }\n\n outro('⛋ Done! 🎉');\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\nasync function newConfigFile(configPath: string, tokens: string[], imports: ImportSpec[] = []) {\n await fs.writeFile(\n configPath,\n `import { defineConfig } from '@terrazzo/cli';\n${imports.map((p) => `import ${p.specifier} from '${p.path}';`).join('\\n')}\n\nexport default defineConfig({\n tokens: ['${tokens.join(\"', '\")}'],\n plugins: [\n ${imports.length ? imports.map((p) => `${p.specifier}(),`).join('\\n ') : '/** @see https://terrazzo.app/docs */'}\n ],\n outDir: './dist/',\n lint: {\n /** @see https://terrazzo.app/docs/linting */\n build: {\n enabled: true,\n },\n rules: {\n 'core/valid-color': 'error',\n 'core/valid-dimension': 'error',\n 'core/valid-font-family': 'error',\n 'core/valid-font-weight': 'error',\n 'core/valid-duration': 'error',\n 'core/valid-cubic-bezier': 'error',\n 'core/valid-number': 'error',\n 'core/valid-link': 'error',\n 'core/valid-boolean': 'error',\n 'core/valid-string': 'error',\n 'core/valid-stroke-style': 'error',\n 'core/valid-border': 'error',\n 'core/valid-transition': 'error',\n 'core/valid-shadow': 'error',\n 'core/valid-gradient': 'error',\n 'core/valid-typography': 'error',\n 'core/consistent-naming': 'warn',\n },\n },\n});`,\n );\n}\n\nfunction getConfigObjFromAst(ast: ESTree.Program, configPath: string) {\n const astExport = ast.body.find((node) => node.type === 'ExportDefaultDeclaration');\n if (!astExport) {\n const relConfigPath = configPath\n ? path.relative(fileURLToPath(cwd), fileURLToPath(new URL(configPath)))\n : undefined;\n throw new Error(`SyntaxError: ${relConfigPath} does not have default export.`);\n }\n\n const astConfig = (\n astExport.declaration.type === 'CallExpression'\n ? // export default defineConfig({ ... })\n astExport.declaration.arguments[0]\n : // export default { ... }\n astExport.declaration\n ) as ESTree.ObjectExpression;\n\n if (astConfig.type !== 'ObjectExpression') {\n throw new Error(`Config: expected object default export, received ${astConfig.type}.`);\n }\n\n return astConfig;\n}\n\nasync function updateConfigTokens(configPath: string, tokens: string[]) {\n const ast = parseModule(await fs.readFile(configPath, 'utf8'));\n const astConfig = getConfigObjFromAst(ast, configPath);\n\n let tokensKey = astConfig.properties.find(\n (p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === 'tokens',\n ) as ESTree.Property | undefined;\n if (!tokensKey) {\n tokensKey = {\n type: 'Property' as const,\n key: { type: 'Identifier', name: 'tokens' },\n method: false,\n computed: false,\n shorthand: false,\n value: {\n type: 'ArrayExpression',\n elements: tokens.map((value) => ({ type: 'Literal', value, raw: `'${value}'` })),\n },\n } as ESTree.Property;\n astConfig.properties.unshift(tokensKey); // inject into first position\n }\n\n await fs.writeFile(configPath, generate(ast, SYNTAX_SETTINGS));\n}\n\n/**\n * Add plugin imports\n * note: this has the potential to duplicate plugins, but we tried our\n * best to filter already, and this may be the user’s fault if they\n * selected to install a plugin already installed. But also, this is\n * easily-fixable, so let’s not waste too much time here (and possibly\n * introduce bugs).\n */\nasync function updateConfigPlugins(configPath: string, plugins: ImportSpec[]) {\n const ast = parseModule(await fs.readFile(configPath, 'utf8'));\n\n ast.body.push(\n ...plugins.map(\n (p) =>\n ({\n type: 'ImportDeclaration' as const,\n source: { type: 'Literal', value: p.path },\n specifiers: [{ type: 'ImportDefaultSpecifier', local: { type: 'Identifier', name: p.specifier } }],\n attributes: [],\n }) as ESTree.ImportDeclaration,\n ),\n );\n\n // add plugins to config.plugins\n const astConfig = getConfigObjFromAst(ast, configPath);\n const pluginsArray = (\n astConfig.properties.find(\n (property) =>\n property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === 'plugins', // ASTs are so fun 😑\n ) as ESTree.Property\n )?.value as ESTree.ArrayExpression | undefined;\n const pluginsAst = plugins.map(\n (p) =>\n ({\n type: 'CallExpression' as const,\n callee: { type: 'Identifier' as const, name: p.specifier },\n arguments: [],\n optional: false,\n }) as ESTree.CallExpression,\n );\n\n if (pluginsArray) {\n pluginsArray.elements.push(...pluginsAst);\n } else {\n astConfig.properties.push({\n type: 'Property',\n key: { type: 'Identifier', name: 'plugins' },\n value: { type: 'ArrayExpression', elements: pluginsAst },\n kind: 'init',\n computed: false,\n method: false,\n shorthand: false,\n });\n }\n\n await fs.writeFile(configPath, generate(ast, SYNTAX_SETTINGS));\n}\n\nconst EXAMPLE_TOKENS = {\n color: {\n $description: 'Color tokens',\n black: {\n '100': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.05, hex: '#0c0c0d' },\n },\n '200': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.1, hex: '#0c0c0d' },\n },\n '300': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.2, hex: '#0c0c0d' },\n },\n '400': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.34, hex: '#0c0c04' },\n },\n '500': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.7, hex: '#0c0c0d' },\n },\n '600': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.8, hex: '#0c0c0d' },\n },\n '700': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.85, hex: '#0c0c0d' },\n },\n '800': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.9, hex: '#0c0c0d' },\n },\n '900': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.95, hex: '#0c0c0d' },\n },\n '1000': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0, hex: '#0c0c0d' },\n },\n },\n },\n border: {\n $description: 'Border tokens',\n default: {\n type: 'border',\n $value: {\n color: '{color.black.900}',\n style: 'solid',\n width: { value: 1, unit: 'px' },\n },\n },\n },\n radius: {\n $description: 'Corner radius tokens',\n '100': { $value: { value: 0.25, unit: 'rem' } },\n },\n space: {\n $description: 'Dimension tokens',\n '100': { $value: { value: 0.25, unit: 'rem' } },\n },\n typography: {\n $description: 'Typography tokens',\n body: {\n $type: 'typography',\n $value: {\n fontFamily: '{typography.family.sans}',\n fontSize: '{typography.scale.03}',\n fontWeight: '{typography.weight.regular}',\n letterSpacing: { value: 0, unit: 'em' },\n lineHeight: 1,\n },\n },\n },\n};\n","import fsSync from 'node:fs';\nimport fs from 'node:fs/promises';\nimport { Readable, Writable } from 'node:stream';\nimport { fileURLToPath } from 'node:url';\nimport { serve } from '@hono/node-server';\nimport type { ConfigInit, Logger } from '@terrazzo/parser';\nimport mime from 'mime';\nimport type { Flags } from './shared.js';\n\nexport interface LabBuildOptions {\n flags: Flags;\n config: ConfigInit;\n configPath: string;\n logger: Logger;\n}\n\nexport async function labCmd({ config, logger }: LabBuildOptions) {\n /** TODO: handle multiple files */\n const [tokenFileUrl] = config.tokens;\n\n const staticFiles = new Set();\n const dirEntries = await fs.readdir(fileURLToPath(import.meta.resolve('./lab')), {\n withFileTypes: true,\n recursive: true,\n });\n for (const entry of dirEntries) {\n if (entry.isFile() === false) {\n continue;\n }\n const absolutePath = `${entry.parentPath.replaceAll('\\\\', '/')}/${entry.name}`;\n staticFiles.add(absolutePath.replace(fileURLToPath(import.meta.resolve('./lab')).replaceAll('\\\\', '/'), ''));\n }\n\n const server = serve(\n {\n port: 9000,\n overrideGlobalObjects: false,\n async fetch(request) {\n const url = new URL(request.url);\n const pathname = url.pathname;\n if (pathname === '/') {\n return new Response(\n Readable.toWeb(\n fsSync.createReadStream(fileURLToPath(import.meta.resolve('./lab/index.html'))),\n ) as ReadableStream,\n {\n headers: {\n 'Content-Type': 'text/html',\n },\n },\n );\n }\n if (pathname === '/api/tokens') {\n if (request.method === 'GET') {\n return new Response(\n Readable.toWeb(fsSync.createReadStream(tokenFileUrl as fsSync.PathLike)) as ReadableStream,\n {\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n },\n },\n );\n } else if (request.method === 'POST' && request.body) {\n await request.body.pipeTo(Writable.toWeb(fsSync.createWriteStream(tokenFileUrl as fsSync.PathLike)));\n return new Response(JSON.stringify({ success: true }), {\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n }\n }\n\n if (staticFiles.has(pathname)) {\n return new Response(\n Readable.toWeb(\n fsSync.createReadStream(fileURLToPath(import.meta.resolve(`./lab${pathname}`))),\n ) as ReadableStream,\n {\n headers: { 'Content-Type': mime.getType(pathname) ?? 'application/octet-stream' },\n },\n );\n }\n return new Response('Not found', { status: 404 });\n },\n },\n (info) => {\n logger.info({\n group: 'server',\n message: `Token Lab running at http://${info.address === '::' ? 'localhost' : info.address}:${info.port}`,\n });\n },\n );\n /**\n * The cli entrypoint is going to manually exit the process after labCmd returns.\n */\n await new Promise<void>((resolve, reject) => {\n server.on('close', resolve);\n server.on('error', reject);\n });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport * as momoa from '@humanwhocodes/momoa';\nimport { getObjMember, getObjMembers, traverse } from '@terrazzo/json-schema-tools';\nimport { defineConfig, type Logger, parse } from '@terrazzo/parser';\nimport { isAlias } from '@terrazzo/token-tools';\nimport { cwd, printError } from './shared.js';\n\nexport interface NormalizeOptions {\n logger: Logger;\n output: URL;\n}\n\nfunction findMember(name: string) {\n return function (member: momoa.MemberNode) {\n return member.name.type === 'String' && member.name.value === name;\n };\n}\n\nexport async function normalizeCmd(filename: string, { logger, output }: NormalizeOptions) {\n try {\n if (!filename) {\n logger.error({ group: 'config', message: 'Expected input: `tz normalize <tokens.json> -o output.json`' });\n return;\n }\n const sourceLoc = new URL(filename, cwd);\n if (!fs.existsSync(sourceLoc)) {\n logger.error({\n group: 'config',\n message: `Couldn’t find ${path.relative(cwd.href, sourceLoc.href)}. Does it exist?`,\n });\n }\n const sourceData = fs.readFileSync(sourceLoc, 'utf8');\n const document = momoa.parse(sourceData, { mode: 'jsonc' });\n const { tokens } = await parse([{ src: sourceData, filename: sourceLoc }], {\n config: defineConfig(\n {\n lint: {\n rules: {\n 'core/valid-color': 'off',\n 'core/valid-dimension': 'off',\n 'core/valid-duration': 'off',\n 'core/valid-typography': 'off',\n },\n },\n },\n { cwd },\n ),\n logger,\n });\n\n traverse(document, {\n enter(node, _parent, nodePath) {\n const token = tokens[nodePath.join('.')];\n if (!token || token.aliasOf || node.type !== 'Member' || node.value.type !== 'Object') {\n return;\n }\n const $valueI = node.value.members.findIndex(findMember('$value'));\n\n switch (token.$type) {\n case 'color': {\n if (node.value.members[$valueI]!.value.type === 'String') {\n if (isAlias(node.value.members[$valueI]!.value.value)) {\n return;\n }\n const hex = (node.value.members[$valueI]!.value as momoa.StringNode).value;\n node.value.members[$valueI]!.value = momoa.parse(\n JSON.stringify({\n ...token.$value,\n hex: hex.startsWith('#') ? hex.slice(0, 7) : undefined,\n }),\n ).body;\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n const modeName = (mode.members[i]!.name as momoa.StringNode).value;\n const hex = (mode.members[i]!.value as momoa.StringNode).value;\n mode.members[i]!.value = momoa.parse(\n JSON.stringify({\n ...token.mode[modeName]!.$value,\n hex: hex.startsWith('#') ? hex.slice(0, 7) : undefined,\n }),\n ).body;\n }\n }\n }\n }\n break;\n }\n case 'dimension':\n case 'duration': {\n if (node.value.members[$valueI]!.value.type === 'String') {\n if (isAlias(node.value.members[$valueI]!.value.value)) {\n return;\n }\n node.value.members[$valueI]!.value = normalizeDurationDimension(node.value.members[$valueI]!.value);\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n mode.members[i]!.value = normalizeDurationDimension(node.value.members[$valueI]!.value);\n }\n }\n }\n }\n break;\n }\n case 'typography': {\n if (node.value.members[$valueI]?.value.type !== 'Object') {\n return;\n }\n node.value.members[$valueI].value = normalizeTypography(node.value.members[$valueI].value);\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n mode.members[i]!.value = normalizeTypography(mode.members[i]!.value as momoa.ObjectNode);\n }\n }\n }\n }\n }\n },\n });\n\n const outputLoc = new URL(output, cwd);\n fs.mkdirSync(new URL('.', outputLoc), { recursive: true });\n fs.writeFileSync(outputLoc, momoa.print(document, { indent: 2 }));\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\nfunction normalizeDurationDimension(node: momoa.StringNode) {\n const value = Number.parseFloat(node.value);\n if (!Number.isFinite(value)) {\n return node;\n }\n (node as any).type = 'Object';\n (node as any).members = (\n momoa.parse(JSON.stringify({ value, unit: node.value.replace(String(value), '') })).body as momoa.ObjectNode\n ).members;\n delete (node as any).value;\n return node;\n}\n\nfunction normalizeTypography(node: momoa.ObjectNode) {\n const { fontFamily, fontSize, fontWeight, letterSpacing, lineHeight } = getObjMembers(node);\n if (!fontFamily) {\n node.members.push((momoa.parse('{\"fontFamily\":[\"inherit\"]}').body as momoa.ObjectNode).members[0]!);\n }\n if (!fontSize) {\n node.members.push((momoa.parse('{\"fontSize\":{\"value\":1,\"unit\":\"rem\"}}').body as momoa.ObjectNode).members[0]!);\n }\n if (!fontWeight) {\n node.members.push((momoa.parse('{\"fontWeight\":400}').body as momoa.ObjectNode).members[0]!);\n }\n if (!letterSpacing) {\n node.members.push((momoa.parse('{\"letterSpacing\":{\"value\":0,\"unit\":\"rem\"}}').body as momoa.ObjectNode).members[0]!);\n }\n if (!lineHeight) {\n node.members.push((momoa.parse('{\"lineHeight\":1}').body as momoa.ObjectNode).members[0]!);\n }\n return node;\n}\n","import fs from 'node:fs';\n\nexport function versionCmd() {\n const { version } = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'));\n // biome-ignore lint/suspicious/noConsole: this is its job\n console.log(version);\n}\n","import { createRequire } from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport { type Config, type ConfigInit, defineConfig as defineConfigCore } from '@terrazzo/parser';\nimport { cwd } from './shared.js';\n\nexport * from './build.js';\nexport * from './check.js';\nexport * from './help.js';\nexport * from './import/index.js';\nexport * from './init.js';\nexport * from './lab.js';\nexport * from './normalize.js';\nexport * from './shared.js';\nexport * from './version.js';\n\nconst require = createRequire(cwd);\n\n// wrap defineConfig from @terrazzo/parser and add Node.js resolution\nexport function defineConfig(config: Config): ConfigInit {\n const normalizedConfig: Config = { ...config }; // note: we only need a shallow copy because we’re only mutating top-level `tokens`\n\n // Resolve tokens from npm modules, if any\n if (typeof normalizedConfig.tokens === 'string' || Array.isArray(normalizedConfig.tokens)) {\n normalizedConfig.tokens = (\n Array.isArray(normalizedConfig.tokens) ? normalizedConfig.tokens : [normalizedConfig.tokens]\n ).map((tokenPath) => {\n if (tokenPath.startsWith('.') || /^(https?|file):\\/\\//i.test(tokenPath)) {\n return tokenPath;\n }\n try {\n return pathToFileURL(require.resolve(tokenPath));\n } catch (err) {\n // biome-ignore lint/suspicious/noConsole: this is its job\n console.error(err);\n // this will throw an error if Node couldn’t automatically resolve it,\n // which will be true for many token paths. We don’t need to surface\n // that error; it’ll get its own error down the line if it’s a bad path.\n return tokenPath;\n }\n }) as string[];\n }\n\n return defineConfigCore(normalizedConfig, { cwd });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["defineConfig","sculeCamelCase","fsSync","fs","fsSync","fs","fs","fsSync","defineConfig","defineConfigCore"],"sources":["../src/shared.ts","../src/build.ts","../src/check.ts","../src/help.ts","../src/import/figma/lib.ts","../src/import/figma/styles.ts","../src/import/figma/variables.ts","../src/import/figma/index.ts","../src/import/index.ts","../src/init.ts","../src/lab.ts","../src/normalize.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { type ConfigInit, defineConfig, type Logger } from '@terrazzo/parser';\nimport pc from 'picocolors';\nimport { createServer, type ViteDevServer } from 'vite';\nimport { ViteNodeRunner } from 'vite-node/client';\nimport { ViteNodeServer } from 'vite-node/server';\n\nexport const cwd = new URL(`${pathToFileURL(process.cwd())}/`); // trailing slash needed to interpret as directory\nexport const DEFAULT_CONFIG_PATH = new URL('./terrazzo.config.ts', cwd);\nexport const DEFAULT_TOKENS_PATH = new URL('./tokens.json', cwd);\n\nexport type Command = 'build' | 'check' | 'help' | 'init' | 'version';\n\nexport const GREEN_CHECK = pc.green('✔');\n\nexport interface Flags {\n /** --config, -c */\n config?: string;\n /** --out, -o */\n out?: string;\n /** --help */\n help?: boolean;\n /** --watch, -w */\n watch?: boolean;\n /** --version */\n version?: boolean;\n}\n\nexport interface LoadConfigOptions {\n cmd: Command;\n flags: Flags;\n logger: Logger;\n}\n\n/** Load config */\nexport async function loadConfig({ cmd, flags, logger }: LoadConfigOptions) {\n /**\n * Vite server for loading .ts config files\n * TODO: remove me when Node 24 is the oldest-supported Node version\n */\n let viteServer: ViteDevServer | undefined;\n try {\n let config: ConfigInit = {\n tokens: [DEFAULT_TOKENS_PATH],\n outDir: new URL('./tokens/', cwd),\n plugins: [],\n lint: {\n build: { enabled: true },\n rules: {},\n },\n alphabetize: false,\n ignore: { tokens: [], deprecated: false },\n };\n let configPath: string | undefined;\n\n if (typeof flags.config === 'string') {\n if (flags.config === '') {\n logger.error({ group: 'config', message: 'Missing path after --config flag' });\n process.exit(1);\n }\n configPath = resolveConfig(flags.config);\n if (!configPath) {\n logger.error({ group: 'config', message: `Could not locate ${flags.config}` });\n }\n }\n\n const resolvedConfigPath = resolveConfig(configPath);\n if (resolvedConfigPath) {\n try {\n // Note: we create a vite-node instance only when resolving the config,\n // because in most scenarios we only ever need this once and never again.\n // even in watch mode we don’t reload the config, so keeping a vite-node\n // “hot” instance doesn’t provide obvious benefits (only potential memory leaks)\n viteServer = await createServer({ mode: 'development' });\n const viteNodeServer = new ViteNodeServer(viteServer);\n const viteNodeRunner = new ViteNodeRunner({\n root: viteServer.config.root,\n base: viteServer.config.base,\n fetchModule(...args) {\n return viteNodeServer.fetchModule(...args);\n },\n resolveId(...args) {\n return viteNodeServer.resolveId(...args);\n },\n });\n const mod = await viteNodeRunner.executeFile(resolvedConfigPath);\n if (!mod.default) {\n // we format it immediately below\n throw new Error(\n `No default export found in ${resolvedConfigPath.replace(fileURLToPath(cwd), '')}. See https://terrazzo.dev/docs for instructions.`,\n );\n }\n config = defineConfig(mod.default, { cwd, logger });\n } catch (err) {\n logger.error({ group: 'config', message: (err as Error).message || (err as string) });\n }\n } else if (cmd !== 'init' && cmd !== 'check') {\n logger.error({ group: 'config', message: 'No config file found. Create one with `npx terrazzo init`.' });\n }\n\n // clean up\n if (viteServer) {\n await viteServer?.close();\n }\n\n return {\n config,\n configPath: resolvedConfigPath,\n };\n } catch (err) {\n printError((err as Error).message);\n\n // clean up\n if (viteServer) {\n await viteServer.close();\n }\n\n process.exit(1);\n }\n}\n\n/** load tokens */\nexport async function loadTokens(tokenPaths: URL[], { logger }: { logger: Logger }) {\n try {\n const allTokens = [];\n\n if (!Array.isArray(tokenPaths)) {\n logger.error({ group: 'config', message: `loadTokens: Expected array, received ${typeof tokenPaths}` });\n }\n\n // if this is the default value, also check for tokens.yaml\n if (tokenPaths.length === 1 && tokenPaths[0]!.href === DEFAULT_TOKENS_PATH.href) {\n if (!fs.existsSync(tokenPaths[0]!)) {\n const yamlPath = new URL('./tokens.yaml', cwd);\n if (fs.existsSync(yamlPath)) {\n tokenPaths[0] = yamlPath;\n } else {\n logger.error({\n group: 'config',\n message: `Could not locate ${path.relative(cwd.href, tokenPaths[0]!.href)}. To create one, run \\`npx tz init\\`.`,\n });\n return;\n }\n }\n }\n\n // download/read\n for (let i = 0; i < tokenPaths.length; i++) {\n const filename = tokenPaths[i];\n\n if (!(filename instanceof URL)) {\n logger.error({ group: 'config', message: `Expected URL, received ${filename}`, label: `loadTokens[${i}]` });\n return;\n } else if (filename.protocol === 'http:' || filename.protocol === 'https:') {\n try {\n // if Figma URL\n if (filename.host === 'figma.com' || filename.host === 'www.figma.com') {\n const [_, fileKeyword, fileKey] = filename.pathname.split('/');\n if (fileKeyword !== 'file' || !fileKey) {\n logger.error({\n group: 'config',\n message: `Unexpected Figma URL. Expected \"https://www.figma.com/file/:file_key/:file_name?…\", received \"${filename.href}\"`,\n });\n }\n const headers = new Headers({\n Accept: '*/*',\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:123.0) Gecko/20100101 Firefox/123.0',\n });\n if (process.env.FIGMA_ACCESS_TOKEN) {\n headers.set('X-FIGMA-TOKEN', process.env.FIGMA_ACCESS_TOKEN);\n } else {\n logger.warn({ group: 'config', message: 'FIGMA_ACCESS_TOKEN not set' });\n }\n const res = await fetch(`https://api.figma.com/v1/files/${fileKey}/variables/local`, {\n method: 'GET',\n headers,\n });\n if (res.ok) {\n allTokens.push({ filename, src: await res.text() });\n }\n const message = res.status !== 404 ? JSON.stringify(await res.json(), undefined, 2) : '';\n logger.error({\n group: 'config',\n message: `Figma responded with ${res.status}${message ? `:\\n${message}` : ''}`,\n });\n break;\n }\n\n // otherwise, expect YAML/JSON\n const res = await fetch(filename, {\n method: 'GET',\n headers: { Accept: '*/*', 'User-Agent': 'Mozilla/5.0 Gecko/20100101 Firefox/123.0' },\n });\n allTokens.push({ filename, src: await res.text() });\n } catch (err) {\n logger.error({ group: 'config', message: `${filename.href}: ${err}` });\n return;\n }\n } else {\n if (fs.existsSync(filename)) {\n allTokens.push({ filename, src: fs.readFileSync(filename, 'utf8') });\n } else {\n logger.error({\n group: 'config',\n message: `Could not locate ${path.relative(cwd.href, filename.href)}. To create one, run \\`npx tz init\\`.`,\n });\n return;\n }\n }\n }\n\n return allTokens;\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** Print error */\nexport function printError(message: string) {\n // biome-ignore lint/suspicious/noConsole: this is its job\n console.error(pc.red(`✗ ${message}`));\n}\n\n/** Print success */\nexport function printSuccess(message: string, startTime?: number) {\n // biome-ignore lint/suspicious/noConsole: this is its job\n console.log(`${GREEN_CHECK} ${message}${startTime ? ` ${time(startTime)}` : ''}`);\n}\n\n/** Resolve config */\nexport function resolveConfig(filename?: string): string | undefined {\n // --config [configpath]\n if (filename && fs.existsSync(new URL(filename, cwd))) {\n return filename;\n }\n // note: the order isn’t significant; just try for most-common first.\n // if a user has multiple config files with different extensions that’s their fault\n for (const ext of ['.ts', '.js', '.mts', '.cts', '.mjs', '.cjs']) {\n const maybeFilename = `terrazzo.config${ext}`;\n if (fs.existsSync(new URL(maybeFilename, cwd))) {\n return fileURLToPath(new URL(maybeFilename, cwd));\n }\n }\n}\n\n/** Resolve tokens.json path (for lint command) */\nexport function resolveTokenPath(filename: string, { logger }: { logger: Logger }) {\n const tokensPath = new URL(filename, cwd);\n if (!fs.existsSync(tokensPath)) {\n logger.error({ group: 'config', message: `Could not locate ${filename}. Does the file exist?` });\n } else if (!fs.statSync(tokensPath).isFile()) {\n logger.error({ group: 'config', message: `Expected JSON or YAML file, received ${filename}.` });\n }\n return tokensPath;\n}\n\n/** Print time elapsed */\nexport function time(start: number) {\n const diff = performance.now() - start;\n return pc.dim(diff < 750 ? `${Math.round(diff)}ms` : `${(diff / 1000).toFixed(1)}s`);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { type BuildRunnerResult, build, type ConfigInit, type Logger, parse } from '@terrazzo/parser';\nimport chokidar from 'chokidar';\nimport pc from 'picocolors';\nimport yamlToMomoa from 'yaml-to-momoa';\nimport {\n cwd,\n DEFAULT_TOKENS_PATH,\n type Flags,\n GREEN_CHECK,\n loadTokens,\n printError,\n printSuccess,\n resolveConfig,\n} from './shared.js';\n\nexport interface BuildOptions {\n flags: Flags;\n config: ConfigInit;\n configPath: string;\n logger: Logger;\n}\n\n/** tz build */\nexport async function buildCmd({ config, configPath, flags, logger }: BuildOptions) {\n try {\n const startTime = performance.now();\n if (!Array.isArray(config.plugins) || !config.plugins.length) {\n logger.error({\n group: 'config',\n message: `No plugins defined! Add some in ${configPath || 'terrazzo.config.ts'}`,\n });\n }\n\n // first build\n let rawSchemas = await loadTokens(config.tokens, { logger });\n if (!rawSchemas) {\n logger.error({\n group: 'config',\n message: `Error loading ${path.relative(fileURLToPath(cwd), fileURLToPath(config.tokens[0] || DEFAULT_TOKENS_PATH))}`,\n });\n return;\n }\n let { tokens, resolver, sources } = await parse(rawSchemas, { config, logger, yamlToMomoa });\n let result = await build(tokens, { resolver, sources, config, logger });\n writeFiles(result, { config, logger });\n\n // --watch (handle rebuild)\n if (flags.watch) {\n const dt = new Intl.DateTimeFormat('en-us', {\n hour: '2-digit',\n minute: '2-digit',\n });\n\n async function rebuild({ messageBefore, messageAfter }: { messageBefore?: string; messageAfter?: string } = {}) {\n try {\n if (messageBefore) {\n logger.info({ group: 'plugin', label: 'watch', message: messageBefore });\n }\n rawSchemas = await loadTokens(config.tokens, { logger });\n if (!rawSchemas) {\n throw new Error(\n `Error loading ${path.relative(fileURLToPath(cwd), fileURLToPath(config.tokens[0] || DEFAULT_TOKENS_PATH))}`,\n );\n }\n const parseResult = await parse(rawSchemas, { config, logger, yamlToMomoa });\n tokens = parseResult.tokens;\n sources = parseResult.sources;\n resolver = parseResult.resolver;\n result = await build(tokens, { resolver, sources, config, logger });\n if (messageAfter) {\n logger.info({ group: 'plugin', label: 'watch', message: messageAfter });\n }\n writeFiles(result, { config, logger });\n } catch (err) {\n // biome-ignore lint/suspicious/noConsole: this is its job\n console.error(pc.red(`✗ ${(err as Error).message || (err as string)}`));\n // don’t exit! we’re watching, so continue as long as possible\n }\n }\n\n const tokenWatcher = chokidar.watch(config.tokens.map((filename) => fileURLToPath(filename)));\n tokenWatcher.on('change', async (filename) => {\n await rebuild({\n messageBefore: `${pc.dim(dt.format(new Date()))} ${pc.green('tz')}} ${pc.yellow(filename)} updated ${GREEN_CHECK}`,\n });\n });\n const configWatcher = chokidar.watch(resolveConfig(configPath)!);\n configWatcher.on('change', async () => {\n await rebuild({\n messageBefore: `${pc.dim(dt.format(new Date()))} ${pc.green('tz')} ${pc.yellow('Config updated. Reloading…')}`,\n });\n });\n\n // keep process occupied\n await new Promise(() => {});\n } else {\n printSuccess(\n `${Object.keys(tokens).length} token${Object.keys(tokens).length !== 1 ? 's' : ''} built`,\n startTime,\n );\n }\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\n/** Write files */\nexport function writeFiles(result: BuildRunnerResult, { config, logger }: { config: ConfigInit; logger: Logger }) {\n for (const { filename, contents } of result.outputFiles) {\n const output = new URL(filename, config.outDir);\n fs.mkdirSync(new URL('.', output), { recursive: true });\n fs.writeFileSync(output, contents);\n logger.debug({ group: 'parser', label: 'buildEnd', message: `Wrote file ${fileURLToPath(output)}` });\n }\n}\n","import { type ConfigInit, type Logger, parse } from '@terrazzo/parser';\nimport yamlToMomoa from 'yaml-to-momoa';\nimport { loadTokens, printError, printSuccess, resolveTokenPath } from './shared.js';\n\nexport interface CheckOptions {\n /** positional CLI args */\n positionals: string[];\n config: ConfigInit;\n logger: Logger;\n}\n\n/** tz check */\nexport async function checkCmd({ config, logger, positionals }: CheckOptions) {\n try {\n const startTime = performance.now();\n const tokenPaths = positionals.slice(1).length\n ? positionals.slice(1).map((tokenPath) => resolveTokenPath(tokenPath, { logger }))\n : config.tokens;\n const sources = await loadTokens(tokenPaths, { logger });\n if (!sources?.length) {\n logger.error({ group: 'config', message: 'Couldn’t find any tokens. Run `npx tz init` to create some.' });\n return;\n }\n await parse(sources, { config, continueOnError: true, logger, yamlToMomoa }); // will throw if errors\n printSuccess('No errors', startTime);\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n","/** Show help */\nexport function helpCmd() {\n // biome-ignore lint/suspicious/noConsole: this is its job\n console.log(`tz\n [commands]\n build Build token artifacts from tokens.json\n --watch, -w Watch tokens.json for changes and recompile\n --no-lint Disable linters running on build\n check [path] Check tokens.json for errors and run linters\n lint [path] (alias of check)\n init Create a starter tokens.json file\n lab Manage your tokens with a web interface\n import [path] Import from a Figma Design file\n --o [file] Save imported JSON\n --unpublished Include unpublished Variables\n --skip-styles Don’t import styles\n --skip-variables\n Don’t import variables\n\n [options]\n --help Show this message\n --config, -c Path to config (default: ./terrazzo.config.ts)\n --quiet Suppress warnings\n`);\n}\n","import type {\n GetFileNodesResponse,\n GetFileResponse,\n GetFileStylesResponse,\n GetLocalVariablesResponse,\n GetPublishedVariablesResponse,\n} from '@figma/rest-api-spec';\nimport type { Logger } from '@terrazzo/parser';\nimport { camelCase as sculeCamelCase } from 'scule';\n\nexport const KEY = ':key';\nexport const FILE_KEY = ':file_key';\nexport const API = {\n file: `https://api.figma.com/v1/files/${FILE_KEY}`,\n fileNodes: `https://api.figma.com/v1/files/${FILE_KEY}/nodes`,\n fileStyles: `https://api.figma.com/v1/files/${FILE_KEY}/styles`,\n localVariables: `https://api.figma.com/v1/files/${FILE_KEY}/variables/local`,\n publishedVariables: `https://api.figma.com/v1/files/${FILE_KEY}/variables/published`,\n styles: `https://api.figma.com/v1/styles/${KEY}`,\n};\n\n/** Wrapper around camelCase to handle more cases */\nexport function formatName(name: string): string {\n return sculeCamelCase(name.replace(/\\s+/g, '-'));\n}\n\nconst nf = new Intl.NumberFormat('en-us');\n\n/** Wrapper around camelCase to handle more cases */\nexport function formatNumber(number: number): string {\n return nf.format(number);\n}\n\n/** Get File ID from design URL */\nexport function getFileID(url: string) {\n return url.match(/^https:\\/\\/(www\\.)?figma\\.com\\/design\\/([^/]+)/)?.[2];\n}\n\n/** /v1/files/:file_key */\nexport async function getFile(fileKey: string, { logger }: { logger: Logger }) {\n const res = await fetch(API.file.replace(FILE_KEY, fileKey), {\n method: 'GET',\n headers: { 'X-Figma-Token': process.env.FIGMA_ACCESS_TOKEN! },\n });\n if (!res.ok) {\n logger.error({ group: 'import', message: `${res.status} ${await res.text()}` });\n }\n return (await res.json()) as GetFileResponse;\n}\n\n/** /v1/files/:file_key/nodes */\nexport async function getFileNodes(fileKey: string, { ids, logger }: { logger: Logger; ids?: string[] }) {\n let url = API.fileNodes.replace(FILE_KEY, fileKey);\n if (ids?.length) {\n url += `?ids=${ids.join(',')}`;\n }\n const res = await fetch(url, {\n method: 'GET',\n headers: { 'X-Figma-Token': process.env.FIGMA_ACCESS_TOKEN! },\n });\n if (!res.ok) {\n logger.error({ group: 'import', message: `${res.status} ${await res.text()}` });\n }\n return (await res.json()) as GetFileNodesResponse;\n}\n\n/** /v1/files/:file_key/styles */\nexport async function getFileStyles(fileKey: string, { logger }: { logger: Logger }) {\n const res = await fetch(API.fileStyles.replace(FILE_KEY, fileKey), {\n method: 'GET',\n headers: { 'X-Figma-Token': process.env.FIGMA_ACCESS_TOKEN! },\n });\n if (!res.ok) {\n logger.error({ group: 'import', message: `${res.status} ${await res.text()}` });\n }\n return (await res.json()) as GetFileStylesResponse;\n}\n\n/** /v1/files/:file_key/variables/local */\nexport async function getFileLocalVariables(fileKey: string, { logger }: { logger: Logger }) {\n const res = await fetch(API.localVariables.replace(FILE_KEY, fileKey), {\n method: 'GET',\n headers: { 'X-Figma-Token': process.env.FIGMA_ACCESS_TOKEN! },\n });\n if (!res.ok) {\n logger.error({ group: 'import', message: `${res.status} ${await res.text}` });\n }\n return (await res.json()) as GetLocalVariablesResponse;\n}\n\n/** /v1/files/:file_key/variables/published */\nexport async function getFilePublishedVariables(fileKey: string, { logger }: { logger: Logger }) {\n const res = await fetch(API.publishedVariables.replace(FILE_KEY, fileKey), {\n method: 'GET',\n headers: { 'X-Figma-Token': process.env.FIGMA_ACCESS_TOKEN! },\n });\n if (!res.ok) {\n logger.error({ group: 'import', message: `${res.status} ${await res.text}` });\n }\n return (await res.json()) as GetPublishedVariablesResponse;\n}\n","import type { DropShadowEffect, InnerShadowEffect, Node, PublishedStyle, Style } from '@figma/rest-api-spec';\nimport type {\n ColorValue,\n DimensionToken,\n GradientValue,\n Logger,\n NumberToken,\n ShadowValue,\n TypographyValue,\n} from '@terrazzo/parser';\nimport { formatName, getFile, getFileNodes, getFileStyles } from './lib.js';\n\n/** /v1/files/:file_key/styles */\nexport async function getStyles(\n fileKey: string,\n { logger, unpublished }: { logger: Logger; unpublished?: boolean },\n): Promise<{ count: number; code: any }> {\n const result: { count: number; code: any } = {\n count: 0,\n code: {\n sets: {\n styles: {\n sources: [{}],\n },\n },\n },\n };\n\n const styleNodeIDs = new Set<string>();\n const stylesByID = new Map<string, Style | PublishedStyle>();\n\n if (unpublished) {\n const styles = await getFile(fileKey, { logger });\n for (const [id, style] of Object.entries(styles.styles)) {\n styleNodeIDs.add(id);\n stylesByID.set(id, style);\n }\n } else {\n const styles = await getFileStyles(fileKey, { logger });\n for (const style of styles.meta.styles) {\n styleNodeIDs.add(style.node_id);\n stylesByID.set(style.node_id, style);\n }\n }\n\n const fileNodes = await getFileNodes(fileKey, { ids: [...styleNodeIDs], logger });\n\n result.count += styleNodeIDs.size;\n for (const [id, s] of stylesByID) {\n const styleNode = fileNodes.nodes[id];\n if (!styleNode) {\n logger.warn({\n group: 'import',\n message: `Style ${s.name} not found in file nodes. Does it need to be published?`,\n });\n continue;\n }\n\n const styleType = 'style_type' in s ? s.style_type : s.styleType;\n const tokenBase = {\n $type: undefined as any,\n $description: s.description || undefined,\n $value: undefined as any,\n $extensions: {\n 'figma.com': {\n name: s.name,\n node_id: id,\n created_at: 'created_at' in s ? s.created_at : undefined,\n updated_at: 'updated_at' in s ? s.updated_at : undefined,\n },\n },\n };\n\n switch (styleType) {\n case 'FILL': {\n const $value = fillStyle(styleNode.document);\n if (!$value) {\n logger.error({ group: 'import', message: `Could not parse fill for ${s.name}`, continueOnError: true });\n }\n if (Array.isArray($value)) {\n tokenBase.$type = 'gradient';\n } else {\n tokenBase.$type = 'color';\n }\n tokenBase.$value = $value;\n break;\n }\n case 'TEXT': {\n const $value = textStyle(styleNode.document);\n if (!$value) {\n logger.error({ group: 'import', message: `Could not parse text for ${s.name}`, continueOnError: true });\n }\n tokenBase.$type = 'typography';\n tokenBase.$value = $value;\n break;\n }\n case 'EFFECT': {\n const $value = effectStyle(styleNode.document);\n if (!$value) {\n logger.error({ group: 'import', message: `Could not parse effect for ${s.name}`, continueOnError: true });\n }\n tokenBase.$type = 'shadow';\n tokenBase.$value = $value;\n break;\n }\n case 'GRID': {\n const layoutGrids = gridStyles(styleNode.document);\n if (!layoutGrids) {\n logger.error({ group: 'import', message: `Could not parse grid for ${s.name}`, continueOnError: true });\n }\n // Note: Grids scaffold out multiple sub-components, so we need to “cheat” a little here\n let node = result.code.sets.styles.sources[0];\n const path = s.name.split('/').map(formatName);\n const name = path.pop()!;\n for (const key of path) {\n if (!(key in node)) {\n node[key] = {};\n }\n node = node[key];\n }\n node[name] = layoutGrids;\n break;\n }\n }\n\n // Only place in tree if we got a value for it\n if (tokenBase.$type !== undefined) {\n let node = result.code.sets.styles.sources[0];\n const path = s.name.split('/').map(formatName);\n const name = path.pop()!;\n for (const key of path) {\n if (!(key in node)) {\n node[key] = {};\n }\n node = node[key];\n }\n node[name] = tokenBase;\n }\n }\n\n return result;\n}\n\n/** Return a shadow token from an effect */\nexport function effectStyle(node: Node): ShadowValue[] | undefined {\n if ('effects' in node) {\n const shadows = node.effects.filter((e) => e.type === 'DROP_SHADOW' || e.type === 'INNER_SHADOW') as (\n | DropShadowEffect\n | InnerShadowEffect\n )[];\n if (shadows.length) {\n return shadows.map((s) => ({\n inset: s.type === 'INNER_SHADOW',\n offsetX: { value: s.offset.x, unit: 'px' },\n offsetY: { value: s.offset.y, unit: 'px' },\n blur: { value: s.radius, unit: 'px' },\n spread: { value: s.spread ?? 0, unit: 'px' },\n color: { colorSpace: 'srgb', components: [s.color.r, s.color.g, s.color.b], alpha: s.color.a },\n }));\n }\n }\n}\n\n/** Return a color or gradient token from a fill */\nexport function fillStyle(node: Node): ColorValue | GradientValue | undefined {\n if ('fills' in node) {\n for (const fill of node.fills) {\n switch (fill.type) {\n case 'SOLID': {\n return { colorSpace: 'srgb', components: [fill.color.r, fill.color.g, fill.color.b], alpha: fill.color.a };\n }\n case 'GRADIENT_LINEAR':\n case 'GRADIENT_RADIAL':\n case 'GRADIENT_ANGULAR':\n case 'GRADIENT_DIAMOND': {\n return fill.gradientStops.map((stop) => ({\n position: stop.position,\n color: { colorSpace: 'srgb', components: [stop.color.r, stop.color.g, stop.color.b], alpha: stop.color.a },\n }));\n }\n }\n }\n }\n}\n\n/** Return a dimension token from grid */\nexport function gridStyles(node: Node): Record<string, Record<string, DimensionToken | NumberToken>> | undefined {\n if (!('layoutGrids' in node) || !node.layoutGrids?.length) {\n return;\n }\n const values: Record<string, Record<string, DimensionToken | NumberToken>> = {};\n for (const grid of node.layoutGrids!) {\n const pattern = grid.pattern.toLowerCase();\n if (values[pattern]) {\n continue;\n }\n values[pattern] = {\n sectionSize: { $type: 'dimension', $value: { value: grid.sectionSize, unit: 'px' } },\n gutterSize: { $type: 'dimension', $value: { value: grid.sectionSize, unit: 'px' } },\n };\n if (grid.count > 0) {\n values[pattern].count = { $type: 'number', $value: grid.count };\n }\n }\n return values;\n}\n\n/** Return a typography token from text */\nexport function textStyle(node: Node): TypographyValue | undefined {\n if (!('style' in node)) {\n return;\n }\n return {\n fontFamily: [node.style.fontFamily!],\n fontWeight: node.style.fontWeight,\n fontStyle: node.style.fontStyle,\n fontSize: node.style.fontSize ? { value: node.style.fontSize, unit: 'px' } : { value: 1, unit: 'em' },\n letterSpacing: { value: node.style.letterSpacing ?? 0, unit: 'px' },\n lineHeight:\n 'lineHeightPercentFontSize' in node.style\n ? node.style.lineHeightPercentFontSize!\n : 'lineHeightPx' in node.style\n ? { value: node.style.lineHeightPx!, unit: 'px' }\n : 1,\n };\n}\n","import type { LocalVariable, LocalVariableCollection, RGBA } from '@figma/rest-api-spec';\nimport type { Logger } from '@terrazzo/parser';\nimport { formatName, getFileLocalVariables, getFilePublishedVariables } from './lib.js';\n\n/** /v1/files/:file_key/variables/published | /v1/files/:file_key/variables/local */\nexport async function getVariables(\n fileKey: string,\n {\n logger,\n unpublished,\n matchers,\n }: {\n logger: Logger;\n unpublished?: boolean;\n matchers: Record<'fontFamily' | 'fontWeight' | 'number', RegExp | undefined>;\n },\n): Promise<{ count: number; remoteCount: number; code: any }> {\n const result: { count: number; remoteCount: number; code: any } = {\n count: 0,\n remoteCount: 0,\n code: {\n sets: {},\n modifiers: {},\n },\n };\n\n const allVariables: Record<string, LocalVariable> = {};\n const variableCollections: Record<string, LocalVariableCollection> = {};\n let finalVariables: Record<string, LocalVariable> = {};\n const modeIDToName: Record<string, string> = {}; // Note: this can have duplicate values; they’ll be scoped in separate modifier contexts\n\n // We must always fetch local variables, no matter what, to get the data we need\n const local = await getFileLocalVariables(fileKey, { logger });\n for (const id of Object.keys(local.meta.variables)) {\n if (local.meta.variables[id]!.hiddenFromPublishing) {\n continue;\n }\n allVariables[id] = local.meta.variables[id]!;\n }\n for (const id of Object.keys(local.meta.variableCollections)) {\n variableCollections[id] = local.meta.variableCollections[id]!;\n for (const mode of local.meta.variableCollections[id]!.modes) {\n modeIDToName[mode.modeId] = formatName(mode.name);\n }\n }\n\n // If --unpublished is set, we’re ready to transform; otherwise, filter set from latest publish\n if (unpublished) {\n finalVariables = allVariables;\n } else {\n const published = await getFilePublishedVariables(fileKey, { logger });\n for (const id of Object.keys(published.meta.variables)) {\n finalVariables[id] = allVariables[id]!;\n }\n }\n\n const remoteIDs = new Set<string>();\n\n for (const id of Object.keys(finalVariables)) {\n const variable = finalVariables[id]!;\n const collection = variableCollections[variable.variableCollectionId]!;\n const collectionName = formatName(collection.name);\n const hasMultipleModes = collection.modes.length > 1;\n if (hasMultipleModes) {\n if (!(collectionName in result.code.modifiers)) {\n result.code.modifiers[collectionName] = {\n contexts: Object.fromEntries(collection.modes.map((m) => [formatName(m.name), [{}]])),\n default: modeIDToName[collection.defaultModeId],\n };\n }\n } else {\n if (!(collectionName in result.code.sets)) {\n result.code.sets[collectionName] = { sources: [{}] };\n }\n }\n\n const matches =\n (matchers.fontFamily?.test(variable.name) && 'fontFamily') ||\n (matchers.fontWeight?.test(variable.name) && 'fontWeight') ||\n (matchers.number?.test(variable.name) && 'number') ||\n undefined;\n\n for (const [modeID, value] of Object.entries(variable.valuesByMode)) {\n const modeName = modeIDToName[modeID]!;\n let node = result.code;\n if (hasMultipleModes) {\n if (!(modeName in result.code.modifiers[collectionName].contexts)) {\n // TODO: why did this happen? Why did we miss this? Is this a hidden conflict?\n result.code.modifiers[collectionName].contexts[modeName] = [{}];\n }\n node = result.code.modifiers[collectionName].contexts[modeName][0]!;\n } else {\n node = result.code.sets[collectionName].sources[0];\n }\n\n const tokenBase = {\n $type: undefined as any,\n $description: (variable as LocalVariable).description || undefined,\n $value: undefined as any,\n $extensions: {\n 'figma.com': {\n name: variable.name,\n id: variable.id,\n variableCollectionId: variable.variableCollectionId,\n codeSyntax: Object.keys(variable.codeSyntax).length ? variable.codeSyntax : undefined,\n },\n },\n };\n\n // If this token is an alias of another, keep this as a value override\n const isAliasOfID =\n (typeof value === 'object' && 'type' in value && value.type === 'VARIABLE_ALIAS' && value.id) || undefined;\n if (isAliasOfID) {\n if (allVariables[isAliasOfID]) {\n tokenBase.$type =\n matches ||\n { COLOR: 'color', BOOLEAN: 'boolean', STRING: 'string', FLOAT: 'dimension' }[variable.resolvedType];\n tokenBase.$value = `{${allVariables[isAliasOfID].name.split('/').map(formatName).join('.')}}`;\n } else {\n remoteIDs.add(isAliasOfID);\n continue;\n }\n } else if (matches === 'fontFamily') {\n tokenBase.$type = 'fontFamily';\n tokenBase.$value = String(value).split(',');\n } else if (matches === 'fontWeight') {\n tokenBase.$type = 'fontWeight';\n tokenBase.$value = value;\n } else if (matches === 'number') {\n if (typeof value === 'object') {\n throw new Error(`Can’t coerce ${variable.name} into number type.`);\n }\n tokenBase.$type = 'number';\n tokenBase.$value = Number(value); // fun fact: this coerces booleans correctly\n } else {\n switch (variable.resolvedType) {\n case 'BOOLEAN':\n case 'STRING': {\n tokenBase.$type = variable.resolvedType.toLowerCase();\n tokenBase.$value = value;\n break;\n }\n case 'FLOAT': {\n tokenBase.$type = 'dimension';\n tokenBase.$value = { value, unit: 'px' };\n break;\n }\n case 'COLOR': {\n const { r, g, b, a } = value as RGBA;\n tokenBase.$type = 'color';\n tokenBase.$value = { colorSpace: 'srgb', components: [r, g, b], alpha: a };\n break;\n }\n }\n }\n\n // Only place in tree if we got a value for it\n if (tokenBase.$value !== undefined) {\n const path = variable.name.split('/').map(formatName);\n const name = path.pop()!;\n for (const key of path) {\n if (!(key in node)) {\n node[key] = {};\n }\n node = node[key];\n }\n node[name] = tokenBase;\n }\n }\n }\n\n // Update counts\n result.count = Object.keys(finalVariables).length;\n result.remoteCount = remoteIDs.size;\n\n return result;\n}\n","import type { Logger } from '@terrazzo/parser';\nimport { pluralize } from '@terrazzo/token-tools';\nimport { merge } from 'merge-anything';\nimport { formatNumber, getFileID } from './lib.js';\nimport { getStyles } from './styles.js';\nimport { getVariables } from './variables.js';\n\nexport interface importFromFigmaOptions {\n url: string;\n logger: Logger;\n /** Grab unpublished Styles/Variables @default false */\n unpublished?: boolean;\n skipStyles?: boolean;\n skipVariables?: boolean;\n /** RegEx for overriding Variable types with fontFamily tokens */\n fontFamilyNames?: string;\n /** RegEx for overriding Variable types with fontWeight tokens */\n fontWeightNames?: string;\n /** RegEx for overriding Variable types with number tokens */\n numberNames?: string;\n}\n\nexport interface FigmaOutput {\n variableCount: number;\n styleCount: number;\n /** The Resolver JSON, in object format (could be any shape) */\n code: Record<string, any>;\n}\n\nexport async function importFromFigma({\n url,\n logger,\n unpublished,\n skipStyles,\n skipVariables,\n fontFamilyNames = '/fontFamily$',\n fontWeightNames = '/fontWeight$',\n numberNames,\n}: importFromFigmaOptions): Promise<FigmaOutput> {\n const fileKey = getFileID(url);\n if (!fileKey) {\n logger.error({ group: 'import', message: `Invalid Figma URL: ${url}` });\n }\n\n const result: FigmaOutput = {\n variableCount: 0,\n styleCount: 0,\n code: {\n $schema: 'https://www.designtokens.org/schemas/2025.10/resolver.json',\n version: '2025.10',\n resolutionOrder: [],\n sets: {},\n modifiers: {},\n },\n };\n\n try {\n const [styles, vars] = await Promise.all([\n !skipStyles ? getStyles(fileKey!, { logger }) : null,\n !skipVariables\n ? getVariables(fileKey!, {\n logger,\n unpublished,\n matchers: {\n fontFamily: fontFamilyNames ? new RegExp(fontFamilyNames) : undefined,\n fontWeight: fontWeightNames ? new RegExp(fontWeightNames) : undefined,\n number: numberNames ? new RegExp(numberNames) : undefined,\n },\n })\n : null,\n ]);\n if (styles) {\n result.styleCount += styles.count;\n result.code = merge(result.code, styles.code);\n }\n if (vars) {\n result.variableCount += vars.count;\n result.code = merge(result.code, vars.code);\n if (vars.remoteCount) {\n logger.warn({\n group: 'import',\n message: `${formatNumber(vars.remoteCount)} ${pluralize(vars.remoteCount, 'Variable', 'Variables')} were remote and could not be accessed. Try importing from other files to grab them.`,\n });\n }\n }\n } catch (err) {\n logger.error({ group: 'import', message: (err as Error).message });\n }\n\n // Arbitrarily guess on resolutionOrder\n for (const group of ['sets', 'modifiers'] as const) {\n for (const name of Object.keys(result.code[group])) {\n result.code.resolutionOrder.push({ $ref: `#/${group}/${name}` });\n }\n }\n\n return result;\n}\n\n/** Is this a valid URL, and one belonging to a Figma file? */\nexport function isFigmaPath(url: string) {\n try {\n new URL(url);\n return /^https:\\/\\/(www\\.)?figma\\.com\\/design\\/[A-Za-z0-9]+/.test(url);\n } catch {\n return false;\n }\n}\n","import fsSync from 'node:fs';\nimport fs from 'node:fs/promises';\nimport type { Logger } from '@terrazzo/parser';\nimport { pluralize } from '@terrazzo/token-tools';\nimport { importFromFigma, isFigmaPath } from './figma/index.js';\nimport { formatNumber } from './figma/lib.js';\n\nexport * from './figma/index.js';\n\nexport interface ImportCmdOptions {\n flags: {\n /** The output file @default stdout */\n output?: string;\n } & Record<string, any>;\n positionals: string[];\n logger: Logger;\n}\n\nexport async function importCmd({ flags, positionals, logger }: ImportCmdOptions) {\n const [_cmd, url] = positionals;\n if (!url) {\n logger.error({\n group: 'import',\n message: 'Missing import path. Expected `tz import [file]`.',\n });\n }\n\n if (isFigmaPath(url!)) {\n const { FIGMA_ACCESS_TOKEN } = process.env;\n if (!FIGMA_ACCESS_TOKEN) {\n logger.error({\n group: 'import',\n message: `FIGMA_ACCESS_TOKEN not set! See https://terrazzo.app/docs/guides/import-from-figma`,\n });\n }\n\n const start = performance.now();\n const result = await importFromFigma({\n url: url!,\n logger,\n unpublished: flags.unpublished,\n skipStyles: flags['skip-styles'],\n skipVariables: flags['skip-variables'],\n fontFamilyNames: flags['font-family-names'],\n fontWeightNames: flags['font-weight-names'],\n numberNames: flags['number-names'],\n });\n const end = performance.now() - start;\n\n if (flags.output) {\n const oldFile = fsSync.existsSync(flags.output) ? JSON.parse(await fs.readFile(flags.output, 'utf8')) : {};\n // merge with old file, if any\n const code = {\n $schema: result.code.$schema, // Reset $schema\n version: result.code.version, // Reset version\n // Note: it’s important to have resolutionOrder higher up, since sets and modifiers will be a mess\n resolutionOrder: oldFile.resolutionOrder?.length ? oldFile.resolutionOrder : result.code.resolutionOrder, // Rely on old file, since the Figma file won’t understand resolutionOrder\n sets: result.code.sets, // Overwrite old sets\n modifiers: result.code.modifiers, // Overwrite old modifiers\n $defs: oldFile.$defs, // Just in case\n $extensions: oldFile.$extensions, // Just in case\n };\n await fs.writeFile(flags.output, `${JSON.stringify(code, undefined, 2)}\\n`);\n logger.info({\n group: 'import',\n message: `Imported ${formatNumber(result.variableCount)} ${pluralize(result.variableCount, 'Variable', 'Variables')}, ${formatNumber(result.styleCount)} ${pluralize(result.styleCount, 'Style', 'Styles')} → ${flags.output}`,\n timing: end,\n });\n } else {\n process.stdout.write(JSON.stringify(result.code));\n }\n\n return;\n }\n\n // Other imports here\n}\n","import { spawn } from 'node:child_process';\nimport fsSync from 'node:fs';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { confirm, intro, multiselect, outro, select, spinner } from '@clack/prompts';\nimport type { Logger } from '@terrazzo/parser';\nimport { pluralize } from '@terrazzo/token-tools';\nimport { detect } from 'detect-package-manager';\nimport { generate } from 'escodegen';\nimport { type ESTree, parseModule } from 'meriyah';\nimport { cwd, loadConfig, printError } from './shared.js';\n\nconst INSTALL_COMMAND = {\n npm: 'install -D --silent',\n yarn: 'add -D --silent',\n pnpm: 'add -D --silent',\n bun: 'install -D --silent',\n};\n\nconst SYNTAX_SETTINGS = {\n format: {\n indent: { style: ' ' },\n quotes: 'single',\n semicolons: true,\n },\n};\n\nconst EXAMPLE_TOKENS_PATH = 'my-tokens.tokens.json';\n\ninterface ImportSpec {\n specifier: string;\n path: string;\n}\n\n// Local copy of dtcg-examples/index.json. Copied partially for security (no\n// arbitrary injection of URL fetches), but also efficiency (saves a\n// round-trip).\ntype DesignSystem =\n | 'adobe-spectrum'\n | 'apple-hig'\n | 'figma-sds'\n | 'github-primer'\n | 'ibm-carbon'\n | 'microsoft-fluent'\n | 'shopify-polaris';\n\nconst DESIGN_SYSTEMS: Record<DesignSystem, { name: string; author: string; tokens: string[] }> = {\n 'adobe-spectrum': {\n name: 'Spectrum',\n author: 'Adobe',\n tokens: ['dtcg-examples/adobe-spectrum.resolver.json'],\n },\n 'apple-hig': {\n name: 'Human Interface Guidelines',\n author: 'Apple',\n tokens: ['dtcg-examples/apple-hig.resolver.json'],\n },\n 'figma-sds': {\n name: 'Simple Design System',\n author: 'Figma',\n tokens: ['dtcg-examples/figma-sds.resolver.json'],\n },\n 'github-primer': {\n name: 'Primer',\n author: 'GitHub',\n tokens: ['dtcg-examples/github-primer.resolver.json'],\n },\n 'ibm-carbon': {\n name: 'Carbon',\n author: 'IBM',\n tokens: ['dtcg-examples/ibm-carbon.resolver.json'],\n },\n 'microsoft-fluent': {\n name: 'Fluent',\n author: 'Microsoft',\n tokens: ['dtcg-examples/microsoft-fluent.resolver.json'],\n },\n 'shopify-polaris': {\n name: 'Polaris',\n author: 'Shopify',\n tokens: ['dtcg-examples/shopify-polaris.resolver.json'],\n },\n};\n\nexport interface InitOptions {\n logger: Logger;\n}\n\nexport async function initCmd({ logger }: InitOptions) {\n try {\n intro('⛋ Welcome to Terrazzo');\n const packageManager = await detect({ cwd: fileURLToPath(cwd) });\n\n // TODO: pass in CLI flags?\n const { config, configPath = 'terrazzo.config.ts' } = await loadConfig({ cmd: 'init', flags: {}, logger });\n const tokensPath = config.tokens[0]!;\n const hasExistingConfig = fsSync.existsSync(configPath);\n let startFromDS = !(tokensPath && fsSync.existsSync(tokensPath));\n\n // 1. tokens\n if (tokensPath && fsSync.existsSync(tokensPath)) {\n if (\n await confirm({\n message: `Found tokens at ${path.relative(fileURLToPath(cwd), fileURLToPath(tokensPath))}. Overwrite with a new design system?`,\n })\n ) {\n startFromDS = true;\n }\n }\n\n if (startFromDS) {\n const ds = DESIGN_SYSTEMS[\n (await select({\n message: 'Start from existing design system?',\n options: [\n ...Object.entries(DESIGN_SYSTEMS).map(([id, { author, name }]) => ({\n value: id,\n label: `${author} ${name}`,\n })),\n { value: 'none', label: 'None' },\n ],\n })) as keyof typeof DESIGN_SYSTEMS\n ] as (typeof DESIGN_SYSTEMS)[DesignSystem] | undefined;\n\n if (ds) {\n const s = spinner();\n s.start('Downloading');\n await new Promise((resolve, reject) => {\n // security: spawn() is much safer than exec()\n const subprocess = spawn(packageManager, [INSTALL_COMMAND[packageManager], 'dtcg-examples'], { cwd });\n subprocess.on('error', reject);\n subprocess.on('exit', resolve);\n });\n s.stop('Download complete');\n\n if (hasExistingConfig) {\n await updateConfigTokens(configPath, ds.tokens);\n } else {\n await newConfigFile(configPath, ds.tokens);\n }\n } else {\n startFromDS = false; // we’ll use this later in the final check\n }\n }\n\n // 2. If a user selected no DS, and doesn’t have a config file, create one\n if (!hasExistingConfig) {\n await newConfigFile(configPath, [EXAMPLE_TOKENS_PATH]);\n await fs.writeFile(EXAMPLE_TOKENS_PATH, JSON.stringify(EXAMPLE_TOKENS, undefined, 2));\n }\n\n // 3. plugins\n const existingPlugins = config.plugins.map((p) => p.name);\n const pluginSelection = await multiselect({\n message: 'Install plugins?',\n options: [\n { value: ['@terrazzo/plugin-css'], label: 'CSS' },\n { value: ['@terrazzo/plugin-js'], label: 'JS + TS' },\n { value: ['@terrazzo/plugin-css', '@terrazzo/plugin-sass'], label: 'Sass' },\n { value: ['@terrazzo/plugin-tailwind'], label: 'Tailwind' },\n ],\n required: false,\n });\n const newPlugins = Array.isArray(pluginSelection)\n ? Array.from(new Set(pluginSelection.flat().filter((p) => !existingPlugins.includes(p))))\n : [];\n if (newPlugins?.length) {\n const plugins: ImportSpec[] = newPlugins.map((p) => ({ specifier: p.replace('@terrazzo/plugin-', ''), path: p }));\n const pluginCount = `${newPlugins.length} ${pluralize(newPlugins.length, 'plugin', 'plugins')}`;\n const s = spinner();\n s.start(`Installing ${pluginCount}`);\n // note: this is async to show the spinner\n await new Promise((resolve, reject) => {\n // security: spawn() is much safer than exec()\n const subprocess = spawn(packageManager, [INSTALL_COMMAND[packageManager], newPlugins.join(' ')], { cwd });\n subprocess.on('error', reject);\n subprocess.on('exit', resolve);\n });\n s.message('Updating config');\n\n await updateConfigPlugins(configPath, plugins);\n\n s.stop(`Installed ${pluginCount}`);\n }\n\n // 4. No tokens, no plugins\n if (!startFromDS && !newPlugins?.length) {\n outro('Nothing to do. Exiting.');\n return;\n }\n\n outro('⛋ Done! 🎉');\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\nasync function newConfigFile(configPath: string, tokens: string[], imports: ImportSpec[] = []) {\n await fs.writeFile(\n configPath,\n `import { defineConfig } from '@terrazzo/cli';\n${imports.map((p) => `import ${p.specifier} from '${p.path}';`).join('\\n')}\n\nexport default defineConfig({\n tokens: ['${tokens.join(\"', '\")}'],\n plugins: [\n ${imports.length ? imports.map((p) => `${p.specifier}(),`).join('\\n ') : '/** @see https://terrazzo.app/docs */'}\n ],\n outDir: './dist/',\n lint: {\n /** @see https://terrazzo.app/docs/linting */\n build: {\n enabled: true,\n },\n rules: {\n 'core/valid-color': 'error',\n 'core/valid-dimension': 'error',\n 'core/valid-font-family': 'error',\n 'core/valid-font-weight': 'error',\n 'core/valid-duration': 'error',\n 'core/valid-cubic-bezier': 'error',\n 'core/valid-number': 'error',\n 'core/valid-link': 'error',\n 'core/valid-boolean': 'error',\n 'core/valid-string': 'error',\n 'core/valid-stroke-style': 'error',\n 'core/valid-border': 'error',\n 'core/valid-transition': 'error',\n 'core/valid-shadow': 'error',\n 'core/valid-gradient': 'error',\n 'core/valid-typography': 'error',\n 'core/consistent-naming': 'warn',\n },\n },\n});`,\n );\n}\n\nfunction getConfigObjFromAst(ast: ESTree.Program, configPath: string) {\n const astExport = ast.body.find((node) => node.type === 'ExportDefaultDeclaration');\n if (!astExport) {\n const relConfigPath = configPath\n ? path.relative(fileURLToPath(cwd), fileURLToPath(new URL(configPath)))\n : undefined;\n throw new Error(`SyntaxError: ${relConfigPath} does not have default export.`);\n }\n\n const astConfig = (\n astExport.declaration.type === 'CallExpression'\n ? // export default defineConfig({ ... })\n astExport.declaration.arguments[0]\n : // export default { ... }\n astExport.declaration\n ) as ESTree.ObjectExpression;\n\n if (astConfig.type !== 'ObjectExpression') {\n throw new Error(`Config: expected object default export, received ${astConfig.type}.`);\n }\n\n return astConfig;\n}\n\nasync function updateConfigTokens(configPath: string, tokens: string[]) {\n const ast = parseModule(await fs.readFile(configPath, 'utf8'));\n const astConfig = getConfigObjFromAst(ast, configPath);\n\n let tokensKey = astConfig.properties.find(\n (p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === 'tokens',\n ) as ESTree.Property | undefined;\n if (!tokensKey) {\n tokensKey = {\n type: 'Property' as const,\n key: { type: 'Identifier', name: 'tokens' },\n method: false,\n computed: false,\n shorthand: false,\n value: {\n type: 'ArrayExpression',\n elements: tokens.map((value) => ({ type: 'Literal', value, raw: `'${value}'` })),\n },\n } as ESTree.Property;\n astConfig.properties.unshift(tokensKey); // inject into first position\n }\n\n await fs.writeFile(configPath, generate(ast, SYNTAX_SETTINGS));\n}\n\n/**\n * Add plugin imports\n * note: this has the potential to duplicate plugins, but we tried our\n * best to filter already, and this may be the user’s fault if they\n * selected to install a plugin already installed. But also, this is\n * easily-fixable, so let’s not waste too much time here (and possibly\n * introduce bugs).\n */\nasync function updateConfigPlugins(configPath: string, plugins: ImportSpec[]) {\n const ast = parseModule(await fs.readFile(configPath, 'utf8'));\n\n ast.body.push(\n ...plugins.map(\n (p) =>\n ({\n type: 'ImportDeclaration' as const,\n source: { type: 'Literal', value: p.path },\n specifiers: [{ type: 'ImportDefaultSpecifier', local: { type: 'Identifier', name: p.specifier } }],\n attributes: [],\n }) as ESTree.ImportDeclaration,\n ),\n );\n\n // add plugins to config.plugins\n const astConfig = getConfigObjFromAst(ast, configPath);\n const pluginsArray = (\n astConfig.properties.find(\n (property) =>\n property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === 'plugins', // ASTs are so fun 😑\n ) as ESTree.Property\n )?.value as ESTree.ArrayExpression | undefined;\n const pluginsAst = plugins.map(\n (p) =>\n ({\n type: 'CallExpression' as const,\n callee: { type: 'Identifier' as const, name: p.specifier },\n arguments: [],\n optional: false,\n }) as ESTree.CallExpression,\n );\n\n if (pluginsArray) {\n pluginsArray.elements.push(...pluginsAst);\n } else {\n astConfig.properties.push({\n type: 'Property',\n key: { type: 'Identifier', name: 'plugins' },\n value: { type: 'ArrayExpression', elements: pluginsAst },\n kind: 'init',\n computed: false,\n method: false,\n shorthand: false,\n });\n }\n\n await fs.writeFile(configPath, generate(ast, SYNTAX_SETTINGS));\n}\n\nconst EXAMPLE_TOKENS = {\n color: {\n $description: 'Color tokens',\n black: {\n '100': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.05, hex: '#0c0c0d' },\n },\n '200': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.1, hex: '#0c0c0d' },\n },\n '300': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.2, hex: '#0c0c0d' },\n },\n '400': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.34, hex: '#0c0c04' },\n },\n '500': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.7, hex: '#0c0c0d' },\n },\n '600': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.8, hex: '#0c0c0d' },\n },\n '700': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.85, hex: '#0c0c0d' },\n },\n '800': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.9, hex: '#0c0c0d' },\n },\n '900': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0.95, hex: '#0c0c0d' },\n },\n '1000': {\n $type: 'color',\n $value: { colorSpace: 'srgb', components: [0.047, 0.047, 0.047], alpha: 0, hex: '#0c0c0d' },\n },\n },\n },\n border: {\n $description: 'Border tokens',\n default: {\n type: 'border',\n $value: {\n color: '{color.black.900}',\n style: 'solid',\n width: { value: 1, unit: 'px' },\n },\n },\n },\n radius: {\n $description: 'Corner radius tokens',\n '100': { $value: { value: 0.25, unit: 'rem' } },\n },\n space: {\n $description: 'Dimension tokens',\n '100': { $value: { value: 0.25, unit: 'rem' } },\n },\n typography: {\n $description: 'Typography tokens',\n body: {\n $type: 'typography',\n $value: {\n fontFamily: '{typography.family.sans}',\n fontSize: '{typography.scale.03}',\n fontWeight: '{typography.weight.regular}',\n letterSpacing: { value: 0, unit: 'em' },\n lineHeight: 1,\n },\n },\n },\n};\n","import fsSync from 'node:fs';\nimport fs from 'node:fs/promises';\nimport { Readable, Writable } from 'node:stream';\nimport { fileURLToPath } from 'node:url';\nimport { serve } from '@hono/node-server';\nimport type { ConfigInit, Logger } from '@terrazzo/parser';\nimport mime from 'mime';\nimport type { Flags } from './shared.js';\n\nexport interface LabBuildOptions {\n flags: Flags;\n config: ConfigInit;\n configPath: string;\n logger: Logger;\n}\n\nexport async function labCmd({ config, logger }: LabBuildOptions) {\n /** TODO: handle multiple files */\n const [tokenFileUrl] = config.tokens;\n\n const staticFiles = new Set();\n const dirEntries = await fs.readdir(fileURLToPath(import.meta.resolve('./lab')), {\n withFileTypes: true,\n recursive: true,\n });\n for (const entry of dirEntries) {\n if (entry.isFile() === false) {\n continue;\n }\n const absolutePath = `${entry.parentPath.replaceAll('\\\\', '/')}/${entry.name}`;\n staticFiles.add(absolutePath.replace(fileURLToPath(import.meta.resolve('./lab')).replaceAll('\\\\', '/'), ''));\n }\n\n const server = serve(\n {\n port: 9000,\n overrideGlobalObjects: false,\n async fetch(request) {\n const url = new URL(request.url);\n const pathname = url.pathname;\n if (pathname === '/') {\n return new Response(\n Readable.toWeb(\n fsSync.createReadStream(fileURLToPath(import.meta.resolve('./lab/index.html'))),\n ) as ReadableStream,\n {\n headers: {\n 'Content-Type': 'text/html',\n },\n },\n );\n }\n if (pathname === '/api/tokens') {\n if (request.method === 'GET') {\n return new Response(\n Readable.toWeb(fsSync.createReadStream(tokenFileUrl as fsSync.PathLike)) as ReadableStream,\n {\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n },\n },\n );\n } else if (request.method === 'POST' && request.body) {\n await request.body.pipeTo(Writable.toWeb(fsSync.createWriteStream(tokenFileUrl as fsSync.PathLike)));\n return new Response(JSON.stringify({ success: true }), {\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n }\n }\n\n if (staticFiles.has(pathname)) {\n return new Response(\n Readable.toWeb(\n fsSync.createReadStream(fileURLToPath(import.meta.resolve(`./lab${pathname}`))),\n ) as ReadableStream,\n {\n headers: { 'Content-Type': mime.getType(pathname) ?? 'application/octet-stream' },\n },\n );\n }\n return new Response('Not found', { status: 404 });\n },\n },\n (info) => {\n logger.info({\n group: 'server',\n message: `Token Lab running at http://${info.address === '::' ? 'localhost' : info.address}:${info.port}`,\n });\n },\n );\n /**\n * The cli entrypoint is going to manually exit the process after labCmd returns.\n */\n await new Promise<void>((resolve, reject) => {\n server.on('close', resolve);\n server.on('error', reject);\n });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport * as momoa from '@humanwhocodes/momoa';\nimport { getObjMember, getObjMembers, traverse } from '@terrazzo/json-schema-tools';\nimport { defineConfig, type Logger, parse } from '@terrazzo/parser';\nimport { isAlias } from '@terrazzo/token-tools';\nimport { cwd, printError } from './shared.js';\n\nexport interface NormalizeOptions {\n logger: Logger;\n output: URL;\n}\n\nfunction findMember(name: string) {\n return function (member: momoa.MemberNode) {\n return member.name.type === 'String' && member.name.value === name;\n };\n}\n\nexport async function normalizeCmd(filename: string, { logger, output }: NormalizeOptions) {\n try {\n if (!filename) {\n logger.error({ group: 'config', message: 'Expected input: `tz normalize <tokens.json> -o output.json`' });\n return;\n }\n const sourceLoc = new URL(filename, cwd);\n if (!fs.existsSync(sourceLoc)) {\n logger.error({\n group: 'config',\n message: `Couldn’t find ${path.relative(cwd.href, sourceLoc.href)}. Does it exist?`,\n });\n }\n const sourceData = fs.readFileSync(sourceLoc, 'utf8');\n const document = momoa.parse(sourceData, { mode: 'jsonc' });\n const { tokens } = await parse([{ src: sourceData, filename: sourceLoc }], {\n config: defineConfig(\n {\n lint: {\n rules: {\n 'core/valid-color': 'off',\n 'core/valid-dimension': 'off',\n 'core/valid-duration': 'off',\n 'core/valid-typography': 'off',\n },\n },\n },\n { cwd },\n ),\n logger,\n });\n\n traverse(document, {\n enter(node, _parent, nodePath) {\n const token = tokens[nodePath.join('.')];\n if (!token || token.aliasOf || node.type !== 'Member' || node.value.type !== 'Object') {\n return;\n }\n const $valueI = node.value.members.findIndex(findMember('$value'));\n\n switch (token.$type) {\n case 'color': {\n if (node.value.members[$valueI]!.value.type === 'String') {\n if (isAlias(node.value.members[$valueI]!.value.value)) {\n return;\n }\n const hex = (node.value.members[$valueI]!.value as momoa.StringNode).value;\n node.value.members[$valueI]!.value = momoa.parse(\n JSON.stringify({\n ...token.$value,\n hex: hex.startsWith('#') ? hex.slice(0, 7) : undefined,\n }),\n ).body;\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n const modeName = (mode.members[i]!.name as momoa.StringNode).value;\n const hex = (mode.members[i]!.value as momoa.StringNode).value;\n mode.members[i]!.value = momoa.parse(\n JSON.stringify({\n ...token.mode[modeName]!.$value,\n hex: hex.startsWith('#') ? hex.slice(0, 7) : undefined,\n }),\n ).body;\n }\n }\n }\n }\n break;\n }\n case 'dimension':\n case 'duration': {\n if (node.value.members[$valueI]!.value.type === 'String') {\n if (isAlias(node.value.members[$valueI]!.value.value)) {\n return;\n }\n node.value.members[$valueI]!.value = normalizeDurationDimension(node.value.members[$valueI]!.value);\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n mode.members[i]!.value = normalizeDurationDimension(node.value.members[$valueI]!.value);\n }\n }\n }\n }\n break;\n }\n case 'typography': {\n if (node.value.members[$valueI]?.value.type !== 'Object') {\n return;\n }\n node.value.members[$valueI].value = normalizeTypography(node.value.members[$valueI].value);\n const $extensions = getObjMember(node.value, '$extensions');\n if ($extensions?.type === 'Object') {\n const mode = getObjMember($extensions, 'mode');\n if (mode?.type === 'Object') {\n for (let i = 0; i < mode.members.length; i++) {\n mode.members[i]!.value = normalizeTypography(mode.members[i]!.value as momoa.ObjectNode);\n }\n }\n }\n }\n }\n },\n });\n\n const outputLoc = new URL(output, cwd);\n fs.mkdirSync(new URL('.', outputLoc), { recursive: true });\n fs.writeFileSync(outputLoc, momoa.print(document, { indent: 2 }));\n } catch (err) {\n printError((err as Error).message);\n process.exit(1);\n }\n}\n\nfunction normalizeDurationDimension(node: momoa.StringNode) {\n const value = Number.parseFloat(node.value);\n if (!Number.isFinite(value)) {\n return node;\n }\n (node as any).type = 'Object';\n (node as any).members = (\n momoa.parse(JSON.stringify({ value, unit: node.value.replace(String(value), '') })).body as momoa.ObjectNode\n ).members;\n delete (node as any).value;\n return node;\n}\n\nfunction normalizeTypography(node: momoa.ObjectNode) {\n const { fontFamily, fontSize, fontWeight, letterSpacing, lineHeight } = getObjMembers(node);\n if (!fontFamily) {\n node.members.push((momoa.parse('{\"fontFamily\":[\"inherit\"]}').body as momoa.ObjectNode).members[0]!);\n }\n if (!fontSize) {\n node.members.push((momoa.parse('{\"fontSize\":{\"value\":1,\"unit\":\"rem\"}}').body as momoa.ObjectNode).members[0]!);\n }\n if (!fontWeight) {\n node.members.push((momoa.parse('{\"fontWeight\":400}').body as momoa.ObjectNode).members[0]!);\n }\n if (!letterSpacing) {\n node.members.push((momoa.parse('{\"letterSpacing\":{\"value\":0,\"unit\":\"rem\"}}').body as momoa.ObjectNode).members[0]!);\n }\n if (!lineHeight) {\n node.members.push((momoa.parse('{\"lineHeight\":1}').body as momoa.ObjectNode).members[0]!);\n }\n return node;\n}\n","import fs from 'node:fs';\n\nexport function versionCmd() {\n const { version } = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'));\n // biome-ignore lint/suspicious/noConsole: this is its job\n console.log(version);\n}\n","import { createRequire } from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport { type Config, type ConfigInit, defineConfig as defineConfigCore } from '@terrazzo/parser';\nimport { cwd } from './shared.js';\n\nexport * from './build.js';\nexport * from './check.js';\nexport * from './help.js';\nexport * from './import/index.js';\nexport * from './init.js';\nexport * from './lab.js';\nexport * from './normalize.js';\nexport * from './shared.js';\nexport * from './version.js';\n\nconst require = createRequire(cwd);\n\n// wrap defineConfig from @terrazzo/parser and add Node.js resolution\nexport function defineConfig(config: Config): ConfigInit {\n const normalizedConfig: Config = { ...config }; // note: we only need a shallow copy because we’re only mutating top-level `tokens`\n\n // Resolve tokens from npm modules, if any\n if (typeof normalizedConfig.tokens === 'string' || Array.isArray(normalizedConfig.tokens)) {\n normalizedConfig.tokens = (\n Array.isArray(normalizedConfig.tokens) ? normalizedConfig.tokens : [normalizedConfig.tokens]\n ).map((tokenPath) => {\n if (tokenPath.startsWith('.') || /^(https?|file):\\/\\//i.test(tokenPath)) {\n return tokenPath;\n }\n try {\n return pathToFileURL(require.resolve(tokenPath));\n } catch (err) {\n // biome-ignore lint/suspicious/noConsole: this is its job\n console.error(err);\n // this will throw an error if Node couldn’t automatically resolve it,\n // which will be true for many token paths. We don’t need to surface\n // that error; it’ll get its own error down the line if it’s a bad path.\n return tokenPath;\n }\n }) as string[];\n }\n\n return defineConfigCore(normalizedConfig, { cwd });\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@terrazzo/cli",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.6",
|
|
4
4
|
"description": "CLI for managing design tokens using the Design Tokens Community Group (DTCG) standard and generating code for any platform via plugins.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -36,17 +36,15 @@
|
|
|
36
36
|
"terrazzo": "bin/cli.js"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@clack/prompts": "^1.0.
|
|
39
|
+
"@clack/prompts": "^1.0.1",
|
|
40
40
|
"@hono/node-server": "^1.19.9",
|
|
41
41
|
"@humanwhocodes/momoa": "^3.3.10",
|
|
42
|
-
"
|
|
43
|
-
"chokidar": "^3.6.0",
|
|
42
|
+
"chokidar": "^5.0.0",
|
|
44
43
|
"detect-package-manager": "^3.0.2",
|
|
45
|
-
"
|
|
46
|
-
"dtcg-examples": "^1.0.2",
|
|
44
|
+
"dtcg-examples": "^1.0.3",
|
|
47
45
|
"escodegen": "^2.1.0",
|
|
48
46
|
"merge-anything": "^5.1.7",
|
|
49
|
-
"meriyah": "^
|
|
47
|
+
"meriyah": "^7.1.0",
|
|
50
48
|
"mime": "^4.1.0",
|
|
51
49
|
"picocolors": "^1.1.1",
|
|
52
50
|
"scule": "^1.3.0",
|
|
@@ -54,8 +52,8 @@
|
|
|
54
52
|
"vite-node": "^5.3.0",
|
|
55
53
|
"yaml-to-momoa": "0.0.8",
|
|
56
54
|
"@terrazzo/json-schema-tools": "^0.2.0",
|
|
57
|
-
"@terrazzo/parser": "^2.0.0-beta.
|
|
58
|
-
"@terrazzo/token-tools": "^2.0.0-beta.
|
|
55
|
+
"@terrazzo/parser": "^2.0.0-beta.6",
|
|
56
|
+
"@terrazzo/token-tools": "^2.0.0-beta.6"
|
|
59
57
|
},
|
|
60
58
|
"devDependencies": {
|
|
61
59
|
"@figma/rest-api-spec": "^0.36.0",
|
|
@@ -70,6 +68,7 @@
|
|
|
70
68
|
"@swc/core-win32-arm64-msvc": "1.13.19",
|
|
71
69
|
"@swc/core-win32-ia32-msvc": "1.13.19",
|
|
72
70
|
"@swc/core-win32-x64-msvc": "1.13.19",
|
|
71
|
+
"@types/escodegen": "^0.0.10",
|
|
73
72
|
"@vitejs/plugin-react-swc": "^4.2.3",
|
|
74
73
|
"react": "^19.2.4",
|
|
75
74
|
"react-dom": "^19.2.4"
|