@terrazzo/parser 0.7.2 → 0.8.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/CHANGELOG.md +20 -0
- package/dist/index.d.ts +707 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4598 -12
- package/dist/index.js.map +1 -1
- package/package.json +11 -7
- package/rolldown.config.ts +24 -0
- package/src/build/index.ts +2 -2
- package/src/index.ts +76 -1
- package/src/parse/index.ts +72 -13
- package/src/parse/json.ts +35 -29
- package/src/parse/normalize.ts +4 -14
- package/src/parse/validate.ts +81 -68
- package/dist/build/index.d.ts +0 -20
- package/dist/build/index.d.ts.map +0 -1
- package/dist/build/index.js +0 -166
- package/dist/build/index.js.map +0 -1
- package/dist/config.d.ts +0 -8
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -290
- package/dist/config.js.map +0 -1
- package/dist/lib/code-frame.d.ts +0 -31
- package/dist/lib/code-frame.d.ts.map +0 -1
- package/dist/lib/code-frame.js +0 -108
- package/dist/lib/code-frame.js.map +0 -1
- package/dist/lint/index.d.ts +0 -12
- package/dist/lint/index.d.ts.map +0 -1
- package/dist/lint/index.js +0 -105
- package/dist/lint/index.js.map +0 -1
- package/dist/lint/plugin-core/index.d.ts +0 -13
- package/dist/lint/plugin-core/index.d.ts.map +0 -1
- package/dist/lint/plugin-core/index.js +0 -40
- package/dist/lint/plugin-core/index.js.map +0 -1
- package/dist/lint/plugin-core/lib/docs.d.ts +0 -2
- package/dist/lint/plugin-core/lib/docs.d.ts.map +0 -1
- package/dist/lint/plugin-core/lib/docs.js +0 -4
- package/dist/lint/plugin-core/lib/docs.js.map +0 -1
- package/dist/lint/plugin-core/rules/a11y-min-contrast.d.ts +0 -40
- package/dist/lint/plugin-core/rules/a11y-min-contrast.d.ts.map +0 -1
- package/dist/lint/plugin-core/rules/a11y-min-contrast.js +0 -58
- package/dist/lint/plugin-core/rules/a11y-min-contrast.js.map +0 -1
- package/dist/lint/plugin-core/rules/a11y-min-font-size.d.ts +0 -14
- package/dist/lint/plugin-core/rules/a11y-min-font-size.d.ts.map +0 -1
- package/dist/lint/plugin-core/rules/a11y-min-font-size.js +0 -45
- package/dist/lint/plugin-core/rules/a11y-min-font-size.js.map +0 -1
- package/dist/lint/plugin-core/rules/colorspace.d.ts +0 -15
- package/dist/lint/plugin-core/rules/colorspace.d.ts.map +0 -1
- package/dist/lint/plugin-core/rules/colorspace.js +0 -85
- package/dist/lint/plugin-core/rules/colorspace.js.map +0 -1
- package/dist/lint/plugin-core/rules/consistent-naming.d.ts +0 -12
- package/dist/lint/plugin-core/rules/consistent-naming.d.ts.map +0 -1
- package/dist/lint/plugin-core/rules/consistent-naming.js +0 -49
- package/dist/lint/plugin-core/rules/consistent-naming.js.map +0 -1
- package/dist/lint/plugin-core/rules/descriptions.d.ts +0 -10
- package/dist/lint/plugin-core/rules/descriptions.d.ts.map +0 -1
- package/dist/lint/plugin-core/rules/descriptions.js +0 -32
- package/dist/lint/plugin-core/rules/descriptions.js.map +0 -1
- package/dist/lint/plugin-core/rules/duplicate-values.d.ts +0 -10
- package/dist/lint/plugin-core/rules/duplicate-values.d.ts.map +0 -1
- package/dist/lint/plugin-core/rules/duplicate-values.js +0 -65
- package/dist/lint/plugin-core/rules/duplicate-values.js.map +0 -1
- package/dist/lint/plugin-core/rules/max-gamut.d.ts +0 -15
- package/dist/lint/plugin-core/rules/max-gamut.d.ts.map +0 -1
- package/dist/lint/plugin-core/rules/max-gamut.js +0 -101
- package/dist/lint/plugin-core/rules/max-gamut.js.map +0 -1
- package/dist/lint/plugin-core/rules/required-children.d.ts +0 -19
- package/dist/lint/plugin-core/rules/required-children.d.ts.map +0 -1
- package/dist/lint/plugin-core/rules/required-children.js +0 -78
- package/dist/lint/plugin-core/rules/required-children.js.map +0 -1
- package/dist/lint/plugin-core/rules/required-modes.d.ts +0 -14
- package/dist/lint/plugin-core/rules/required-modes.d.ts.map +0 -1
- package/dist/lint/plugin-core/rules/required-modes.js +0 -52
- package/dist/lint/plugin-core/rules/required-modes.js.map +0 -1
- package/dist/lint/plugin-core/rules/required-typography-properties.d.ts +0 -11
- package/dist/lint/plugin-core/rules/required-typography-properties.d.ts.map +0 -1
- package/dist/lint/plugin-core/rules/required-typography-properties.js +0 -38
- package/dist/lint/plugin-core/rules/required-typography-properties.js.map +0 -1
- package/dist/logger.d.ts +0 -77
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -136
- package/dist/logger.js.map +0 -1
- package/dist/parse/alias.d.ts +0 -34
- package/dist/parse/alias.d.ts.map +0 -1
- package/dist/parse/alias.js +0 -302
- package/dist/parse/alias.js.map +0 -1
- package/dist/parse/index.d.ts +0 -36
- package/dist/parse/index.d.ts.map +0 -1
- package/dist/parse/index.js +0 -226
- package/dist/parse/index.js.map +0 -1
- package/dist/parse/json.d.ts +0 -52
- package/dist/parse/json.d.ts.map +0 -1
- package/dist/parse/json.js +0 -161
- package/dist/parse/json.js.map +0 -1
- package/dist/parse/normalize.d.ts +0 -24
- package/dist/parse/normalize.d.ts.map +0 -1
- package/dist/parse/normalize.js +0 -185
- package/dist/parse/normalize.js.map +0 -1
- package/dist/parse/validate.d.ts +0 -63
- package/dist/parse/validate.d.ts.map +0 -1
- package/dist/parse/validate.js +0 -798
- package/dist/parse/validate.js.map +0 -1
- package/dist/types.d.ts +0 -265
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@terrazzo/parser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Parser/validator for the Design Tokens Community Group (DTCG) standard.",
|
|
5
|
+
"license": "MIT",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"author": {
|
|
7
8
|
"name": "Drew Powers",
|
|
@@ -22,33 +23,36 @@
|
|
|
22
23
|
"lint"
|
|
23
24
|
],
|
|
24
25
|
"main": "./dist/index.js",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": "./dist/index.js",
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
25
30
|
"homepage": "https://terrazzo.app/docs/cli/api/js",
|
|
26
31
|
"repository": {
|
|
27
32
|
"type": "git",
|
|
28
33
|
"url": "https://github.com/terrazzoapp/terrazzo.git",
|
|
29
34
|
"directory": "./packages/parser/"
|
|
30
35
|
},
|
|
31
|
-
"license": "MIT",
|
|
32
36
|
"dependencies": {
|
|
33
37
|
"@humanwhocodes/momoa": "^3.3.8",
|
|
34
38
|
"@types/babel__code-frame": "^7.0.6",
|
|
35
39
|
"@types/culori": "^4.0.0",
|
|
36
40
|
"culori": "^4.0.1",
|
|
37
|
-
"is-what": "^4.1.16",
|
|
38
41
|
"merge-anything": "^5.1.7",
|
|
39
42
|
"picocolors": "^1.1.1",
|
|
40
43
|
"scule": "^1.3.0",
|
|
41
44
|
"wildcard-match": "^5.1.4",
|
|
42
|
-
"
|
|
43
|
-
"@terrazzo/token-tools": "^0.7.3"
|
|
45
|
+
"@terrazzo/token-tools": "^0.8.0"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
46
48
|
"yaml-to-momoa": "^0.0.3"
|
|
47
49
|
},
|
|
48
50
|
"scripts": {
|
|
49
|
-
"build": "
|
|
51
|
+
"build": "rolldown -c && attw --profile esm-only --pack .",
|
|
50
52
|
"dev": "pnpm run build --watch",
|
|
51
|
-
"lint": "
|
|
53
|
+
"lint": "pnpm --filter @terrazzo/parser run \"/^lint:(js|ts)/\"",
|
|
54
|
+
"lint:js": "biome check .",
|
|
55
|
+
"lint:ts": "tsc --noEmit",
|
|
52
56
|
"test": "vitest run"
|
|
53
57
|
}
|
|
54
58
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { defineConfig } from 'rolldown';
|
|
2
|
+
import { dts } from 'rolldown-plugin-dts';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
input: {
|
|
6
|
+
index: './src/index.ts',
|
|
7
|
+
},
|
|
8
|
+
plugins: [dts()],
|
|
9
|
+
external: [
|
|
10
|
+
'@humanwhocodes/mamoa',
|
|
11
|
+
'@terrazzo/token-tools',
|
|
12
|
+
'culori',
|
|
13
|
+
'merge-anything',
|
|
14
|
+
'picocolors',
|
|
15
|
+
'wildcard-match',
|
|
16
|
+
'yaml-to-momoa',
|
|
17
|
+
'yaml',
|
|
18
|
+
],
|
|
19
|
+
output: {
|
|
20
|
+
dir: 'dist',
|
|
21
|
+
format: 'es',
|
|
22
|
+
sourcemap: true,
|
|
23
|
+
},
|
|
24
|
+
});
|
package/src/build/index.ts
CHANGED
|
@@ -18,7 +18,7 @@ function validateTransformParams({
|
|
|
18
18
|
params,
|
|
19
19
|
logger,
|
|
20
20
|
pluginName,
|
|
21
|
-
}: { params: TokenTransformed; logger: Logger; pluginName: string }) {
|
|
21
|
+
}: { params: TokenTransformed; logger: Logger; pluginName: string }): void {
|
|
22
22
|
const baseMessage: LogEntry = { group: 'plugin', label: pluginName, message: '' };
|
|
23
23
|
|
|
24
24
|
// validate value is valid for SINGLE_VALUE or MULTI_VALUE
|
|
@@ -48,7 +48,7 @@ function validateTransformParams({
|
|
|
48
48
|
export default async function build(
|
|
49
49
|
tokens: Record<string, TokenNormalized>,
|
|
50
50
|
{ sources, logger = new Logger(), config }: BuildRunnerOptions,
|
|
51
|
-
) {
|
|
51
|
+
): Promise<BuildRunnerResult> {
|
|
52
52
|
const formats: Record<string, TokenTransformed[]> = {};
|
|
53
53
|
const result: BuildRunnerResult = { outputFiles: [] };
|
|
54
54
|
|
package/src/index.ts
CHANGED
|
@@ -15,4 +15,79 @@ export * from './parse/index.js';
|
|
|
15
15
|
|
|
16
16
|
export * from './types.js';
|
|
17
17
|
|
|
18
|
-
export
|
|
18
|
+
export type {
|
|
19
|
+
AliasToken,
|
|
20
|
+
AliasValue,
|
|
21
|
+
BooleanToken,
|
|
22
|
+
BooleanTokenNormalized,
|
|
23
|
+
BooleanValue,
|
|
24
|
+
BorderToken,
|
|
25
|
+
BorderTokenNormalized,
|
|
26
|
+
BorderValue,
|
|
27
|
+
BorderValueNormalized,
|
|
28
|
+
ColorSpace,
|
|
29
|
+
ColorToken,
|
|
30
|
+
ColorTokenNormalized,
|
|
31
|
+
ColorValue,
|
|
32
|
+
ColorValueNormalized,
|
|
33
|
+
CubicBezierToken,
|
|
34
|
+
CubicBezierTokenNormalized,
|
|
35
|
+
CubicBezierValue,
|
|
36
|
+
CustomTransformOptions,
|
|
37
|
+
DimensionToken,
|
|
38
|
+
DimensionTokenNormalized,
|
|
39
|
+
DimensionValue,
|
|
40
|
+
DurationToken,
|
|
41
|
+
DurationTokenNormalized,
|
|
42
|
+
DurationValue,
|
|
43
|
+
FontFamilyToken,
|
|
44
|
+
FontFamilyTokenNormalized,
|
|
45
|
+
FontFamilyValue,
|
|
46
|
+
FontFamilyValueNormalized,
|
|
47
|
+
FontWeightToken,
|
|
48
|
+
FontWeightTokenNormalized,
|
|
49
|
+
FontWeightValue,
|
|
50
|
+
FontWeightValueNormalized,
|
|
51
|
+
GradientStop,
|
|
52
|
+
GradientStopNormalized,
|
|
53
|
+
GradientToken,
|
|
54
|
+
GradientTokenNormalized,
|
|
55
|
+
GradientValue,
|
|
56
|
+
GradientValueNormalized,
|
|
57
|
+
Group,
|
|
58
|
+
GroupCore,
|
|
59
|
+
GroupOrToken,
|
|
60
|
+
LinkToken,
|
|
61
|
+
LinkTokenNormalized,
|
|
62
|
+
LinkValue,
|
|
63
|
+
ModeMap,
|
|
64
|
+
NumberToken,
|
|
65
|
+
NumberTokenNormalized,
|
|
66
|
+
NumberValue,
|
|
67
|
+
ShadowToken,
|
|
68
|
+
ShadowTokenNormalized,
|
|
69
|
+
ShadowValue,
|
|
70
|
+
ShadowValueNormalized,
|
|
71
|
+
StringToken,
|
|
72
|
+
StringTokenNormalized,
|
|
73
|
+
StringValue,
|
|
74
|
+
StrokeStyleToken,
|
|
75
|
+
StrokeStyleTokenNormalized,
|
|
76
|
+
StrokeStyleValue,
|
|
77
|
+
StrokeStyleValueExpanded,
|
|
78
|
+
Token,
|
|
79
|
+
TokenCore,
|
|
80
|
+
TokenMode,
|
|
81
|
+
TokenNormalized,
|
|
82
|
+
TokenNormalizedCore,
|
|
83
|
+
TokenNormalizedSet,
|
|
84
|
+
TokensSet,
|
|
85
|
+
TransitionToken,
|
|
86
|
+
TransitionTokenNormalized,
|
|
87
|
+
TransitionValue,
|
|
88
|
+
TransitionValueNormalized,
|
|
89
|
+
TypographyToken,
|
|
90
|
+
TypographyTokenNormalized,
|
|
91
|
+
TypographyValue,
|
|
92
|
+
TypographyValueNormalized,
|
|
93
|
+
} from '@terrazzo/token-tools';
|
package/src/parse/index.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type DocumentNode, type MemberNode, type ObjectNode, evaluate } from '@humanwhocodes/momoa';
|
|
2
2
|
import { type Token, type TokenNormalized, pluralize, splitID } from '@terrazzo/token-tools';
|
|
3
3
|
import type ytm from 'yaml-to-momoa';
|
|
4
4
|
import lintRunner from '../lint/index.js';
|
|
5
5
|
import Logger from '../logger.js';
|
|
6
6
|
import type { ConfigInit, InputSource } from '../types.js';
|
|
7
7
|
import applyAliases from './alias.js';
|
|
8
|
-
import { getObjMembers, toMomoa, traverse } from './json.js';
|
|
8
|
+
import { getObjMembers, parseJSON, replaceObjMembers, toMomoa, traverse } from './json.js';
|
|
9
9
|
import normalize from './normalize.js';
|
|
10
|
-
import validateTokenNode from './validate.js';
|
|
10
|
+
import validateTokenNode, { type Visitors, getInheritedType } from './validate.js';
|
|
11
11
|
|
|
12
12
|
export * from './alias.js';
|
|
13
13
|
export * from './normalize.js';
|
|
@@ -30,6 +30,11 @@ export interface ParseOptions {
|
|
|
30
30
|
continueOnError?: boolean;
|
|
31
31
|
/** Provide yamlToMomoa module to parse YAML (by default, this isn’t shipped to cut down on package weight) */
|
|
32
32
|
yamlToMomoa?: typeof ytm;
|
|
33
|
+
/**
|
|
34
|
+
* Transform API
|
|
35
|
+
* @see https://terrazzo.app/docs/api/js#transform-api
|
|
36
|
+
*/
|
|
37
|
+
transform?: Visitors;
|
|
33
38
|
/** (internal cache; do not use) */
|
|
34
39
|
_sources?: Record<string, InputSource>;
|
|
35
40
|
}
|
|
@@ -48,6 +53,7 @@ export default async function parse(
|
|
|
48
53
|
config = {} as ConfigInit,
|
|
49
54
|
continueOnError = false,
|
|
50
55
|
yamlToMomoa,
|
|
56
|
+
transform,
|
|
51
57
|
_sources = {},
|
|
52
58
|
}: ParseOptions = {} as ParseOptions,
|
|
53
59
|
): Promise<ParseResult> {
|
|
@@ -91,6 +97,7 @@ export default async function parse(
|
|
|
91
97
|
skipLint,
|
|
92
98
|
continueOnError,
|
|
93
99
|
yamlToMomoa,
|
|
100
|
+
transform,
|
|
94
101
|
});
|
|
95
102
|
tokensSet = Object.assign(tokensSet, result.tokens);
|
|
96
103
|
if (src.filename) {
|
|
@@ -166,6 +173,7 @@ async function parseSingle(
|
|
|
166
173
|
config,
|
|
167
174
|
skipLint,
|
|
168
175
|
continueOnError = false,
|
|
176
|
+
transform,
|
|
169
177
|
yamlToMomoa, // optional dependency, declared here so the parser itself doesn’t have to load a heavy dep in-browser
|
|
170
178
|
}: {
|
|
171
179
|
filename: URL;
|
|
@@ -173,12 +181,13 @@ async function parseSingle(
|
|
|
173
181
|
config: ConfigInit;
|
|
174
182
|
skipLint: boolean;
|
|
175
183
|
continueOnError?: boolean;
|
|
184
|
+
transform: ParseOptions['transform'] | undefined;
|
|
176
185
|
yamlToMomoa?: typeof ytm;
|
|
177
186
|
},
|
|
178
187
|
): Promise<{ tokens: Record<string, Token>; document: DocumentNode; src?: string }> {
|
|
179
188
|
// 1. Build AST
|
|
180
189
|
const startParsing = performance.now();
|
|
181
|
-
|
|
190
|
+
let { src, document } = toMomoa(input, { filename, logger, continueOnError, yamlToMomoa });
|
|
182
191
|
logger.debug({
|
|
183
192
|
group: 'parser',
|
|
184
193
|
label: 'json',
|
|
@@ -187,27 +196,77 @@ async function parseSingle(
|
|
|
187
196
|
});
|
|
188
197
|
const tokensSet: Record<string, TokenNormalized> = {};
|
|
189
198
|
|
|
199
|
+
// 1a. if there’s a root() transformer, then re-parse
|
|
200
|
+
if (transform?.root) {
|
|
201
|
+
const json = typeof input === 'string' ? JSON.parse(input) : input;
|
|
202
|
+
const result = transform?.root(json, '.', document);
|
|
203
|
+
if (result) {
|
|
204
|
+
const reRunResult = toMomoa(result, { filename, logger, continueOnError /* YAML not needed in transform() */ });
|
|
205
|
+
src = reRunResult.src;
|
|
206
|
+
document = reRunResult.document;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
190
210
|
// 2. Walk AST to validate tokens
|
|
191
211
|
let tokenCount = 0;
|
|
192
212
|
const startValidate = performance.now();
|
|
193
|
-
const $typeInheritance: Record<string,
|
|
213
|
+
const $typeInheritance: Record<string, MemberNode> = {};
|
|
194
214
|
traverse(document, {
|
|
195
215
|
enter(node, parent, subpath) {
|
|
196
216
|
// if $type appears at root of tokens.json, collect it
|
|
197
217
|
if (node.type === 'Document' && node.body.type === 'Object' && node.body.members) {
|
|
198
|
-
const members =
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
218
|
+
const { members: rootMembers } = node.body;
|
|
219
|
+
const root$type = rootMembers.find((m) => m.name.type === 'String' && m.name.value === '$type');
|
|
220
|
+
const root$value = rootMembers.find((m) => m.name.type === 'String' && m.name.value === '$value');
|
|
221
|
+
if (root$type && !root$value) {
|
|
222
|
+
$typeInheritance['.'] = root$type;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// for transform() visitors, all non-tokens MUST be handled at this point (besides "root", which was handled above)
|
|
227
|
+
if (
|
|
228
|
+
node.type === 'Object' && // JSON object
|
|
229
|
+
subpath.length &&
|
|
230
|
+
!node.members.some((m) => m.name.type === 'String' && m.name.value === '$value') && // not the token node itself
|
|
231
|
+
!subpath.includes('$value') && // not a child of a token node, either
|
|
232
|
+
!subpath.includes('$extensions') // not metadata
|
|
233
|
+
) {
|
|
234
|
+
if (transform?.group) {
|
|
235
|
+
const newJSON = transform?.group(evaluate(node), subpath.join('.'), node);
|
|
236
|
+
if (newJSON) {
|
|
237
|
+
replaceObjMembers(node, parseJSON(newJSON));
|
|
238
|
+
}
|
|
202
239
|
}
|
|
203
240
|
}
|
|
204
241
|
|
|
205
242
|
// handle tokens
|
|
206
243
|
if (node.type === 'Member') {
|
|
207
|
-
const
|
|
208
|
-
if (
|
|
209
|
-
|
|
210
|
-
|
|
244
|
+
const inheritedTypeNode = getInheritedType(node, { subpath, $typeInheritance });
|
|
245
|
+
if (node.value.type === 'Object') {
|
|
246
|
+
const $type =
|
|
247
|
+
node.value.members.find((m) => m.name.type === 'String' && m.name.value === '$type') || inheritedTypeNode;
|
|
248
|
+
const $value = node.value.members.find((m) => m.name.type === 'String' && m.name.value === '$value');
|
|
249
|
+
if ($value && $type?.value.type === 'String' && transform?.[$type.value.value]) {
|
|
250
|
+
const result = transform[$type.value.value]?.(evaluate(node.value), subpath.join('.'), node);
|
|
251
|
+
if (result) {
|
|
252
|
+
node.value = parseJSON(result).body;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const token = validateTokenNode(node, {
|
|
257
|
+
filename,
|
|
258
|
+
src,
|
|
259
|
+
config,
|
|
260
|
+
logger,
|
|
261
|
+
parent,
|
|
262
|
+
subpath,
|
|
263
|
+
transform,
|
|
264
|
+
inheritedTypeNode,
|
|
265
|
+
});
|
|
266
|
+
if (token) {
|
|
267
|
+
tokensSet[token.id] = token;
|
|
268
|
+
tokenCount++;
|
|
269
|
+
}
|
|
211
270
|
}
|
|
212
271
|
}
|
|
213
272
|
},
|
package/src/parse/json.ts
CHANGED
|
@@ -3,15 +3,16 @@ import {
|
|
|
3
3
|
type DocumentNode,
|
|
4
4
|
type MemberNode,
|
|
5
5
|
type ObjectNode,
|
|
6
|
+
type ParseOptions,
|
|
6
7
|
type ValueNode,
|
|
7
|
-
parse as
|
|
8
|
+
parse as momoaParse,
|
|
8
9
|
print,
|
|
9
10
|
} from '@humanwhocodes/momoa';
|
|
10
11
|
import type yamlToMomoa from 'yaml-to-momoa';
|
|
11
12
|
import type Logger from '../logger.js';
|
|
12
13
|
import type { InputSource } from '../types.js';
|
|
13
14
|
|
|
14
|
-
export interface
|
|
15
|
+
export interface JSONVisitor {
|
|
15
16
|
enter?: (node: AnyNode, parent: AnyNode | undefined, path: string[]) => void;
|
|
16
17
|
exit?: (node: AnyNode, parent: AnyNode | undefined, path: string[]) => void;
|
|
17
18
|
}
|
|
@@ -54,11 +55,7 @@ export function getObjMembers(node: ObjectNode): Record<string | number, ValueNo
|
|
|
54
55
|
return members;
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
/**
|
|
58
|
-
* Inject members to ObjectNode
|
|
59
|
-
* @param {ObjectNode} node
|
|
60
|
-
* @param {MemberNode[]} members
|
|
61
|
-
*/
|
|
58
|
+
/** Inject members to ObjectNode */
|
|
62
59
|
export function injectObjMembers(node: ObjectNode, members: MemberNode[] = []) {
|
|
63
60
|
if (node.type !== 'Object') {
|
|
64
61
|
return;
|
|
@@ -66,11 +63,16 @@ export function injectObjMembers(node: ObjectNode, members: MemberNode[] = []) {
|
|
|
66
63
|
node.members.push(...members);
|
|
67
64
|
}
|
|
68
65
|
|
|
66
|
+
/** Replace an ObjectNode’s contents outright with another */
|
|
67
|
+
export function replaceObjMembers(a: ObjectNode, b: DocumentNode | ObjectNode) {
|
|
68
|
+
a.members = (b.type === 'Document' && (b.body as ObjectNode)?.members) || (b as ObjectNode).members;
|
|
69
|
+
}
|
|
70
|
+
|
|
69
71
|
/**
|
|
70
72
|
* Variation of Momoa’s traverse(), which keeps track of global path.
|
|
71
73
|
* Allows mutation of AST (along with any consequences)
|
|
72
74
|
*/
|
|
73
|
-
export function traverse(root: AnyNode, visitor:
|
|
75
|
+
export function traverse(root: AnyNode, visitor: JSONVisitor) {
|
|
74
76
|
/**
|
|
75
77
|
* Recursively visits a node.
|
|
76
78
|
* @param {AnyNode} node The node to visit.
|
|
@@ -89,20 +91,15 @@ export function traverse(root: AnyNode, visitor: Visitor) {
|
|
|
89
91
|
const childNode = CHILD_KEYS[node.type];
|
|
90
92
|
for (const key of childNode ?? []) {
|
|
91
93
|
const value = node[key as keyof typeof node];
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
value[i],
|
|
99
|
-
node,
|
|
100
|
-
key === 'elements' ? [...nextPath, String(i)] : nextPath,
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
} else if (isNode(value)) {
|
|
104
|
-
visitNode(value as unknown as AnyNode, node, nextPath);
|
|
94
|
+
if (!value) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (Array.isArray(value)) {
|
|
98
|
+
for (let i = 0; i < value.length; i++) {
|
|
99
|
+
visitNode(value[i] as unknown as AnyNode, node, key === 'elements' ? [...nextPath, String(i)] : nextPath);
|
|
105
100
|
}
|
|
101
|
+
} else if (isNode(value)) {
|
|
102
|
+
visitNode(value as unknown as AnyNode, node, nextPath);
|
|
106
103
|
}
|
|
107
104
|
}
|
|
108
105
|
|
|
@@ -189,17 +186,26 @@ export function toMomoa(
|
|
|
189
186
|
});
|
|
190
187
|
}
|
|
191
188
|
} else {
|
|
192
|
-
document = parseJSON(
|
|
193
|
-
typeof input === 'string' ? input : JSON.stringify(input, undefined, 2), // everything else: assert it’s JSON-serializable
|
|
194
|
-
{
|
|
195
|
-
mode: 'jsonc',
|
|
196
|
-
ranges: true,
|
|
197
|
-
tokens: true,
|
|
198
|
-
},
|
|
199
|
-
);
|
|
189
|
+
document = parseJSON(input);
|
|
200
190
|
}
|
|
201
191
|
if (!src) {
|
|
202
192
|
src = print(document, { indent: 2 });
|
|
203
193
|
}
|
|
204
194
|
return { src, document };
|
|
205
195
|
}
|
|
196
|
+
|
|
197
|
+
/** Momoa, just with default options pre-set */
|
|
198
|
+
export function parseJSON(input: string | Record<string, any>, options?: ParseOptions): any {
|
|
199
|
+
return momoaParse(
|
|
200
|
+
// note: it seems silly, at first glance, to have JSON.stringify() inside an actual JSON parser. But
|
|
201
|
+
// this provides a common interface to generate a Momoa AST for JSON created in-memory, which we already
|
|
202
|
+
// know is 100% valid because it’s already deserialized.
|
|
203
|
+
typeof input === 'string' ? input : JSON.stringify(input, undefined, 2),
|
|
204
|
+
{
|
|
205
|
+
mode: 'jsonc',
|
|
206
|
+
ranges: true,
|
|
207
|
+
tokens: true,
|
|
208
|
+
...options,
|
|
209
|
+
},
|
|
210
|
+
);
|
|
211
|
+
}
|
package/src/parse/normalize.ts
CHANGED
|
@@ -34,9 +34,6 @@ export const FONT_WEIGHT_MAP = {
|
|
|
34
34
|
'ultra-black': 950,
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
// Note: because we’re handling a lot of input values, the type inference gets lost.
|
|
38
|
-
// This file is expected to have a lot of `@ts-ignore` comments.
|
|
39
|
-
|
|
40
37
|
const NUMBER_WITH_UNIT_RE = /(-?\d*\.?\d+)(.*)/;
|
|
41
38
|
|
|
42
39
|
/** Fill in defaults, and return predictable shapes for tokens */
|
|
@@ -140,14 +137,10 @@ export default function normalizeValue<T extends Token>(token: T): T['$value'] {
|
|
|
140
137
|
(layer) =>
|
|
141
138
|
({
|
|
142
139
|
color: normalizeValue({ $type: 'color', $value: layer.color }),
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
// @ts-ignore
|
|
148
|
-
blur: normalizeValue({ $type: 'dimension', $value: layer.blur ?? 0 }),
|
|
149
|
-
// @ts-ignore
|
|
150
|
-
spread: normalizeValue({ $type: 'dimension', $value: layer.spread ?? 0 }),
|
|
140
|
+
offsetX: normalizeValue({ $type: 'dimension', $value: layer.offsetX ?? { value: 0, unit: 'px' } }),
|
|
141
|
+
offsetY: normalizeValue({ $type: 'dimension', $value: layer.offsetY ?? { value: 0, unit: 'px' } }),
|
|
142
|
+
blur: normalizeValue({ $type: 'dimension', $value: layer.blur ?? { value: 0, unit: 'px' } }),
|
|
143
|
+
spread: normalizeValue({ $type: 'dimension', $value: layer.spread ?? { value: 0, unit: 'px' } }),
|
|
151
144
|
inset: layer.inset === true,
|
|
152
145
|
}) as ShadowValueNormalized,
|
|
153
146
|
);
|
|
@@ -163,11 +156,8 @@ export default function normalizeValue<T extends Token>(token: T): T['$value'] {
|
|
|
163
156
|
return token.$value;
|
|
164
157
|
}
|
|
165
158
|
return {
|
|
166
|
-
// @ts-ignore
|
|
167
159
|
duration: normalizeValue({ $type: 'duration', $value: token.$value.duration ?? 0 }),
|
|
168
|
-
// @ts-ignore
|
|
169
160
|
delay: normalizeValue({ $type: 'duration', $value: token.$value.delay ?? 0 }),
|
|
170
|
-
// @ts-ignore
|
|
171
161
|
timingFunction: normalizeValue({ $type: 'cubicBezier', $value: token.$value.timingFunction }),
|
|
172
162
|
} as TransitionValue;
|
|
173
163
|
}
|