@primer/primitives 11.4.0-rc.f798df25 → 11.4.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/dist/build/filters/hasLlmExtensions.d.ts +7 -0
- package/dist/build/filters/hasLlmExtensions.js +11 -0
- package/dist/build/filters/index.d.ts +1 -0
- package/dist/build/filters/index.js +1 -0
- package/dist/build/formats/index.d.ts +1 -0
- package/dist/build/formats/index.js +1 -0
- package/dist/build/formats/markdownLlmGuidelines.d.ts +10 -0
- package/dist/build/formats/markdownLlmGuidelines.js +194 -0
- package/dist/build/platforms/index.d.ts +1 -0
- package/dist/build/platforms/index.js +1 -0
- package/dist/build/platforms/llmGuidelines.d.ts +2 -0
- package/dist/build/platforms/llmGuidelines.js +17 -0
- package/dist/build/preprocessors/inheritGroupProperties.d.ts +7 -0
- package/dist/build/preprocessors/inheritGroupProperties.js +70 -0
- package/dist/build/primerStyleDictionary.js +7 -1
- package/dist/build/schemas/borderToken.d.ts +6 -0
- package/dist/build/schemas/borderToken.js +6 -0
- package/dist/build/schemas/colorToken.d.ts +4 -0
- package/dist/build/schemas/colorToken.js +2 -0
- package/dist/build/schemas/cubicBezierToken.d.ts +6 -0
- package/dist/build/schemas/cubicBezierToken.js +10 -2
- package/dist/build/schemas/designToken.d.ts +1 -1
- package/dist/build/schemas/designToken.js +113 -21
- package/dist/build/schemas/dimensionToken.d.ts +6 -2
- package/dist/build/schemas/dimensionToken.js +6 -2
- package/dist/build/schemas/durationToken.d.ts +6 -0
- package/dist/build/schemas/durationToken.js +6 -0
- package/dist/build/schemas/fontFamilyToken.d.ts +4 -0
- package/dist/build/schemas/fontFamilyToken.js +2 -0
- package/dist/build/schemas/fontWeightToken.d.ts +4 -0
- package/dist/build/schemas/fontWeightToken.js +2 -0
- package/dist/build/schemas/gradientToken.d.ts +4 -0
- package/dist/build/schemas/gradientToken.js +2 -0
- package/dist/build/schemas/llmExtension.d.ts +9 -0
- package/dist/build/schemas/llmExtension.js +11 -0
- package/dist/build/schemas/numberToken.d.ts +4 -0
- package/dist/build/schemas/numberToken.js +2 -0
- package/dist/build/schemas/shadowToken.d.ts +4 -0
- package/dist/build/schemas/shadowToken.js +2 -0
- package/dist/build/schemas/stringToken.d.ts +6 -0
- package/dist/build/schemas/stringToken.js +6 -0
- package/dist/build/schemas/transitionToken.d.ts +6 -0
- package/dist/build/schemas/transitionToken.js +6 -0
- package/dist/build/schemas/typographyToken.d.ts +6 -0
- package/dist/build/schemas/typographyToken.js +6 -0
- package/dist/build/schemas/validTokenType.d.ts +5 -1
- package/dist/build/schemas/validTokenType.js +71 -17
- package/dist/build/schemas/viewportRangeToken.d.ts +6 -0
- package/dist/build/schemas/viewportRangeToken.js +6 -0
- package/dist/css/base/motion/motion.css +5 -4
- package/dist/css/functional/size/border.css +9 -14
- package/dist/css/functional/size/radius.css +7 -0
- package/dist/css/functional/size/size-coarse.css +3 -3
- package/dist/css/functional/size/size-fine.css +3 -3
- package/dist/css/functional/size/viewport.css +1 -1
- package/dist/css/functional/themes/dark-colorblind-high-contrast.css +176 -176
- package/dist/css/functional/themes/dark-colorblind.css +176 -176
- package/dist/css/functional/themes/dark-dimmed-high-contrast.css +176 -176
- package/dist/css/functional/themes/dark-dimmed.css +176 -176
- package/dist/css/functional/themes/dark-high-contrast.css +176 -176
- package/dist/css/functional/themes/dark-tritanopia-high-contrast.css +176 -176
- package/dist/css/functional/themes/dark-tritanopia.css +176 -176
- package/dist/css/functional/themes/dark.css +176 -176
- package/dist/css/functional/themes/light-colorblind-high-contrast.css +176 -176
- package/dist/css/functional/themes/light-colorblind.css +176 -176
- package/dist/css/functional/themes/light-high-contrast.css +176 -176
- package/dist/css/functional/themes/light-tritanopia-high-contrast.css +176 -176
- package/dist/css/functional/themes/light-tritanopia.css +176 -176
- package/dist/css/functional/themes/light.css +176 -176
- package/dist/css/functional/typography/typography.css +4 -4
- package/dist/css/primitives.css +1 -0
- package/dist/docs/base/motion/motion.json +85 -8
- package/dist/docs/functional/size/border.json +42 -177
- package/dist/docs/functional/size/radius.json +209 -0
- package/dist/docs/functional/size/size-coarse.json +45 -3
- package/dist/docs/functional/size/size-fine.json +45 -3
- package/dist/docs/functional/size/viewport.json +2 -2
- package/dist/docs/functional/themes/dark-colorblind-high-contrast.json +934 -90
- package/dist/docs/functional/themes/dark-colorblind.json +934 -90
- package/dist/docs/functional/themes/dark-dimmed-high-contrast.json +934 -90
- package/dist/docs/functional/themes/dark-dimmed.json +972 -128
- package/dist/docs/functional/themes/dark-high-contrast.json +934 -90
- package/dist/docs/functional/themes/dark-tritanopia-high-contrast.json +934 -90
- package/dist/docs/functional/themes/dark-tritanopia.json +934 -90
- package/dist/docs/functional/themes/dark.json +934 -90
- package/dist/docs/functional/themes/light-colorblind-high-contrast.json +934 -90
- package/dist/docs/functional/themes/light-colorblind.json +934 -90
- package/dist/docs/functional/themes/light-high-contrast.json +934 -90
- package/dist/docs/functional/themes/light-tritanopia-high-contrast.json +934 -90
- package/dist/docs/functional/themes/light-tritanopia.json +934 -90
- package/dist/docs/functional/themes/light.json +934 -90
- package/dist/docs/functional/typography/typography.json +172 -8
- package/dist/fallbacks/base/motion/motion.json +1 -0
- package/dist/fallbacks/functional/size/border.json +0 -5
- package/dist/fallbacks/functional/size/radius.json +7 -0
- package/dist/fallbacks/functional/size/viewport.json +1 -1
- package/dist/figma/dimension/dimension.json +30 -20
- package/dist/figma/themes/dark-colorblind.json +85 -0
- package/dist/figma/themes/dark-dimmed.json +134 -49
- package/dist/figma/themes/dark-high-contrast.json +85 -0
- package/dist/figma/themes/dark-tritanopia.json +85 -0
- package/dist/figma/themes/dark.json +85 -0
- package/dist/figma/themes/light-colorblind.json +85 -0
- package/dist/figma/themes/light-high-contrast.json +85 -0
- package/dist/figma/themes/light-tritanopia.json +85 -0
- package/dist/figma/themes/light.json +85 -0
- package/dist/figma/typography/typography.json +44 -40
- package/dist/internalCss/dark-colorblind-high-contrast.css +194 -204
- package/dist/internalCss/dark-colorblind.css +194 -204
- package/dist/internalCss/dark-dimmed-high-contrast.css +194 -204
- package/dist/internalCss/dark-dimmed.css +194 -204
- package/dist/internalCss/dark-high-contrast.css +194 -204
- package/dist/internalCss/dark-tritanopia-high-contrast.css +194 -204
- package/dist/internalCss/dark-tritanopia.css +194 -204
- package/dist/internalCss/dark.css +194 -204
- package/dist/internalCss/light-colorblind-high-contrast.css +194 -204
- package/dist/internalCss/light-colorblind.css +194 -204
- package/dist/internalCss/light-high-contrast.css +194 -204
- package/dist/internalCss/light-tritanopia-high-contrast.css +194 -204
- package/dist/internalCss/light-tritanopia.css +194 -204
- package/dist/internalCss/light.css +194 -204
- package/dist/styleLint/base/motion/motion.json +85 -8
- package/dist/styleLint/functional/size/border.json +34 -169
- package/dist/styleLint/functional/size/radius.json +209 -0
- package/dist/styleLint/functional/size/size-coarse.json +42 -0
- package/dist/styleLint/functional/size/size-fine.json +42 -0
- package/dist/styleLint/functional/size/viewport.json +2 -2
- package/dist/styleLint/functional/themes/dark-colorblind-high-contrast.json +846 -2
- package/dist/styleLint/functional/themes/dark-colorblind.json +846 -2
- package/dist/styleLint/functional/themes/dark-dimmed-high-contrast.json +846 -2
- package/dist/styleLint/functional/themes/dark-dimmed.json +884 -40
- package/dist/styleLint/functional/themes/dark-high-contrast.json +846 -2
- package/dist/styleLint/functional/themes/dark-tritanopia-high-contrast.json +846 -2
- package/dist/styleLint/functional/themes/dark-tritanopia.json +846 -2
- package/dist/styleLint/functional/themes/dark.json +846 -2
- package/dist/styleLint/functional/themes/light-colorblind-high-contrast.json +846 -2
- package/dist/styleLint/functional/themes/light-colorblind.json +846 -2
- package/dist/styleLint/functional/themes/light-high-contrast.json +846 -2
- package/dist/styleLint/functional/themes/light-tritanopia-high-contrast.json +846 -2
- package/dist/styleLint/functional/themes/light-tritanopia.json +846 -2
- package/dist/styleLint/functional/themes/light.json +846 -2
- package/dist/styleLint/functional/typography/typography.json +168 -4
- package/guidelines/color.llm.md +16 -0
- package/guidelines/guidelines.llm.md +34 -0
- package/guidelines/motion.llm.md +41 -0
- package/guidelines/spacing.llm.md +20 -0
- package/guidelines/typography.llm.md +14 -0
- package/package.json +5 -3
- package/src/tokens/base/motion/easing.json5 +39 -4
- package/src/tokens/functional/border/border.json5 +25 -0
- package/src/tokens/functional/color/bgColor.json5 +157 -0
- package/src/tokens/functional/color/borderColor.json5 +146 -0
- package/src/tokens/functional/color/control.json5 +24 -0
- package/src/tokens/functional/color/data-vis.json5 +7 -0
- package/src/tokens/functional/color/fgColor.json5 +93 -1
- package/src/tokens/functional/color/focus.json5 +5 -0
- package/src/tokens/functional/color/selection.json5 +5 -0
- package/src/tokens/functional/shadow/shadow.json5 +10 -0
- package/src/tokens/functional/size/border.json5 +17 -69
- package/src/tokens/functional/size/radius.json5 +90 -0
- package/src/tokens/functional/size/size-coarse.json5 +24 -3
- package/src/tokens/functional/size/size-fine.json5 +45 -24
- package/src/tokens/functional/size/size.json5 +35 -0
- package/src/tokens/functional/size/viewport.json5 +1 -1
- package/src/tokens/functional/typography/font-stack.json5 +60 -0
- package/src/tokens/functional/typography/typography.json5 +67 -44
- package/token-guidelines.llm.md +695 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TransformedToken } from 'style-dictionary/types';
|
|
2
|
+
/**
|
|
3
|
+
* @description Checks if token has LLM extensions (`org.primer.llm` in `$extensions`)
|
|
4
|
+
* @param arguments [TransformedToken](https://github.com/amzn/style-dictionary/blob/main/types/TransformedToken.d.ts)
|
|
5
|
+
* @returns boolean
|
|
6
|
+
*/
|
|
7
|
+
export declare const hasLlmExtensions: (token: TransformedToken) => boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description Checks if token has LLM extensions (`org.primer.llm` in `$extensions`)
|
|
3
|
+
* @param arguments [TransformedToken](https://github.com/amzn/style-dictionary/blob/main/types/TransformedToken.d.ts)
|
|
4
|
+
* @returns boolean
|
|
5
|
+
*/
|
|
6
|
+
export const hasLlmExtensions = (token) => {
|
|
7
|
+
return (token.$extensions !== undefined &&
|
|
8
|
+
token.$extensions !== null &&
|
|
9
|
+
typeof token.$extensions === 'object' &&
|
|
10
|
+
'org.primer.llm' in token.$extensions);
|
|
11
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { cssCustomMedia } from './cssCustomMedia.js';
|
|
2
2
|
export { cssAdvanced } from './cssAdvanced.js';
|
|
3
|
+
export { markdownLlmGuidelines } from './markdownLlmGuidelines.js';
|
|
3
4
|
export { jsonFigma } from './jsonFigma.js';
|
|
4
5
|
export { javascriptCommonJs } from './javascriptCommonJs.js';
|
|
5
6
|
export { javascriptEsm } from './javascriptEsm.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { cssCustomMedia } from './cssCustomMedia.js';
|
|
2
2
|
export { cssAdvanced } from './cssAdvanced.js';
|
|
3
|
+
export { markdownLlmGuidelines } from './markdownLlmGuidelines.js';
|
|
3
4
|
export { jsonFigma } from './jsonFigma.js';
|
|
4
5
|
export { javascriptCommonJs } from './javascriptCommonJs.js';
|
|
5
6
|
export { javascriptEsm } from './javascriptEsm.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FormatFn } from 'style-dictionary/types';
|
|
2
|
+
/**
|
|
3
|
+
* @description Outputs a markdown file with LLM token guidelines, extracting
|
|
4
|
+
* description from $description and usage/rules from $extensions['org.primer.llm'].
|
|
5
|
+
* Tokens with identical guidelines (from group-level inheritance) are consolidated
|
|
6
|
+
* into a single entry listing all token names.
|
|
7
|
+
* @param FormatFnArguments
|
|
8
|
+
* @returns formatted markdown `string`
|
|
9
|
+
*/
|
|
10
|
+
export declare const markdownLlmGuidelines: FormatFn;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { sortByName } from 'style-dictionary/utils';
|
|
11
|
+
/**
|
|
12
|
+
* Creates a unique key for grouping tokens with identical guidelines
|
|
13
|
+
*/
|
|
14
|
+
function createGuidelineKey(guideline) {
|
|
15
|
+
var _a;
|
|
16
|
+
return JSON.stringify({
|
|
17
|
+
description: guideline.description || '',
|
|
18
|
+
usage: ((_a = guideline.usage) === null || _a === void 0 ? void 0 : _a.sort()) || [],
|
|
19
|
+
rules: guideline.rules || '',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Extracts category from token name
|
|
24
|
+
* - For "base-*" tokens, uses second word (e.g., "base-easing-ease" -> "easing")
|
|
25
|
+
* - Otherwise uses first word (e.g., "bgColor-danger-emphasis" -> "bgColor")
|
|
26
|
+
*/
|
|
27
|
+
function extractCategory(tokenName) {
|
|
28
|
+
const parts = tokenName.split('-');
|
|
29
|
+
if (parts[0] === 'base' && parts[1]) {
|
|
30
|
+
return parts[1];
|
|
31
|
+
}
|
|
32
|
+
return parts[0] || 'other';
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Formats category name for display
|
|
36
|
+
*/
|
|
37
|
+
function formatCategoryName(category) {
|
|
38
|
+
const categoryMap = {
|
|
39
|
+
bgColor: 'background color',
|
|
40
|
+
fgColor: 'text and foreground color',
|
|
41
|
+
};
|
|
42
|
+
if (categoryMap[category]) {
|
|
43
|
+
return categoryMap[category];
|
|
44
|
+
}
|
|
45
|
+
// Capitalize first letter
|
|
46
|
+
return category.charAt(0).toUpperCase() + category.slice(1);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Creates a key for grouping by usage and rules only (not description)
|
|
50
|
+
*/
|
|
51
|
+
function createUsageRulesKey(guideline) {
|
|
52
|
+
var _a;
|
|
53
|
+
return JSON.stringify({
|
|
54
|
+
usage: ((_a = guideline.usage) === null || _a === void 0 ? void 0 : _a.sort()) || [],
|
|
55
|
+
rules: guideline.rules || '',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Extracts a subcategory name from token names for headings
|
|
60
|
+
* e.g., "border-accent-emphasis" -> "accent"
|
|
61
|
+
*/
|
|
62
|
+
function extractSubcategory(tokenNames) {
|
|
63
|
+
if (tokenNames.length < 2)
|
|
64
|
+
return null;
|
|
65
|
+
// Get the second part of each token name
|
|
66
|
+
const subcategories = tokenNames.map(name => {
|
|
67
|
+
const parts = name.split('-');
|
|
68
|
+
return parts[1] || null;
|
|
69
|
+
});
|
|
70
|
+
// Check if all tokens share the same subcategory
|
|
71
|
+
const uniqueSubcats = [...new Set(subcategories.filter(Boolean))];
|
|
72
|
+
if (uniqueSubcats.length === 1) {
|
|
73
|
+
return uniqueSubcats[0];
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* @description Outputs a markdown file with LLM token guidelines, extracting
|
|
79
|
+
* description from $description and usage/rules from $extensions['org.primer.llm'].
|
|
80
|
+
* Tokens with identical guidelines (from group-level inheritance) are consolidated
|
|
81
|
+
* into a single entry listing all token names.
|
|
82
|
+
* @param FormatFnArguments
|
|
83
|
+
* @returns formatted markdown `string`
|
|
84
|
+
*/
|
|
85
|
+
export const markdownLlmGuidelines = (_a) => __awaiter(void 0, [_a], void 0, function* ({ dictionary }) {
|
|
86
|
+
var _b;
|
|
87
|
+
const tokens = dictionary.allTokens.sort(sortByName);
|
|
88
|
+
const guidelines = [];
|
|
89
|
+
for (const token of tokens) {
|
|
90
|
+
const llmExt = (_b = token.$extensions) === null || _b === void 0 ? void 0 : _b['org.primer.llm'];
|
|
91
|
+
if (!llmExt)
|
|
92
|
+
continue;
|
|
93
|
+
const guideline = {
|
|
94
|
+
name: token.name,
|
|
95
|
+
category: extractCategory(token.name),
|
|
96
|
+
};
|
|
97
|
+
if (token.$description && typeof token.$description === 'string') {
|
|
98
|
+
guideline.description = token.$description;
|
|
99
|
+
}
|
|
100
|
+
if (llmExt.usage && Array.isArray(llmExt.usage)) {
|
|
101
|
+
guideline.usage = llmExt.usage;
|
|
102
|
+
}
|
|
103
|
+
if (llmExt.rules && typeof llmExt.rules === 'string') {
|
|
104
|
+
guideline.rules = llmExt.rules;
|
|
105
|
+
}
|
|
106
|
+
guidelines.push(guideline);
|
|
107
|
+
}
|
|
108
|
+
// Group by category
|
|
109
|
+
const grouped = {};
|
|
110
|
+
for (const guideline of guidelines) {
|
|
111
|
+
if (!Object.hasOwn(grouped, guideline.category)) {
|
|
112
|
+
grouped[guideline.category] = [];
|
|
113
|
+
}
|
|
114
|
+
grouped[guideline.category].push(guideline);
|
|
115
|
+
}
|
|
116
|
+
// Build markdown output
|
|
117
|
+
const lines = ['# Token Guidelines', ''];
|
|
118
|
+
for (const category of Object.keys(grouped).sort()) {
|
|
119
|
+
lines.push(`## ${formatCategoryName(category)}`, '');
|
|
120
|
+
const categoryGuidelines = grouped[category];
|
|
121
|
+
// Check if all tokens in category share the same usage/rules AND there are multiple tokens
|
|
122
|
+
const usageRulesKeys = new Set(categoryGuidelines.map(createUsageRulesKey));
|
|
123
|
+
const sharedUsageRules = usageRulesKeys.size === 1 && categoryGuidelines.length > 1;
|
|
124
|
+
// If shared, output usage/rules once at category level
|
|
125
|
+
if (sharedUsageRules) {
|
|
126
|
+
const first = categoryGuidelines[0];
|
|
127
|
+
if (first.usage && first.usage.length > 0) {
|
|
128
|
+
lines.push(`**Usage:** ${first.usage.join(', ')}`);
|
|
129
|
+
}
|
|
130
|
+
if (first.rules) {
|
|
131
|
+
lines.push(`**Rules:** ${first.rules}`);
|
|
132
|
+
}
|
|
133
|
+
lines.push('');
|
|
134
|
+
}
|
|
135
|
+
// Group tokens with identical guidelines (description + usage + rules)
|
|
136
|
+
const consolidatedGroups = new Map();
|
|
137
|
+
for (const guideline of categoryGuidelines) {
|
|
138
|
+
const key = createGuidelineKey(guideline);
|
|
139
|
+
if (!consolidatedGroups.has(key)) {
|
|
140
|
+
consolidatedGroups.set(key, []);
|
|
141
|
+
}
|
|
142
|
+
consolidatedGroups.get(key).push(guideline);
|
|
143
|
+
}
|
|
144
|
+
for (const [, guidelinesGroup] of consolidatedGroups) {
|
|
145
|
+
const first = guidelinesGroup[0];
|
|
146
|
+
const tokenNames = guidelinesGroup.map(g => g.name);
|
|
147
|
+
if (guidelinesGroup.length > 1) {
|
|
148
|
+
// Multiple tokens share the same guidelines - consolidate
|
|
149
|
+
const subcategory = extractSubcategory(tokenNames);
|
|
150
|
+
if (subcategory) {
|
|
151
|
+
lines.push(`### ${subcategory}`);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
// No common subcategory - use "general" or skip heading if description serves as intro
|
|
155
|
+
if (first.description && consolidatedGroups.size > 1) {
|
|
156
|
+
lines.push(`### general`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (first.description) {
|
|
160
|
+
lines.push(first.description);
|
|
161
|
+
}
|
|
162
|
+
// Only show usage/rules if not already shown at category level
|
|
163
|
+
if (!sharedUsageRules) {
|
|
164
|
+
if (first.usage && first.usage.length > 0) {
|
|
165
|
+
lines.push(`**Usage:** ${first.usage.join(', ')}`);
|
|
166
|
+
}
|
|
167
|
+
if (first.rules) {
|
|
168
|
+
lines.push(`**Rules:** ${first.rules}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
lines.push(`**Tokens:** ${tokenNames.join(', ')}`);
|
|
172
|
+
lines.push('');
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
// Single token - output individually
|
|
176
|
+
lines.push(`### ${first.name}`);
|
|
177
|
+
if (first.description) {
|
|
178
|
+
lines.push(first.description);
|
|
179
|
+
}
|
|
180
|
+
// Only show usage/rules if not already shown at category level
|
|
181
|
+
if (!sharedUsageRules) {
|
|
182
|
+
if (first.usage && first.usage.length > 0) {
|
|
183
|
+
lines.push(`**Usage:** ${first.usage.join(', ')}`);
|
|
184
|
+
}
|
|
185
|
+
if (first.rules) {
|
|
186
|
+
lines.push(`**Rules:** ${first.rules}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
lines.push('');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return lines.join('\n');
|
|
194
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { hasLlmExtensions } from '../filters/index.js';
|
|
2
|
+
export const llmGuidelines = (outputFile, prefix, buildPath) => ({
|
|
3
|
+
prefix,
|
|
4
|
+
buildPath,
|
|
5
|
+
preprocessors: ['inheritGroupProperties'],
|
|
6
|
+
transforms: ['name/pathToKebabCase'],
|
|
7
|
+
files: [
|
|
8
|
+
{
|
|
9
|
+
destination: outputFile,
|
|
10
|
+
format: 'json/llm-guidelines',
|
|
11
|
+
filter: hasLlmExtensions,
|
|
12
|
+
options: {
|
|
13
|
+
outputReferences: false,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Preprocessor } from 'style-dictionary/types';
|
|
2
|
+
/**
|
|
3
|
+
* Preprocessor that inherits group-level $description and $extensions to child tokens.
|
|
4
|
+
* This enables W3C Design Tokens group properties to be available on individual tokens
|
|
5
|
+
* during formatting.
|
|
6
|
+
*/
|
|
7
|
+
export declare const inheritGroupProperties: Preprocessor;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively walks tokens and inherits group-level properties to child tokens.
|
|
3
|
+
* Group properties ($description, $extensions at group level) are merged into child tokens
|
|
4
|
+
* that don't have their own values for those properties.
|
|
5
|
+
*
|
|
6
|
+
* Per W3C Design Tokens spec: https://www.designtokens.org/tr/drafts/format/#group-properties
|
|
7
|
+
*/
|
|
8
|
+
function inheritProperties(tokens, inheritedProps = {}) {
|
|
9
|
+
var _a;
|
|
10
|
+
const result = {};
|
|
11
|
+
// Extract group-level properties from current level
|
|
12
|
+
const currentGroupProps = {};
|
|
13
|
+
if (typeof tokens.$description === 'string') {
|
|
14
|
+
currentGroupProps.$description = tokens.$description;
|
|
15
|
+
}
|
|
16
|
+
if (tokens.$extensions && typeof tokens.$extensions === 'object') {
|
|
17
|
+
currentGroupProps.$extensions = tokens.$extensions;
|
|
18
|
+
}
|
|
19
|
+
// Merge inherited with current (current takes precedence)
|
|
20
|
+
const mergedProps = Object.assign(Object.assign({}, inheritedProps), currentGroupProps);
|
|
21
|
+
// Merge $extensions deeply
|
|
22
|
+
if (inheritedProps.$extensions || currentGroupProps.$extensions) {
|
|
23
|
+
mergedProps.$extensions = Object.assign(Object.assign({}, inheritedProps.$extensions), currentGroupProps.$extensions);
|
|
24
|
+
}
|
|
25
|
+
for (const [key, value] of Object.entries(tokens)) {
|
|
26
|
+
// Skip group-level properties (they're inherited, not copied)
|
|
27
|
+
if (key === '$description' || key === '$extensions') {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (typeof value !== 'object' || value === null) {
|
|
31
|
+
result[key] = value;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const tokenValue = value;
|
|
35
|
+
// Check if this is a design token (has $value or value)
|
|
36
|
+
if ('$value' in tokenValue || 'value' in tokenValue) {
|
|
37
|
+
// It's a token - merge inherited properties
|
|
38
|
+
const token = tokenValue;
|
|
39
|
+
// Only inherit $description if token doesn't have its own
|
|
40
|
+
const inheritedDescription = !token.$description && mergedProps.$description ? mergedProps.$description : undefined;
|
|
41
|
+
// Merge $extensions (token-level takes precedence over inherited)
|
|
42
|
+
let mergedExtensions = token.$extensions;
|
|
43
|
+
if (mergedProps.$extensions) {
|
|
44
|
+
const inheritedLlm = mergedProps.$extensions['org.primer.llm'];
|
|
45
|
+
const tokenLlm = (_a = token.$extensions) === null || _a === void 0 ? void 0 : _a['org.primer.llm'];
|
|
46
|
+
if (inheritedLlm && !tokenLlm) {
|
|
47
|
+
// Token has no LLM extension, inherit from group
|
|
48
|
+
mergedExtensions = Object.assign(Object.assign({}, token.$extensions), { 'org.primer.llm': inheritedLlm });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
result[key] = Object.assign(Object.assign(Object.assign({}, token), (inheritedDescription ? { $description: inheritedDescription } : {})), (mergedExtensions ? { $extensions: mergedExtensions } : {}));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// It's a nested group - recurse with merged properties
|
|
55
|
+
result[key] = inheritProperties(tokenValue, mergedProps);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Preprocessor that inherits group-level $description and $extensions to child tokens.
|
|
62
|
+
* This enables W3C Design Tokens group properties to be available on individual tokens
|
|
63
|
+
* during formatting.
|
|
64
|
+
*/
|
|
65
|
+
export const inheritGroupProperties = {
|
|
66
|
+
name: 'inheritGroupProperties',
|
|
67
|
+
preprocessor: (dictionary) => {
|
|
68
|
+
return inheritProperties(dictionary);
|
|
69
|
+
},
|
|
70
|
+
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import StyleDictionary from 'style-dictionary';
|
|
2
2
|
import { borderToCss, colorToRgbAlpha, colorToHex, colorToRgbaFloat, cubicBezierToCss, dimensionToRem, dimensionToPixelUnitless, durationToCss, figmaAttributes, fontFamilyToCss, fontFamilyToFigma, fontWeightToNumber, gradientToCss, jsonDeprecated, namePathToDotNotation, namePathToCamelCase, namePathToPascalCase, namePathToKebabCase, namePathToSlashNotation, namePathToFigma, shadowToCss, typographyToCss, dimensionToRemPxArray, floatToPixel, floatToPixelUnitless, transitionToCss, } from './transformers/index.js';
|
|
3
|
-
import { javascriptCommonJs, javascriptEsm, typescriptExportDefinition, jsonNestedPrefixed, cssCustomMedia, jsonOneDimensional, jsonPostCssFallback, cssAdvanced, jsonFigma, } from './formats/index.js';
|
|
3
|
+
import { javascriptCommonJs, javascriptEsm, typescriptExportDefinition, jsonNestedPrefixed, cssCustomMedia, jsonOneDimensional, jsonPostCssFallback, cssAdvanced, jsonFigma, markdownLlmGuidelines, } from './formats/index.js';
|
|
4
4
|
import { themeOverrides } from './preprocessors/themeOverrides.js';
|
|
5
|
+
import { inheritGroupProperties } from './preprocessors/inheritGroupProperties.js';
|
|
5
6
|
import { colorAlphaToCss } from './transformers/colorAlphaToCss.js';
|
|
6
7
|
/**
|
|
7
8
|
* @name {@link PrimerStyleDictionary}
|
|
@@ -55,6 +56,10 @@ PrimerStyleDictionary.registerFormat({
|
|
|
55
56
|
name: 'json/figma',
|
|
56
57
|
format: jsonFigma,
|
|
57
58
|
});
|
|
59
|
+
PrimerStyleDictionary.registerFormat({
|
|
60
|
+
name: 'json/llm-guidelines',
|
|
61
|
+
format: markdownLlmGuidelines,
|
|
62
|
+
});
|
|
58
63
|
/**
|
|
59
64
|
* Transformers
|
|
60
65
|
*
|
|
@@ -88,3 +93,4 @@ PrimerStyleDictionary.registerTransform(fontFamilyToCss);
|
|
|
88
93
|
PrimerStyleDictionary.registerTransform(fontFamilyToFigma);
|
|
89
94
|
PrimerStyleDictionary.registerTransform(gradientToCss);
|
|
90
95
|
PrimerStyleDictionary.registerPreprocessor(themeOverrides);
|
|
96
|
+
PrimerStyleDictionary.registerPreprocessor(inheritGroupProperties);
|
|
@@ -31,4 +31,10 @@ export declare const borderToken: z.ZodObject<{
|
|
|
31
31
|
width: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"0">, z.ZodLiteral<0>]>, z.ZodString]>;
|
|
32
32
|
}, z.core.$strip>, z.ZodString]>;
|
|
33
33
|
$type: z.ZodLiteral<"string" | "number" | "border" | "color" | "fontFamily" | "fontWeight" | "transition" | "dimension" | "duration" | "gradient" | "shadow" | "typography" | "cubicBezier" | "custom-viewportRange">;
|
|
34
|
+
$extensions: z.ZodOptional<z.ZodObject<{
|
|
35
|
+
'org.primer.llm': z.ZodOptional<z.ZodObject<{
|
|
36
|
+
usage: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
37
|
+
rules: z.ZodOptional<z.ZodString>;
|
|
38
|
+
}, z.core.$strip>>;
|
|
39
|
+
}, z.core.$strip>>;
|
|
34
40
|
}, z.core.$strict>;
|
|
@@ -4,6 +4,7 @@ import { referenceValue } from './referenceValue.js';
|
|
|
4
4
|
import { colorHexValue } from './colorHexValue.js';
|
|
5
5
|
import { dimensionValue } from './dimensionValue.js';
|
|
6
6
|
import { tokenType } from './tokenType.js';
|
|
7
|
+
import { llmExtension } from './llmExtension.js';
|
|
7
8
|
export const borderValue = z.object({
|
|
8
9
|
color: z.union([colorHexValue, referenceValue]),
|
|
9
10
|
style: z.enum(['solid', 'dashed', 'dotted', 'double', 'groove', 'ridge', 'outset', 'inset']),
|
|
@@ -13,5 +14,10 @@ export const borderToken = baseToken
|
|
|
13
14
|
.extend({
|
|
14
15
|
$value: z.union([borderValue, referenceValue]),
|
|
15
16
|
$type: tokenType('border'),
|
|
17
|
+
$extensions: z
|
|
18
|
+
.object({
|
|
19
|
+
'org.primer.llm': llmExtension,
|
|
20
|
+
})
|
|
21
|
+
.optional(),
|
|
16
22
|
})
|
|
17
23
|
.strict();
|
|
@@ -98,5 +98,9 @@ export declare const colorToken: z.ZodObject<{
|
|
|
98
98
|
alpha: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodAny>>>;
|
|
99
99
|
}, z.core.$strict>]>>;
|
|
100
100
|
}, z.core.$strict>>;
|
|
101
|
+
'org.primer.llm': z.ZodOptional<z.ZodObject<{
|
|
102
|
+
usage: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
103
|
+
rules: z.ZodOptional<z.ZodString>;
|
|
104
|
+
}, z.core.$strip>>;
|
|
101
105
|
}, z.core.$strict>>;
|
|
102
106
|
}, z.core.$strict>;
|
|
@@ -6,6 +6,7 @@ import { baseToken } from './baseToken.js';
|
|
|
6
6
|
import { collection, mode } from './collections.js';
|
|
7
7
|
import { scopes } from './scopes.js';
|
|
8
8
|
import { tokenType } from './tokenType.js';
|
|
9
|
+
import { llmExtension } from './llmExtension.js';
|
|
9
10
|
const baseColorToken = baseToken.extend({
|
|
10
11
|
$value: z.union([colorHexValue, referenceValue]),
|
|
11
12
|
alpha: alphaValue.optional().nullable(),
|
|
@@ -75,6 +76,7 @@ export const colorToken = baseColorToken
|
|
|
75
76
|
})
|
|
76
77
|
.strict()
|
|
77
78
|
.optional(),
|
|
79
|
+
'org.primer.llm': llmExtension,
|
|
78
80
|
})
|
|
79
81
|
.strict()
|
|
80
82
|
.optional(),
|
|
@@ -4,4 +4,10 @@ export declare const cubicBezierToken: z.ZodObject<{
|
|
|
4
4
|
$deprecated: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodBoolean]>>;
|
|
5
5
|
$value: z.ZodUnion<readonly [z.ZodArray<z.ZodNumber>, z.ZodString]>;
|
|
6
6
|
$type: z.ZodLiteral<"string" | "number" | "border" | "color" | "fontFamily" | "fontWeight" | "transition" | "dimension" | "duration" | "gradient" | "shadow" | "typography" | "cubicBezier" | "custom-viewportRange">;
|
|
7
|
+
$extensions: z.ZodOptional<z.ZodObject<{
|
|
8
|
+
'org.primer.llm': z.ZodOptional<z.ZodObject<{
|
|
9
|
+
usage: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
10
|
+
rules: z.ZodOptional<z.ZodString>;
|
|
11
|
+
}, z.core.$strip>>;
|
|
12
|
+
}, z.core.$strip>>;
|
|
7
13
|
}, z.core.$strict>;
|
|
@@ -2,7 +2,15 @@ import { z } from 'zod';
|
|
|
2
2
|
import { baseToken } from './baseToken.js';
|
|
3
3
|
import { referenceValue } from './referenceValue.js';
|
|
4
4
|
import { tokenType } from './tokenType.js';
|
|
5
|
-
|
|
5
|
+
import { llmExtension } from './llmExtension.js';
|
|
6
|
+
export const cubicBezierToken = baseToken
|
|
7
|
+
.extend({
|
|
6
8
|
$value: z.union([z.array(z.number()).length(4), referenceValue]),
|
|
7
9
|
$type: tokenType('cubicBezier'),
|
|
8
|
-
|
|
10
|
+
$extensions: z
|
|
11
|
+
.object({
|
|
12
|
+
'org.primer.llm': llmExtension,
|
|
13
|
+
})
|
|
14
|
+
.optional(),
|
|
15
|
+
})
|
|
16
|
+
.strict();
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
export declare const designToken: z.
|
|
2
|
+
export declare const designToken: z.ZodType<unknown>;
|
|
@@ -14,26 +14,118 @@ import { durationToken } from './durationToken.js';
|
|
|
14
14
|
import { cubicBezierToken } from './cubicBezierToken.js';
|
|
15
15
|
import { gradientToken } from './gradientToken.js';
|
|
16
16
|
import { transitionToken } from './transitionToken.js';
|
|
17
|
+
import { llmExtension } from './llmExtension.js';
|
|
18
|
+
/**
|
|
19
|
+
* Group-level extensions schema (W3C Design Tokens spec)
|
|
20
|
+
* https://www.designtokens.org/tr/drafts/format/#group-properties
|
|
21
|
+
*/
|
|
22
|
+
const groupExtensions = z
|
|
23
|
+
.object({
|
|
24
|
+
'org.primer.llm': llmExtension,
|
|
25
|
+
})
|
|
26
|
+
.passthrough();
|
|
27
|
+
/**
|
|
28
|
+
* All valid token types with $type discriminator
|
|
29
|
+
*/
|
|
30
|
+
const tokenTypes = z.discriminatedUnion('$type', [
|
|
31
|
+
colorToken,
|
|
32
|
+
cubicBezierToken,
|
|
33
|
+
dimensionToken,
|
|
34
|
+
shadowToken,
|
|
35
|
+
borderToken,
|
|
36
|
+
fontFamilyToken,
|
|
37
|
+
fontWeightToken,
|
|
38
|
+
gradientToken,
|
|
39
|
+
typographyToken,
|
|
40
|
+
viewportRangeToken,
|
|
41
|
+
numberToken,
|
|
42
|
+
durationToken,
|
|
43
|
+
stringToken,
|
|
44
|
+
transitionToken,
|
|
45
|
+
]);
|
|
46
|
+
/**
|
|
47
|
+
* Validates a record allowing both token names and group properties ($description, $extensions)
|
|
48
|
+
* Recursively validates nested groups
|
|
49
|
+
*/
|
|
50
|
+
const createDesignTokenSchema = () => {
|
|
51
|
+
return z.record(z.string(), z.unknown()).superRefine((obj, ctx) => {
|
|
52
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
53
|
+
if (key === '$description') {
|
|
54
|
+
// Group-level $description must be a string
|
|
55
|
+
if (typeof value !== 'string') {
|
|
56
|
+
ctx.addIssue({
|
|
57
|
+
code: z.ZodIssueCode.custom,
|
|
58
|
+
message: `$description must be a string, got ${typeof value}`,
|
|
59
|
+
path: [key],
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else if (key === '$extensions') {
|
|
64
|
+
// Group-level $extensions must be an object
|
|
65
|
+
if (typeof value !== 'object' || value === null) {
|
|
66
|
+
ctx.addIssue({
|
|
67
|
+
code: z.ZodIssueCode.custom,
|
|
68
|
+
message: `$extensions must be an object`,
|
|
69
|
+
path: [key],
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
const result = groupExtensions.safeParse(value);
|
|
74
|
+
if (!result.success) {
|
|
75
|
+
for (const issue of result.error.issues) {
|
|
76
|
+
ctx.addIssue(Object.assign(Object.assign({}, issue), { path: [key, ...issue.path] }));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else if (key.startsWith('$')) {
|
|
82
|
+
// Unknown $-prefixed keys at group level are not allowed
|
|
83
|
+
ctx.addIssue({
|
|
84
|
+
code: z.ZodIssueCode.custom,
|
|
85
|
+
message: `Unknown group property: ${key}. Only $description and $extensions are allowed.`,
|
|
86
|
+
path: [key],
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Validate token name
|
|
91
|
+
const nameResult = tokenName.safeParse(key);
|
|
92
|
+
if (!nameResult.success) {
|
|
93
|
+
for (const issue of nameResult.error.issues) {
|
|
94
|
+
ctx.addIssue(Object.assign(Object.assign({}, issue), { path: [key] }));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Validate value as either a token or nested group
|
|
98
|
+
if (typeof value === 'object' && value !== null) {
|
|
99
|
+
// Check if it's a token (has $type) or a nested group
|
|
100
|
+
if ('$type' in value) {
|
|
101
|
+
const tokenResult = tokenTypes.safeParse(value);
|
|
102
|
+
if (!tokenResult.success) {
|
|
103
|
+
for (const issue of tokenResult.error.issues) {
|
|
104
|
+
ctx.addIssue(Object.assign(Object.assign({}, issue), { path: [key, ...issue.path] }));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// Recursively validate nested group
|
|
110
|
+
const nestedResult = designToken.safeParse(value);
|
|
111
|
+
if (!nestedResult.success) {
|
|
112
|
+
for (const issue of nestedResult.error.issues) {
|
|
113
|
+
ctx.addIssue(Object.assign(Object.assign({}, issue), { path: [key, ...issue.path] }));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
ctx.addIssue({
|
|
120
|
+
code: z.ZodIssueCode.custom,
|
|
121
|
+
message: `Expected token or group object, got ${typeof value}`,
|
|
122
|
+
path: [key],
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
};
|
|
17
129
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
18
130
|
// @ts-ignore: TODO: fix this
|
|
19
|
-
export const designToken =
|
|
20
|
-
return z.union([
|
|
21
|
-
z.discriminatedUnion('$type', [
|
|
22
|
-
colorToken,
|
|
23
|
-
cubicBezierToken,
|
|
24
|
-
dimensionToken,
|
|
25
|
-
shadowToken,
|
|
26
|
-
borderToken,
|
|
27
|
-
fontFamilyToken,
|
|
28
|
-
fontWeightToken,
|
|
29
|
-
gradientToken,
|
|
30
|
-
typographyToken,
|
|
31
|
-
viewportRangeToken,
|
|
32
|
-
numberToken,
|
|
33
|
-
durationToken,
|
|
34
|
-
stringToken,
|
|
35
|
-
transitionToken,
|
|
36
|
-
]),
|
|
37
|
-
designToken,
|
|
38
|
-
]);
|
|
39
|
-
}));
|
|
131
|
+
export const designToken = createDesignTokenSchema();
|
|
@@ -5,10 +5,14 @@ export declare const dimensionToken: z.ZodObject<{
|
|
|
5
5
|
$value: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"0">, z.ZodLiteral<0>]>, z.ZodString]>;
|
|
6
6
|
$type: z.ZodLiteral<"string" | "number" | "border" | "color" | "fontFamily" | "fontWeight" | "transition" | "dimension" | "duration" | "gradient" | "shadow" | "typography" | "cubicBezier" | "custom-viewportRange">;
|
|
7
7
|
$extensions: z.ZodOptional<z.ZodObject<{
|
|
8
|
-
'org.primer.figma': z.ZodObject<{
|
|
8
|
+
'org.primer.figma': z.ZodOptional<z.ZodObject<{
|
|
9
9
|
collection: z.ZodString;
|
|
10
10
|
scopes: z.ZodArray<z.ZodString>;
|
|
11
11
|
group: z.ZodOptional<z.ZodString>;
|
|
12
|
-
}, z.core.$strip
|
|
12
|
+
}, z.core.$strip>>;
|
|
13
|
+
'org.primer.llm': z.ZodOptional<z.ZodObject<{
|
|
14
|
+
usage: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
15
|
+
rules: z.ZodOptional<z.ZodString>;
|
|
16
|
+
}, z.core.$strip>>;
|
|
13
17
|
}, z.core.$strip>>;
|
|
14
18
|
}, z.core.$strict>;
|