dembrandt 0.16.0 → 0.17.1

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 (120) hide show
  1. package/README.md +41 -15
  2. package/dist/index.d.ts +8 -0
  3. package/dist/index.js +392 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/lib/browser.d.ts +14 -0
  6. package/dist/lib/browser.js +25 -0
  7. package/dist/lib/browser.js.map +1 -0
  8. package/dist/lib/colors.d.ts +101 -0
  9. package/dist/lib/colors.js +405 -0
  10. package/dist/lib/colors.js.map +1 -0
  11. package/dist/lib/discovery.d.ts +31 -0
  12. package/dist/lib/discovery.js +243 -0
  13. package/dist/lib/discovery.js.map +1 -0
  14. package/dist/lib/drift.d.ts +64 -0
  15. package/dist/lib/drift.js +376 -0
  16. package/dist/lib/drift.js.map +1 -0
  17. package/dist/lib/dtcg/validate.d.ts +51 -0
  18. package/dist/lib/dtcg/validate.js +1403 -0
  19. package/dist/lib/dtcg/validate.js.map +1 -0
  20. package/dist/lib/extractors/breakpoints.d.ts +5 -0
  21. package/dist/lib/extractors/breakpoints.js +450 -0
  22. package/dist/lib/extractors/breakpoints.js.map +1 -0
  23. package/dist/lib/extractors/colors.d.ts +2 -0
  24. package/dist/lib/extractors/colors.js +657 -0
  25. package/dist/lib/extractors/colors.js.map +1 -0
  26. package/dist/lib/extractors/components.d.ts +4 -0
  27. package/dist/lib/extractors/components.js +370 -0
  28. package/dist/lib/extractors/components.js.map +1 -0
  29. package/dist/lib/extractors/index.d.ts +9 -0
  30. package/dist/lib/extractors/index.js +1095 -0
  31. package/dist/lib/extractors/index.js.map +1 -0
  32. package/dist/lib/extractors/logo.d.ts +2 -0
  33. package/dist/lib/extractors/logo.js +626 -0
  34. package/dist/lib/extractors/logo.js.map +1 -0
  35. package/dist/lib/extractors/spacing.d.ts +4 -0
  36. package/dist/lib/extractors/spacing.js +162 -0
  37. package/dist/lib/extractors/spacing.js.map +1 -0
  38. package/dist/lib/extractors/typography.d.ts +1 -0
  39. package/dist/lib/extractors/typography.js +163 -0
  40. package/dist/lib/extractors/typography.js.map +1 -0
  41. package/dist/lib/formatters/dtcg.d.ts +10 -0
  42. package/dist/lib/formatters/dtcg.js +416 -0
  43. package/dist/lib/formatters/dtcg.js.map +1 -0
  44. package/dist/lib/formatters/markdown.d.ts +5 -0
  45. package/dist/lib/formatters/markdown.js +568 -0
  46. package/dist/lib/formatters/markdown.js.map +1 -0
  47. package/dist/lib/formatters/pdf.d.ts +12 -0
  48. package/dist/lib/formatters/pdf.js +1117 -0
  49. package/dist/lib/formatters/pdf.js.map +1 -0
  50. package/dist/lib/formatters/terminal.d.ts +6 -0
  51. package/dist/lib/formatters/terminal.js +954 -0
  52. package/dist/lib/formatters/terminal.js.map +1 -0
  53. package/dist/lib/formatters/theme.d.ts +35 -0
  54. package/{lib → dist/lib}/formatters/theme.js +15 -16
  55. package/dist/lib/formatters/theme.js.map +1 -0
  56. package/dist/lib/merger.d.ts +14 -0
  57. package/dist/lib/merger.js +362 -0
  58. package/dist/lib/merger.js.map +1 -0
  59. package/dist/lib/normalize.d.ts +28 -0
  60. package/dist/lib/normalize.js +55 -0
  61. package/dist/lib/normalize.js.map +1 -0
  62. package/dist/lib/robots.d.ts +12 -0
  63. package/dist/lib/robots.js +110 -0
  64. package/dist/lib/robots.js.map +1 -0
  65. package/dist/lib/types.d.ts +319 -0
  66. package/dist/lib/types.js +7 -0
  67. package/dist/lib/types.js.map +1 -0
  68. package/dist/lib/version.d.ts +126 -0
  69. package/dist/lib/version.js +145 -0
  70. package/dist/lib/version.js.map +1 -0
  71. package/dist/mcp-server.d.ts +11 -0
  72. package/dist/mcp-server.js +249 -0
  73. package/dist/mcp-server.js.map +1 -0
  74. package/dist/package.json +78 -0
  75. package/dist/test/_vitest-shim.d.ts +13 -0
  76. package/dist/test/_vitest-shim.js +23 -0
  77. package/dist/test/_vitest-shim.js.map +1 -0
  78. package/dist/test/cli.test.d.ts +1 -0
  79. package/dist/test/cli.test.js +24 -0
  80. package/dist/test/cli.test.js.map +1 -0
  81. package/dist/test/colors.test.d.ts +1 -0
  82. package/dist/test/colors.test.js +64 -0
  83. package/dist/test/colors.test.js.map +1 -0
  84. package/dist/test/dtcg-formatter.test.d.ts +1 -0
  85. package/dist/test/dtcg-formatter.test.js +44 -0
  86. package/dist/test/dtcg-formatter.test.js.map +1 -0
  87. package/dist/test/dtcg-validate.test.d.ts +1 -0
  88. package/dist/test/dtcg-validate.test.js +2129 -0
  89. package/dist/test/dtcg-validate.test.js.map +1 -0
  90. package/dist/test/markdown.test.d.ts +1 -0
  91. package/dist/test/markdown.test.js +145 -0
  92. package/dist/test/markdown.test.js.map +1 -0
  93. package/dist/test/merger.test.d.ts +1 -0
  94. package/dist/test/merger.test.js +98 -0
  95. package/dist/test/merger.test.js.map +1 -0
  96. package/dist/test/normalize.test.d.ts +1 -0
  97. package/dist/test/normalize.test.js +45 -0
  98. package/dist/test/normalize.test.js.map +1 -0
  99. package/dist/test/version.test.d.ts +1 -0
  100. package/dist/test/version.test.js +73 -0
  101. package/dist/test/version.test.js.map +1 -0
  102. package/package.json +35 -17
  103. package/index.js +0 -367
  104. package/lib/colors.js +0 -336
  105. package/lib/discovery.js +0 -247
  106. package/lib/extractors/breakpoints.js +0 -432
  107. package/lib/extractors/colors.js +0 -572
  108. package/lib/extractors/components.js +0 -368
  109. package/lib/extractors/index.js +0 -1051
  110. package/lib/extractors/logo.js +0 -602
  111. package/lib/extractors/spacing.js +0 -178
  112. package/lib/extractors/typography.js +0 -173
  113. package/lib/formatters/markdown.js +0 -591
  114. package/lib/formatters/pdf.js +0 -975
  115. package/lib/formatters/terminal.js +0 -1085
  116. package/lib/formatters/w3c.js +0 -497
  117. package/lib/merger.js +0 -364
  118. package/lib/robots.js +0 -101
  119. package/lib/types.js +0 -204
  120. package/mcp-server.js +0 -321
package/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  [![npm version](https://img.shields.io/npm/v/dembrandt.svg)](https://www.npmjs.com/package/dembrandt)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/dembrandt.svg)](https://www.npmjs.com/package/dembrandt)
5
5
  [![license](https://img.shields.io/npm/l/dembrandt.svg)](https://github.com/dembrandt/dembrandt/blob/main/LICENSE)
6
+ [![GitHub Sponsors](https://img.shields.io/badge/Sponsor-me-pink?style=flat&logo=github-sponsors)](https://github.com/sponsors/dembrandt)
6
7
 
7
8
  Extract a website's design system into design tokens in a few seconds: logo, colors, typography, borders, and more. One command.
8
9
 
@@ -25,7 +26,7 @@ Requires Node.js 18+
25
26
  Use Dembrandt as a tool in Claude Code, Cursor, Windsurf, or any MCP-compatible client. Ask your agent to "extract the color palette from example.com" and it calls Dembrandt automatically.
26
27
 
27
28
  ```bash
28
- claude mcp add --transport stdio dembrandt -- npx -y dembrandt-mcp
29
+ claude mcp add --transport stdio dembrandt -- npx -y --package dembrandt dembrandt-mcp
29
30
  ```
30
31
 
31
32
  Or add to your project's `.mcp.json`:
@@ -35,7 +36,7 @@ Or add to your project's `.mcp.json`:
35
36
  "mcpServers": {
36
37
  "dembrandt": {
37
38
  "command": "npx",
38
- "args": ["-y", "dembrandt-mcp"]
39
+ "args": ["-y", "--package", "dembrandt", "dembrandt-mcp"]
39
40
  }
40
41
  }
41
42
  }
@@ -57,7 +58,7 @@ Load extractions, track token drift, and compare snapshots. **[dembrandt.com/app
57
58
  * **Visual diff.** Color swatches, before/after values, delta scores per category.
58
59
  * **Snapshot history.** GitHub-style calendar per domain.
59
60
  * **Copy tokens.** Paste values straight into Copilot, Claude, or Cursor.
60
- * **No login.** Your data stays in the browser, nothing is sent to any server.
61
+ * **No login.** Your data stays in the browser. Drift is computed locally — nothing is sent to any server.
61
62
 
62
63
  ## Recipes
63
64
 
@@ -145,7 +146,7 @@ dembrandt example.com --browser=firefox --save-output --dtcg
145
146
  Firefox browser is installed automatically with `npm install`. If you need to install manually:
146
147
 
147
148
  ```bash
148
- npx playwright install firefox
149
+ npx playwright@$(node -p "require('playwright-core/package.json').version") install firefox
149
150
  ```
150
151
 
151
152
  ### W3C Design Tokens (DTCG) Format
@@ -175,7 +176,7 @@ DESIGN.md reports only what Dembrandt observed on the source site. Exact values
175
176
  Use `--wcag` to check accessibility contrast ratios across the page. Unlike palette-based checkers, dembrandt walks the actual DOM and finds what color is rendered on top of what background — per element.
176
177
 
177
178
  ```bash
178
- dembrandt stripe.com --wcag
179
+ dembrandt dembrandt.com --wcag
179
180
  ```
180
181
 
181
182
  Returns every text/background pair with contrast ratio and WCAG 2.1 grade (AA, AA-Large, AAA, or fail), sorted by how often each pair appears. Results are shown in terminal and included in JSON output as `wcag`.
@@ -187,7 +188,7 @@ Also captures **interactive state contrast**: dembrandt simulates hover, focus,
187
188
  Motion tokens are extracted automatically on every run — no flag needed. Dembrandt analyzes CSS transitions and animations across the page and returns a structured motion profile.
188
189
 
189
190
  ```bash
190
- dembrandt stripe.com
191
+ dembrandt dembrandt.com
191
192
  ```
192
193
 
193
194
  Returns:
@@ -207,51 +208,66 @@ dembrandt example.com --brand-guide
207
208
  # Saves to: output/example.com/TIMESTAMP.brand-guide.pdf
208
209
  ```
209
210
 
211
+ ## Continuous integration
212
+
213
+ Dembrandt drives a real browser, so the browser revision must match `playwright-core`.
214
+
215
+ If you are not using the Playwright container image, install the browser revision that matches `playwright-core`:
216
+
217
+ ```bash
218
+ # in dembrandt's own repo
219
+ npm run install-browser
220
+ # elsewhere — derive the version so it always matches
221
+ npx playwright@$(node -p "require('playwright-core/package.json').version") install --with-deps chromium
222
+ ```
223
+
224
+ A mismatched version fails with "Executable doesn't exist". The container image avoids this entirely — just match its tag (`v1.60.0`) to the `playwright-core` version.
225
+
210
226
  ## Recipes
211
227
 
212
228
  **Quick brand scan**
213
229
  ```bash
214
- dembrandt stripe.com
230
+ dembrandt dembrandt.com
215
231
  ```
216
232
 
217
233
  **Compare two sites**
218
234
  ```bash
219
- dembrandt stripe.com --save-output
235
+ dembrandt dembrandt.com --save-output
220
236
  dembrandt braintree.com --save-output
221
- # Compare output/stripe.com and output/braintree.com side by side
237
+ # Compare output/dembrandt.com and output/braintree.com side by side
222
238
  ```
223
239
 
224
240
  **Multi-page audit** — get a fuller picture across the whole site
225
241
  ```bash
226
- dembrandt stripe.com --crawl 10 --sitemap --save-output
242
+ dembrandt dembrandt.com --crawl 10 --sitemap --save-output
227
243
  ```
228
244
 
229
245
  **Spot-check a value** — verify a specific token fast
230
246
  ```bash
231
- dembrandt stripe.com --json-only | grep -i "border-radius"
247
+ dembrandt dembrandt.com --json-only | grep -i "border-radius"
232
248
  ```
233
249
 
234
250
  **Export for Tailwind** — get spacing and color values into your config
235
251
  ```bash
236
- dembrandt stripe.com --dtcg --save-output
252
+ dembrandt dembrandt.com --dtcg --save-output
237
253
  # Use the .tokens.json with Style Dictionary to generate tailwind.config.js
238
254
  ```
239
255
 
240
256
  **Export for Tokens Studio / Figma**
241
257
  ```bash
242
- dembrandt stripe.com --dtcg --save-output
258
+ dembrandt dembrandt.com --dtcg --save-output
243
259
  # Import the .tokens.json directly into Tokens Studio
244
260
  ```
245
261
 
246
262
  **Generate DESIGN.md for your AI agent**
247
263
  ```bash
248
- dembrandt stripe.com --design-md
264
+ dembrandt dembrandt.com --design-md
249
265
  # Point your agent at the output DESIGN.md
250
266
  ```
251
267
 
252
268
  **Accessibility audit** — check contrast on any live URL
253
269
  ```bash
254
- dembrandt stripe.com --wcag
270
+ dembrandt dembrandt.com --wcag
255
271
  ```
256
272
 
257
273
  **Regression baseline** — snapshot now, catch drift later
@@ -311,6 +327,16 @@ Only run Dembrandt against sites whose Terms of Service permit automated access,
311
327
 
312
328
  Dembrandt does not host, redistribute, or claim rights to any third-party brand assets.
313
329
 
330
+ ## Sponsors
331
+
332
+ The CLI is MIT-licensed and free. Sponsorship funds the enforcement layer: a committed project-level token baseline, `--compare` and the ingest API for CI/CD drift gates, and the App platform (snapshot history, team drift dashboard, alerts to Slack, Linear, and GitHub).
333
+
334
+ [![GitHub Sponsors](https://img.shields.io/badge/Sponsor-me-pink?style=flat&logo=github-sponsors)](https://github.com/sponsors/dembrandt)
335
+
336
+ <!-- sponsors -->
337
+ <!-- Backer ($25+) and Lead sponsor ($500+) logos appear here. -->
338
+ <!-- sponsors -->
339
+
314
340
  ## Contributing
315
341
 
316
342
  Bugs, weird sites, pull requests. All welcome.
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Dembrandt - Design Token Extraction CLI
4
+ *
5
+ * Extracts design tokens, brand colors, typography, spacing, and component styles
6
+ * from any website using Playwright.
7
+ */
8
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,392 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Dembrandt - Design Token Extraction CLI
4
+ *
5
+ * Extracts design tokens, brand colors, typography, spacing, and component styles
6
+ * from any website using Playwright.
7
+ */
8
+ import { program } from "commander";
9
+ import chalk from "chalk";
10
+ import ora from "ora";
11
+ import { chromium, firefox } from "playwright-core";
12
+ import { extractBranding } from "./lib/extractors/index.js";
13
+ import { displayResults } from "./lib/formatters/terminal.js";
14
+ import { color } from "./lib/formatters/theme.js";
15
+ import { toDtcgTokens } from "./lib/formatters/dtcg.js";
16
+ import { generatePDF } from "./lib/formatters/pdf.js";
17
+ import { generateDesignMd } from "./lib/formatters/markdown.js";
18
+ import { parseSitemap } from "./lib/discovery.js";
19
+ import { mergeResults } from "./lib/merger.js";
20
+ import { writeFileSync, mkdirSync, readFileSync } from "fs";
21
+ import { join, dirname } from "path";
22
+ import { fileURLToPath } from "url";
23
+ import { checkRobotsTxt } from "./lib/robots.js";
24
+ const __dirname = dirname(fileURLToPath(import.meta.url));
25
+ const { version } = JSON.parse(readFileSync(join(__dirname, "package.json"), "utf8"));
26
+ /**
27
+ * ora options for a spinner on the given stream. The spinner animates only on
28
+ * a real interactive terminal: a non-TTY (piped) or CI environment gets the
29
+ * final status lines without the frame churn that garbles logs. Some CI runners
30
+ * allocate a pseudo-TTY, so we check CI explicitly rather than rely on isTTY.
31
+ */
32
+ function spinnerOptions(useStderr = false) {
33
+ const stream = useStderr ? process.stderr : process.stdout;
34
+ return { stream, isEnabled: Boolean(stream.isTTY) && !process.env.CI };
35
+ }
36
+ program
37
+ .name("dembrandt")
38
+ .description("Extract design tokens from any website.")
39
+ .version(version)
40
+ .enablePositionalOptions()
41
+ .argument("<url>")
42
+ .argument("[paths...]", "Additional paths on the same domain to extract and merge, e.g. /pricing /docs")
43
+ .option("--browser <type>", "Browser to use (chromium|firefox); set BROWSER_CDP_ENDPOINT env var to connect to an existing Chromium instance via CDP", "chromium")
44
+ .option("--json-only", "Output raw JSON")
45
+ .option("--save-output", "Save JSON file to output folder")
46
+ .option("--dtcg", "Export in W3C Design Tokens (DTCG) format")
47
+ .option("--dark-mode", "Extract colors from dark mode")
48
+ .option("--mobile", "Extract from mobile viewport")
49
+ .option("--slow", "3x longer timeouts for slow-loading sites")
50
+ .option("--brand-guide", "Export a brand guide PDF")
51
+ .option("--design-md", "Export a DESIGN.md file")
52
+ .option("--no-sandbox", "Disable browser sandbox (needed for Docker/CI)")
53
+ .option("--raw-colors", "Include pre-filter raw colors in JSON output")
54
+ .option("--screenshot <path>", "Save a viewport screenshot of the page (not full-page)")
55
+ .option("--wcag", "Analyze WCAG contrast ratios between palette colors")
56
+ .option("--crawl [n]", "Auto-discover and extract up to N pages via DOM links (default: 5); combine with --sitemap to use sitemap discovery instead", (v) => {
57
+ if (v === undefined || v === true)
58
+ return 5;
59
+ const n = parseInt(v, 10);
60
+ if (isNaN(n) || n < 1)
61
+ throw new Error(`--crawl must be a positive integer, got: ${v}`);
62
+ return n;
63
+ })
64
+ .option("--sitemap", "Discover pages from sitemap.xml instead of DOM links; use alone or combine with --crawl to set page limit")
65
+ .option("--cookie <string>", "Cookie string for authenticated pages, e.g. \"session=abc; token=xyz\"")
66
+ .option("--header <string>", "Extra HTTP header, e.g. \"Authorization: Bearer eyJ...\"")
67
+ .option("--stealth", "Enable anti-detection: navigator spoofing, human mouse simulation, randomized fingerprint (use only when authorized)")
68
+ .option("--user-agent <string>", "Custom user agent string")
69
+ .option("--locale <string>", "Browser locale for fingerprint, e.g. en-GB, fi-FI; affects content only if the site reacts to Accept-Language (default: en-US)")
70
+ .option("--timezone <string>", "Browser timezone for fingerprint, e.g. Europe/Helsinki; affects content only if the site reacts to timezone (default: America/New_York)")
71
+ .option("--accept-language <string>", "Custom Accept-Language header value")
72
+ .option("--screen-size <WxH>", "Physical screen resolution to report, e.g. 1920x1080 (default: 1920x1080)")
73
+ .action(async (input, paths, opts) => {
74
+ let url = input;
75
+ if (!url.startsWith("http://") && !url.startsWith("https://")) {
76
+ url = "https://" + url;
77
+ }
78
+ // In --json-only mode, redirect all status output to stderr so stdout is clean JSON
79
+ const originalConsoleLog = console.log;
80
+ if (opts.jsonOnly) {
81
+ console.log = (...args) => console.error(...args);
82
+ }
83
+ const spinner = ora({ text: "Starting extraction...", ...spinnerOptions(opts.jsonOnly) }).start();
84
+ try {
85
+ const robots = await checkRobotsTxt(url);
86
+ if (robots.status === "ok" && robots.allowed === false) {
87
+ spinner.warn(chalk.hex("#FFB86C")(`robots.txt disallows this path (rule: "${robots.rule}"). Proceeding anyway — respect the site's terms.`));
88
+ spinner.start("Starting extraction...");
89
+ }
90
+ }
91
+ catch {
92
+ // robots check is advisory; never block extraction
93
+ }
94
+ let browser = null;
95
+ try {
96
+ let useHeaded = false;
97
+ let result;
98
+ while (true) {
99
+ // Select browser type based on --browser flag
100
+ const browserType = opts.browser === 'firefox' ? firefox : chromium;
101
+ spinner.text = `Launching browser (${useHeaded ? "visible" : "headless"} mode)`;
102
+ // Firefox-specific launch args (Firefox doesn't support Chromium flags)
103
+ const launchArgs = opts.browser === 'firefox'
104
+ ? [] // Firefox has different flags
105
+ : ["--disable-blink-features=AutomationControlled"];
106
+ if (opts.noSandbox && opts.browser === 'chromium') {
107
+ launchArgs.push("--no-sandbox", "--disable-setuid-sandbox");
108
+ }
109
+ if (process.env.BROWSER_CDP_ENDPOINT) {
110
+ if (opts.browser !== 'chromium') {
111
+ throw new Error("BROWSER_CDP_ENDPOINT is only supported with --browser chromium.");
112
+ }
113
+ spinner.text = "Connecting over CDP...";
114
+ browser = await browserType.connectOverCDP(process.env.BROWSER_CDP_ENDPOINT);
115
+ }
116
+ else {
117
+ browser = await browserType.launch({
118
+ headless: !useHeaded,
119
+ args: launchArgs,
120
+ });
121
+ }
122
+ try {
123
+ const crawlN = opts.crawl ?? null;
124
+ const isAutoCrawl = crawlN && !opts.sitemap && (!paths || paths.length === 0);
125
+ const hasExplicitPaths = paths && paths.length > 0;
126
+ result = await extractBranding(url, spinner, browser, {
127
+ navigationTimeout: 90000,
128
+ verbose: !opts.jsonOnly,
129
+ darkMode: opts.darkMode,
130
+ mobile: opts.mobile,
131
+ slow: opts.slow,
132
+ screenshotPath: opts.screenshot,
133
+ discoverLinks: isAutoCrawl ? crawlN - 1 : null,
134
+ wcag: opts.wcag,
135
+ includeRawColors: opts.rawColors,
136
+ stealth: opts.stealth,
137
+ cookie: opts.cookie,
138
+ header: opts.header,
139
+ userAgent: opts.userAgent,
140
+ locale: opts.locale,
141
+ timezoneId: opts.timezone,
142
+ acceptLanguage: opts.acceptLanguage,
143
+ screenSize: opts.screenSize,
144
+ _version: version,
145
+ });
146
+ // Build list of additional URLs to extract
147
+ let additionalUrls = [];
148
+ if (hasExplicitPaths) {
149
+ // Explicit paths: resolve against base URL
150
+ const base = new URL(result.url);
151
+ additionalUrls = paths.map(p => {
152
+ if (p.startsWith('http'))
153
+ return p;
154
+ return `${base.protocol}//${base.host}${p.startsWith('/') ? p : '/' + p}`;
155
+ });
156
+ }
157
+ else if (opts.sitemap) {
158
+ if (!opts.jsonOnly)
159
+ spinner.start("Fetching sitemap...");
160
+ const max = crawlN ? crawlN - 1 : 20;
161
+ additionalUrls = await parseSitemap(result.url, max);
162
+ if (additionalUrls.length === 0 && result.url !== url) {
163
+ additionalUrls = await parseSitemap(url, max);
164
+ }
165
+ }
166
+ else if (isAutoCrawl) {
167
+ additionalUrls = result._discoveredLinks || [];
168
+ }
169
+ delete result._discoveredLinks;
170
+ if (additionalUrls.length === 0) {
171
+ if ((hasExplicitPaths || opts.sitemap || isAutoCrawl) && !opts.jsonOnly) {
172
+ spinner.warn("No additional pages discovered");
173
+ }
174
+ }
175
+ else {
176
+ spinner.stop();
177
+ if (!opts.jsonOnly)
178
+ console.log(chalk.dim(` Found ${additionalUrls.length} page(s) to analyze`));
179
+ const allResults = [result];
180
+ for (let i = 0; i < additionalUrls.length; i++) {
181
+ const pageUrl = additionalUrls[i];
182
+ const pageNum = i + 2;
183
+ const total = additionalUrls.length + 1;
184
+ if (!opts.jsonOnly)
185
+ spinner.start(`Extracting page ${pageNum}/${total}: ${new URL(pageUrl).pathname}`);
186
+ await new Promise(r => setTimeout(r, 1500 + Math.random() * 1500));
187
+ try {
188
+ const pageResult = await extractBranding(pageUrl, spinner, browser, {
189
+ navigationTimeout: 90000,
190
+ verbose: !opts.jsonOnly,
191
+ darkMode: opts.darkMode,
192
+ mobile: opts.mobile,
193
+ slow: opts.slow,
194
+ stealth: opts.stealth,
195
+ userAgent: opts.userAgent,
196
+ locale: opts.locale,
197
+ timezoneId: opts.timezone,
198
+ acceptLanguage: opts.acceptLanguage,
199
+ });
200
+ delete pageResult._discoveredLinks;
201
+ allResults.push(pageResult);
202
+ }
203
+ catch (err) {
204
+ if (!opts.jsonOnly)
205
+ spinner.warn(`Skipping ${pageUrl}: ${String(err?.message || err).slice(0, 80)}`);
206
+ }
207
+ }
208
+ spinner.stop();
209
+ result = mergeResults(allResults);
210
+ }
211
+ if (!hasExplicitPaths && !opts.sitemap && !isAutoCrawl) {
212
+ delete result._discoveredLinks;
213
+ }
214
+ break;
215
+ }
216
+ catch (err) {
217
+ await browser.close();
218
+ browser = null;
219
+ if (useHeaded || process.env.BROWSER_CDP_ENDPOINT)
220
+ throw err;
221
+ if (err.message.includes("Timeout") ||
222
+ err.message.includes("net::ERR_")) {
223
+ spinner.warn("Navigation failed → retrying with visible browser");
224
+ console.error(chalk.dim(` ↳ Error: ${err.message}`));
225
+ console.error(chalk.dim(` ↳ URL: ${url}`));
226
+ console.error(chalk.dim(` ↳ Mode: headless`));
227
+ useHeaded = true;
228
+ continue;
229
+ }
230
+ throw err;
231
+ }
232
+ }
233
+ console.log();
234
+ // Strip raw colors unless --raw-colors flag is set
235
+ if (!opts.rawColors && result.colors && result.colors.rawColors) {
236
+ delete result.colors.rawColors;
237
+ }
238
+ // Convert to W3C format if requested
239
+ const outputData = opts.dtcg ? toDtcgTokens(result) : result;
240
+ // Collect "saved to" notices and print them after the results below
241
+ const savedNotices = [];
242
+ // Save JSON output if --save-output or --dtcg is specified
243
+ if (opts.saveOutput || opts.dtcg) {
244
+ try {
245
+ const domain = new URL(url).hostname.replace("www.", "");
246
+ const timestamp = new Date()
247
+ .toISOString()
248
+ .replace(/[:.]/g, "-")
249
+ .split(".")[0];
250
+ // Save to current working directory, not installation directory
251
+ const outputDir = join(process.cwd(), "output", domain);
252
+ mkdirSync(outputDir, { recursive: true });
253
+ const suffix = opts.dtcg ? '.tokens' : '';
254
+ const filename = `${timestamp}_v${version}${suffix}.json`;
255
+ const filepath = join(outputDir, filename);
256
+ writeFileSync(filepath, JSON.stringify(outputData, null, 2));
257
+ const jsonLabel = opts.dtcg
258
+ ? 'DTCG tokens saved (--dtcg)'
259
+ : 'JSON saved (--save-output)';
260
+ savedNotices.push(chalk.dim(`💾 ${jsonLabel}: ${color.info(`output/${domain}/${filename}`)}`));
261
+ }
262
+ catch (err) {
263
+ console.log(color.warning(`! Could not save JSON file: ${err.message}`));
264
+ }
265
+ }
266
+ // Generate PDF brand guide
267
+ if (opts.brandGuide) {
268
+ try {
269
+ const pdfDomain = new URL(url).hostname.replace("www.", "");
270
+ const now = new Date();
271
+ const pdfDate = now.toISOString().slice(0, 10);
272
+ const pdfTime = `${String(now.getHours()).padStart(2, '0')}-${String(now.getMinutes()).padStart(2, '0')}`;
273
+ const pdfDir = join(process.cwd(), "output", pdfDomain);
274
+ mkdirSync(pdfDir, { recursive: true });
275
+ const pdfFilename = `${pdfDomain}-brand-guide-${pdfDate}-${pdfTime}.pdf`;
276
+ const pdfPath = join(pdfDir, pdfFilename);
277
+ spinner.start("Generating PDF brand guide...");
278
+ await generatePDF(result, pdfPath, browser);
279
+ spinner.stop();
280
+ savedNotices.push(chalk.dim(`💾 Brand guide PDF saved (--brand-guide): ${color.info(`output/${pdfDomain}/${pdfFilename}`)}`));
281
+ }
282
+ catch (err) {
283
+ spinner.stop();
284
+ console.log(color.warning(`Could not generate PDF: ${err.message}`));
285
+ }
286
+ }
287
+ // Generate DESIGN.md
288
+ if (opts.designMd) {
289
+ try {
290
+ const mdDomain = new URL(url).hostname.replace("www.", "");
291
+ const mdDir = join(process.cwd(), "output", mdDomain);
292
+ mkdirSync(mdDir, { recursive: true });
293
+ const mdPath = join(mdDir, "DESIGN.md");
294
+ writeFileSync(mdPath, generateDesignMd(result));
295
+ savedNotices.push(chalk.dim(`💾 DESIGN.md saved (--design-md): ${color.info(`output/${mdDomain}/DESIGN.md`)}`));
296
+ }
297
+ catch (err) {
298
+ console.log(color.warning(`Could not generate DESIGN.md: ${err.message}`));
299
+ }
300
+ }
301
+ // Output to terminal
302
+ const summaryLine = color.accent('✨ Analysis summary: ') +
303
+ chalk.dim(`${result.colors?.palette?.length ?? 0} colors, ` +
304
+ `${result.typography?.styles?.length ?? 0} text styles, ` +
305
+ `${result.breakpoints?.length ?? 0} breakpoints.`);
306
+ if (opts.jsonOnly) {
307
+ console.log = originalConsoleLog;
308
+ console.log(JSON.stringify(outputData, null, 2));
309
+ console.error(summaryLine);
310
+ for (const notice of savedNotices)
311
+ console.error(notice);
312
+ }
313
+ else {
314
+ console.log();
315
+ displayResults(result);
316
+ console.log();
317
+ console.log(summaryLine);
318
+ for (const notice of savedNotices)
319
+ console.log(notice);
320
+ }
321
+ }
322
+ catch (err) {
323
+ spinner.fail("Failed");
324
+ console.error(chalk.red("\n✗ Extraction failed"));
325
+ console.error(chalk.red(` Error: ${err.message}`));
326
+ console.error(chalk.dim(` URL: ${url}`));
327
+ process.exit(1);
328
+ }
329
+ finally {
330
+ if (browser)
331
+ await browser.close();
332
+ }
333
+ });
334
+ // Grouped --help for the root command. Commander 11 has no native option groups,
335
+ // so render them via a custom formatHelp. Subcommands keep a single flat list.
336
+ const OPTION_GROUPS = [
337
+ ["Extraction", ["--dark-mode", "--mobile", "--slow", "--crawl", "--sitemap", "--browser"]],
338
+ ["Output & export", ["--json-only", "--save-output", "--dtcg", "--brand-guide", "--design-md", "--screenshot", "--raw-colors"]],
339
+ ["Analysis", ["--wcag"]],
340
+ ["Network & auth", ["--cookie", "--header", "--user-agent", "--locale", "--timezone", "--accept-language", "--screen-size"]],
341
+ ["Anti-detection", ["--stealth", "--no-sandbox"]],
342
+ ];
343
+ program.configureHelp({
344
+ formatHelp(cmd, helper) {
345
+ const helpWidth = helper.helpWidth ?? 80;
346
+ const termWidth = helper.padWidth(cmd, helper);
347
+ const indent = 2;
348
+ const item = (term, desc) => {
349
+ if (!desc)
350
+ return term;
351
+ const full = `${term.padEnd(termWidth + 2)}${desc}`;
352
+ return helper.wrap(full, helpWidth - indent, termWidth + 2);
353
+ };
354
+ const block = (lines) => lines.map((l) => " ".repeat(indent) + l).join("\n");
355
+ const out = [`Usage: ${helper.commandUsage(cmd)}`, ""];
356
+ const description = helper.commandDescription(cmd);
357
+ if (description)
358
+ out.push(description, "");
359
+ const args = helper.visibleArguments(cmd);
360
+ if (args.length) {
361
+ out.push("Arguments:", block(args.map((a) => item(helper.argumentTerm(a), helper.argumentDescription(a)))), "");
362
+ }
363
+ const options = helper.visibleOptions(cmd);
364
+ if (options.length) {
365
+ if (cmd.parent) {
366
+ out.push("Options:", block(options.map((o) => item(helper.optionTerm(o), helper.optionDescription(o)))), "");
367
+ }
368
+ else {
369
+ const byLong = new Map(options.map((o) => [o.long ?? o.short, o]));
370
+ const used = new Set();
371
+ for (const [title, flags] of OPTION_GROUPS) {
372
+ const groupOpts = flags.map((f) => byLong.get(f)).filter(Boolean);
373
+ if (!groupOpts.length)
374
+ continue;
375
+ groupOpts.forEach((o) => used.add(o));
376
+ out.push(`${title}:`, block(groupOpts.map((o) => item(helper.optionTerm(o), helper.optionDescription(o)))), "");
377
+ }
378
+ const rest = options.filter((o) => !used.has(o));
379
+ if (rest.length) {
380
+ out.push("General:", block(rest.map((o) => item(helper.optionTerm(o), helper.optionDescription(o)))), "");
381
+ }
382
+ }
383
+ }
384
+ const commands = helper.visibleCommands(cmd);
385
+ if (commands.length) {
386
+ out.push("Commands:", block(commands.map((c) => item(helper.subcommandTerm(c), helper.subcommandDescription(c)))), "");
387
+ }
388
+ return out.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd() + "\n";
389
+ },
390
+ });
391
+ program.parse();
392
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Lazy loader for the playwright-core browser engines.
3
+ *
4
+ * playwright is an optionalDependency: consumers that use only the pure
5
+ * exports (drift, types, normalize, dtcg) are not forced to install the
6
+ * browser stack. Anything that actually drives a browser routes its import
7
+ * through here, so a missing install surfaces a clear instruction instead of
8
+ * a raw ERR_MODULE_NOT_FOUND at startup. Static `import` would fail at module
9
+ * load, before any guard could run; dynamic `import()` defers it to use.
10
+ */
11
+ export declare class PlaywrightMissingError extends Error {
12
+ constructor();
13
+ }
14
+ export declare function loadBrowserEngines(): Promise<typeof import('playwright-core')>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Lazy loader for the playwright-core browser engines.
3
+ *
4
+ * playwright is an optionalDependency: consumers that use only the pure
5
+ * exports (drift, types, normalize, dtcg) are not forced to install the
6
+ * browser stack. Anything that actually drives a browser routes its import
7
+ * through here, so a missing install surfaces a clear instruction instead of
8
+ * a raw ERR_MODULE_NOT_FOUND at startup. Static `import` would fail at module
9
+ * load, before any guard could run; dynamic `import()` defers it to use.
10
+ */
11
+ export class PlaywrightMissingError extends Error {
12
+ constructor() {
13
+ super('playwright not installed, run: npm i playwright');
14
+ this.name = 'PlaywrightMissingError';
15
+ }
16
+ }
17
+ export async function loadBrowserEngines() {
18
+ try {
19
+ return await import('playwright-core');
20
+ }
21
+ catch {
22
+ throw new PlaywrightMissingError();
23
+ }
24
+ }
25
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../lib/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C;QACE,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,sBAAsB,EAAE,CAAC;IACrC,CAAC;AACH,CAAC"}