@terrazzo/parser 0.1.3 → 0.2.0

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.
Files changed (118) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +17 -0
  3. package/CONTRIBUTING.md +0 -12
  4. package/dist/build/index.d.ts +19 -0
  5. package/dist/build/index.js +165 -0
  6. package/dist/build/index.js.map +1 -0
  7. package/dist/config.d.ts +7 -0
  8. package/dist/config.js +269 -0
  9. package/dist/config.js.map +1 -0
  10. package/{index.d.ts → dist/index.d.ts} +1 -5
  11. package/dist/index.js +13 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/lib/code-frame.d.ts +30 -0
  14. package/dist/lib/code-frame.js +108 -0
  15. package/dist/lib/code-frame.js.map +1 -0
  16. package/dist/lint/index.d.ts +11 -0
  17. package/dist/lint/index.js +102 -0
  18. package/dist/lint/index.js.map +1 -0
  19. package/dist/lint/plugin-core/index.d.ts +12 -0
  20. package/dist/lint/plugin-core/index.js +40 -0
  21. package/dist/lint/plugin-core/index.js.map +1 -0
  22. package/dist/lint/plugin-core/lib/docs.d.ts +1 -0
  23. package/dist/lint/plugin-core/lib/docs.js +4 -0
  24. package/dist/lint/plugin-core/lib/docs.js.map +1 -0
  25. package/dist/lint/plugin-core/rules/a11y-min-contrast.d.ts +39 -0
  26. package/dist/lint/plugin-core/rules/a11y-min-contrast.js +58 -0
  27. package/dist/lint/plugin-core/rules/a11y-min-contrast.js.map +1 -0
  28. package/dist/lint/plugin-core/rules/a11y-min-font-size.d.ts +13 -0
  29. package/dist/lint/plugin-core/rules/a11y-min-font-size.js +45 -0
  30. package/dist/lint/plugin-core/rules/a11y-min-font-size.js.map +1 -0
  31. package/dist/lint/plugin-core/rules/colorspace.d.ts +14 -0
  32. package/dist/lint/plugin-core/rules/colorspace.js +85 -0
  33. package/dist/lint/plugin-core/rules/colorspace.js.map +1 -0
  34. package/dist/lint/plugin-core/rules/consistent-naming.d.ts +11 -0
  35. package/dist/lint/plugin-core/rules/consistent-naming.js +49 -0
  36. package/dist/lint/plugin-core/rules/consistent-naming.js.map +1 -0
  37. package/dist/lint/plugin-core/rules/descriptions.d.ts +9 -0
  38. package/dist/lint/plugin-core/rules/descriptions.js +32 -0
  39. package/dist/lint/plugin-core/rules/descriptions.js.map +1 -0
  40. package/dist/lint/plugin-core/rules/duplicate-values.d.ts +9 -0
  41. package/dist/lint/plugin-core/rules/duplicate-values.js +65 -0
  42. package/dist/lint/plugin-core/rules/duplicate-values.js.map +1 -0
  43. package/dist/lint/plugin-core/rules/max-gamut.d.ts +14 -0
  44. package/dist/lint/plugin-core/rules/max-gamut.js +101 -0
  45. package/dist/lint/plugin-core/rules/max-gamut.js.map +1 -0
  46. package/dist/lint/plugin-core/rules/required-children.d.ts +18 -0
  47. package/dist/lint/plugin-core/rules/required-children.js +78 -0
  48. package/dist/lint/plugin-core/rules/required-children.js.map +1 -0
  49. package/dist/lint/plugin-core/rules/required-modes.d.ts +13 -0
  50. package/dist/lint/plugin-core/rules/required-modes.js +52 -0
  51. package/dist/lint/plugin-core/rules/required-modes.js.map +1 -0
  52. package/dist/lint/plugin-core/rules/required-typography-properties.d.ts +10 -0
  53. package/dist/lint/plugin-core/rules/required-typography-properties.js +38 -0
  54. package/dist/lint/plugin-core/rules/required-typography-properties.js.map +1 -0
  55. package/dist/logger.d.ts +76 -0
  56. package/dist/logger.js +123 -0
  57. package/dist/logger.js.map +1 -0
  58. package/dist/parse/alias.d.ts +51 -0
  59. package/dist/parse/alias.js +188 -0
  60. package/dist/parse/alias.js.map +1 -0
  61. package/dist/parse/index.d.ts +27 -0
  62. package/dist/parse/index.js +379 -0
  63. package/dist/parse/index.js.map +1 -0
  64. package/dist/parse/json.d.ts +36 -0
  65. package/dist/parse/json.js +88 -0
  66. package/dist/parse/json.js.map +1 -0
  67. package/dist/parse/normalize.d.ts +23 -0
  68. package/dist/parse/normalize.js +163 -0
  69. package/dist/parse/normalize.js.map +1 -0
  70. package/dist/parse/validate.d.ts +45 -0
  71. package/dist/parse/validate.js +601 -0
  72. package/dist/parse/validate.js.map +1 -0
  73. package/dist/types.d.ts +264 -0
  74. package/dist/types.js +2 -0
  75. package/dist/types.js.map +1 -0
  76. package/package.json +7 -7
  77. package/{build/index.js → src/build/index.ts} +47 -63
  78. package/src/config.ts +280 -0
  79. package/src/index.ts +18 -0
  80. package/{lib/code-frame.js → src/lib/code-frame.ts} +41 -8
  81. package/src/lint/index.ts +135 -0
  82. package/src/lint/plugin-core/index.ts +47 -0
  83. package/src/lint/plugin-core/lib/docs.ts +3 -0
  84. package/src/lint/plugin-core/rules/a11y-min-contrast.ts +91 -0
  85. package/src/lint/plugin-core/rules/a11y-min-font-size.ts +64 -0
  86. package/src/lint/plugin-core/rules/colorspace.ts +101 -0
  87. package/src/lint/plugin-core/rules/consistent-naming.ts +65 -0
  88. package/src/lint/plugin-core/rules/descriptions.ts +41 -0
  89. package/src/lint/plugin-core/rules/duplicate-values.ts +80 -0
  90. package/src/lint/plugin-core/rules/max-gamut.ts +121 -0
  91. package/src/lint/plugin-core/rules/required-children.ts +104 -0
  92. package/src/lint/plugin-core/rules/required-modes.ts +71 -0
  93. package/src/lint/plugin-core/rules/required-typography-properties.ts +53 -0
  94. package/{logger.js → src/logger.ts} +55 -16
  95. package/src/parse/alias.ts +224 -0
  96. package/src/parse/index.ts +457 -0
  97. package/src/parse/json.ts +106 -0
  98. package/{parse/normalize.js → src/parse/normalize.ts} +70 -24
  99. package/{parse/validate.js → src/parse/validate.ts} +154 -236
  100. package/src/types.ts +310 -0
  101. package/build/index.d.ts +0 -113
  102. package/config.d.ts +0 -64
  103. package/config.js +0 -206
  104. package/index.js +0 -35
  105. package/lib/code-frame.d.ts +0 -56
  106. package/lint/index.d.ts +0 -44
  107. package/lint/index.js +0 -59
  108. package/lint/plugin-core/index.d.ts +0 -3
  109. package/lint/plugin-core/index.js +0 -12
  110. package/lint/plugin-core/rules/duplicate-values.d.ts +0 -10
  111. package/lint/plugin-core/rules/duplicate-values.js +0 -68
  112. package/logger.d.ts +0 -71
  113. package/parse/index.d.ts +0 -45
  114. package/parse/index.js +0 -592
  115. package/parse/json.d.ts +0 -30
  116. package/parse/json.js +0 -94
  117. package/parse/normalize.d.ts +0 -3
  118. package/parse/validate.d.ts +0 -43
@@ -0,0 +1,264 @@
1
+ import type { AnyNode, DocumentNode } from '@humanwhocodes/momoa';
2
+ import type { TokenNormalized } from '@terrazzo/token-tools';
3
+ import type Logger from './logger.js';
4
+ export interface BuildHookOptions {
5
+ /** Map of tokens */
6
+ tokens: Record<string, TokenNormalized>;
7
+ /** Query transformed values */
8
+ getTransforms(params: TransformParams): TokenTransformed[];
9
+ /** Momoa documents */
10
+ sources: InputSource[];
11
+ outputFile: (
12
+ /** Filename to output (relative to outDir) */
13
+ filename: string,
14
+ /** Contents to write to file */
15
+ contents: string | Buffer) => void;
16
+ }
17
+ export interface BuildRunnerResult {
18
+ outputFiles: OutputFile[];
19
+ }
20
+ export interface BuildEndHookOptions {
21
+ /** Map of tokens */
22
+ tokens: Record<string, TokenNormalized>;
23
+ /** Query transformed values */
24
+ getTransforms(params: TransformParams): TokenTransformed[];
25
+ /** Momoa documents */
26
+ sources: InputSource[];
27
+ /** Final files to be written */
28
+ outputFiles: OutputFileExpanded[];
29
+ }
30
+ export interface Config {
31
+ /**
32
+ * Path to tokens.json
33
+ * @default "./tokens.json"
34
+ */
35
+ tokens?: string | string[];
36
+ /**
37
+ * Output directory
38
+ * @default "./tokens/"
39
+ */
40
+ outDir?: string;
41
+ /** Specify plugins */
42
+ plugins?: Plugin[];
43
+ /** Specify linting settings */
44
+ lint?: {
45
+ /** Configure build behavior */
46
+ build?: {
47
+ /**
48
+ * Should linters run with `tz build`?
49
+ * @default true
50
+ */
51
+ enabled?: boolean;
52
+ };
53
+ /** Configure lint rules */
54
+ rules?: Record<string, LintRuleShorthand | LintRuleLonghand>;
55
+ };
56
+ /** Ignore token groups */
57
+ ignore?: {
58
+ /** Token patterns to ignore. Accepts globs. */
59
+ tokens?: string[];
60
+ /** Ignore deprecated tokens */
61
+ deprecated?: boolean;
62
+ };
63
+ }
64
+ export interface ConfigInit {
65
+ tokens: URL[];
66
+ outDir: URL;
67
+ plugins: Plugin[];
68
+ lint: {
69
+ build: NonNullable<NonNullable<Config['lint']>['build']>;
70
+ rules: Record<string, [LintRuleSeverity, any]>;
71
+ };
72
+ ignore: {
73
+ tokens: string[];
74
+ deprecated: boolean;
75
+ };
76
+ }
77
+ export interface ConfigOptions {
78
+ logger?: Logger;
79
+ /** @terrazzo/parser needs cwd so this can be run without Node.js. Importing defineConfig from @terrazzo/cli doesn’t need this. */
80
+ cwd: URL;
81
+ }
82
+ export interface InputSource {
83
+ filename?: URL;
84
+ src: string;
85
+ document: DocumentNode;
86
+ }
87
+ export interface LintNotice {
88
+ /** Lint message shown to the user */
89
+ message: string;
90
+ /** Erring node (used to point to a specific line) */
91
+ node?: AnyNode;
92
+ }
93
+ export type LintRuleSeverity = 'error' | 'warn' | 'off';
94
+ export type LintRuleShorthand = LintRuleSeverity | 0 | 1 | 2;
95
+ export type LintRuleLonghand = [LintRuleSeverity | 0 | 1 | 2, any];
96
+ export interface LintRuleNormalized<O = any> {
97
+ id: string;
98
+ severity: LintRuleSeverity;
99
+ options?: O;
100
+ }
101
+ export type LintReportDescriptor<MessageIds extends string> = {
102
+ /** To error on a specific token source file, provide an erring node */
103
+ node?: AnyNode;
104
+ /** To error on a specific token source file, also provide the source */
105
+ source?: InputSource;
106
+ /** Provide data for messages */
107
+ data?: Record<string, unknown>;
108
+ } & ({
109
+ /** Provide the error message to display */
110
+ message: string;
111
+ messageId?: never;
112
+ } | {
113
+ message?: never;
114
+ /** Provide the error message ID */
115
+ messageId: MessageIds;
116
+ });
117
+ export interface LintRule<MessageIds extends string, LintRuleOptions extends object | undefined = undefined, LintRuleDocs = unknown> {
118
+ meta?: LintRuleMetaData<MessageIds, LintRuleOptions, LintRuleDocs>;
119
+ /**
120
+ * Function which returns an object with methods that ESLint calls to “visit”
121
+ * nodes while traversing the abstract syntax tree.
122
+ */
123
+ create(context: Readonly<LintRuleContext<MessageIds, LintRuleOptions>>): void | Promise<void>;
124
+ /**
125
+ * Default options the rule will be run with
126
+ */
127
+ defaultOptions: LintRuleOptions;
128
+ }
129
+ export interface LintRuleContext<MessageIds extends string, LintRuleOptions extends object | undefined = undefined> {
130
+ /** The rule ID. */
131
+ id: string;
132
+ /**
133
+ * An array of the configured options for this rule. This array does not
134
+ * include the rule severity.
135
+ */
136
+ options: LintRuleOptions;
137
+ /** The current working directory. */
138
+ cwd?: URL;
139
+ /** Source file the token came from. */
140
+ src: string;
141
+ /** Source file location. */
142
+ filename?: URL;
143
+ /** ID:Token map of all tokens. */
144
+ tokens: Record<string, TokenNormalized>;
145
+ /** Reports a problem in the code. */
146
+ report(descriptor: LintReportDescriptor<MessageIds>): void;
147
+ }
148
+ export interface LintRuleMetaData<MessageIds extends string, LintRuleOptions extends object | undefined = undefined, LintRuleDocs = unknown> {
149
+ /**
150
+ * Documentation for the rule
151
+ */
152
+ docs?: LintRuleDocs & LintRuleMetaDataDocs;
153
+ /**
154
+ * A map of messages which the rule can report. The key is the messageId, and
155
+ * the string is the parameterised error string.
156
+ */
157
+ messages?: Record<MessageIds, string>;
158
+ /**
159
+ * Specifies default options for the rule. If present, any user-provided
160
+ * options in their config will be merged on top of them recursively. This
161
+ * merging will be applied directly to `context.options`.
162
+ */
163
+ defaultOptions?: LintRuleOptions;
164
+ }
165
+ export interface LintRuleMetaDataDocs {
166
+ /** Concise description of the rule. */
167
+ description: string;
168
+ /** The URL of the rule's docs. */
169
+ url?: string;
170
+ }
171
+ export interface OutputFile {
172
+ /** Filename, relative to outDir */
173
+ filename: string;
174
+ /** File contents */
175
+ contents: string | Buffer;
176
+ /** Plugin name that generated the file */
177
+ plugin?: string;
178
+ /** Time taken to generate file */
179
+ time?: number;
180
+ }
181
+ export interface OutputFileExpanded extends OutputFile {
182
+ /** The `name` of the plugin that produced this file. */
183
+ plugin: string;
184
+ /** How long this output took to make. */
185
+ time: number;
186
+ }
187
+ export interface Plugin {
188
+ name: string;
189
+ /** Read config, and optionally modify */
190
+ config?(config: ConfigInit): void | ConfigInit | undefined;
191
+ /**
192
+ * Declare:
193
+ * - `"pre"`: run this plugin BEFORE all others
194
+ * - `"post"`: run this plugin AFTER all others
195
+ * - (default) run this plugin in default order (array order)
196
+ */
197
+ enforce?: 'pre' | 'post';
198
+ /** Throw lint errors/warnings */
199
+ lint?(): Record<string, LintRule<any, any, any>>;
200
+ transform?(options: TransformHookOptions): Promise<void>;
201
+ build?(options: BuildHookOptions): Promise<void>;
202
+ buildEnd?(result: BuildRunnerResult): Promise<void>;
203
+ }
204
+ /** Transformed token with a single value. Note that this may be any type! */
205
+ export interface TokenTransformedSingleValue {
206
+ /** Original Token ID */
207
+ id: string;
208
+ /** ID unique to this format. */
209
+ localID?: string;
210
+ type: 'SINGLE_VALUE';
211
+ value: string;
212
+ /**
213
+ * The mode of this value
214
+ * @default "."
215
+ */
216
+ mode: string;
217
+ /** The original token. */
218
+ token: TokenNormalized;
219
+ }
220
+ /** Transformed token with multiple values. Note that this may be any type! */
221
+ export interface TokenTransformedMultiValue {
222
+ /** Original Token ID */
223
+ id: string;
224
+ /** ID unique to this format.*/
225
+ localID?: string;
226
+ type: 'MULTI_VALUE';
227
+ value: Record<string, string>;
228
+ /**
229
+ * The mode of this value
230
+ * @default "."
231
+ */
232
+ mode: string;
233
+ /** The original token */
234
+ token: TokenNormalized;
235
+ }
236
+ export type TokenTransformed = TokenTransformedSingleValue | TokenTransformedMultiValue;
237
+ export interface TransformParams {
238
+ /** ID of an existing format */
239
+ format: string;
240
+ /** Glob of tokens to select (e.g. `"color.*"` to select all tokens starting with `"color."`) */
241
+ id?: string | string[];
242
+ /** $type(s) to filter for */
243
+ $type?: string | string[];
244
+ /**
245
+ * Mode name, if selecting a mode
246
+ * @default "."
247
+ */
248
+ mode?: string | string[];
249
+ }
250
+ export interface TransformHookOptions {
251
+ /** Map of tokens */
252
+ tokens: Record<string, TokenNormalized>;
253
+ /** Query transformed values */
254
+ getTransforms(params: TransformParams): TokenTransformed[];
255
+ /** Update transformed values */
256
+ setTransform(id: string, params: {
257
+ format: string;
258
+ localID?: string;
259
+ value: string | Record<string, string>;
260
+ mode?: string;
261
+ }): void;
262
+ /** Momoa documents */
263
+ sources: InputSource[];
264
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@terrazzo/parser",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "Parser/validator for the Design Tokens Community Group (DTCG) standard.",
5
5
  "type": "module",
6
6
  "author": {
@@ -21,7 +21,7 @@
21
21
  "linting",
22
22
  "lint"
23
23
  ],
24
- "main": "./index.js",
24
+ "main": "./dist/index.js",
25
25
  "homepage": "https://terrazzoapp.com/docs/cli/api/js",
26
26
  "repository": {
27
27
  "type": "git",
@@ -37,18 +37,18 @@
37
37
  "is-what": "^4.1.16",
38
38
  "merge-anything": "^5.1.7",
39
39
  "picocolors": "^1.1.1",
40
+ "scule": "^1.3.0",
40
41
  "wildcard-match": "^5.1.3",
41
- "yaml": "^2.6.0",
42
- "@terrazzo/token-tools": "^0.1.3"
42
+ "yaml": "^2.6.1",
43
+ "@terrazzo/token-tools": "^0.2.0"
43
44
  },
44
45
  "devDependencies": {
45
46
  "esbuild": "^0.23.1",
46
47
  "yaml-to-momoa": "^0.0.1"
47
48
  },
48
49
  "scripts": {
50
+ "build": "tsc -p tsconfig.build.json",
49
51
  "lint": "biome check .",
50
- "test": "pnpm --filter @terrazzo/parser run \"/^test:.*/\"",
51
- "test:js": "vitest run",
52
- "test:ts": "tsc --noEmit"
52
+ "test": "vitest run"
53
53
  }
54
54
  }
@@ -1,39 +1,26 @@
1
- import { isTokenMatch } from '@terrazzo/token-tools';
1
+ import type { DocumentNode } from '@humanwhocodes/momoa';
2
+ import { type TokenNormalized, isTokenMatch } from '@terrazzo/token-tools';
2
3
  import wcmatch from 'wildcard-match';
3
- import Logger from '../logger.js';
4
+ import Logger, { type LogEntry } from '../logger.js';
5
+ import type { BuildRunnerResult, ConfigInit, TokenTransformed, TransformParams } from '../types.js';
4
6
 
5
- /**
6
- * @typedef {object} BuildRunnerOptions
7
- * @typedef {Record<string, TokenNormalized>} BuildRunnerOptions.tokens
8
- * @typedef {Array} BuildRunnerOptions.sources
9
- * @typedef {ConfigInit} BuildRunnerOptions.config
10
- * @typedef {Logger} BuildRunnerOptions.logger
11
- * @typedef {import("@humanwhocodes/momoa").DocumentNode} DocumentNode
12
- * @typedef {import("../config.js").ConfigInit} ConfigInit
13
- * @typedef {import("../logger.js")} Logger
14
- * @typedef {import("../types.js").TokenNormalized} TokenNormalized
15
- *
16
- * @typedef {object} BuildRunnerResult
17
- * @typedef {OutputFile[]} BuildRunnerResult.outputFiles
18
- * @typedef {object} OutputFile
19
- * @typedef {string} OutputFile.filename
20
- * @typedef {string | Buffer} OutputFile.contents
21
- */
7
+ export interface BuildRunnerOptions {
8
+ sources: { filename?: URL; src: string; document: DocumentNode }[];
9
+ config: ConfigInit;
10
+ logger?: Logger;
11
+ }
22
12
 
23
13
  export const SINGLE_VALUE = 'SINGLE_VALUE';
24
14
  export const MULTI_VALUE = 'MULTI_VALUE';
25
15
 
26
16
  /** Validate plugin setTransform() calls for immediate feedback */
27
- function validateTransformParams({ params, token, logger, pluginName }) {
28
- const baseEntry = { group: 'plugin', task: pluginName };
17
+ function validateTransformParams({
18
+ params,
19
+ logger,
20
+ pluginName,
21
+ }: { params: TokenTransformed; logger: Logger; pluginName: string }) {
22
+ const baseEntry: LogEntry = { group: 'plugin', label: pluginName, message: '' };
29
23
 
30
- // validate ID
31
- if (!token) {
32
- logger.error({
33
- ...baseEntry,
34
- message: `setTransform() tried to transform token "${id}" but it doesn’t exist.`,
35
- });
36
- }
37
24
  // validate value is valid for SINGLE_VALUE or MULTI_VALUE
38
25
  if (
39
26
  !params.value ||
@@ -57,19 +44,20 @@ function validateTransformParams({ params, token, logger, pluginName }) {
57
44
 
58
45
  /**
59
46
  * Run build stage
60
- * @param {BuildOptions} options
61
- * @return {Promise<BuildResult>}
62
47
  */
63
- export default async function build(tokens, { sources, logger = new Logger(), config }) {
64
- const formats = {};
65
- const result = { outputFiles: [] };
48
+ export default async function build(
49
+ tokens: Record<string, TokenNormalized>,
50
+ { sources, logger = new Logger(), config }: BuildRunnerOptions,
51
+ ) {
52
+ const formats: Record<string, TokenTransformed[]> = {};
53
+ const result: BuildRunnerResult = { outputFiles: [] };
66
54
 
67
- function getTransforms(params) {
55
+ function getTransforms(params: TransformParams) {
68
56
  return (formats[params.format] ?? []).filter((token) => {
69
57
  if (params.$type) {
70
58
  if (typeof params.$type === 'string' && token.token.$type !== params.$type) {
71
59
  return false;
72
- } else if (Array.isArray(params.$type) && !params.$type.some(($type) => token.token.type === $type)) {
60
+ } else if (Array.isArray(params.$type) && !params.$type.some(($type) => token.token.$type === $type)) {
73
61
  return false;
74
62
  }
75
63
  }
@@ -90,7 +78,7 @@ export default async function build(tokens, { sources, logger = new Logger(), co
90
78
  // transform()
91
79
  let transformsLocked = false; // prevent plugins from transforming after stage has ended
92
80
  const startTransform = performance.now();
93
- logger.debug({ group: 'parser', task: 'transform', message: 'Start transform' });
81
+ logger.debug({ group: 'parser', label: 'transform', message: 'Start transform' });
94
82
  for (const plugin of config.plugins) {
95
83
  if (typeof plugin.transform === 'function') {
96
84
  await plugin.transform({
@@ -102,16 +90,17 @@ export default async function build(tokens, { sources, logger = new Logger(), co
102
90
  logger.warn({
103
91
  message: 'Attempted to call setTransform() after transform step has completed.',
104
92
  group: 'plugin',
105
- task: plugin.name,
93
+ label: plugin.name,
106
94
  });
107
95
  return;
108
96
  }
109
- const token = tokens[id];
97
+ const token = tokens[id]!;
110
98
 
111
99
  // allow `undefined` values, but remove them here
112
- const cleanValue = typeof params.value === 'string' ? params.value : { ...params.value };
100
+ const cleanValue: TokenTransformed['value'] =
101
+ typeof params.value === 'string' ? params.value : { ...(params.value as Record<string, string>) };
113
102
  if (typeof cleanValue === 'object') {
114
- for (const k in cleanValue) {
103
+ for (const k of Object.keys(cleanValue)) {
115
104
  if (Object.hasOwn(cleanValue, k)) {
116
105
  if (cleanValue[k] === undefined) {
117
106
  delete cleanValue[k];
@@ -120,30 +109,31 @@ export default async function build(tokens, { sources, logger = new Logger(), co
120
109
  }
121
110
  }
122
111
 
123
- validateTransformParams({ token, logger, params: { ...params, value: cleanValue }, pluginName: plugin.name });
112
+ validateTransformParams({
113
+ logger,
114
+ params: { ...(params as any), value: cleanValue },
115
+ pluginName: plugin.name,
116
+ });
124
117
 
125
118
  // upsert
126
119
  if (!formats[params.format]) {
127
120
  formats[params.format] = [];
128
121
  }
129
- const foundTokenI = formats[params.format].findIndex(
130
- (t) =>
131
- id === t.id &&
132
- params.localID === t.localID &&
133
- (!params.mode || params.mode === t.mode) &&
134
- (!params.variant || params.variant === t.variant),
122
+ const foundTokenI = formats[params.format]!.findIndex(
123
+ (t) => id === t.id && params.localID === t.localID && (!params.mode || params.mode === t.mode),
135
124
  );
136
125
  if (foundTokenI === -1) {
137
- formats[params.format].push({
126
+ formats[params.format]!.push({
138
127
  ...params,
128
+ id,
139
129
  value: cleanValue,
140
130
  type: typeof cleanValue === 'string' ? SINGLE_VALUE : MULTI_VALUE,
141
131
  mode: params.mode || '.',
142
132
  token: structuredClone(token),
143
- });
133
+ } as TokenTransformed);
144
134
  } else {
145
- formats[params.format][foundTokenI].value = cleanValue;
146
- formats[params.format][foundTokenI].type = typeof cleanValue === 'string' ? SINGLE_VALUE : MULTI_VALUE;
135
+ formats[params.format]![foundTokenI]!.value = cleanValue;
136
+ formats[params.format]![foundTokenI]!.type = typeof cleanValue === 'string' ? SINGLE_VALUE : MULTI_VALUE;
147
137
  }
148
138
  },
149
139
  });
@@ -152,14 +142,14 @@ export default async function build(tokens, { sources, logger = new Logger(), co
152
142
  transformsLocked = true;
153
143
  logger.debug({
154
144
  group: 'parser',
155
- task: 'transform',
145
+ label: 'transform',
156
146
  message: 'Finish transform',
157
147
  timing: performance.now() - startTransform,
158
148
  });
159
149
 
160
150
  // build()
161
151
  const startBuild = performance.now();
162
- logger.debug({ group: 'parser', task: 'build', message: 'Start build' });
152
+ logger.debug({ group: 'parser', label: 'build', message: 'Start build' });
163
153
  for (const plugin of config.plugins) {
164
154
  if (typeof plugin.build === 'function') {
165
155
  const pluginBuildStart = performance.now();
@@ -184,28 +174,22 @@ export default async function build(tokens, { sources, logger = new Logger(), co
184
174
  }
185
175
  logger.debug({
186
176
  group: 'parser',
187
- task: 'build',
177
+ label: 'build',
188
178
  message: 'Finish build',
189
179
  timing: performance.now() - startBuild,
190
180
  });
191
181
 
192
182
  // buildEnd()
193
183
  const startBuildEnd = performance.now();
194
- logger.debug({ group: 'parser', task: 'build', message: 'Start buildEnd' });
184
+ logger.debug({ group: 'parser', label: 'build', message: 'Start buildEnd' });
195
185
  for (const plugin of config.plugins) {
196
186
  if (typeof plugin.buildEnd === 'function') {
197
- await plugin.buildEnd({
198
- tokens,
199
- sources,
200
- getTransforms,
201
- format: (formatID) => createFormatter(formatID),
202
- outputFiles: structruedClone(result.outputFiles),
203
- });
187
+ await plugin.buildEnd({ outputFiles: structuredClone(result.outputFiles) });
204
188
  }
205
189
  }
206
190
  logger.debug({
207
191
  group: 'parser',
208
- task: 'build',
192
+ label: 'build',
209
193
  message: 'Finish buildEnd',
210
194
  timing: performance.now() - startBuildEnd,
211
195
  });