prism-design 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/CHANGELOG.md +292 -0
  2. package/LICENSE +21 -0
  3. package/README.md +203 -0
  4. package/bin/clone-architect.mjs +476 -0
  5. package/bin/prism.mjs +467 -0
  6. package/catalog/index.json +1155 -0
  7. package/extractions/airbnb.com/DESIGN.md +1068 -0
  8. package/extractions/airbnb.com/tokens.json +507 -0
  9. package/extractions/attio.com/DESIGN.md +1295 -0
  10. package/extractions/attio.com/tokens.json +438 -0
  11. package/extractions/auroxdashboard.com/DESIGN.md +724 -0
  12. package/extractions/auroxdashboard.com/tokens.json +195 -0
  13. package/extractions/careerexplorer.com/DESIGN.md +1178 -0
  14. package/extractions/careerexplorer.com/tokens.json +141 -0
  15. package/extractions/chance.co/DESIGN.md +1209 -0
  16. package/extractions/chance.co/tokens.json +160 -0
  17. package/extractions/choisis-ton-avenir.com/DESIGN.md +1265 -0
  18. package/extractions/choisis-ton-avenir.com/tokens.json +227 -0
  19. package/extractions/example.com/DESIGN.md +436 -0
  20. package/extractions/example.com/tokens.json +91 -0
  21. package/extractions/getdesign.md/DESIGN.md +1009 -0
  22. package/extractions/getdesign.md/tokens.json +219 -0
  23. package/extractions/github.com/DESIGN.md +1130 -0
  24. package/extractions/github.com/tokens.json +2092 -0
  25. package/extractions/hello-charly.com/DESIGN.md +1146 -0
  26. package/extractions/hello-charly.com/tokens.json +322 -0
  27. package/extractions/hyperliquid.xyz/DESIGN.md +779 -0
  28. package/extractions/hyperliquid.xyz/tokens.json +598 -0
  29. package/extractions/instagram.com/DESIGN.md +996 -0
  30. package/extractions/instagram.com/tokens.json +1240 -0
  31. package/extractions/jobirl.com/DESIGN.md +1160 -0
  32. package/extractions/jobirl.com/tokens.json +139 -0
  33. package/extractions/life360.com/DESIGN.md +1133 -0
  34. package/extractions/life360.com/tokens.json +491 -0
  35. package/extractions/lifesum.com/DESIGN.md +965 -0
  36. package/extractions/lifesum.com/tokens.json +170 -0
  37. package/extractions/linear.app/DESIGN.md +1301 -0
  38. package/extractions/linear.app/tokens.json +732 -0
  39. package/extractions/mavoie.org/DESIGN.md +1148 -0
  40. package/extractions/mavoie.org/tokens.json +128 -0
  41. package/extractions/miro.com/DESIGN.md +1237 -0
  42. package/extractions/miro.com/tokens.json +401 -0
  43. package/extractions/notion.so/DESIGN.md +1319 -0
  44. package/extractions/notion.so/tokens.json +906 -0
  45. package/extractions/onetonline.org/DESIGN.md +909 -0
  46. package/extractions/onetonline.org/tokens.json +280 -0
  47. package/extractions/posthog.com/DESIGN.md +1024 -0
  48. package/extractions/posthog.com/tokens.json +197 -0
  49. package/extractions/revolut.com/DESIGN.md +1080 -0
  50. package/extractions/revolut.com/tokens.json +401 -0
  51. package/extractions/stripe.com/DESIGN.md +1272 -0
  52. package/extractions/stripe.com/tokens.json +794 -0
  53. package/extractions/switchcollective.com/DESIGN.md +1040 -0
  54. package/extractions/switchcollective.com/tokens.json +98 -0
  55. package/extractions/truity.com/DESIGN.md +970 -0
  56. package/extractions/truity.com/tokens.json +166 -0
  57. package/extractions/uniquekicks.be/DESIGN.md +1171 -0
  58. package/extractions/uniquekicks.be/tokens.json +237 -0
  59. package/package.json +122 -0
  60. package/scripts/analyze.ts +281 -0
  61. package/scripts/bank-register.ts +379 -0
  62. package/scripts/bank.ts +374 -0
  63. package/scripts/browser-stealth.ts +189 -0
  64. package/scripts/clone.ts +198 -0
  65. package/scripts/compare-vs-gd-final.ts +273 -0
  66. package/scripts/compare-vs-gd.ts +269 -0
  67. package/scripts/compare.ts +405 -0
  68. package/scripts/deploy-site.ts +181 -0
  69. package/scripts/diff-snapshots.ts +340 -0
  70. package/scripts/enrich-catalog.ts +212 -0
  71. package/scripts/extract.ts +2038 -0
  72. package/scripts/extractors/advanced.ts +524 -0
  73. package/scripts/extractors/widgets.ts +711 -0
  74. package/scripts/generate-design-md.ts +5775 -0
  75. package/scripts/generate-final-pdf.ts +274 -0
  76. package/scripts/generate-og-image.ts +87 -0
  77. package/scripts/generate-showcase.ts +1588 -0
  78. package/scripts/generate-site.ts +847 -0
  79. package/scripts/mass-extract.sh +91 -0
  80. package/scripts/post-process-all.sh +55 -0
  81. package/scripts/regen-catalog.ts +203 -0
  82. package/scripts/shared/cache.ts +149 -0
  83. package/scripts/shared/css-helpers.ts +263 -0
  84. package/scripts/shared/logger.ts +57 -0
  85. package/scripts/shared/named-colors.ts +355 -0
  86. package/scripts/shared/types.ts +220 -0
  87. package/scripts/sync-catalog.ts +105 -0
  88. package/scripts/tokenize.ts +988 -0
  89. package/templates/layout-template.md +52 -0
  90. package/templates/tokens-template.json +34 -0
@@ -0,0 +1,220 @@
1
+ /**
2
+ * shared/types.ts — Prism Phase 5 Sprint 80/20
3
+ * Contrat unique pour tous les types partagƩs (Ʃlimine divergences)
4
+ */
5
+
6
+ // ─── SiteTokens (unifiĆ© — bank-register + retheme convergent) ────────────────
7
+
8
+ export interface SiteTokens {
9
+ colors: {
10
+ background: string;
11
+ text: string;
12
+ accent: string;
13
+ border: string;
14
+ };
15
+ typography: {
16
+ primary: string;
17
+ secondary?: string;
18
+ mono?: string;
19
+ };
20
+ borderRadius: {
21
+ sm: string;
22
+ md: string;
23
+ full: string;
24
+ };
25
+ spacing: {
26
+ xs: string;
27
+ sm: string;
28
+ md: string;
29
+ lg: string;
30
+ xl?: string;
31
+ };
32
+ isDark: boolean;
33
+ }
34
+
35
+ // ─── Bank types (source : bank-register.ts) ───────────────────────────────────
36
+
37
+ export interface ComponentSnapshot {
38
+ id: string;
39
+ domain: string;
40
+ extractionPath: string;
41
+ url: string;
42
+ extractedAt: string;
43
+ registeredAt: string;
44
+ componentType: string;
45
+ componentLabel: string;
46
+ variantIndex: number;
47
+ siteTokens: SiteTokens;
48
+ styles: Record<string, any>;
49
+ tags: string[];
50
+ screenshotPath?: string;
51
+ designMdPath?: string;
52
+ }
53
+
54
+ export interface BankIndexEntry {
55
+ id: string;
56
+ domain: string;
57
+ type: string;
58
+ label: string;
59
+ tags: string[];
60
+ accent: string;
61
+ background: string;
62
+ isDark: boolean;
63
+ extractedAt: string;
64
+ registeredAt: string;
65
+ }
66
+
67
+ export interface BankIndex {
68
+ version: string;
69
+ updatedAt: string;
70
+ components: BankIndexEntry[];
71
+ }
72
+
73
+ export interface BankCatalog {
74
+ version: string;
75
+ updatedAt: string;
76
+ byType: Record<string, string[]>;
77
+ byDomain: Record<string, string[]>;
78
+ byTags: Record<string, string[]>;
79
+ }
80
+
81
+ // ─── Block types (source : extract-block.ts) ──────────────────────────────────
82
+
83
+ export interface BlockNode {
84
+ tag: string;
85
+ classes: string[];
86
+ id?: string;
87
+ text: string;
88
+ attributes: Record<string, string>;
89
+ rect: { x: number; y: number; width: number; height: number };
90
+ styles: Record<string, string>;
91
+ children: BlockNode[];
92
+ }
93
+
94
+ export interface BlockExtraction {
95
+ url: string;
96
+ domain: string;
97
+ selector: string;
98
+ extractedAt: string;
99
+ viewport: { width: number; height: number };
100
+ rootNode: BlockNode;
101
+ nodeCount: number;
102
+ maxDepthReached: number;
103
+ truncated: boolean;
104
+ screenshotPath?: string;
105
+ }
106
+
107
+ // ─── Extraction types (Phase 1.3) — shared boundary types for raw-css.json data ─
108
+
109
+ /** Computed CSS styles extracted via getComputedStyle() — Playwright snapshot per element */
110
+ export interface ComputedStylesShared {
111
+ backgroundColor?: string;
112
+ backgroundImage?: string;
113
+ color?: string;
114
+ fontFamily?: string;
115
+ fontSize?: string;
116
+ fontWeight?: string;
117
+ lineHeight?: string;
118
+ letterSpacing?: string;
119
+ textAlign?: string;
120
+ padding?: string;
121
+ margin?: string;
122
+ borderRadius?: string;
123
+ border?: string;
124
+ boxShadow?: string;
125
+ width?: string;
126
+ height?: string;
127
+ display?: string;
128
+ gap?: string;
129
+ gridTemplateColumns?: string;
130
+ flexDirection?: string;
131
+ alignItems?: string;
132
+ justifyContent?: string;
133
+ position?: string;
134
+ transition?: string;
135
+ opacity?: string;
136
+ textTransform?: string;
137
+ [key: string]: string | undefined; // allow future props
138
+ }
139
+
140
+ export interface ElementExtractionShared {
141
+ selector: string;
142
+ tag: string;
143
+ classes: string[];
144
+ text: string;
145
+ styles: ComputedStylesShared;
146
+ children?: number;
147
+ rect?: { x: number; y: number; width: number; height: number };
148
+ }
149
+
150
+ export interface SectionExtractionShared {
151
+ index: number;
152
+ tag: string;
153
+ classes: string[];
154
+ role?: string;
155
+ estimatedPurpose?: string;
156
+ rect?: { x: number; y: number; width: number; height: number };
157
+ styles?: Partial<ComputedStylesShared> | Record<string, string>;
158
+ childCount?: number;
159
+ }
160
+
161
+ export interface ComponentVariantShared {
162
+ tag: string;
163
+ classes: string[];
164
+ text?: string;
165
+ styles: ComputedStylesShared;
166
+ rect?: { x: number; y: number; width: number; height: number };
167
+ }
168
+
169
+ /** Imagery profile extracted in Phase 0.2 */
170
+ export interface ImageryProfileShared {
171
+ ogImage: string | null;
172
+ ogImageWidth: number | null;
173
+ ogImageHeight: number | null;
174
+ twitterImage: string | null;
175
+ heroImage: { src: string; alt: string; width: number; height: number; aspectRatio: number } | null;
176
+ formats: { png: number; jpg: number; webp: number; svg: number; gif: number; other: number };
177
+ totalImages: number;
178
+ totalAboveFold: number;
179
+ aspectRatioBuckets: { landscape: number; portrait: number; square: number; ultrawide: number };
180
+ illustrationHeavy: boolean;
181
+ photoHeavy: boolean;
182
+ avgImageSize: { width: number; height: number };
183
+ }
184
+
185
+ /** Full viewport extraction = one snapshot at a specific viewport (desktop/mobile) */
186
+ export interface ViewportExtraction {
187
+ url: string;
188
+ domain: string;
189
+ timestamp: string;
190
+ viewport: { width: number; height: number };
191
+ pageTitle: string;
192
+ cssCustomProperties: Record<string, string>;
193
+ elements: Record<string, ElementExtractionShared | null>;
194
+ sections: SectionExtractionShared[];
195
+ allColors: string[];
196
+ allFontFamilies: string[];
197
+ allFontSizes: string[];
198
+ allBorderRadii: string[];
199
+ allShadows: string[];
200
+ allTransitions: string[];
201
+ images: { src: string; alt: string; width: number; height: number }[];
202
+ imageryProfile?: ImageryProfileShared;
203
+ links: { href: string; text: string; isNav: boolean }[];
204
+ componentVariants: Record<string, ComponentVariantShared[]>;
205
+ componentStates: Record<string, Record<string, ComputedStylesShared>>;
206
+ fontFaces: Array<{ family: string; src: string; weight: string; style: string; display: string }>;
207
+ mediaBreakpoints: string[];
208
+ openTypeFeatures: string[];
209
+ variableAxes: string[];
210
+ keyframes?: Record<string, Record<string, Record<string, string>>>;
211
+ zIndexMap?: Array<{ selector: string; z: number; stackingRoot: string }>;
212
+ }
213
+
214
+ /** Top-level raw-css.json structure (desktop + optional mobile viewports) */
215
+ export interface RawCssData {
216
+ desktop: ViewportExtraction;
217
+ mobile?: ViewportExtraction;
218
+ /** Optional schema version (Phase 1.2 added — undefined for pre-v2.4 archives) */
219
+ version?: string;
220
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Sync catalog/index.json with filesystem state:
3
+ * - Add brands that exist on disk but missing from catalog
4
+ * - Remove brands in catalog but missing on disk (wipe cleanup)
5
+ * - Then enrich-catalog runs over the synced list
6
+ */
7
+
8
+ import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from 'fs';
9
+ import { join } from 'path';
10
+
11
+ const ROOT = process.cwd();
12
+ const CATALOG_PATH = join(ROOT, 'catalog', 'index.json');
13
+ const EXTRACT_DIR = join(ROOT, 'extractions');
14
+
15
+ interface Brand {
16
+ domain: string;
17
+ hasDesignMd: boolean;
18
+ hasTokens: boolean;
19
+ hasScreenshots: boolean;
20
+ hasFrontmatter: boolean;
21
+ accent: string;
22
+ description: string;
23
+ sizeKb: number;
24
+ category: string;
25
+ dark: boolean;
26
+ font: string;
27
+ completeness: number;
28
+ extractedAt: string;
29
+ }
30
+
31
+ function makeEntry(domain: string): Brand {
32
+ return {
33
+ domain,
34
+ hasDesignMd: existsSync(join(EXTRACT_DIR, domain, 'DESIGN.md')),
35
+ hasTokens: existsSync(join(EXTRACT_DIR, domain, 'tokens.json')),
36
+ hasScreenshots: existsSync(join(EXTRACT_DIR, domain, 'screenshots')),
37
+ hasFrontmatter: false,
38
+ accent: '#5e6ad2',
39
+ description: `Design system extracted from ${domain}`,
40
+ sizeKb: 0,
41
+ category: 'SaaS / Product',
42
+ dark: false,
43
+ font: 'Inter',
44
+ completeness: 0,
45
+ extractedAt: new Date().toISOString(),
46
+ };
47
+ }
48
+
49
+ async function main() {
50
+ console.log('šŸ”„ Sync catalog/index.json with filesystem state\n');
51
+
52
+ const catalog = JSON.parse(readFileSync(CATALOG_PATH, 'utf-8'));
53
+ const existing = new Map<string, Brand>(catalog.brands.map((b: Brand) => [b.domain, b]));
54
+
55
+ // List on-disk extractions with at least raw-css.json (real extraction, not orphan)
56
+ const onDisk = readdirSync(EXTRACT_DIR)
57
+ .filter(d => !d.startsWith('_'))
58
+ .filter(d => statSync(join(EXTRACT_DIR, d)).isDirectory())
59
+ .filter(d => existsSync(join(EXTRACT_DIR, d, 'raw-css.json')));
60
+
61
+ console.log(` šŸ“ ${onDisk.length} extractions on disk (with raw-css.json)`);
62
+ console.log(` šŸ“š ${existing.size} brands in catalog before sync`);
63
+
64
+ // Add missing
65
+ let added = 0;
66
+ for (const domain of onDisk) {
67
+ if (!existing.has(domain)) {
68
+ existing.set(domain, makeEntry(domain));
69
+ added++;
70
+ console.log(` + ${domain}`);
71
+ }
72
+ }
73
+
74
+ // Remove ghost entries (catalog declares but no raw-css.json on disk)
75
+ let removed = 0;
76
+ const validDomains = new Set(onDisk);
77
+ for (const domain of [...existing.keys()]) {
78
+ if (!validDomains.has(domain)) {
79
+ // Skip removal only if the brand is in tests/goldens (preserve for tests)
80
+ const goldenPath = join(ROOT, 'tests', 'goldens', `${domain}.DESIGN.md`);
81
+ if (existsSync(goldenPath)) {
82
+ console.log(` ā­ ${domain} (ghost, but golden test present — keep)`);
83
+ continue;
84
+ }
85
+ existing.delete(domain);
86
+ removed++;
87
+ console.log(` - ${domain}`);
88
+ }
89
+ }
90
+
91
+ const newBrands = [...existing.values()];
92
+ catalog.brands = newBrands;
93
+ catalog.count = newBrands.length;
94
+ catalog.version = '1.5.0';
95
+ catalog.lastSyncedAt = new Date().toISOString();
96
+
97
+ writeFileSync(CATALOG_PATH, JSON.stringify(catalog, null, 2));
98
+
99
+ console.log(`\nāœ… Catalog synced`);
100
+ console.log(` + ${added} added`);
101
+ console.log(` - ${removed} removed`);
102
+ console.log(` = ${newBrands.length} total brands`);
103
+ }
104
+
105
+ main().catch(err => { console.error(err); process.exit(1); });