@hh.ru/magritte-design-tokens-utils 4.0.1 → 5.0.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/constants.d.ts CHANGED
@@ -1,2 +1,5 @@
1
- export declare const BASE_SET: string[];
2
1
  export declare const TOKENS_DEFAULT_THEME = "hh-day";
2
+ export declare const SOURCES_GROUP = "sources";
3
+ export declare const THEMES_GROUP = "themes";
4
+ export declare const BASE_COLLECTIONS_ORDER: string[];
5
+ export declare const BASE_TOKEN_SET = "base";
package/constants.js CHANGED
@@ -1,5 +1,10 @@
1
- const BASE_SET = ['core', 'colors', 'semantic', 'typography'];
2
1
  const TOKENS_DEFAULT_THEME = 'hh-day';
2
+ // группы коллекций в config.json репозитория токенов
3
+ const SOURCES_GROUP = 'sources';
4
+ const THEMES_GROUP = 'themes';
5
+ // порядок базовых коллекций, определяющий порядок переменных в base-variables.less
6
+ const BASE_COLLECTIONS_ORDER = ['typography', 'palette', 'common', 'core'];
7
+ const BASE_TOKEN_SET = 'base';
3
8
 
4
- export { BASE_SET, TOKENS_DEFAULT_THEME };
9
+ export { BASE_COLLECTIONS_ORDER, BASE_TOKEN_SET, SOURCES_GROUP, THEMES_GROUP, TOKENS_DEFAULT_THEME };
5
10
  //# sourceMappingURL=constants.js.map
package/constants.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sources":["src/constants.ts"],"sourcesContent":["export const BASE_SET = ['core', 'colors', 'semantic', 'typography'];\n\nexport const TOKENS_DEFAULT_THEME = 'hh-day';\n"],"names":[],"mappings":"AAAO,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE;AAE9D,MAAM,oBAAoB,GAAG;;;;"}
1
+ {"version":3,"file":"constants.js","sources":["src/constants.ts"],"sourcesContent":["export const TOKENS_DEFAULT_THEME = 'hh-day';\n\n// группы коллекций в config.json репозитория токенов\nexport const SOURCES_GROUP = 'sources';\nexport const THEMES_GROUP = 'themes';\n\n// порядок базовых коллекций, определяющий порядок переменных в base-variables.less\nexport const BASE_COLLECTIONS_ORDER = ['typography', 'palette', 'common', 'core'];\n\nexport const BASE_TOKEN_SET = 'base';\n"],"names":[],"mappings":"AAAO,MAAM,oBAAoB,GAAG,SAAS;AAE7C;AACO,MAAM,aAAa,GAAG,UAAU;AAChC,MAAM,YAAY,GAAG,SAAS;AAErC;AACO,MAAM,sBAAsB,GAAG,CAAC,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE;AAE3E,MAAM,cAAc,GAAG;;;;"}
package/convert.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import type { FlatToken, TransformerConfigSchema } from '@sxl-studio/token-transformer';
2
+ import type { Tokens, TokensProjectConfig } from '@hh.ru/magritte-design-tokens-utils/types';
3
+ export type TransformerInput = (typeof TransformerConfigSchema)['_input'];
4
+ export declare const getEnabledFiles: (projectConfig: TokensProjectConfig) => string[];
5
+ export declare const buildTransformerInput: (tokenDir: string, projectConfig: TokensProjectConfig, includeThemes?: string[]) => TransformerInput;
6
+ export declare const buildTokensTree: (tokens: FlatToken[]) => Tokens;
package/convert.js ADDED
@@ -0,0 +1,158 @@
1
+ import { BASE_TOKEN_SET, SOURCES_GROUP, THEMES_GROUP, BASE_COLLECTIONS_ORDER } from './constants.js';
2
+
3
+ const getCollection = (projectConfig, name) => {
4
+ const collection = projectConfig.collections.find((item) => item.name === name);
5
+ if (!collection) {
6
+ throw new Error(`Collection "${name}" not found in tokens config`);
7
+ }
8
+ return collection;
9
+ };
10
+ const isEnabled = ({ enabled }) => enabled !== false;
11
+ // файлы токенов включенных коллекций и режимов, пути относительно папки токенов
12
+ const getEnabledFiles = (projectConfig) => projectConfig.collections
13
+ .filter(isEnabled)
14
+ .flatMap((collection) => collection.modes.filter(isEnabled))
15
+ .flatMap((mode) => Object.entries(mode.files))
16
+ .filter(([, status]) => status === 'enabled')
17
+ .map(([filePath]) => filePath);
18
+ const getEnabledModes = (collection) => {
19
+ const enabledModes = collection.modes.filter(isEnabled).map((mode) => mode.name);
20
+ if (!enabledModes.length) {
21
+ throw new Error(`Collection "${collection.name}" has no enabled modes`);
22
+ }
23
+ return enabledModes;
24
+ };
25
+ // выключенные коллекции не скачиваются fetch и не участвуют в сборке
26
+ const getGroupCollections = (projectConfig, groupName) => {
27
+ const group = projectConfig.groups?.find((item) => item.name === groupName);
28
+ if (!group) {
29
+ throw new Error(`Group "${groupName}" not found in tokens config`);
30
+ }
31
+ const collections = group.collections.map((name) => getCollection(projectConfig, name)).filter(isEnabled);
32
+ if (!collections.length) {
33
+ throw new Error(`Group "${groupName}" has no enabled collections`);
34
+ }
35
+ return collections;
36
+ };
37
+ const orderBaseCollections = (collections) => {
38
+ const orderIndex = ({ name }) => {
39
+ const index = BASE_COLLECTIONS_ORDER.indexOf(name);
40
+ return index === -1 ? BASE_COLLECTIONS_ORDER.length : index;
41
+ };
42
+ return [...collections].sort((a, b) => orderIndex(a) - orderIndex(b));
43
+ };
44
+ // конфиг sxl-transform: базовый набор токенов и по набору на тему
45
+ const buildTransformerInput = (tokenDir, projectConfig, includeThemes = []) => {
46
+ const sources = orderBaseCollections(getGroupCollections(projectConfig, SOURCES_GROUP));
47
+ const sourceSelectors = sources.map((collection) => {
48
+ const modes = getEnabledModes(collection);
49
+ // у базовой коллекции один режим, иначе неизвестно, какой из них брать
50
+ if (modes.length > 1) {
51
+ throw new Error(`Source collection "${collection.name}" has several enabled modes: ${modes.join(', ')}`);
52
+ }
53
+ return { collection: collection.name, mode: modes[0] };
54
+ });
55
+ const themeCollections = getGroupCollections(projectConfig, THEMES_GROUP);
56
+ const allThemeSelectors = themeCollections.flatMap((collection) => getEnabledModes(collection).map((mode) => ({ collection: collection.name, mode })));
57
+ const unknownThemes = includeThemes.filter((theme) => !allThemeSelectors.some(({ mode }) => mode === theme));
58
+ if (unknownThemes.length) {
59
+ throw new Error(`Unknown themes: ${unknownThemes.join(', ')}`);
60
+ }
61
+ const themeSelectors = allThemeSelectors.filter(({ mode }) => !includeThemes.length || includeThemes.includes(mode));
62
+ const tokenSets = [
63
+ { id: BASE_TOKEN_SET, selectors: sourceSelectors },
64
+ ...themeSelectors.map((selector) => ({ id: selector.mode, selectors: [selector] })),
65
+ ];
66
+ return {
67
+ // версия формата конфига sxl-transform (в 3.4.1 допустима только 1), меняется только при обновлении sxl
68
+ version: 1,
69
+ source: { tokenDir, configFile: null, include: ['**/*.json'] },
70
+ projectConfig: {
71
+ settings: projectConfig.settings,
72
+ // темы ссылаются на базовые коллекции, но в config.json эти связи (ref) не описаны
73
+ collections: projectConfig.collections.map((collection) => themeCollections.includes(collection)
74
+ ? { ...collection, ref: sourceSelectors.map((selector) => ({ type: 'local', ...selector })) }
75
+ : collection),
76
+ },
77
+ options: { unsupportedTypes: { default: 'error' } },
78
+ tokenSets,
79
+ // хотя бы один output обязателен, файлы манифеста не записываются
80
+ outputs: [
81
+ {
82
+ id: 'manifest',
83
+ platform: 'manifest',
84
+ outputDir: tokenDir,
85
+ files: tokenSets.map(({ id }) => ({ tokenSet: id, output: `${id}.manifest.json` })),
86
+ },
87
+ ],
88
+ };
89
+ };
90
+ const isRgba = (value) => typeof value === 'object' && value !== null && 'r' in value && 'g' in value && 'b' in value;
91
+ const toHexChannel = (channel) => Math.round(channel * 255)
92
+ .toString(16)
93
+ .padStart(2, '0');
94
+ const toHex = ({ r, g, b, a }) => `#${toHexChannel(r)}${toHexChannel(g)}${toHexChannel(b)}${a === undefined || a === 1 ? '' : toHexChannel(a)}`;
95
+ // sxl не вычисляет rgba() внутри градиентов: rgba(#000000, 48%), rgba(0, 0, 0, 0.06), rgb(0, 0, 0)
96
+ const resolveRgbaExpressions = (value) => value
97
+ .replace(/rgba\(\s*#([0-9a-f]{6})\s*,\s*([\d.]+)(%?)\s*\)/gi, (_, hex, alpha, percent) => toHex({
98
+ r: parseInt(hex.slice(0, 2), 16) / 255,
99
+ g: parseInt(hex.slice(2, 4), 16) / 255,
100
+ b: parseInt(hex.slice(4, 6), 16) / 255,
101
+ a: parseFloat(alpha) / (percent ? 100 : 1),
102
+ }))
103
+ .replace(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+)\s*)?\)/gi, (_, r, g, b, a) => toHex({
104
+ r: Number(r) / 255,
105
+ g: Number(g) / 255,
106
+ b: Number(b) / 255,
107
+ a: a === undefined ? 1 : parseFloat(a),
108
+ }));
109
+ const normalizeScalar = (value) => {
110
+ const trimmed = value.trim();
111
+ if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
112
+ return Number(trimmed);
113
+ }
114
+ return value;
115
+ };
116
+ const convertValue = (value) => {
117
+ if (isRgba(value)) {
118
+ return toHex(value);
119
+ }
120
+ if (typeof value === 'string') {
121
+ return normalizeScalar(resolveRgbaExpressions(value));
122
+ }
123
+ if (Array.isArray(value)) {
124
+ return value.map(convertValue);
125
+ }
126
+ if (typeof value === 'object' && value !== null) {
127
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, convertValue(item)]));
128
+ }
129
+ return value;
130
+ };
131
+ // неразрешенные цветовые выражения и алиасы дали бы невалидный css без ошибки
132
+ const UNRESOLVED_COLOR = /rgba?\(|\{/i;
133
+ const convertToken = (token) => {
134
+ const value = convertValue(token.resolvedValue);
135
+ if (token.type === 'color' && typeof value === 'string' && UNRESOLVED_COLOR.test(value)) {
136
+ throw new Error(`Unresolved color value in "${token.path}": ${value}`);
137
+ }
138
+ return {
139
+ value,
140
+ type: token.type,
141
+ ...(token.description ? { description: token.description } : {}),
142
+ };
143
+ };
144
+ // собирает вложенное дерево токенов { value, type }: prepare-tokens пишет его в themes/*.json,
145
+ // читают gen-types, gen-js-tokens и tokenize
146
+ const buildTokensTree = (tokens) => tokens.reduce((tree, token) => {
147
+ const keys = token.path.split('/');
148
+ let node = tree;
149
+ keys.slice(0, -1).forEach((key) => {
150
+ node[key] ??= {};
151
+ node = node[key];
152
+ });
153
+ node[keys[keys.length - 1]] = convertToken(token);
154
+ return tree;
155
+ }, {});
156
+
157
+ export { buildTokensTree, buildTransformerInput, getEnabledFiles };
158
+ //# sourceMappingURL=convert.js.map
package/convert.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert.js","sources":["src/convert.ts"],"sourcesContent":["import type { FlatToken, TransformerConfigSchema } from '@sxl-studio/token-transformer';\n\nimport {\n BASE_COLLECTIONS_ORDER,\n BASE_TOKEN_SET,\n SOURCES_GROUP,\n THEMES_GROUP,\n} from '@hh.ru/magritte-design-tokens-utils/constants';\nimport type { TokenValue, Tokens, TokensProjectConfig, TreeToken } from '@hh.ru/magritte-design-tokens-utils/types';\n\ntype Collection = TokensProjectConfig['collections'][number];\ntype Rgba = { r: number; g: number; b: number; a?: number };\n\n// входные данные TransformerConfigSchema из sxl-transform (тип до применения значений по умолчанию, как z.input)\nexport type TransformerInput = (typeof TransformerConfigSchema)['_input'];\n\nconst getCollection = (projectConfig: TokensProjectConfig, name: string): Collection => {\n const collection = projectConfig.collections.find((item) => item.name === name);\n if (!collection) {\n throw new Error(`Collection \"${name}\" not found in tokens config`);\n }\n return collection;\n};\n\nconst isEnabled = ({ enabled }: { enabled?: boolean }) => enabled !== false;\n\n// файлы токенов включенных коллекций и режимов, пути относительно папки токенов\nexport const getEnabledFiles = (projectConfig: TokensProjectConfig): string[] =>\n projectConfig.collections\n .filter(isEnabled)\n .flatMap((collection) => collection.modes.filter(isEnabled))\n .flatMap((mode) => Object.entries(mode.files))\n .filter(([, status]) => status === 'enabled')\n .map(([filePath]) => filePath);\n\nconst getEnabledModes = (collection: Collection): string[] => {\n const enabledModes = collection.modes.filter(isEnabled).map((mode) => mode.name);\n if (!enabledModes.length) {\n throw new Error(`Collection \"${collection.name}\" has no enabled modes`);\n }\n return enabledModes;\n};\n\n// выключенные коллекции не скачиваются fetch и не участвуют в сборке\nconst getGroupCollections = (projectConfig: TokensProjectConfig, groupName: string): Collection[] => {\n const group = projectConfig.groups?.find((item) => item.name === groupName);\n if (!group) {\n throw new Error(`Group \"${groupName}\" not found in tokens config`);\n }\n const collections = group.collections.map((name) => getCollection(projectConfig, name)).filter(isEnabled);\n if (!collections.length) {\n throw new Error(`Group \"${groupName}\" has no enabled collections`);\n }\n return collections;\n};\n\nconst orderBaseCollections = (collections: Collection[]): Collection[] => {\n const orderIndex = ({ name }: Collection) => {\n const index = BASE_COLLECTIONS_ORDER.indexOf(name);\n return index === -1 ? BASE_COLLECTIONS_ORDER.length : index;\n };\n return [...collections].sort((a, b) => orderIndex(a) - orderIndex(b));\n};\n\n// конфиг sxl-transform: базовый набор токенов и по набору на тему\nexport const buildTransformerInput = (\n tokenDir: string,\n projectConfig: TokensProjectConfig,\n includeThemes: string[] = []\n): TransformerInput => {\n const sources = orderBaseCollections(getGroupCollections(projectConfig, SOURCES_GROUP));\n const sourceSelectors = sources.map((collection) => {\n const modes = getEnabledModes(collection);\n // у базовой коллекции один режим, иначе неизвестно, какой из них брать\n if (modes.length > 1) {\n throw new Error(`Source collection \"${collection.name}\" has several enabled modes: ${modes.join(', ')}`);\n }\n return { collection: collection.name, mode: modes[0] };\n });\n const themeCollections = getGroupCollections(projectConfig, THEMES_GROUP);\n const allThemeSelectors = themeCollections.flatMap((collection) =>\n getEnabledModes(collection).map((mode) => ({ collection: collection.name, mode }))\n );\n const unknownThemes = includeThemes.filter((theme) => !allThemeSelectors.some(({ mode }) => mode === theme));\n if (unknownThemes.length) {\n throw new Error(`Unknown themes: ${unknownThemes.join(', ')}`);\n }\n const themeSelectors = allThemeSelectors.filter(\n ({ mode }) => !includeThemes.length || includeThemes.includes(mode)\n );\n const tokenSets = [\n { id: BASE_TOKEN_SET, selectors: sourceSelectors },\n ...themeSelectors.map((selector) => ({ id: selector.mode, selectors: [selector] })),\n ];\n\n return {\n // версия формата конфига sxl-transform (в 3.4.1 допустима только 1), меняется только при обновлении sxl\n version: 1,\n source: { tokenDir, configFile: null, include: ['**/*.json'] },\n projectConfig: {\n settings: projectConfig.settings,\n // темы ссылаются на базовые коллекции, но в config.json эти связи (ref) не описаны\n collections: projectConfig.collections.map((collection) =>\n themeCollections.includes(collection)\n ? { ...collection, ref: sourceSelectors.map((selector) => ({ type: 'local', ...selector })) }\n : collection\n ),\n },\n options: { unsupportedTypes: { default: 'error' } },\n tokenSets,\n // хотя бы один output обязателен, файлы манифеста не записываются\n outputs: [\n {\n id: 'manifest',\n platform: 'manifest',\n outputDir: tokenDir,\n files: tokenSets.map(({ id }) => ({ tokenSet: id, output: `${id}.manifest.json` })),\n },\n ],\n };\n};\n\nconst isRgba = (value: unknown): value is Rgba =>\n typeof value === 'object' && value !== null && 'r' in value && 'g' in value && 'b' in value;\n\nconst toHexChannel = (channel: number) =>\n Math.round(channel * 255)\n .toString(16)\n .padStart(2, '0');\n\nconst toHex = ({ r, g, b, a }: Rgba) =>\n `#${toHexChannel(r)}${toHexChannel(g)}${toHexChannel(b)}${a === undefined || a === 1 ? '' : toHexChannel(a)}`;\n\n// sxl не вычисляет rgba() внутри градиентов: rgba(#000000, 48%), rgba(0, 0, 0, 0.06), rgb(0, 0, 0)\nconst resolveRgbaExpressions = (value: string) =>\n value\n .replace(\n /rgba\\(\\s*#([0-9a-f]{6})\\s*,\\s*([\\d.]+)(%?)\\s*\\)/gi,\n (_, hex: string, alpha: string, percent: string) =>\n toHex({\n r: parseInt(hex.slice(0, 2), 16) / 255,\n g: parseInt(hex.slice(2, 4), 16) / 255,\n b: parseInt(hex.slice(4, 6), 16) / 255,\n a: parseFloat(alpha) / (percent ? 100 : 1),\n })\n )\n .replace(\n /rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(?:,\\s*([\\d.]+)\\s*)?\\)/gi,\n (_, r: string, g: string, b: string, a?: string) =>\n toHex({\n r: Number(r) / 255,\n g: Number(g) / 255,\n b: Number(b) / 255,\n a: a === undefined ? 1 : parseFloat(a),\n })\n );\n\nconst normalizeScalar = (value: string): string | number => {\n const trimmed = value.trim();\n if (/^-?\\d+(\\.\\d+)?$/.test(trimmed)) {\n return Number(trimmed);\n }\n return value;\n};\n\nconst convertValue = (value: unknown): unknown => {\n if (isRgba(value)) {\n return toHex(value);\n }\n if (typeof value === 'string') {\n return normalizeScalar(resolveRgbaExpressions(value));\n }\n if (Array.isArray(value)) {\n return value.map(convertValue);\n }\n if (typeof value === 'object' && value !== null) {\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, convertValue(item)]));\n }\n return value;\n};\n\n// неразрешенные цветовые выражения и алиасы дали бы невалидный css без ошибки\nconst UNRESOLVED_COLOR = /rgba?\\(|\\{/i;\n\nconst convertToken = (token: FlatToken): TreeToken => {\n const value = convertValue(token.resolvedValue) as TokenValue;\n if (token.type === 'color' && typeof value === 'string' && UNRESOLVED_COLOR.test(value)) {\n throw new Error(`Unresolved color value in \"${token.path}\": ${value}`);\n }\n return {\n value,\n type: token.type,\n ...(token.description ? { description: token.description } : {}),\n };\n};\n\n// собирает вложенное дерево токенов { value, type }: prepare-tokens пишет его в themes/*.json,\n// читают gen-types, gen-js-tokens и tokenize\nexport const buildTokensTree = (tokens: FlatToken[]): Tokens =>\n tokens.reduce<Tokens>((tree, token) => {\n const keys = token.path.split('/');\n let node = tree;\n keys.slice(0, -1).forEach((key) => {\n node[key] ??= {};\n node = node[key] as Tokens;\n });\n node[keys[keys.length - 1]] = convertToken(token);\n return tree;\n }, {});\n"],"names":[],"mappings":"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"}
package/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export * from '@hh.ru/magritte-design-tokens-utils/purify';
2
1
  export * from '@hh.ru/magritte-design-tokens-utils/tokenize';
2
+ export * from '@hh.ru/magritte-design-tokens-utils/render';
3
3
  export * from '@hh.ru/magritte-design-tokens-utils/prepare';
4
+ export { getEnabledFiles } from '@hh.ru/magritte-design-tokens-utils/convert';
4
5
  export * from '@hh.ru/magritte-design-tokens-utils/constants';
5
6
  export * from '@hh.ru/magritte-design-tokens-utils/deduplicate';
6
7
  export * from '@hh.ru/magritte-design-tokens-utils/types';
package/index.js CHANGED
@@ -1,9 +1,12 @@
1
- export { purify } from './purify.js';
2
- export { TYPES, getFontWeightValue, getVariableUnit, kebabWithUnderscoreTransformer, renderTokensWithFormatter, typographyTransformations } from './tokenize.js';
3
- export { filterThemeSets, prepareBaseTokens, prepareThemesTokens } from './prepare.js';
4
- export { BASE_SET, TOKENS_DEFAULT_THEME } from './constants.js';
1
+ export { ANIMATION_TYPES, TYPES, flattenTokens, getCoreTokenValue, getFontWeightValue, getShadowProperties, getTypographyProperties, getVariableUnit, isAnimationToken, isLinearGradient, makeTokenName, parseCubicBezier, parseDuration, parseLinearGradient, parseSpring, parseTransition, typographyTransformations } from './tokenize.js';
2
+ export { renderAnimationCssVariables, renderCssVariables, renderCssVariablesBlock, renderLessVariablesWithCssReferences, renderLessVariablesWithValues, renderVisualTestsOverrides } from './render.js';
3
+ export { prepareTokens } from './prepare.js';
4
+ export { getEnabledFiles } from './convert.js';
5
+ export { BASE_COLLECTIONS_ORDER, BASE_TOKEN_SET, SOURCES_GROUP, THEMES_GROUP, TOKENS_DEFAULT_THEME } from './constants.js';
5
6
  export { cleanThemeFile, collectAllowedProps, collectDefaultTokenValues, removeRedundantByValue } from './deduplicate.js';
6
7
  import 'change-case';
7
8
  import 'spring-easing';
8
- import 'token-transformer';
9
+ import 'node:fs';
10
+ import 'node:path';
11
+ import '@sxl-studio/token-transformer';
9
12
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hh.ru/magritte-design-tokens-utils",
3
- "version": "4.0.1",
3
+ "version": "5.0.0",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "type": "module",
@@ -10,20 +10,19 @@
10
10
  "prepack": "yarn root:prepack $(pwd)",
11
11
  "postpublish": "yarn root:postpublish $(pwd)",
12
12
  "stylelint-check": "yarn root:stylelint-check $(pwd)",
13
- "eslint-check": "yarn root:eslint-check $(pwd)",
13
+ "lint-check": "yarn root:lint-check $(pwd)",
14
14
  "ts-config": "yarn root:ts-config $(pwd)",
15
15
  "ts-check": "yarn root:ts-check $(pwd)",
16
16
  "test": "yarn root:test $(pwd)",
17
17
  "watch": "yarn root:watch $(pwd)"
18
18
  },
19
19
  "dependencies": {
20
+ "@sxl-studio/token-transformer": "3.4.1",
20
21
  "change-case": "4.1.2",
21
- "spring-easing": "2.3.3",
22
- "style-dictionary": "^3.7.1",
23
- "token-transformer": "^0.0.32"
22
+ "spring-easing": "2.3.3"
24
23
  },
25
24
  "publishConfig": {
26
25
  "access": "public"
27
26
  },
28
- "gitHead": "ec7d56f576ca5581c2acb5010b53bbfb8da52962"
27
+ "gitHead": "b0ff5da48fb29d516c8289082560ee1882d16986"
29
28
  }
package/prepare.d.ts CHANGED
@@ -1,5 +1,2 @@
1
- import { Options } from 'token-transformer';
2
- import { Tokens, PreparedThemesTokens } from '@hh.ru/magritte-design-tokens-utils/types';
3
- export declare const prepareBaseTokens: (tokens: Tokens, config?: Options) => Tokens;
4
- export declare const filterThemeSets: (tokens: Tokens) => string[];
5
- export declare const prepareThemesTokens: (tokens: Tokens, config?: Options, includeThemes?: string[]) => PreparedThemesTokens[];
1
+ import type { PreparedTokens, PrepareTokensOptions, TokensProjectConfig } from '@hh.ru/magritte-design-tokens-utils/types';
2
+ export declare const prepareTokens: (tokenDir: string, projectConfig: TokensProjectConfig, { includeThemes }?: PrepareTokensOptions) => Promise<PreparedTokens>;
package/prepare.js CHANGED
@@ -1,48 +1,42 @@
1
- import { transformTokens } from 'token-transformer';
2
- import { BASE_SET } from './constants.js';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { TransformerConfigSchema, runTransform } from '@sxl-studio/token-transformer';
4
+ import { BASE_TOKEN_SET } from './constants.js';
5
+ import { getEnabledFiles, buildTransformerInput, buildTokensTree } from './convert.js';
3
6
 
4
- const isObject = (obj) => {
5
- return typeof obj === 'object';
6
- };
7
- const traverse = (tokens) => {
8
- Object.keys(tokens).forEach((key) => {
9
- const objKey = tokens[key];
10
- if (objKey && isObject(objKey)) {
11
- if (objKey.value && !objKey.type) {
12
- objKey['#value'] = objKey.value;
13
- delete objKey.value;
14
- }
15
- traverse(objKey);
16
- }
17
- });
18
- return tokens;
19
- };
20
- const prepareBaseTokens = (tokens, config) => {
21
- const transformerOptions = {
22
- expandShadow: true,
23
- preserveRawValue: true,
24
- ...config,
7
+ const prepareTokens = async (tokenDir, projectConfig, { includeThemes = [] } = {}) => {
8
+ // sxl молча пропускает отсутствующие файлы, и тема получилась бы пустой
9
+ const missingFiles = getEnabledFiles(projectConfig).filter((file) => !fs.existsSync(path.join(tokenDir, file)));
10
+ if (missingFiles.length) {
11
+ throw new Error(`Token files listed in config.json are missing in ${tokenDir}: ${missingFiles.join(', ')}`);
12
+ }
13
+ const parsed = TransformerConfigSchema.parse(buildTransformerInput(tokenDir, projectConfig, includeThemes));
14
+ const config = {
15
+ ...parsed,
16
+ source: { ...parsed.source, tokenDir: path.resolve(tokenDir), configFile: null },
17
+ outputs: parsed.outputs.map((output) => ({ ...output, outputDir: path.resolve(output.outputDir) })),
25
18
  };
26
- const baseTokens = transformTokens(tokens, BASE_SET, [], transformerOptions);
27
- return traverse(baseTokens);
28
- };
29
- const filterThemeSets = (tokens) => {
30
- const sets = Object.keys(tokens).filter((set) => !set.startsWith('$'));
31
- return sets.filter((set) => !BASE_SET.includes(set));
32
- };
33
- const prepareThemesTokens = (tokens, config, includeThemes = []) => {
34
- const themes = includeThemes.length ? includeThemes : filterThemeSets(tokens);
35
- const transformerOptions = {
36
- expandShadow: true,
37
- ...config,
19
+ const result = await runTransform(config, { mode: 'force' });
20
+ // предупреждения тоже фатальны: сборка токенов работает без присмотра в update-tokens
21
+ const issues = result.diagnostics.filter(({ level }) => level === 'error' || level === 'warn');
22
+ if (issues.length) {
23
+ throw new Error(`Tokens transformation failed:\n${issues.map(({ level, code, message }) => `[${level}][${code}] ${message}`).join('\n')}`);
24
+ }
25
+ const emptyTokenSets = result.tokenSets.filter(({ tokens }) => !tokens.length).map(({ id }) => id);
26
+ if (emptyTokenSets.length) {
27
+ throw new Error(`Token sets have no tokens: ${emptyTokenSets.join(', ')}`);
28
+ }
29
+ const baseTokenSet = result.tokenSets.find(({ id }) => id === BASE_TOKEN_SET);
30
+ if (!baseTokenSet) {
31
+ throw new Error('Base token set was not resolved');
32
+ }
33
+ return {
34
+ baseTokens: buildTokensTree(baseTokenSet.tokens),
35
+ themesTokens: result.tokenSets
36
+ .filter(({ id }) => id !== BASE_TOKEN_SET)
37
+ .map(({ id, tokens }) => ({ themeName: id, themeTokens: buildTokensTree(tokens) })),
38
38
  };
39
- const result = themes.reduce((res, theme) => {
40
- const themeTokens = transformTokens(tokens, [...BASE_SET, theme], BASE_SET, transformerOptions);
41
- res.push({ themeTokens: traverse(themeTokens), themeName: theme });
42
- return res;
43
- }, []);
44
- return result;
45
39
  };
46
40
 
47
- export { filterThemeSets, prepareBaseTokens, prepareThemesTokens };
41
+ export { prepareTokens };
48
42
  //# sourceMappingURL=prepare.js.map
package/prepare.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"prepare.js","sources":["src/prepare.ts"],"sourcesContent":["import { Options, transformTokens } from 'token-transformer';\n\nimport { BASE_SET } from '@hh.ru/magritte-design-tokens-utils/constants';\nimport { Tokens, PreparedThemesTokens } from '@hh.ru/magritte-design-tokens-utils/types';\n\nconst isObject = (obj: unknown): obj is Record<string, unknown> => {\n return typeof obj === 'object';\n};\n\nconst traverse = (tokens: Tokens): Tokens => {\n Object.keys(tokens).forEach((key) => {\n const objKey = tokens[key];\n if (objKey && isObject(objKey)) {\n if (objKey.value && !objKey.type) {\n objKey['#value'] = objKey.value;\n delete objKey.value;\n }\n traverse(objKey);\n }\n });\n return tokens;\n};\n\nexport const prepareBaseTokens = (tokens: Tokens, config?: Options): Tokens => {\n const transformerOptions = {\n expandShadow: true,\n preserveRawValue: true,\n ...config,\n };\n const baseTokens = transformTokens(tokens, BASE_SET, [], transformerOptions);\n return traverse(baseTokens);\n};\n\nexport const filterThemeSets = (tokens: Tokens): string[] => {\n const sets = Object.keys(tokens).filter((set) => !set.startsWith('$'));\n return sets.filter((set) => !BASE_SET.includes(set));\n};\n\nexport const prepareThemesTokens = (\n tokens: Tokens,\n config?: Options,\n includeThemes: string[] = []\n): PreparedThemesTokens[] => {\n const themes = includeThemes.length ? includeThemes : filterThemeSets(tokens);\n const transformerOptions = {\n expandShadow: true,\n ...config,\n };\n const result = themes.reduce<PreparedThemesTokens[]>((res, theme) => {\n const themeTokens = transformTokens(tokens, [...BASE_SET, theme], BASE_SET, transformerOptions);\n res.push({ themeTokens: traverse(themeTokens), themeName: theme });\n return res;\n }, []);\n\n return result;\n};\n"],"names":[],"mappings":";;;AAKA,MAAM,QAAQ,GAAG,CAAC,GAAY,KAAoC;AAC9D,IAAA,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC;AACnC,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,MAAc,KAAY;IACxC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,KAAI;AAChC,QAAA,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;AAC3B,QAAA,IAAI,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE;YAC5B,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;AAC9B,gBAAA,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;gBAChC,OAAO,MAAM,CAAC,KAAK,CAAC;aACvB;YACD,QAAQ,CAAC,MAAM,CAAC,CAAC;SACpB;AACL,KAAC,CAAC,CAAC;AACH,IAAA,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC;MAEW,iBAAiB,GAAG,CAAC,MAAc,EAAE,MAAgB,KAAY;AAC1E,IAAA,MAAM,kBAAkB,GAAG;AACvB,QAAA,YAAY,EAAE,IAAI;AAClB,QAAA,gBAAgB,EAAE,IAAI;AACtB,QAAA,GAAG,MAAM;KACZ,CAAC;AACF,IAAA,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAC7E,IAAA,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC;AAChC,EAAE;AAEW,MAAA,eAAe,GAAG,CAAC,MAAc,KAAc;IACxD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACvE,IAAA,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AACzD,EAAE;AAEK,MAAM,mBAAmB,GAAG,CAC/B,MAAc,EACd,MAAgB,EAChB,aAAA,GAA0B,EAAE,KACJ;AACxB,IAAA,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,GAAG,aAAa,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;AAC9E,IAAA,MAAM,kBAAkB,GAAG;AACvB,QAAA,YAAY,EAAE,IAAI;AAClB,QAAA,GAAG,MAAM;KACZ,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAyB,CAAC,GAAG,EAAE,KAAK,KAAI;AAChE,QAAA,MAAM,WAAW,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC;AAChG,QAAA,GAAG,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;AACnE,QAAA,OAAO,GAAG,CAAC;KACd,EAAE,EAAE,CAAC,CAAC;AAEP,IAAA,OAAO,MAAM,CAAC;AAClB;;;;"}
1
+ {"version":3,"file":"prepare.js","sources":["src/prepare.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { TransformerConfigSchema, runTransform } from '@sxl-studio/token-transformer';\n\nimport { BASE_TOKEN_SET } from '@hh.ru/magritte-design-tokens-utils/constants';\nimport { buildTokensTree, buildTransformerInput, getEnabledFiles } from '@hh.ru/magritte-design-tokens-utils/convert';\nimport type {\n PreparedTokens,\n PrepareTokensOptions,\n TokensProjectConfig,\n} from '@hh.ru/magritte-design-tokens-utils/types';\n\nexport const prepareTokens = async (\n tokenDir: string,\n projectConfig: TokensProjectConfig,\n { includeThemes = [] }: PrepareTokensOptions = {}\n): Promise<PreparedTokens> => {\n // sxl молча пропускает отсутствующие файлы, и тема получилась бы пустой\n const missingFiles = getEnabledFiles(projectConfig).filter((file) => !fs.existsSync(path.join(tokenDir, file)));\n if (missingFiles.length) {\n throw new Error(`Token files listed in config.json are missing in ${tokenDir}: ${missingFiles.join(', ')}`);\n }\n\n const parsed = TransformerConfigSchema.parse(buildTransformerInput(tokenDir, projectConfig, includeThemes));\n const config = {\n ...parsed,\n source: { ...parsed.source, tokenDir: path.resolve(tokenDir), configFile: null },\n outputs: parsed.outputs.map((output) => ({ ...output, outputDir: path.resolve(output.outputDir) })),\n };\n const result = await runTransform(config, { mode: 'force' });\n\n // предупреждения тоже фатальны: сборка токенов работает без присмотра в update-tokens\n const issues = result.diagnostics.filter(({ level }) => level === 'error' || level === 'warn');\n if (issues.length) {\n throw new Error(\n `Tokens transformation failed:\\n${issues.map(({ level, code, message }) => `[${level}][${code}] ${message}`).join('\\n')}`\n );\n }\n\n const emptyTokenSets = result.tokenSets.filter(({ tokens }) => !tokens.length).map(({ id }) => id);\n if (emptyTokenSets.length) {\n throw new Error(`Token sets have no tokens: ${emptyTokenSets.join(', ')}`);\n }\n\n const baseTokenSet = result.tokenSets.find(({ id }) => id === BASE_TOKEN_SET);\n if (!baseTokenSet) {\n throw new Error('Base token set was not resolved');\n }\n\n return {\n baseTokens: buildTokensTree(baseTokenSet.tokens),\n themesTokens: result.tokenSets\n .filter(({ id }) => id !== BASE_TOKEN_SET)\n .map(({ id, tokens }) => ({ themeName: id, themeTokens: buildTokensTree(tokens) })),\n };\n};\n"],"names":[],"mappings":"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"}
package/render.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import type { NamedToken } from '@hh.ru/magritte-design-tokens-utils/types';
2
+ export declare const renderCssVariables: (tokens: NamedToken[], versionPostfix: string) => string;
3
+ export declare const renderCssVariablesBlock: (tokens: NamedToken[], selector: string, versionPostfix: string) => string;
4
+ export declare const renderAnimationCssVariables: (tokens: NamedToken[], versionPostfix: string) => string;
5
+ export declare const renderVisualTestsOverrides: (tokens: NamedToken[], versionPostfix: string) => string;
6
+ export declare const renderLessVariablesWithCssReferences: (tokens: NamedToken[], versionPostfix: string) => string;
7
+ export declare const renderLessVariablesWithValues: (tokens: NamedToken[], versionPostfix: string) => string;
package/render.js ADDED
@@ -0,0 +1,135 @@
1
+ import { CSSSpringEasing } from 'spring-easing';
2
+ import { isAnimationToken, TYPES, getShadowProperties, isLinearGradient, parseLinearGradient, getTypographyProperties, getFontWeightValue, parseTransition, parseDuration, parseCubicBezier, parseSpring, getVariableUnit } from './tokenize.js';
3
+ import 'change-case';
4
+
5
+ const cssVariable = (versionPostfix) => (name, value) => ` --${name}${versionPostfix}: ${value};`;
6
+ const lessVariable = (name, value) => `@${name}: ${value};`;
7
+ const lessVariableWithCssReference = (name, versionPostfix) => `@${name}: var(--${name}${versionPostfix});`;
8
+ const formatCubicBezier = (points) => `cubic-bezier(${points.join(', ')})`;
9
+ const formatSpring = ({ mass, stiffness, damping, velocity }) => {
10
+ const [easings] = CSSSpringEasing({ easing: `spring(${mass}, ${stiffness}, ${damping}, ${velocity})` });
11
+ return `linear(${easings})`;
12
+ };
13
+ // типографика в less — миксин, свойства которого получают значения напрямую или из css-переменных
14
+ const renderTypographyMixin = (token, formatValue) => {
15
+ const styles = getTypographyProperties(token.value).map(([property, value]) => ` ${property}: ${formatValue(property, value)};`);
16
+ const fontStyle = token.name.includes('italic') ? ' font-style: italic;\n' : '';
17
+ return `.${token.name}() {\n${fontStyle}${styles.join('\n')}\n}`;
18
+ };
19
+ // раскладывает токены на декларации (составные токены — на несколько) и форматирует их
20
+ const renderDeclarations = (tokens, formatDeclaration, renderTypography) => tokens
21
+ .reduce((result, token) => {
22
+ const { name, value, type } = token;
23
+ if (type === 'typography') {
24
+ result.push(...renderTypography(token));
25
+ }
26
+ else if (type === TYPES.FONT_WEIGHT) {
27
+ result.push(formatDeclaration(name, getFontWeightValue(value)));
28
+ }
29
+ else if (type === TYPES.TRANSITION) {
30
+ const { duration, easing } = parseTransition(value);
31
+ result.push(formatDeclaration(`${name}-timing-function`, formatCubicBezier(easing)));
32
+ result.push(formatDeclaration(`${name}-duration`, `${duration}ms`));
33
+ }
34
+ else if (type === TYPES.DURATION) {
35
+ result.push(formatDeclaration(`${name}-duration`, `${parseDuration(value)}ms`));
36
+ }
37
+ else if (type === TYPES.CUBIC_BEZIER) {
38
+ result.push(formatDeclaration(`${name}-timing-function`, formatCubicBezier(parseCubicBezier(value))));
39
+ }
40
+ else if (type === TYPES.EASING) {
41
+ result.push(formatDeclaration(`${name}-timing-function`, formatSpring(parseSpring(value))));
42
+ }
43
+ else if (type === TYPES.SHADOW) {
44
+ getShadowProperties(value).forEach(([property, propertyValue]) => result.push(formatDeclaration(`${name}-${property}`, propertyValue)));
45
+ }
46
+ else if (type === 'border') {
47
+ const { width, style } = value;
48
+ result.push(formatDeclaration(name, `${width}px ${style}`));
49
+ }
50
+ else if (type === TYPES.LETTER_SPACING) {
51
+ result.push(formatDeclaration(name, `${parseFloat(value) / 100}em`));
52
+ }
53
+ else if (type === TYPES.COLOR && isLinearGradient(value)) {
54
+ // угол градиента не нужен в css-переменной, его задает less-миксин
55
+ result.push(formatDeclaration(name, parseLinearGradient(value).stops));
56
+ }
57
+ else {
58
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
59
+ result.push(formatDeclaration(name, `${value}${getVariableUnit(token)}`));
60
+ }
61
+ return result;
62
+ }, [])
63
+ .join('\n');
64
+ // css-переменные: `--magritte-color-text-primary-v1-0-0: #000000;`
65
+ const renderCssVariables = (tokens, versionPostfix) => {
66
+ const formatDeclaration = cssVariable(versionPostfix);
67
+ return renderDeclarations(tokens, formatDeclaration, (token) => getTypographyProperties(token.value).map(([property, value]) => formatDeclaration(`${token.name}-${property}`, value)));
68
+ };
69
+ // css-переменные внутри селектора, например `:root` для дефолтной темы
70
+ const renderCssVariablesBlock = (tokens, selector, versionPostfix) => `${selector} {\n${renderCssVariables(tokens, versionPostfix)}\n}`;
71
+ // анимации остаются css-переменными, так как визуальные тесты их переопределяют
72
+ const renderAnimationCssVariables = (tokens, versionPostfix) => renderCssVariablesBlock(tokens.filter(isAnimationToken), ':root', versionPostfix);
73
+ // в визуальных тестах анимации укорачиваются до 10ms
74
+ const renderVisualTestsOverrides = (tokens, versionPostfix) => {
75
+ const overrides = tokens
76
+ .filter(({ type }) => type === TYPES.TRANSITION || type === TYPES.DURATION)
77
+ .map(({ name }) => ` --${name}-duration${versionPostfix}: 10ms;`)
78
+ .join('\n');
79
+ return `:global(.visual-tests-overrides) {\n${overrides}\n}\n`;
80
+ };
81
+ // less-переменные со ссылками на css-переменные, чтобы значения переключались вместе с темой;
82
+ // типографика и градиенты дополнительно оформляются less-миксинами
83
+ const renderLessVariablesWithCssReferences = (tokens, versionPostfix) => tokens
84
+ .reduce((result, token) => {
85
+ const { name, type, value } = token;
86
+ const reference = (suffix) => lessVariableWithCssReference(`${name}${suffix}`, versionPostfix);
87
+ if (type === 'typography') {
88
+ result.push(renderTypographyMixin(token, (property) => `var(--${name}-${property}${versionPostfix})`));
89
+ result.push(reference('-line-height'));
90
+ }
91
+ else if (type === TYPES.TRANSITION) {
92
+ result.push(reference('-duration'), reference('-timing-function'));
93
+ }
94
+ else if (type === TYPES.DURATION) {
95
+ result.push(reference('-duration'));
96
+ }
97
+ else if (type === TYPES.SHADOW) {
98
+ getShadowProperties(value).forEach(([property]) => result.push(reference(`-${property}`)));
99
+ }
100
+ else if (type === TYPES.CUBIC_BEZIER || type === TYPES.EASING) {
101
+ result.push(reference('-timing-function'));
102
+ }
103
+ else if (type === TYPES.COLOR && isLinearGradient(value)) {
104
+ const variable = `var(--${name}${versionPostfix})`;
105
+ result.push([
106
+ `.${name}(@prop, @angle: 0deg) {`,
107
+ ` @{prop}: linear-gradient(@angle, ${variable});`,
108
+ `}`,
109
+ `@${name}: linear-gradient(${parseLinearGradient(value).angle}, ${variable});`,
110
+ ].join('\n'));
111
+ }
112
+ else {
113
+ result.push(reference(''));
114
+ }
115
+ return result;
116
+ }, [])
117
+ .join('\n');
118
+ // less-переменные с конкретными значениями (базовые токены не переключаются темой, css-переменные не нужны)
119
+ const renderLessVariablesWithValues = (tokens, versionPostfix) => {
120
+ const tokensWithoutAnimations = tokens.filter((token) => !isAnimationToken(token));
121
+ const variables = renderDeclarations(tokensWithoutAnimations, lessVariable, (token) => [
122
+ renderTypographyMixin(token, (_property, value) => value),
123
+ ]);
124
+ // line-height нужен и вне миксинов
125
+ const lineHeights = tokensWithoutAnimations
126
+ .filter(({ type }) => type === 'typography')
127
+ .map(({ name, value }) => lessVariable(`${name}-line-height`, `${value.lineHeight}px`))
128
+ .join('\n');
129
+ // анимации ссылаются на css-переменные, так как визуальные тесты их переопределяют
130
+ const animations = renderLessVariablesWithCssReferences(tokens.filter(isAnimationToken), versionPostfix);
131
+ return `${variables}\n${lineHeights}\n${animations}`;
132
+ };
133
+
134
+ export { renderAnimationCssVariables, renderCssVariables, renderCssVariablesBlock, renderLessVariablesWithCssReferences, renderLessVariablesWithValues, renderVisualTestsOverrides };
135
+ //# sourceMappingURL=render.js.map
package/render.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sources":["src/render.ts"],"sourcesContent":["import { CSSSpringEasing } from 'spring-easing';\n\nimport {\n type CubicBezier,\n type Spring,\n TYPES,\n getFontWeightValue,\n getShadowProperties,\n getTypographyProperties,\n getVariableUnit,\n isAnimationToken,\n isLinearGradient,\n parseCubicBezier,\n parseDuration,\n parseLinearGradient,\n parseSpring,\n parseTransition,\n} from '@hh.ru/magritte-design-tokens-utils/tokenize';\nimport type { NamedToken, TokenCasualValue, TypographyTokenValue } from '@hh.ru/magritte-design-tokens-utils/types';\n\ntype FormatDeclaration = (name: string, value: TokenCasualValue) => string;\ntype RenderTypography = (token: NamedToken) => string[];\n\nconst cssVariable =\n (versionPostfix: string): FormatDeclaration =>\n (name, value) =>\n ` --${name}${versionPostfix}: ${value};`;\n\nconst lessVariable: FormatDeclaration = (name, value) => `@${name}: ${value};`;\n\nconst lessVariableWithCssReference = (name: string, versionPostfix: string) =>\n `@${name}: var(--${name}${versionPostfix});`;\n\nconst formatCubicBezier = (points: CubicBezier) => `cubic-bezier(${points.join(', ')})`;\n\nconst formatSpring = ({ mass, stiffness, damping, velocity }: Spring) => {\n const [easings] = CSSSpringEasing({ easing: `spring(${mass}, ${stiffness}, ${damping}, ${velocity})` });\n return `linear(${easings})`;\n};\n\n// типографика в less — миксин, свойства которого получают значения напрямую или из css-переменных\nconst renderTypographyMixin = (\n token: NamedToken,\n formatValue: (property: string, value: TokenCasualValue) => TokenCasualValue\n) => {\n const styles = getTypographyProperties(token.value).map(\n ([property, value]) => ` ${property}: ${formatValue(property, value)};`\n );\n const fontStyle = token.name.includes('italic') ? ' font-style: italic;\\n' : '';\n return `.${token.name}() {\\n${fontStyle}${styles.join('\\n')}\\n}`;\n};\n\n// раскладывает токены на декларации (составные токены — на несколько) и форматирует их\nconst renderDeclarations = (\n tokens: NamedToken[],\n formatDeclaration: FormatDeclaration,\n renderTypography: RenderTypography\n): string =>\n tokens\n .reduce<string[]>((result, token) => {\n const { name, value, type } = token;\n if (type === 'typography') {\n result.push(...renderTypography(token));\n } else if (type === TYPES.FONT_WEIGHT) {\n result.push(formatDeclaration(name, getFontWeightValue(value as TokenCasualValue)));\n } else if (type === TYPES.TRANSITION) {\n const { duration, easing } = parseTransition(value);\n result.push(formatDeclaration(`${name}-timing-function`, formatCubicBezier(easing)));\n result.push(formatDeclaration(`${name}-duration`, `${duration}ms`));\n } else if (type === TYPES.DURATION) {\n result.push(formatDeclaration(`${name}-duration`, `${parseDuration(value)}ms`));\n } else if (type === TYPES.CUBIC_BEZIER) {\n result.push(formatDeclaration(`${name}-timing-function`, formatCubicBezier(parseCubicBezier(value))));\n } else if (type === TYPES.EASING) {\n result.push(formatDeclaration(`${name}-timing-function`, formatSpring(parseSpring(value))));\n } else if (type === TYPES.SHADOW) {\n getShadowProperties(value).forEach(([property, propertyValue]) =>\n result.push(formatDeclaration(`${name}-${property}`, propertyValue))\n );\n } else if (type === 'border') {\n const { width, style } = value as Record<string, string | number>;\n result.push(formatDeclaration(name, `${width}px ${style}`));\n } else if (type === TYPES.LETTER_SPACING) {\n result.push(formatDeclaration(name, `${parseFloat(value as string) / 100}em`));\n } else if (type === TYPES.COLOR && isLinearGradient(value)) {\n // угол градиента не нужен в css-переменной, его задает less-миксин\n result.push(formatDeclaration(name, parseLinearGradient(value).stops));\n } else {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n result.push(formatDeclaration(name, `${value}${getVariableUnit(token)}`));\n }\n return result;\n }, [])\n .join('\\n');\n\n// css-переменные: `--magritte-color-text-primary-v1-0-0: #000000;`\nexport const renderCssVariables = (tokens: NamedToken[], versionPostfix: string): string => {\n const formatDeclaration = cssVariable(versionPostfix);\n return renderDeclarations(tokens, formatDeclaration, (token) =>\n getTypographyProperties(token.value).map(([property, value]) =>\n formatDeclaration(`${token.name}-${property}`, value)\n )\n );\n};\n\n// css-переменные внутри селектора, например `:root` для дефолтной темы\nexport const renderCssVariablesBlock = (tokens: NamedToken[], selector: string, versionPostfix: string): string =>\n `${selector} {\\n${renderCssVariables(tokens, versionPostfix)}\\n}`;\n\n// анимации остаются css-переменными, так как визуальные тесты их переопределяют\nexport const renderAnimationCssVariables = (tokens: NamedToken[], versionPostfix: string): string =>\n renderCssVariablesBlock(tokens.filter(isAnimationToken), ':root', versionPostfix);\n\n// в визуальных тестах анимации укорачиваются до 10ms\nexport const renderVisualTestsOverrides = (tokens: NamedToken[], versionPostfix: string): string => {\n const overrides = tokens\n .filter(({ type }) => type === TYPES.TRANSITION || type === TYPES.DURATION)\n .map(({ name }) => ` --${name}-duration${versionPostfix}: 10ms;`)\n .join('\\n');\n return `:global(.visual-tests-overrides) {\\n${overrides}\\n}\\n`;\n};\n\n// less-переменные со ссылками на css-переменные, чтобы значения переключались вместе с темой;\n// типографика и градиенты дополнительно оформляются less-миксинами\nexport const renderLessVariablesWithCssReferences = (tokens: NamedToken[], versionPostfix: string): string =>\n tokens\n .reduce<string[]>((result, token) => {\n const { name, type, value } = token;\n const reference = (suffix: string) => lessVariableWithCssReference(`${name}${suffix}`, versionPostfix);\n if (type === 'typography') {\n result.push(renderTypographyMixin(token, (property) => `var(--${name}-${property}${versionPostfix})`));\n result.push(reference('-line-height'));\n } else if (type === TYPES.TRANSITION) {\n result.push(reference('-duration'), reference('-timing-function'));\n } else if (type === TYPES.DURATION) {\n result.push(reference('-duration'));\n } else if (type === TYPES.SHADOW) {\n getShadowProperties(value).forEach(([property]) => result.push(reference(`-${property}`)));\n } else if (type === TYPES.CUBIC_BEZIER || type === TYPES.EASING) {\n result.push(reference('-timing-function'));\n } else if (type === TYPES.COLOR && isLinearGradient(value)) {\n const variable = `var(--${name}${versionPostfix})`;\n result.push(\n [\n `.${name}(@prop, @angle: 0deg) {`,\n ` @{prop}: linear-gradient(@angle, ${variable});`,\n `}`,\n `@${name}: linear-gradient(${parseLinearGradient(value).angle}, ${variable});`,\n ].join('\\n')\n );\n } else {\n result.push(reference(''));\n }\n return result;\n }, [])\n .join('\\n');\n\n// less-переменные с конкретными значениями (базовые токены не переключаются темой, css-переменные не нужны)\nexport const renderLessVariablesWithValues = (tokens: NamedToken[], versionPostfix: string): string => {\n const tokensWithoutAnimations = tokens.filter((token) => !isAnimationToken(token));\n const variables = renderDeclarations(tokensWithoutAnimations, lessVariable, (token) => [\n renderTypographyMixin(token, (_property, value) => value),\n ]);\n // line-height нужен и вне миксинов\n const lineHeights = tokensWithoutAnimations\n .filter(({ type }) => type === 'typography')\n .map(({ name, value }) =>\n lessVariable(`${name}-line-height`, `${(value as TypographyTokenValue).lineHeight}px`)\n )\n .join('\\n');\n // анимации ссылаются на css-переменные, так как визуальные тесты их переопределяют\n const animations = renderLessVariablesWithCssReferences(tokens.filter(isAnimationToken), versionPostfix);\n return `${variables}\\n${lineHeights}\\n${animations}`;\n};\n"],"names":[],"mappings":"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"}
package/tokenize.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { Named, Transform, TransformedToken, Dictionary } from 'style-dictionary';
2
- import type { TokenCasualValue, TypographyTransformations, RealTransformedToken } from '@hh.ru/magritte-design-tokens-utils/types';
1
+ import type { TokenCasualValue, TypographyTransformations, NamedToken, Tokens } from '@hh.ru/magritte-design-tokens-utils/types';
3
2
  export declare const TYPES: {
4
3
  BORDER_RADIUS: string;
5
4
  BORDER_WIDTH: string;
@@ -14,19 +13,44 @@ export declare const TYPES: {
14
13
  SPACING: string;
15
14
  TEXT_CASE: string;
16
15
  TEXT_DECORATION: string;
17
- X: string;
18
- Y: string;
19
16
  BLUR: string;
20
- SPREAD: string;
17
+ SHADOW: string;
18
+ DURATION: string;
19
+ CUBIC_BEZIER: string;
20
+ EASING: string;
21
+ TRANSITION: string;
21
22
  };
23
+ export declare const ANIMATION_TYPES: string[];
24
+ export declare const isAnimationToken: ({ type }: Pick<NamedToken, "type">) => boolean;
22
25
  export declare const getFontWeightValue: (value: TokenCasualValue) => TokenCasualValue;
23
26
  export declare const typographyTransformations: TypographyTransformations;
24
- export declare const getVariableUnit: (token: TransformedToken) => string;
25
- export interface FormatterTypographyToken {
26
- (token: RealTransformedToken, versionPostfix?: string): string[];
27
+ export declare const getTypographyProperties: (value: unknown) => Array<[string, TokenCasualValue]>;
28
+ export declare const getVariableUnit: (token: Pick<NamedToken, "type">) => string;
29
+ export type CubicBezier = [x1: number, y1: number, x2: number, y2: number];
30
+ export interface Spring {
31
+ stiffness: number;
32
+ damping: number;
33
+ mass: number;
34
+ velocity: number;
27
35
  }
28
- export interface FormatterToken {
29
- (name: string, value: TokenCasualValue, versionPostfix?: string): string;
30
- }
31
- export declare const renderTokensWithFormatter: (dictionary: Dictionary, versionPostfix: string, formatter?: FormatterToken, formatterTypography?: FormatterTypographyToken) => string;
32
- export declare const kebabWithUnderscoreTransformer: Named<Transform>;
36
+ type Transition = {
37
+ duration: number;
38
+ easing: CubicBezier;
39
+ };
40
+ export type CoreTokenValue = {
41
+ duration: number;
42
+ } | CubicBezier | Spring | Transition;
43
+ export declare const parseDuration: (value: unknown) => number;
44
+ export declare const parseCubicBezier: (value: unknown) => CubicBezier;
45
+ export declare const parseSpring: (value: unknown) => Spring;
46
+ export declare const parseTransition: (value: unknown) => Transition;
47
+ export declare const isLinearGradient: (value: unknown) => value is string;
48
+ export declare const parseLinearGradient: (value: string) => {
49
+ angle: string;
50
+ stops: string;
51
+ };
52
+ export declare const getShadowProperties: (value: unknown) => Array<[string, string]>;
53
+ export declare const getCoreTokenValue: (type: string, value: unknown) => CoreTokenValue;
54
+ export declare const makeTokenName: (path: string[], prefix: string) => string;
55
+ export declare const flattenTokens: (tree: Tokens, prefix: string) => NamedToken[];
56
+ export {};
package/tokenize.js CHANGED
@@ -1,26 +1,29 @@
1
1
  import { paramCase } from 'change-case';
2
- import { CSSSpringEasing } from 'spring-easing';
3
2
 
4
3
  const TYPES = {
5
4
  BORDER_RADIUS: 'borderRadius',
6
5
  BORDER_WIDTH: 'borderWidth',
7
6
  COLOR: 'color',
8
7
  FONT_FAMILY: 'fontFamily',
9
- FONT_SIZE: 'fontSizes',
10
- FONT_WEIGHT: 'fontWeights',
8
+ FONT_SIZE: 'fontSize',
9
+ FONT_WEIGHT: 'fontWeight',
11
10
  LETTER_SPACING: 'letterSpacing',
12
- LINE_HEIGHT: 'lineHeights',
11
+ LINE_HEIGHT: 'lineHeight',
13
12
  PARAGRAPH_SPACING: 'paragraphSpacing',
14
13
  SIZING: 'sizing',
15
14
  SPACING: 'spacing',
16
15
  TEXT_CASE: 'textCase',
17
16
  TEXT_DECORATION: 'textDecoration',
18
- // shadows
19
- X: 'x',
20
- Y: 'y',
21
17
  BLUR: 'blur',
22
- SPREAD: 'spread',
18
+ SHADOW: 'shadow',
19
+ // animations
20
+ DURATION: 'duration',
21
+ CUBIC_BEZIER: 'cubicBezier',
22
+ EASING: 'easing',
23
+ TRANSITION: 'transition',
23
24
  };
25
+ const ANIMATION_TYPES = [TYPES.DURATION, TYPES.CUBIC_BEZIER, TYPES.EASING, TYPES.TRANSITION];
26
+ const isAnimationToken = ({ type }) => ANIMATION_TYPES.includes(type);
24
27
  const FONT_WEIGHT_VALUES = { Bold: 700, 'Semi Bold': 600, Medium: 500, Regular: 400, Italic: 400, Display: 800 };
25
28
  const getFontWeightValue = (value) => value in FONT_WEIGHT_VALUES ? FONT_WEIGHT_VALUES[value] : value;
26
29
  const typographyTransformations = {
@@ -38,6 +41,17 @@ const typographyTransformations = {
38
41
  textDecoration: (value) => [{ name: 'text-decoration', value: value.toLowerCase() }],
39
42
  paragraphIndent: (value) => [{ name: 'text-indent', value }],
40
43
  };
44
+ // типографика раскладывается на css-свойства: font-family, font-weight, font-size, line-height и т.д.
45
+ const getTypographyProperties = (value) => {
46
+ const typography = value;
47
+ return Object.keys(typography).reduce((result, key) => {
48
+ if (!typographyTransformations[key]) {
49
+ return result;
50
+ }
51
+ typographyTransformations[key](typography[key]).forEach(({ name, value: propertyValue }) => result.push([name, propertyValue]));
52
+ return result;
53
+ }, []);
54
+ };
41
55
  const getVariableUnit = (token) => {
42
56
  const { type } = token;
43
57
  switch (type) {
@@ -46,91 +60,145 @@ const getVariableUnit = (token) => {
46
60
  case TYPES.PARAGRAPH_SPACING:
47
61
  case TYPES.SIZING:
48
62
  case TYPES.SPACING:
49
- case TYPES.X:
50
- case TYPES.Y:
51
63
  case TYPES.BLUR:
52
- case TYPES.SPREAD:
53
64
  case TYPES.FONT_SIZE:
54
65
  return 'px';
55
66
  default:
56
67
  return '';
57
68
  }
58
69
  };
59
- const formatterTypographyToCssVariable = (token, versionPostfix) => {
60
- const tokenValue = token.value;
61
- return Object.keys(tokenValue)
62
- .reduce((result, key) => {
63
- if (!typographyTransformations[key]) {
64
- return result;
65
- }
66
- const transformed = typographyTransformations[key](tokenValue[key]);
67
- result.push(...transformed);
68
- return result;
69
- }, [])
70
- .map(({ name, value }) => ` --${token.name}-${name}${versionPostfix}: ${value};`);
70
+ const toNumber = (value) => {
71
+ const number = typeof value === 'number' ? value : parseFloat(String(value));
72
+ if (Number.isNaN(number)) {
73
+ throw new Error(`Unsupported number value: ${JSON.stringify(value)}`);
74
+ }
75
+ return number;
71
76
  };
72
- const formatterTokenToCssVariable = (name, value, versionPostfix) => ` --${name}${versionPostfix}: ${value};`;
73
- // рендерит токены с использованием выбранных форматоров
74
- // дефолтные форматеры позволят получить токены в виде css переменных
75
- const renderTokensWithFormatter = (dictionary, versionPostfix, formatter = formatterTokenToCssVariable, formatterTypography = formatterTypographyToCssVariable) => {
76
- const props = dictionary.allProperties
77
- .reduce((result, token) => {
78
- const { name, value, type, rawValue } = token;
79
- if (type === 'typography') {
80
- result.push(...formatterTypography(token, versionPostfix));
81
- }
82
- else if (type === 'fontWeights') {
83
- result.push(formatter(name, getFontWeightValue(value), versionPostfix));
84
- }
85
- else if (type === 'animation') {
86
- const { x1, y1, x2, y2, duration } = rawValue;
87
- result.push(formatter(`${name}-timing-function`, `cubic-bezier(${x1}, ${y1}, ${x2}, ${y2})`, versionPostfix));
88
- result.push(formatter(`${name}-duration`, `${duration}ms`, versionPostfix));
89
- }
90
- else if (type === 'animationTime') {
91
- const { duration } = rawValue;
92
- result.push(formatter(`${name}-duration`, `${duration}ms`, versionPostfix));
93
- }
94
- else if (type === 'animationEaseBase') {
95
- const { x1, y1, x2, y2 } = rawValue;
96
- result.push(formatter(`${name}-timing-function`, `cubic-bezier(${x1}, ${y1}, ${x2}, ${y2})`, versionPostfix));
97
- }
98
- else if (type === 'animationEaseSpring') {
99
- const { stiffness, damping, mass } = rawValue;
100
- const [easings] = CSSSpringEasing({ easing: `spring(${mass}, ${stiffness}, ${damping})` });
101
- result.push(formatter(`${name}-timing-function`, `linear(${easings})`, versionPostfix));
102
- }
103
- else if (type === 'border') {
104
- const { width, style } = rawValue;
105
- result.push(formatter(name, `${width}px ${style}`, versionPostfix));
106
- }
107
- else if (type === 'letterSpacing') {
108
- result.push(formatter(name, `${parseFloat(value) / 100}em`, versionPostfix));
109
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
110
- }
111
- else if (type === 'color' && value.toString().includes('linear-gradient')) {
112
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
113
- let colorString = value.toString().replace('linear-gradient(', '').replace(')', '');
114
- // убираем угол градиента, так как он не нужен в css переменной
115
- colorString = colorString.split(', ').slice(1).join(', ');
116
- result.push(formatter(name, colorString, versionPostfix));
117
- }
118
- else {
119
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
120
- result.push(formatter(name, `${value}${getVariableUnit(token)}`, versionPostfix));
121
- }
122
- return result;
123
- }, [])
124
- .join('\n');
125
- return props;
77
+ // "100ms", "0.1s" или { value: 100, unit: 'ms' } -> миллисекунды
78
+ const parseDuration = (value) => {
79
+ const isDtcgDuration = typeof value === 'object' && value !== null && 'value' in value && 'unit' in value;
80
+ const [amount, unit] = isDtcgDuration
81
+ ? [toNumber(value.value), String(value.unit)]
82
+ : [
83
+ toNumber(value),
84
+ String(value)
85
+ .trim()
86
+ .replace(/^[-\d.]+/, ''),
87
+ ];
88
+ if (!['', 'ms', 's'].includes(unit)) {
89
+ throw new Error(`Unsupported duration value: ${JSON.stringify(value)}`);
90
+ }
91
+ return unit === 's' ? parseFloat((amount * 1000).toPrecision(12)) : amount;
92
+ };
93
+ // [0.4, 0.24, 0, 1] или "cubic-bezier(0.4, 0.24, 0, 1)"
94
+ const parseCubicBezier = (value) => {
95
+ const points = Array.isArray(value)
96
+ ? value
97
+ : /^cubic-bezier\(([^)]*)\)$/i.exec(String(value).trim())?.[1].split(',');
98
+ if (!points || points.length !== 4) {
99
+ throw new Error(`Unsupported cubic bezier value: ${JSON.stringify(value)}`);
100
+ }
101
+ const [x1, y1, x2, y2] = points.map(toNumber);
102
+ return [x1, y1, x2, y2];
103
+ };
104
+ // "spring(mass, stiffness, damping, velocity)", velocity необязателен
105
+ const parseSpring = (value) => {
106
+ const params = /^spring\(([^)]*)\)$/i.exec(String(value).trim())?.[1].split(',');
107
+ if (!params || params.length < 3 || params.length > 4) {
108
+ throw new Error(`Unsupported easing value: ${JSON.stringify(value)}`);
109
+ }
110
+ const [mass, stiffness, damping, velocity = 0] = params.map(toNumber);
111
+ return { stiffness, damping, mass, velocity };
112
+ };
113
+ // { duration, delay, easing | timingFunction }
114
+ const parseTransition = (value) => {
115
+ const { duration, delay, easing, timingFunction } = (value ?? {});
116
+ if (delay !== undefined && parseDuration(delay) !== 0) {
117
+ throw new Error(`Transition delay is not supported: ${JSON.stringify(value)}`);
118
+ }
119
+ return { duration: parseDuration(duration), easing: parseCubicBezier(easing ?? timingFunction) };
120
+ };
121
+ const isLinearGradient = (value) => typeof value === 'string' && value.includes('linear-gradient');
122
+ // "linear-gradient(180deg, #000 0%, #fff 100%)" -> угол и цвета с позициями
123
+ const parseLinearGradient = (value) => {
124
+ const inner = value.replace('linear-gradient(', '');
125
+ // закрывающая скобка градиента — последняя, внутри могут быть скобки цветов
126
+ const closingIndex = inner.lastIndexOf(')');
127
+ const content = closingIndex === -1 ? inner : `${inner.slice(0, closingIndex)}${inner.slice(closingIndex + 1)}`;
128
+ const [angle, ...stops] = content.split(', ');
129
+ return { angle, stops: stops.join(', ') };
126
130
  };
127
- const kebabWithUnderscoreTransformer = {
128
- type: 'name',
129
- name: 'name/cti/kebabWithUnderscore',
130
- transformer: (token, options = {}) => paramCase([options.prefix].concat(token.path).join(' '), {
131
- stripRegexp: /[^A-Z0-9_]+/gi,
132
- }),
131
+ const toPixels = (value) => {
132
+ const match = /^(-?[\d.]+)(px)?$/.exec(String(value).trim());
133
+ if (!match) {
134
+ throw new Error(`Unsupported shadow dimension: ${JSON.stringify(value)}`);
135
+ }
136
+ return `${parseFloat(match[1])}px`;
137
+ };
138
+ // тень раскладывается на отдельные css-переменные: -color, -type, -x, -y, -blur, -spread
139
+ const getShadowProperties = (value) => {
140
+ const layers = Array.isArray(value) ? value : [value];
141
+ if (layers.length !== 1) {
142
+ throw new Error(`Multi-layer shadows are not supported: ${JSON.stringify(value)}`);
143
+ }
144
+ const { color, type = 'dropShadow', offsetX, offsetY, blur, spread } = layers[0];
145
+ return [
146
+ ['color', String(color)],
147
+ ['type', String(type)],
148
+ ['x', toPixels(offsetX)],
149
+ ['y', toPixels(offsetY)],
150
+ ['blur', toPixels(blur)],
151
+ ['spread', toPixels(spread)],
152
+ ];
153
+ };
154
+ // значения анимационных токенов для core-tokens.ts (публичный JS API)
155
+ const getCoreTokenValue = (type, value) => {
156
+ switch (type) {
157
+ case TYPES.DURATION:
158
+ return { duration: parseDuration(value) };
159
+ case TYPES.CUBIC_BEZIER:
160
+ return parseCubicBezier(value);
161
+ case TYPES.EASING:
162
+ return parseSpring(value);
163
+ case TYPES.TRANSITION:
164
+ return parseTransition(value);
165
+ default:
166
+ throw new Error(`Unsupported animation token type: ${type}`);
167
+ }
168
+ };
169
+ // kebab-case с сохранением подчеркиваний: ['color', '_button'] -> magritte-color-_button
170
+ const makeTokenName = (path, prefix) => paramCase([prefix, ...path].join(' '), {
171
+ stripRegexp: /[^A-Z0-9_]+/gi,
172
+ });
173
+ const isPlainObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
174
+ // раскладывает дерево токенов в список, порядок — порядок обхода объекта
175
+ const flattenTokens = (tree, prefix) => {
176
+ const tokens = [];
177
+ const walk = (node, parentPath) => {
178
+ Object.entries(node).forEach(([key, child]) => {
179
+ if (!isPlainObject(child)) {
180
+ return;
181
+ }
182
+ const path = [...parentPath, key];
183
+ if ('value' in child) {
184
+ tokens.push({ ...child, path, name: makeTokenName(path, prefix) });
185
+ }
186
+ else {
187
+ walk(child, path);
188
+ }
189
+ });
190
+ };
191
+ walk(tree, []);
192
+ const names = new Map();
193
+ tokens.forEach(({ name, path }) => {
194
+ const existingPath = names.get(name);
195
+ if (existingPath) {
196
+ throw new Error(`Token name collision: ${name} (${existingPath.join('.')}, ${path.join('.')})`);
197
+ }
198
+ names.set(name, path);
199
+ });
200
+ return tokens;
133
201
  };
134
202
 
135
- export { TYPES, getFontWeightValue, getVariableUnit, kebabWithUnderscoreTransformer, renderTokensWithFormatter, typographyTransformations };
203
+ export { ANIMATION_TYPES, TYPES, flattenTokens, getCoreTokenValue, getFontWeightValue, getShadowProperties, getTypographyProperties, getVariableUnit, isAnimationToken, isLinearGradient, makeTokenName, parseCubicBezier, parseDuration, parseLinearGradient, parseSpring, parseTransition, typographyTransformations };
136
204
  //# sourceMappingURL=tokenize.js.map
package/tokenize.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tokenize.js","sources":["src/tokenize.ts"],"sourcesContent":["import { paramCase } from 'change-case';\nimport { CSSSpringEasing } from 'spring-easing';\nimport { Named, Transform, TransformedToken, Dictionary } from 'style-dictionary';\n\nimport type {\n TypographyTokenValue,\n TokenCasualValue,\n TypographyTransformationsResult,\n TypographyTransformations,\n RealTransformedToken,\n} from '@hh.ru/magritte-design-tokens-utils/types';\n\nexport const TYPES = {\n BORDER_RADIUS: 'borderRadius',\n BORDER_WIDTH: 'borderWidth',\n COLOR: 'color',\n FONT_FAMILY: 'fontFamily',\n FONT_SIZE: 'fontSizes',\n FONT_WEIGHT: 'fontWeights',\n LETTER_SPACING: 'letterSpacing',\n LINE_HEIGHT: 'lineHeights',\n PARAGRAPH_SPACING: 'paragraphSpacing',\n SIZING: 'sizing',\n SPACING: 'spacing',\n TEXT_CASE: 'textCase',\n\n TEXT_DECORATION: 'textDecoration',\n // shadows\n X: 'x',\n Y: 'y',\n BLUR: 'blur',\n SPREAD: 'spread',\n};\n\nconst FONT_WEIGHT_VALUES = { Bold: 700, 'Semi Bold': 600, Medium: 500, Regular: 400, Italic: 400, Display: 800 };\n\nexport const getFontWeightValue = (value: TokenCasualValue): TokenCasualValue =>\n value in FONT_WEIGHT_VALUES ? FONT_WEIGHT_VALUES[value as keyof typeof FONT_WEIGHT_VALUES] : value;\n\nexport const typographyTransformations: TypographyTransformations = {\n fontFamily: (value) => [{ name: 'font-family', value: `\"${value}\"` }],\n fontWeight: (value) => [\n {\n name: 'font-weight',\n value: getFontWeightValue(value),\n },\n ],\n fontSize: (value) => [{ name: 'font-size', value: `${value}px` }],\n lineHeight: (value) => [{ name: 'line-height', value: `${value}px` }],\n letterSpacing: (value) => [{ name: 'letter-spacing', value: `${parseFloat(value as string) / 100}em` }],\n textCase: (value) => [{ name: 'text-transform', value: (value as string).toLowerCase() }],\n textDecoration: (value) => [{ name: 'text-decoration', value: (value as string).toLowerCase() }],\n paragraphIndent: (value) => [{ name: 'text-indent', value }],\n};\n\nexport const getVariableUnit = (token: TransformedToken): string => {\n const { type } = token;\n\n switch (type) {\n case TYPES.BORDER_RADIUS:\n case TYPES.BORDER_WIDTH:\n case TYPES.PARAGRAPH_SPACING:\n case TYPES.SIZING:\n case TYPES.SPACING:\n case TYPES.X:\n case TYPES.Y:\n case TYPES.BLUR:\n case TYPES.SPREAD:\n case TYPES.FONT_SIZE:\n return 'px';\n default:\n return '';\n }\n};\n\nexport interface FormatterTypographyToken {\n (token: RealTransformedToken, versionPostfix?: string): string[];\n}\nconst formatterTypographyToCssVariable: FormatterTypographyToken = (token, versionPostfix) => {\n const tokenValue = token.value as TypographyTokenValue;\n return Object.keys(tokenValue)\n .reduce<TypographyTransformationsResult>((result, key) => {\n if (!typographyTransformations[key]) {\n return result;\n }\n const transformed = typographyTransformations[key](tokenValue[key]);\n result.push(...transformed);\n return result;\n }, [])\n .map(({ name, value }) => ` --${token.name}-${name}${versionPostfix}: ${value};`);\n};\n\ntype Duration = { duration: number };\n\ntype Ease = { x1: number; y1: number; x2: number; y2: number };\n\ntype Spring = { stiffness: number; damping: number; mass: number };\n\nexport interface FormatterToken {\n (name: string, value: TokenCasualValue, versionPostfix?: string): string;\n}\nconst formatterTokenToCssVariable: FormatterToken = (name, value, versionPostfix) =>\n ` --${name}${versionPostfix}: ${value};`;\n\n// рендерит токены с использованием выбранных форматоров\n// дефолтные форматеры позволят получить токены в виде css переменных\nexport const renderTokensWithFormatter = (\n dictionary: Dictionary,\n versionPostfix: string,\n formatter = formatterTokenToCssVariable,\n formatterTypography = formatterTypographyToCssVariable\n): string => {\n const props = dictionary.allProperties\n .reduce<string[]>((result, token) => {\n const { name, value, type, rawValue } = token as RealTransformedToken;\n if (type === 'typography') {\n result.push(...formatterTypography(token, versionPostfix));\n } else if (type === 'fontWeights') {\n result.push(formatter(name, getFontWeightValue(value as TokenCasualValue), versionPostfix));\n } else if (type === 'animation') {\n const { x1, y1, x2, y2, duration } = rawValue as Duration & Ease;\n result.push(\n formatter(`${name}-timing-function`, `cubic-bezier(${x1}, ${y1}, ${x2}, ${y2})`, versionPostfix)\n );\n result.push(formatter(`${name}-duration`, `${duration}ms`, versionPostfix));\n } else if (type === 'animationTime') {\n const { duration } = rawValue as Duration;\n result.push(formatter(`${name}-duration`, `${duration}ms`, versionPostfix));\n } else if (type === 'animationEaseBase') {\n const { x1, y1, x2, y2 } = rawValue as Ease;\n result.push(\n formatter(`${name}-timing-function`, `cubic-bezier(${x1}, ${y1}, ${x2}, ${y2})`, versionPostfix)\n );\n } else if (type === 'animationEaseSpring') {\n const { stiffness, damping, mass } = rawValue as Spring;\n const [easings] = CSSSpringEasing({ easing: `spring(${mass}, ${stiffness}, ${damping})` });\n result.push(formatter(`${name}-timing-function`, `linear(${easings})`, versionPostfix));\n } else if (type === 'border') {\n const { width, style } = rawValue as Record<string, string | number>;\n result.push(formatter(name, `${width}px ${style}`, versionPostfix));\n } else if (type === 'letterSpacing') {\n result.push(formatter(name, `${parseFloat(value as string) / 100}em`, versionPostfix));\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n } else if (type === 'color' && value.toString().includes('linear-gradient')) {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n let colorString = value.toString().replace('linear-gradient(', '').replace(')', '');\n // убираем угол градиента, так как он не нужен в css переменной\n colorString = colorString.split(', ').slice(1).join(', ');\n result.push(formatter(name, colorString, versionPostfix));\n } else {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n result.push(formatter(name, `${value}${getVariableUnit(token)}`, versionPostfix));\n }\n return result;\n }, [])\n .join('\\n');\n\n return props;\n};\n\nexport const kebabWithUnderscoreTransformer: Named<Transform> = {\n type: 'name',\n name: 'name/cti/kebabWithUnderscore',\n transformer: (token, options = {}) =>\n paramCase([options.prefix].concat(token.path).join(' '), {\n stripRegexp: /[^A-Z0-9_]+/gi,\n }),\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tokenize.js","sources":["src/tokenize.ts"],"sourcesContent":["import { paramCase } from 'change-case';\n\nimport type {\n TypographyTokenValue,\n TokenCasualValue,\n TypographyTransformations,\n NamedToken,\n Tokens,\n TreeToken,\n} from '@hh.ru/magritte-design-tokens-utils/types';\n\nexport const TYPES = {\n BORDER_RADIUS: 'borderRadius',\n BORDER_WIDTH: 'borderWidth',\n COLOR: 'color',\n FONT_FAMILY: 'fontFamily',\n FONT_SIZE: 'fontSize',\n FONT_WEIGHT: 'fontWeight',\n LETTER_SPACING: 'letterSpacing',\n LINE_HEIGHT: 'lineHeight',\n PARAGRAPH_SPACING: 'paragraphSpacing',\n SIZING: 'sizing',\n SPACING: 'spacing',\n TEXT_CASE: 'textCase',\n\n TEXT_DECORATION: 'textDecoration',\n BLUR: 'blur',\n SHADOW: 'shadow',\n // animations\n DURATION: 'duration',\n CUBIC_BEZIER: 'cubicBezier',\n EASING: 'easing',\n TRANSITION: 'transition',\n};\n\nexport const ANIMATION_TYPES = [TYPES.DURATION, TYPES.CUBIC_BEZIER, TYPES.EASING, TYPES.TRANSITION];\n\nexport const isAnimationToken = ({ type }: Pick<NamedToken, 'type'>): boolean => ANIMATION_TYPES.includes(type);\n\nconst FONT_WEIGHT_VALUES = { Bold: 700, 'Semi Bold': 600, Medium: 500, Regular: 400, Italic: 400, Display: 800 };\n\nexport const getFontWeightValue = (value: TokenCasualValue): TokenCasualValue =>\n value in FONT_WEIGHT_VALUES ? FONT_WEIGHT_VALUES[value as keyof typeof FONT_WEIGHT_VALUES] : value;\n\nexport const typographyTransformations: TypographyTransformations = {\n fontFamily: (value) => [{ name: 'font-family', value: `\"${value}\"` }],\n fontWeight: (value) => [\n {\n name: 'font-weight',\n value: getFontWeightValue(value),\n },\n ],\n fontSize: (value) => [{ name: 'font-size', value: `${value}px` }],\n lineHeight: (value) => [{ name: 'line-height', value: `${value}px` }],\n letterSpacing: (value) => [{ name: 'letter-spacing', value: `${parseFloat(value as string) / 100}em` }],\n textCase: (value) => [{ name: 'text-transform', value: (value as string).toLowerCase() }],\n textDecoration: (value) => [{ name: 'text-decoration', value: (value as string).toLowerCase() }],\n paragraphIndent: (value) => [{ name: 'text-indent', value }],\n};\n\n// типографика раскладывается на css-свойства: font-family, font-weight, font-size, line-height и т.д.\nexport const getTypographyProperties = (value: unknown): Array<[string, TokenCasualValue]> => {\n const typography = value as TypographyTokenValue;\n return Object.keys(typography).reduce<Array<[string, TokenCasualValue]>>((result, key) => {\n if (!typographyTransformations[key]) {\n return result;\n }\n typographyTransformations[key](typography[key]).forEach(({ name, value: propertyValue }) =>\n result.push([name, propertyValue])\n );\n return result;\n }, []);\n};\n\nexport const getVariableUnit = (token: Pick<NamedToken, 'type'>): string => {\n const { type } = token;\n\n switch (type) {\n case TYPES.BORDER_RADIUS:\n case TYPES.BORDER_WIDTH:\n case TYPES.PARAGRAPH_SPACING:\n case TYPES.SIZING:\n case TYPES.SPACING:\n case TYPES.BLUR:\n case TYPES.FONT_SIZE:\n return 'px';\n default:\n return '';\n }\n};\n\nexport type CubicBezier = [x1: number, y1: number, x2: number, y2: number];\n\nexport interface Spring {\n stiffness: number;\n damping: number;\n mass: number;\n velocity: number;\n}\n\ntype Transition = { duration: number; easing: CubicBezier };\n\nexport type CoreTokenValue = { duration: number } | CubicBezier | Spring | Transition;\n\nconst toNumber = (value: unknown): number => {\n const number = typeof value === 'number' ? value : parseFloat(String(value));\n if (Number.isNaN(number)) {\n throw new Error(`Unsupported number value: ${JSON.stringify(value)}`);\n }\n return number;\n};\n\n// \"100ms\", \"0.1s\" или { value: 100, unit: 'ms' } -> миллисекунды\nexport const parseDuration = (value: unknown): number => {\n const isDtcgDuration = typeof value === 'object' && value !== null && 'value' in value && 'unit' in value;\n const [amount, unit] = isDtcgDuration\n ? [toNumber(value.value), String(value.unit)]\n : [\n toNumber(value),\n String(value)\n .trim()\n .replace(/^[-\\d.]+/, ''),\n ];\n if (!['', 'ms', 's'].includes(unit)) {\n throw new Error(`Unsupported duration value: ${JSON.stringify(value)}`);\n }\n return unit === 's' ? parseFloat((amount * 1000).toPrecision(12)) : amount;\n};\n\n// [0.4, 0.24, 0, 1] или \"cubic-bezier(0.4, 0.24, 0, 1)\"\nexport const parseCubicBezier = (value: unknown): CubicBezier => {\n const points = Array.isArray(value)\n ? value\n : /^cubic-bezier\\(([^)]*)\\)$/i.exec(String(value).trim())?.[1].split(',');\n if (!points || points.length !== 4) {\n throw new Error(`Unsupported cubic bezier value: ${JSON.stringify(value)}`);\n }\n const [x1, y1, x2, y2] = points.map(toNumber);\n return [x1, y1, x2, y2];\n};\n\n// \"spring(mass, stiffness, damping, velocity)\", velocity необязателен\nexport const parseSpring = (value: unknown): Spring => {\n const params = /^spring\\(([^)]*)\\)$/i.exec(String(value).trim())?.[1].split(',');\n if (!params || params.length < 3 || params.length > 4) {\n throw new Error(`Unsupported easing value: ${JSON.stringify(value)}`);\n }\n const [mass, stiffness, damping, velocity = 0] = params.map(toNumber);\n return { stiffness, damping, mass, velocity };\n};\n\n// { duration, delay, easing | timingFunction }\nexport const parseTransition = (value: unknown): Transition => {\n const { duration, delay, easing, timingFunction } = (value ?? {}) as Record<string, unknown>;\n if (delay !== undefined && parseDuration(delay) !== 0) {\n throw new Error(`Transition delay is not supported: ${JSON.stringify(value)}`);\n }\n return { duration: parseDuration(duration), easing: parseCubicBezier(easing ?? timingFunction) };\n};\n\nexport const isLinearGradient = (value: unknown): value is string =>\n typeof value === 'string' && value.includes('linear-gradient');\n\n// \"linear-gradient(180deg, #000 0%, #fff 100%)\" -> угол и цвета с позициями\nexport const parseLinearGradient = (value: string): { angle: string; stops: string } => {\n const inner = value.replace('linear-gradient(', '');\n // закрывающая скобка градиента — последняя, внутри могут быть скобки цветов\n const closingIndex = inner.lastIndexOf(')');\n const content = closingIndex === -1 ? inner : `${inner.slice(0, closingIndex)}${inner.slice(closingIndex + 1)}`;\n const [angle, ...stops] = content.split(', ');\n return { angle, stops: stops.join(', ') };\n};\n\nconst toPixels = (value: unknown): string => {\n const match = /^(-?[\\d.]+)(px)?$/.exec(String(value).trim());\n if (!match) {\n throw new Error(`Unsupported shadow dimension: ${JSON.stringify(value)}`);\n }\n return `${parseFloat(match[1])}px`;\n};\n\n// тень раскладывается на отдельные css-переменные: -color, -type, -x, -y, -blur, -spread\nexport const getShadowProperties = (value: unknown): Array<[string, string]> => {\n const layers = Array.isArray(value) ? value : [value];\n if (layers.length !== 1) {\n throw new Error(`Multi-layer shadows are not supported: ${JSON.stringify(value)}`);\n }\n const { color, type = 'dropShadow', offsetX, offsetY, blur, spread } = layers[0] as Record<string, unknown>;\n return [\n ['color', String(color)],\n ['type', String(type)],\n ['x', toPixels(offsetX)],\n ['y', toPixels(offsetY)],\n ['blur', toPixels(blur)],\n ['spread', toPixels(spread)],\n ];\n};\n\n// значения анимационных токенов для core-tokens.ts (публичный JS API)\nexport const getCoreTokenValue = (type: string, value: unknown): CoreTokenValue => {\n switch (type) {\n case TYPES.DURATION:\n return { duration: parseDuration(value) };\n case TYPES.CUBIC_BEZIER:\n return parseCubicBezier(value);\n case TYPES.EASING:\n return parseSpring(value);\n case TYPES.TRANSITION:\n return parseTransition(value);\n default:\n throw new Error(`Unsupported animation token type: ${type}`);\n }\n};\n\n// kebab-case с сохранением подчеркиваний: ['color', '_button'] -> magritte-color-_button\nexport const makeTokenName = (path: string[], prefix: string): string =>\n paramCase([prefix, ...path].join(' '), {\n stripRegexp: /[^A-Z0-9_]+/gi,\n });\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\n// раскладывает дерево токенов в список, порядок — порядок обхода объекта\nexport const flattenTokens = (tree: Tokens, prefix: string): NamedToken[] => {\n const tokens: NamedToken[] = [];\n const walk = (node: Record<string, unknown>, parentPath: string[]) => {\n Object.entries(node).forEach(([key, child]) => {\n if (!isPlainObject(child)) {\n return;\n }\n const path = [...parentPath, key];\n if ('value' in child) {\n tokens.push({ ...(child as unknown as TreeToken), path, name: makeTokenName(path, prefix) });\n } else {\n walk(child, path);\n }\n });\n };\n walk(tree, []);\n\n const names = new Map<string, string[]>();\n tokens.forEach(({ name, path }) => {\n const existingPath = names.get(name);\n if (existingPath) {\n throw new Error(`Token name collision: ${name} (${existingPath.join('.')}, ${path.join('.')})`);\n }\n names.set(name, path);\n });\n return tokens;\n};\n"],"names":[],"mappings":"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"}
package/types.d.ts CHANGED
@@ -1,20 +1,47 @@
1
- import type { TransformedToken } from 'style-dictionary';
2
1
  export type Tokens = Record<string, unknown>;
3
2
  export type TypographyTokenValue = Record<string, string | number>;
4
3
  export type TokenCasualValue = string | number;
5
- export type TokenValue = TokenCasualValue | TypographyTokenValue;
4
+ export type TokenValue = TokenCasualValue | TypographyTokenValue | TokenCasualValue[];
6
5
  export type TypographyTransformationsResult = Array<{
7
6
  name: string;
8
7
  value: TokenCasualValue;
9
8
  }>;
10
9
  export type TypographyTransformations = Record<string, (value: TokenCasualValue) => TypographyTransformationsResult>;
11
- export type RealTransformedToken = Omit<TransformedToken, 'value'> & {
12
- name: string;
10
+ export interface TreeToken {
13
11
  value: TokenValue;
14
- rawValue?: TokenValue;
15
- type?: string;
16
- };
12
+ type: string;
13
+ description?: string;
14
+ }
15
+ export interface NamedToken extends TreeToken {
16
+ name: string;
17
+ path: string[];
18
+ }
17
19
  export interface PreparedThemesTokens {
18
20
  themeTokens: Tokens;
19
21
  themeName: string;
20
22
  }
23
+ export interface PreparedTokens {
24
+ baseTokens: Tokens;
25
+ themesTokens: PreparedThemesTokens[];
26
+ }
27
+ export interface PrepareTokensOptions {
28
+ includeThemes?: string[];
29
+ }
30
+ export interface TokensProjectConfig {
31
+ settings?: {
32
+ remBase?: number;
33
+ };
34
+ collections: Array<{
35
+ name: string;
36
+ enabled?: boolean;
37
+ modes: Array<{
38
+ name: string;
39
+ enabled?: boolean;
40
+ files: Record<string, string>;
41
+ }>;
42
+ }>;
43
+ groups?: Array<{
44
+ name: string;
45
+ collections: string[];
46
+ }>;
47
+ }
package/purify.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { Tokens } from '@hh.ru/magritte-design-tokens-utils/types';
2
- export declare const purify: (tokensData: Tokens) => Tokens;
package/purify.js DELETED
@@ -1,32 +0,0 @@
1
- const purify = (tokensData) => {
2
- const removeEmptyValues = (obj) => {
3
- if (Array.isArray(obj)) {
4
- const filteredObj = obj.filter((item) => item);
5
- filteredObj.map((item) => {
6
- if (typeof item === 'object') {
7
- return removeEmptyValues(item);
8
- }
9
- else if (Array.isArray(item)) {
10
- return removeEmptyValues(item);
11
- }
12
- return item;
13
- });
14
- return filteredObj;
15
- }
16
- const filteredObj = Object.keys(obj).reduce((acc, key) => (obj[key] ? { ...acc, [key]: obj[key] } : acc), {});
17
- Object.keys(filteredObj).forEach((key) => {
18
- const item = filteredObj[key];
19
- if (typeof item === 'object') {
20
- filteredObj[key] = removeEmptyValues(item);
21
- }
22
- else if (Array.isArray(item)) {
23
- filteredObj[key] = removeEmptyValues(item);
24
- }
25
- });
26
- return filteredObj;
27
- };
28
- return removeEmptyValues(tokensData);
29
- };
30
-
31
- export { purify };
32
- //# sourceMappingURL=purify.js.map
package/purify.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"purify.js","sources":["src/purify.ts"],"sourcesContent":["import { Tokens } from '@hh.ru/magritte-design-tokens-utils/types';\n\nexport const purify = (tokensData: Tokens): Tokens => {\n const removeEmptyValues = (obj: Tokens | Array<unknown>): Tokens | Array<unknown> => {\n if (Array.isArray(obj)) {\n const filteredObj: unknown[] = obj.filter((item) => item);\n filteredObj.map((item) => {\n if (typeof item === 'object') {\n return removeEmptyValues(item as Record<string, unknown>);\n } else if (Array.isArray(item)) {\n return removeEmptyValues(item);\n }\n return item;\n });\n return filteredObj;\n }\n const filteredObj = Object.keys(obj).reduce<Tokens>(\n (acc, key) => (obj[key] ? { ...acc, [key]: obj[key] } : acc),\n {}\n );\n Object.keys(filteredObj).forEach((key) => {\n const item = filteredObj[key];\n if (typeof item === 'object') {\n filteredObj[key] = removeEmptyValues(item as Record<string, unknown>);\n } else if (Array.isArray(item)) {\n filteredObj[key] = removeEmptyValues(item);\n }\n });\n return filteredObj;\n };\n\n return removeEmptyValues(tokensData) as Tokens;\n};\n"],"names":[],"mappings":"AAEa,MAAA,MAAM,GAAG,CAAC,UAAkB,KAAY;AACjD,IAAA,MAAM,iBAAiB,GAAG,CAAC,GAA4B,KAA6B;AAChF,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AACpB,YAAA,MAAM,WAAW,GAAc,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC1D,YAAA,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;AACrB,gBAAA,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;AAC1B,oBAAA,OAAO,iBAAiB,CAAC,IAA+B,CAAC,CAAC;iBAC7D;AAAM,qBAAA,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AAC5B,oBAAA,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC;iBAClC;AACD,gBAAA,OAAO,IAAI,CAAC;AAChB,aAAC,CAAC,CAAC;AACH,YAAA,OAAO,WAAW,CAAC;SACtB;QACD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CACvC,CAAC,GAAG,EAAE,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,EAC5D,EAAE,CACL,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,KAAI;AACrC,YAAA,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;AAC9B,YAAA,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;gBAC1B,WAAW,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,IAA+B,CAAC,CAAC;aACzE;AAAM,iBAAA,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;gBAC5B,WAAW,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;aAC9C;AACL,SAAC,CAAC,CAAC;AACH,QAAA,OAAO,WAAW,CAAC;AACvB,KAAC,CAAC;AAEF,IAAA,OAAO,iBAAiB,CAAC,UAAU,CAAW,CAAC;AACnD;;;;"}