@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.
- package/.turbo/turbo-build.log +4 -0
- package/CHANGELOG.md +17 -0
- package/CONTRIBUTING.md +0 -12
- package/dist/build/index.d.ts +19 -0
- package/dist/build/index.js +165 -0
- package/dist/build/index.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.js +269 -0
- package/dist/config.js.map +1 -0
- package/{index.d.ts → dist/index.d.ts} +1 -5
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/code-frame.d.ts +30 -0
- package/dist/lib/code-frame.js +108 -0
- package/dist/lib/code-frame.js.map +1 -0
- package/dist/lint/index.d.ts +11 -0
- package/dist/lint/index.js +102 -0
- package/dist/lint/index.js.map +1 -0
- package/dist/lint/plugin-core/index.d.ts +12 -0
- package/dist/lint/plugin-core/index.js +40 -0
- package/dist/lint/plugin-core/index.js.map +1 -0
- package/dist/lint/plugin-core/lib/docs.d.ts +1 -0
- package/dist/lint/plugin-core/lib/docs.js +4 -0
- package/dist/lint/plugin-core/lib/docs.js.map +1 -0
- package/dist/lint/plugin-core/rules/a11y-min-contrast.d.ts +39 -0
- package/dist/lint/plugin-core/rules/a11y-min-contrast.js +58 -0
- package/dist/lint/plugin-core/rules/a11y-min-contrast.js.map +1 -0
- package/dist/lint/plugin-core/rules/a11y-min-font-size.d.ts +13 -0
- package/dist/lint/plugin-core/rules/a11y-min-font-size.js +45 -0
- package/dist/lint/plugin-core/rules/a11y-min-font-size.js.map +1 -0
- package/dist/lint/plugin-core/rules/colorspace.d.ts +14 -0
- package/dist/lint/plugin-core/rules/colorspace.js +85 -0
- package/dist/lint/plugin-core/rules/colorspace.js.map +1 -0
- package/dist/lint/plugin-core/rules/consistent-naming.d.ts +11 -0
- package/dist/lint/plugin-core/rules/consistent-naming.js +49 -0
- package/dist/lint/plugin-core/rules/consistent-naming.js.map +1 -0
- package/dist/lint/plugin-core/rules/descriptions.d.ts +9 -0
- package/dist/lint/plugin-core/rules/descriptions.js +32 -0
- package/dist/lint/plugin-core/rules/descriptions.js.map +1 -0
- package/dist/lint/plugin-core/rules/duplicate-values.d.ts +9 -0
- package/dist/lint/plugin-core/rules/duplicate-values.js +65 -0
- package/dist/lint/plugin-core/rules/duplicate-values.js.map +1 -0
- package/dist/lint/plugin-core/rules/max-gamut.d.ts +14 -0
- package/dist/lint/plugin-core/rules/max-gamut.js +101 -0
- package/dist/lint/plugin-core/rules/max-gamut.js.map +1 -0
- package/dist/lint/plugin-core/rules/required-children.d.ts +18 -0
- package/dist/lint/plugin-core/rules/required-children.js +78 -0
- package/dist/lint/plugin-core/rules/required-children.js.map +1 -0
- package/dist/lint/plugin-core/rules/required-modes.d.ts +13 -0
- package/dist/lint/plugin-core/rules/required-modes.js +52 -0
- package/dist/lint/plugin-core/rules/required-modes.js.map +1 -0
- package/dist/lint/plugin-core/rules/required-typography-properties.d.ts +10 -0
- package/dist/lint/plugin-core/rules/required-typography-properties.js +38 -0
- package/dist/lint/plugin-core/rules/required-typography-properties.js.map +1 -0
- package/dist/logger.d.ts +76 -0
- package/dist/logger.js +123 -0
- package/dist/logger.js.map +1 -0
- package/dist/parse/alias.d.ts +51 -0
- package/dist/parse/alias.js +188 -0
- package/dist/parse/alias.js.map +1 -0
- package/dist/parse/index.d.ts +27 -0
- package/dist/parse/index.js +379 -0
- package/dist/parse/index.js.map +1 -0
- package/dist/parse/json.d.ts +36 -0
- package/dist/parse/json.js +88 -0
- package/dist/parse/json.js.map +1 -0
- package/dist/parse/normalize.d.ts +23 -0
- package/dist/parse/normalize.js +163 -0
- package/dist/parse/normalize.js.map +1 -0
- package/dist/parse/validate.d.ts +45 -0
- package/dist/parse/validate.js +601 -0
- package/dist/parse/validate.js.map +1 -0
- package/dist/types.d.ts +264 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +7 -7
- package/{build/index.js → src/build/index.ts} +47 -63
- package/src/config.ts +280 -0
- package/src/index.ts +18 -0
- package/{lib/code-frame.js → src/lib/code-frame.ts} +41 -8
- package/src/lint/index.ts +135 -0
- package/src/lint/plugin-core/index.ts +47 -0
- package/src/lint/plugin-core/lib/docs.ts +3 -0
- package/src/lint/plugin-core/rules/a11y-min-contrast.ts +91 -0
- package/src/lint/plugin-core/rules/a11y-min-font-size.ts +64 -0
- package/src/lint/plugin-core/rules/colorspace.ts +101 -0
- package/src/lint/plugin-core/rules/consistent-naming.ts +65 -0
- package/src/lint/plugin-core/rules/descriptions.ts +41 -0
- package/src/lint/plugin-core/rules/duplicate-values.ts +80 -0
- package/src/lint/plugin-core/rules/max-gamut.ts +121 -0
- package/src/lint/plugin-core/rules/required-children.ts +104 -0
- package/src/lint/plugin-core/rules/required-modes.ts +71 -0
- package/src/lint/plugin-core/rules/required-typography-properties.ts +53 -0
- package/{logger.js → src/logger.ts} +55 -16
- package/src/parse/alias.ts +224 -0
- package/src/parse/index.ts +457 -0
- package/src/parse/json.ts +106 -0
- package/{parse/normalize.js → src/parse/normalize.ts} +70 -24
- package/{parse/validate.js → src/parse/validate.ts} +154 -236
- package/src/types.ts +310 -0
- package/build/index.d.ts +0 -113
- package/config.d.ts +0 -64
- package/config.js +0 -206
- package/index.js +0 -35
- package/lib/code-frame.d.ts +0 -56
- package/lint/index.d.ts +0 -44
- package/lint/index.js +0 -59
- package/lint/plugin-core/index.d.ts +0 -3
- package/lint/plugin-core/index.js +0 -12
- package/lint/plugin-core/rules/duplicate-values.d.ts +0 -10
- package/lint/plugin-core/rules/duplicate-values.js +0 -68
- package/logger.d.ts +0 -71
- package/parse/index.d.ts +0 -45
- package/parse/index.js +0 -592
- package/parse/json.d.ts +0 -30
- package/parse/json.js +0 -94
- package/parse/normalize.d.ts +0 -3
- package/parse/validate.d.ts +0 -43
package/dist/types.d.ts
ADDED
|
@@ -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 @@
|
|
|
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.
|
|
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.
|
|
42
|
-
"@terrazzo/token-tools": "^0.
|
|
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": "
|
|
51
|
-
"test:js": "vitest run",
|
|
52
|
-
"test:ts": "tsc --noEmit"
|
|
52
|
+
"test": "vitest run"
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -1,39 +1,26 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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({
|
|
28
|
-
|
|
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(
|
|
64
|
-
|
|
65
|
-
|
|
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
|
|
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',
|
|
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
|
-
|
|
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
|
|
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
|
|
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({
|
|
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]
|
|
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]
|
|
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]
|
|
146
|
-
formats[params.format][foundTokenI]
|
|
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
|
-
|
|
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',
|
|
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
|
-
|
|
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',
|
|
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
|
-
|
|
192
|
+
label: 'build',
|
|
209
193
|
message: 'Finish buildEnd',
|
|
210
194
|
timing: performance.now() - startBuildEnd,
|
|
211
195
|
});
|