@mseep/dembrandt 0.19.5
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/LICENSE +21 -0
- package/README.md +408 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +532 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/browser.d.ts +16 -0
- package/dist/lib/browser.js +27 -0
- package/dist/lib/browser.js.map +1 -0
- package/dist/lib/colors.d.ts +101 -0
- package/dist/lib/colors.js +405 -0
- package/dist/lib/colors.js.map +1 -0
- package/dist/lib/compare.d.ts +31 -0
- package/dist/lib/compare.js +46 -0
- package/dist/lib/compare.js.map +1 -0
- package/dist/lib/discovery.d.ts +31 -0
- package/dist/lib/discovery.js +243 -0
- package/dist/lib/discovery.js.map +1 -0
- package/dist/lib/drift.d.ts +64 -0
- package/dist/lib/drift.js +383 -0
- package/dist/lib/drift.js.map +1 -0
- package/dist/lib/dtcg/validate.d.ts +51 -0
- package/dist/lib/dtcg/validate.js +1403 -0
- package/dist/lib/dtcg/validate.js.map +1 -0
- package/dist/lib/exit-codes.d.ts +29 -0
- package/dist/lib/exit-codes.js +26 -0
- package/dist/lib/exit-codes.js.map +1 -0
- package/dist/lib/extractors/breakpoints.d.ts +5 -0
- package/dist/lib/extractors/breakpoints.js +450 -0
- package/dist/lib/extractors/breakpoints.js.map +1 -0
- package/dist/lib/extractors/colors.d.ts +2 -0
- package/dist/lib/extractors/colors.js +657 -0
- package/dist/lib/extractors/colors.js.map +1 -0
- package/dist/lib/extractors/components.d.ts +4 -0
- package/dist/lib/extractors/components.js +370 -0
- package/dist/lib/extractors/components.js.map +1 -0
- package/dist/lib/extractors/index.d.ts +9 -0
- package/dist/lib/extractors/index.js +1257 -0
- package/dist/lib/extractors/index.js.map +1 -0
- package/dist/lib/extractors/logo.d.ts +2 -0
- package/dist/lib/extractors/logo.js +626 -0
- package/dist/lib/extractors/logo.js.map +1 -0
- package/dist/lib/extractors/spacing.d.ts +4 -0
- package/dist/lib/extractors/spacing.js +163 -0
- package/dist/lib/extractors/spacing.js.map +1 -0
- package/dist/lib/extractors/teach.d.ts +1 -0
- package/dist/lib/extractors/teach.js +66 -0
- package/dist/lib/extractors/teach.js.map +1 -0
- package/dist/lib/extractors/typography.d.ts +1 -0
- package/dist/lib/extractors/typography.js +163 -0
- package/dist/lib/extractors/typography.js.map +1 -0
- package/dist/lib/findings.d.ts +34 -0
- package/dist/lib/findings.js +166 -0
- package/dist/lib/findings.js.map +1 -0
- package/dist/lib/formatters/dtcg.d.ts +10 -0
- package/dist/lib/formatters/dtcg.js +416 -0
- package/dist/lib/formatters/dtcg.js.map +1 -0
- package/dist/lib/formatters/html.d.ts +25 -0
- package/dist/lib/formatters/html.js +479 -0
- package/dist/lib/formatters/html.js.map +1 -0
- package/dist/lib/formatters/markdown.d.ts +5 -0
- package/dist/lib/formatters/markdown.js +568 -0
- package/dist/lib/formatters/markdown.js.map +1 -0
- package/dist/lib/formatters/pdf.d.ts +12 -0
- package/dist/lib/formatters/pdf.js +1121 -0
- package/dist/lib/formatters/pdf.js.map +1 -0
- package/dist/lib/formatters/terminal.d.ts +6 -0
- package/dist/lib/formatters/terminal.js +954 -0
- package/dist/lib/formatters/terminal.js.map +1 -0
- package/dist/lib/formatters/theme.d.ts +35 -0
- package/dist/lib/formatters/theme.js +37 -0
- package/dist/lib/formatters/theme.js.map +1 -0
- package/dist/lib/merger.d.ts +14 -0
- package/dist/lib/merger.js +362 -0
- package/dist/lib/merger.js.map +1 -0
- package/dist/lib/normalize.d.ts +29 -0
- package/dist/lib/normalize.js +59 -0
- package/dist/lib/normalize.js.map +1 -0
- package/dist/lib/robots.d.ts +12 -0
- package/dist/lib/robots.js +110 -0
- package/dist/lib/robots.js.map +1 -0
- package/dist/lib/run-summary.d.ts +40 -0
- package/dist/lib/run-summary.js +64 -0
- package/dist/lib/run-summary.js.map +1 -0
- package/dist/lib/types.d.ts +329 -0
- package/dist/lib/types.js +7 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/version.d.ts +134 -0
- package/dist/lib/version.js +153 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/mcp-server.d.ts +11 -0
- package/dist/mcp-server.js +311 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/package.json +106 -0
- package/dist/test/_vitest-shim.d.ts +13 -0
- package/dist/test/_vitest-shim.js +23 -0
- package/dist/test/_vitest-shim.js.map +1 -0
- package/dist/test/cli.test.d.ts +1 -0
- package/dist/test/cli.test.js +24 -0
- package/dist/test/cli.test.js.map +1 -0
- package/dist/test/colors.test.d.ts +1 -0
- package/dist/test/colors.test.js +64 -0
- package/dist/test/colors.test.js.map +1 -0
- package/dist/test/compare.test.d.ts +1 -0
- package/dist/test/compare.test.js +57 -0
- package/dist/test/compare.test.js.map +1 -0
- package/dist/test/drift.test.d.ts +1 -0
- package/dist/test/drift.test.js +53 -0
- package/dist/test/drift.test.js.map +1 -0
- package/dist/test/dtcg-formatter.test.d.ts +1 -0
- package/dist/test/dtcg-formatter.test.js +48 -0
- package/dist/test/dtcg-formatter.test.js.map +1 -0
- package/dist/test/dtcg-validate.test.d.ts +1 -0
- package/dist/test/dtcg-validate.test.js +2129 -0
- package/dist/test/dtcg-validate.test.js.map +1 -0
- package/dist/test/exit-codes.test.d.ts +1 -0
- package/dist/test/exit-codes.test.js +53 -0
- package/dist/test/exit-codes.test.js.map +1 -0
- package/dist/test/findings.test.d.ts +1 -0
- package/dist/test/findings.test.js +77 -0
- package/dist/test/findings.test.js.map +1 -0
- package/dist/test/html.test.d.ts +1 -0
- package/dist/test/html.test.js +95 -0
- package/dist/test/html.test.js.map +1 -0
- package/dist/test/markdown.test.d.ts +1 -0
- package/dist/test/markdown.test.js +145 -0
- package/dist/test/markdown.test.js.map +1 -0
- package/dist/test/merger.test.d.ts +1 -0
- package/dist/test/merger.test.js +98 -0
- package/dist/test/merger.test.js.map +1 -0
- package/dist/test/normalize.test.d.ts +1 -0
- package/dist/test/normalize.test.js +47 -0
- package/dist/test/normalize.test.js.map +1 -0
- package/dist/test/run-summary.test.d.ts +1 -0
- package/dist/test/run-summary.test.js +45 -0
- package/dist/test/run-summary.test.js.map +1 -0
- package/dist/test/version.test.d.ts +1 -0
- package/dist/test/version.test.js +73 -0
- package/dist/test/version.test.js.map +1 -0
- package/package.json +106 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,532 @@
|
|
|
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, Option } from "commander";
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import ora from "ora";
|
|
11
|
+
import { loadBrowserEngines } from "./lib/browser.js";
|
|
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 { generateHtmlReport } from "./lib/formatters/html.js";
|
|
19
|
+
import { resolveCompare } from "./lib/compare.js";
|
|
20
|
+
import { parseSitemap } from "./lib/discovery.js";
|
|
21
|
+
import { mergeResults } from "./lib/merger.js";
|
|
22
|
+
import { writeFileSync, mkdirSync, readFileSync } from "fs";
|
|
23
|
+
import { join, dirname, resolve } from "path";
|
|
24
|
+
import { fileURLToPath } from "url";
|
|
25
|
+
import { checkRobotsTxt } from "./lib/robots.js";
|
|
26
|
+
import { EXIT, classifyError } from "./lib/exit-codes.js";
|
|
27
|
+
import { activeFlags, pathSummary } from "./lib/run-summary.js";
|
|
28
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
29
|
+
const { version } = JSON.parse(readFileSync(join(__dirname, "package.json"), "utf8"));
|
|
30
|
+
/**
|
|
31
|
+
* ora options for a spinner on the given stream. The spinner animates only on
|
|
32
|
+
* a real interactive terminal: a non-TTY (piped) or CI environment gets the
|
|
33
|
+
* final status lines without the frame churn that garbles logs. Some CI runners
|
|
34
|
+
* allocate a pseudo-TTY, so we check CI explicitly rather than rely on isTTY.
|
|
35
|
+
*/
|
|
36
|
+
function spinnerOptions(useStderr = false) {
|
|
37
|
+
const stream = useStderr ? process.stderr : process.stdout;
|
|
38
|
+
return { stream, isEnabled: Boolean(stream.isTTY) && !process.env.CI };
|
|
39
|
+
}
|
|
40
|
+
program
|
|
41
|
+
.name("dembrandt")
|
|
42
|
+
.description("Extract design tokens from any website.")
|
|
43
|
+
.version(version)
|
|
44
|
+
.enablePositionalOptions()
|
|
45
|
+
.argument("<url>")
|
|
46
|
+
.argument("[paths...]", "Additional paths on the same domain to extract and merge, e.g. /pricing /docs")
|
|
47
|
+
.option("--browser <type>", "Browser to use (chromium|firefox); set BROWSER_CDP_ENDPOINT env var to connect to an existing Chromium instance via CDP", "chromium")
|
|
48
|
+
.option("--json-only", "Output raw JSON")
|
|
49
|
+
.option("--save-output", "Save JSON file to output folder")
|
|
50
|
+
.option("--dtcg", "Export in W3C Design Tokens (DTCG) format")
|
|
51
|
+
.option("--dark-mode", "Extract colors from dark mode")
|
|
52
|
+
.option("--mobile", "Extract from mobile viewport")
|
|
53
|
+
.option("--slow", "3x longer timeouts for slow-loading sites")
|
|
54
|
+
.option("--brand-guide", "Export a brand guide PDF")
|
|
55
|
+
.option("--design-md", "Export a DESIGN.md file")
|
|
56
|
+
.option("--html [path]", "Write a self-contained HTML report (default: output/<domain>/<timestamp>.html)")
|
|
57
|
+
.option("--compare <baseline>", "Drift-compare against a baseline: a local JSON file, or an App baseline id (posts to the .dembrandtrc endpoint, default dembrandt.com). Exits 1 on drift.")
|
|
58
|
+
.option("--approve", "With --compare <file>: accept the current extraction as the new baseline by overwriting that local file, and pass instead of failing. Ignored for App baseline ids.")
|
|
59
|
+
.option("--no-sandbox", "Disable browser sandbox (needed for Docker/CI)")
|
|
60
|
+
.option("--raw-colors", "Include pre-filter raw colors in JSON output")
|
|
61
|
+
.option("--screenshot <path>", "Save a viewport screenshot of the page (not full-page)")
|
|
62
|
+
// Internal, undocumented flag. Hidden from --help; not part of the product surface.
|
|
63
|
+
.addOption(new Option("--teach").hideHelp())
|
|
64
|
+
.option("--wcag", "Analyze WCAG contrast ratios between palette colors")
|
|
65
|
+
.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) => {
|
|
66
|
+
if (v === undefined || v === true)
|
|
67
|
+
return 5;
|
|
68
|
+
const n = parseInt(v, 10);
|
|
69
|
+
if (isNaN(n) || n < 1)
|
|
70
|
+
throw new Error(`--crawl must be a positive integer, got: ${v}`);
|
|
71
|
+
return n;
|
|
72
|
+
})
|
|
73
|
+
.option("--sitemap", "Discover pages from sitemap.xml instead of DOM links; use alone or combine with --crawl to set page limit")
|
|
74
|
+
.option("--cookie <string>", "Cookie string for authenticated pages, e.g. \"session=abc; token=xyz\"")
|
|
75
|
+
.option("--header <string>", "Extra HTTP header, e.g. \"Authorization: Bearer eyJ...\"")
|
|
76
|
+
.option("--stealth", "Enable anti-detection: navigator spoofing, human mouse simulation, randomized fingerprint (use only when authorized)")
|
|
77
|
+
.option("--user-agent <string>", "Custom user agent string")
|
|
78
|
+
.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)")
|
|
79
|
+
.option("--timezone <string>", "Browser timezone for fingerprint, e.g. Europe/Helsinki; affects content only if the site reacts to timezone (default: America/New_York)")
|
|
80
|
+
.option("--accept-language <string>", "Custom Accept-Language header value")
|
|
81
|
+
.option("--screen-size <WxH>", "Physical screen resolution to report, e.g. 1920x1080 (default: 1920x1080)")
|
|
82
|
+
.action(async (input, paths, opts) => {
|
|
83
|
+
let url = input;
|
|
84
|
+
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
|
85
|
+
url = "https://" + url;
|
|
86
|
+
}
|
|
87
|
+
if (opts.approve && !opts.compare) {
|
|
88
|
+
console.error(color.warning("! --approve has no effect without --compare <file>."));
|
|
89
|
+
}
|
|
90
|
+
// In --json-only mode, redirect all status output to stderr so stdout is clean JSON
|
|
91
|
+
const originalConsoleLog = console.log;
|
|
92
|
+
if (opts.jsonOnly) {
|
|
93
|
+
console.log = (...args) => console.error(...args);
|
|
94
|
+
}
|
|
95
|
+
const spinner = ora({ text: "Starting extraction...", ...spinnerOptions(opts.jsonOnly) }).start();
|
|
96
|
+
try {
|
|
97
|
+
const robots = await checkRobotsTxt(url);
|
|
98
|
+
if (robots.status === "ok" && robots.allowed === false) {
|
|
99
|
+
spinner.warn(chalk.hex("#FFB86C")(`robots.txt disallows this path (rule: "${robots.rule}"). Proceeding anyway — respect the site's terms.`));
|
|
100
|
+
spinner.start("Starting extraction...");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// robots check is advisory; never block extraction
|
|
105
|
+
}
|
|
106
|
+
let chromium, firefox;
|
|
107
|
+
try {
|
|
108
|
+
({ chromium, firefox } = await loadBrowserEngines());
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
spinner.fail(err.message);
|
|
112
|
+
if (opts.jsonOnly) {
|
|
113
|
+
console.log = originalConsoleLog;
|
|
114
|
+
console.log(JSON.stringify({ url, error: { code: "BROWSER_UNAVAILABLE", message: err.message } }, null, 2));
|
|
115
|
+
}
|
|
116
|
+
process.exit(EXIT.RUNTIME);
|
|
117
|
+
}
|
|
118
|
+
let browser = null;
|
|
119
|
+
try {
|
|
120
|
+
let useHeaded = false;
|
|
121
|
+
let result;
|
|
122
|
+
while (true) {
|
|
123
|
+
// Select browser type based on --browser flag
|
|
124
|
+
const browserType = opts.browser === 'firefox' ? firefox : chromium;
|
|
125
|
+
spinner.text = `Launching browser (${useHeaded ? "visible" : "headless"} mode)`;
|
|
126
|
+
// Firefox-specific launch args (Firefox doesn't support Chromium flags)
|
|
127
|
+
const launchArgs = opts.browser === 'firefox'
|
|
128
|
+
? [] // Firefox has different flags
|
|
129
|
+
: ["--disable-blink-features=AutomationControlled"];
|
|
130
|
+
if (opts.noSandbox && opts.browser === 'chromium') {
|
|
131
|
+
launchArgs.push("--no-sandbox", "--disable-setuid-sandbox");
|
|
132
|
+
}
|
|
133
|
+
if (process.env.BROWSER_CDP_ENDPOINT) {
|
|
134
|
+
if (opts.browser !== 'chromium') {
|
|
135
|
+
throw new Error("BROWSER_CDP_ENDPOINT is only supported with --browser chromium.");
|
|
136
|
+
}
|
|
137
|
+
spinner.text = "Connecting over CDP...";
|
|
138
|
+
browser = await browserType.connectOverCDP(process.env.BROWSER_CDP_ENDPOINT);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
browser = await browserType.launch({
|
|
142
|
+
headless: !useHeaded,
|
|
143
|
+
args: launchArgs,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
const crawlN = opts.crawl ?? null;
|
|
148
|
+
const isAutoCrawl = crawlN && !opts.sitemap && (!paths || paths.length === 0);
|
|
149
|
+
const hasExplicitPaths = paths && paths.length > 0;
|
|
150
|
+
result = await extractBranding(url, spinner, browser, {
|
|
151
|
+
navigationTimeout: 90000,
|
|
152
|
+
verbose: !opts.jsonOnly,
|
|
153
|
+
darkMode: opts.darkMode,
|
|
154
|
+
mobile: opts.mobile,
|
|
155
|
+
slow: opts.slow,
|
|
156
|
+
screenshotPath: opts.screenshot,
|
|
157
|
+
discoverLinks: isAutoCrawl ? crawlN - 1 : null,
|
|
158
|
+
wcag: opts.wcag,
|
|
159
|
+
includeRawColors: opts.rawColors,
|
|
160
|
+
stealth: opts.stealth,
|
|
161
|
+
cookie: opts.cookie,
|
|
162
|
+
header: opts.header,
|
|
163
|
+
userAgent: opts.userAgent,
|
|
164
|
+
locale: opts.locale,
|
|
165
|
+
timezoneId: opts.timezone,
|
|
166
|
+
acceptLanguage: opts.acceptLanguage,
|
|
167
|
+
screenSize: opts.screenSize,
|
|
168
|
+
teach: opts.teach,
|
|
169
|
+
_version: version,
|
|
170
|
+
});
|
|
171
|
+
// Build list of additional URLs to extract
|
|
172
|
+
let additionalUrls = [];
|
|
173
|
+
if (hasExplicitPaths) {
|
|
174
|
+
// Explicit paths: resolve against base URL
|
|
175
|
+
const base = new URL(result.url);
|
|
176
|
+
additionalUrls = paths.map(p => {
|
|
177
|
+
if (p.startsWith('http'))
|
|
178
|
+
return p;
|
|
179
|
+
return `${base.protocol}//${base.host}${p.startsWith('/') ? p : '/' + p}`;
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
else if (opts.sitemap) {
|
|
183
|
+
if (!opts.jsonOnly)
|
|
184
|
+
spinner.start("Fetching sitemap...");
|
|
185
|
+
const max = crawlN ? crawlN - 1 : 20;
|
|
186
|
+
additionalUrls = await parseSitemap(result.url, max);
|
|
187
|
+
if (additionalUrls.length === 0 && result.url !== url) {
|
|
188
|
+
additionalUrls = await parseSitemap(url, max);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else if (isAutoCrawl) {
|
|
192
|
+
additionalUrls = result._discoveredLinks || [];
|
|
193
|
+
}
|
|
194
|
+
delete result._discoveredLinks;
|
|
195
|
+
if (additionalUrls.length === 0) {
|
|
196
|
+
if ((hasExplicitPaths || opts.sitemap || isAutoCrawl) && !opts.jsonOnly) {
|
|
197
|
+
spinner.warn("No additional pages discovered");
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
spinner.stop();
|
|
202
|
+
if (!opts.jsonOnly)
|
|
203
|
+
console.log(chalk.dim(` Found ${additionalUrls.length} page(s) to analyze`));
|
|
204
|
+
const allResults = [result];
|
|
205
|
+
for (let i = 0; i < additionalUrls.length; i++) {
|
|
206
|
+
const pageUrl = additionalUrls[i];
|
|
207
|
+
const pageNum = i + 2;
|
|
208
|
+
const total = additionalUrls.length + 1;
|
|
209
|
+
if (!opts.jsonOnly)
|
|
210
|
+
spinner.start(`Extracting page ${pageNum}/${total}: ${new URL(pageUrl).pathname}`);
|
|
211
|
+
await new Promise(r => setTimeout(r, 1500 + Math.random() * 1500));
|
|
212
|
+
try {
|
|
213
|
+
const pageResult = await extractBranding(pageUrl, spinner, browser, {
|
|
214
|
+
navigationTimeout: 90000,
|
|
215
|
+
verbose: !opts.jsonOnly,
|
|
216
|
+
darkMode: opts.darkMode,
|
|
217
|
+
mobile: opts.mobile,
|
|
218
|
+
slow: opts.slow,
|
|
219
|
+
stealth: opts.stealth,
|
|
220
|
+
userAgent: opts.userAgent,
|
|
221
|
+
locale: opts.locale,
|
|
222
|
+
timezoneId: opts.timezone,
|
|
223
|
+
acceptLanguage: opts.acceptLanguage,
|
|
224
|
+
});
|
|
225
|
+
delete pageResult._discoveredLinks;
|
|
226
|
+
allResults.push(pageResult);
|
|
227
|
+
}
|
|
228
|
+
catch (err) {
|
|
229
|
+
if (!opts.jsonOnly)
|
|
230
|
+
spinner.warn(`Skipping ${pageUrl}: ${String(err?.message || err).slice(0, 80)}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
spinner.stop();
|
|
234
|
+
result = mergeResults(allResults);
|
|
235
|
+
}
|
|
236
|
+
if (!hasExplicitPaths && !opts.sitemap && !isAutoCrawl) {
|
|
237
|
+
delete result._discoveredLinks;
|
|
238
|
+
}
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
await browser.close();
|
|
243
|
+
browser = null;
|
|
244
|
+
if (useHeaded || process.env.BROWSER_CDP_ENDPOINT)
|
|
245
|
+
throw err;
|
|
246
|
+
if (err.message.includes("Timeout") ||
|
|
247
|
+
err.message.includes("net::ERR_")) {
|
|
248
|
+
spinner.warn("Navigation failed → retrying with visible browser");
|
|
249
|
+
console.error(chalk.dim(` ↳ Error: ${err.message}`));
|
|
250
|
+
console.error(chalk.dim(` ↳ URL: ${url}`));
|
|
251
|
+
console.error(chalk.dim(` ↳ Mode: headless`));
|
|
252
|
+
useHeaded = true;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
throw err;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
console.log();
|
|
259
|
+
// Strip raw colors unless --raw-colors flag is set
|
|
260
|
+
if (!opts.rawColors && result.colors && result.colors.rawColors) {
|
|
261
|
+
delete result.colors.rawColors;
|
|
262
|
+
}
|
|
263
|
+
// Pull the internal payload off the result before it can reach stdout or
|
|
264
|
+
// the normal saved output, and write it to its own sidecar.
|
|
265
|
+
const teachData = result._teach;
|
|
266
|
+
delete result._teach;
|
|
267
|
+
if (opts.teach && teachData) {
|
|
268
|
+
try {
|
|
269
|
+
const tDomain = new URL(url).hostname.replace("www.", "");
|
|
270
|
+
const tStamp = new Date().toISOString().replace(/[:.]/g, "-").split(".")[0];
|
|
271
|
+
const tDir = join(process.cwd(), "output", tDomain);
|
|
272
|
+
mkdirSync(tDir, { recursive: true });
|
|
273
|
+
const tFile = `${tStamp}_v${version}.teach.json`;
|
|
274
|
+
writeFileSync(join(tDir, tFile), JSON.stringify({ url: result.url, extractedAt: new Date().toISOString(), ...teachData }, null, 2));
|
|
275
|
+
if (!opts.jsonOnly)
|
|
276
|
+
console.error(chalk.dim(` teach → output/${tDomain}/${tFile}`));
|
|
277
|
+
}
|
|
278
|
+
catch { /* non-fatal */ }
|
|
279
|
+
}
|
|
280
|
+
// Convert to W3C format if requested
|
|
281
|
+
const outputData = opts.dtcg ? toDtcgTokens(result) : result;
|
|
282
|
+
// Collect "saved to" notices and print them after the results below
|
|
283
|
+
const savedNotices = [];
|
|
284
|
+
// Save JSON output if --save-output or --dtcg is specified
|
|
285
|
+
if (opts.saveOutput || opts.dtcg) {
|
|
286
|
+
try {
|
|
287
|
+
const domain = new URL(url).hostname.replace("www.", "");
|
|
288
|
+
const timestamp = new Date()
|
|
289
|
+
.toISOString()
|
|
290
|
+
.replace(/[:.]/g, "-")
|
|
291
|
+
.split(".")[0];
|
|
292
|
+
// Save to current working directory, not installation directory
|
|
293
|
+
const outputDir = join(process.cwd(), "output", domain);
|
|
294
|
+
mkdirSync(outputDir, { recursive: true });
|
|
295
|
+
const suffix = opts.dtcg ? '.tokens' : '';
|
|
296
|
+
const filename = `${timestamp}_v${version}${suffix}.json`;
|
|
297
|
+
const filepath = join(outputDir, filename);
|
|
298
|
+
writeFileSync(filepath, JSON.stringify(outputData, null, 2));
|
|
299
|
+
const jsonLabel = opts.dtcg
|
|
300
|
+
? 'DTCG tokens saved (--dtcg)'
|
|
301
|
+
: 'JSON saved (--save-output)';
|
|
302
|
+
savedNotices.push(chalk.dim(`💾 ${jsonLabel}: ${color.info(`output/${domain}/${filename}`)}`));
|
|
303
|
+
}
|
|
304
|
+
catch (err) {
|
|
305
|
+
console.log(color.warning(`! Could not save JSON file: ${err.message}`));
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// Generate PDF brand guide
|
|
309
|
+
if (opts.brandGuide) {
|
|
310
|
+
try {
|
|
311
|
+
const pdfDomain = new URL(url).hostname.replace("www.", "");
|
|
312
|
+
const now = new Date();
|
|
313
|
+
const pdfDate = now.toISOString().slice(0, 10);
|
|
314
|
+
const pdfTime = `${String(now.getHours()).padStart(2, '0')}-${String(now.getMinutes()).padStart(2, '0')}`;
|
|
315
|
+
const pdfDir = join(process.cwd(), "output", pdfDomain);
|
|
316
|
+
mkdirSync(pdfDir, { recursive: true });
|
|
317
|
+
const pdfFilename = `${pdfDomain}-brand-guide-${pdfDate}-${pdfTime}.pdf`;
|
|
318
|
+
const pdfPath = join(pdfDir, pdfFilename);
|
|
319
|
+
spinner.start("Generating PDF brand guide...");
|
|
320
|
+
await generatePDF(result, pdfPath, browser);
|
|
321
|
+
spinner.stop();
|
|
322
|
+
savedNotices.push(chalk.dim(`💾 Brand guide PDF saved (--brand-guide): ${color.info(`output/${pdfDomain}/${pdfFilename}`)}`));
|
|
323
|
+
}
|
|
324
|
+
catch (err) {
|
|
325
|
+
spinner.stop();
|
|
326
|
+
console.log(color.warning(`Could not generate PDF: ${err.message}`));
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
// Generate DESIGN.md
|
|
330
|
+
if (opts.designMd) {
|
|
331
|
+
try {
|
|
332
|
+
const mdDomain = new URL(url).hostname.replace("www.", "");
|
|
333
|
+
const mdDir = join(process.cwd(), "output", mdDomain);
|
|
334
|
+
mkdirSync(mdDir, { recursive: true });
|
|
335
|
+
const mdPath = join(mdDir, "DESIGN.md");
|
|
336
|
+
writeFileSync(mdPath, generateDesignMd(result));
|
|
337
|
+
savedNotices.push(chalk.dim(`💾 DESIGN.md saved (--design-md): ${color.info(`output/${mdDomain}/DESIGN.md`)}`));
|
|
338
|
+
}
|
|
339
|
+
catch (err) {
|
|
340
|
+
console.log(color.warning(`Could not generate DESIGN.md: ${err.message}`));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// Compare against a baseline: a local file (free, offline) or an App
|
|
344
|
+
// baseline id (platform). resolveCompare dispatches on file-vs-id.
|
|
345
|
+
let driftReport;
|
|
346
|
+
if (opts.compare) {
|
|
347
|
+
try {
|
|
348
|
+
// The App endpoint for baseline-id compares comes from .dembrandtrc.
|
|
349
|
+
let apiBase;
|
|
350
|
+
try {
|
|
351
|
+
const rc = JSON.parse(readFileSync(join(process.cwd(), ".dembrandtrc"), "utf-8"));
|
|
352
|
+
if (typeof rc.endpoint === "string")
|
|
353
|
+
apiBase = rc.endpoint;
|
|
354
|
+
}
|
|
355
|
+
catch { /* no .dembrandtrc, or unreadable — use the default */ }
|
|
356
|
+
const { report, source, mode } = await resolveCompare(opts.compare, result, apiBase ? { api: apiBase } : {});
|
|
357
|
+
driftReport = report;
|
|
358
|
+
const verdict = report.status === "drift"
|
|
359
|
+
? color.warning(`drift ${report.score} (threshold ${report.threshold})`)
|
|
360
|
+
: color.accent(`stable ${report.score}`);
|
|
361
|
+
savedNotices.push(chalk.dim(`⟂ Drift vs ${source} (${mode}): ${verdict} — ` +
|
|
362
|
+
`${report.summary.changed} changed, ${report.summary.added} added, ${report.summary.removed} removed`));
|
|
363
|
+
// --approve: accept the current extraction as the new baseline.
|
|
364
|
+
// Only local files can be overwritten; App baseline ids are read-only.
|
|
365
|
+
if (opts.approve) {
|
|
366
|
+
if (mode === "local") {
|
|
367
|
+
writeFileSync(resolve(process.cwd(), source), JSON.stringify(result, null, 2));
|
|
368
|
+
savedNotices.push(chalk.dim(`✓ Baseline accepted (--approve): ${color.info(source)}`));
|
|
369
|
+
// Accepted — pass the run regardless of drift.
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
savedNotices.push(color.warning("! --approve only updates local baseline files, not App baseline ids — drift stands."));
|
|
373
|
+
if (report.status === "drift")
|
|
374
|
+
process.exitCode = EXIT.DRIFT;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
else if (report.status === "drift") {
|
|
378
|
+
// CI gate: drift fails the run, but the report still writes first.
|
|
379
|
+
process.exitCode = EXIT.DRIFT;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
catch (err) {
|
|
383
|
+
console.log(color.warning(`! Could not compare against baseline: ${err.message}`));
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
// Generate self-contained HTML report
|
|
387
|
+
if (opts.html !== undefined) {
|
|
388
|
+
try {
|
|
389
|
+
const htmlDomain = new URL(url).hostname.replace("www.", "");
|
|
390
|
+
let htmlPath;
|
|
391
|
+
if (typeof opts.html === "string") {
|
|
392
|
+
htmlPath = resolve(process.cwd(), opts.html);
|
|
393
|
+
mkdirSync(dirname(htmlPath), { recursive: true });
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
const htmlStamp = new Date().toISOString().replace(/[:.]/g, "-").split(".")[0];
|
|
397
|
+
const htmlDir = join(process.cwd(), "output", htmlDomain);
|
|
398
|
+
mkdirSync(htmlDir, { recursive: true });
|
|
399
|
+
htmlPath = join(htmlDir, `${htmlStamp}_v${version}.html`);
|
|
400
|
+
}
|
|
401
|
+
writeFileSync(htmlPath, generateHtmlReport(result, {
|
|
402
|
+
version,
|
|
403
|
+
drift: driftReport,
|
|
404
|
+
baselineLabel: opts.compare,
|
|
405
|
+
}));
|
|
406
|
+
const htmlLabel = typeof opts.html === "string" ? opts.html : `output/${htmlDomain}/${htmlPath.split("/").pop()}`;
|
|
407
|
+
savedNotices.push(chalk.dim(`💾 HTML report saved (--html): ${color.info(htmlLabel)}`));
|
|
408
|
+
}
|
|
409
|
+
catch (err) {
|
|
410
|
+
console.log(color.warning(`! Could not write HTML report: ${err.message}`));
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
// Output to terminal
|
|
414
|
+
const summaryLine = color.accent('✨ Analysis summary: ') +
|
|
415
|
+
chalk.dim(`${result.colors?.palette?.length ?? 0} colors, ` +
|
|
416
|
+
`${result.typography?.styles?.length ?? 0} text styles, ` +
|
|
417
|
+
`${result.breakpoints?.length ?? 0} breakpoints.`);
|
|
418
|
+
// Surface what shaped this run (DEM-99) — active flags and merged paths —
|
|
419
|
+
// so the summary confirms what was asked for, not just what was extracted.
|
|
420
|
+
const flagBits = activeFlags(opts);
|
|
421
|
+
const flagsLine = flagBits.length ? chalk.dim(` Flags: ${flagBits.join(' ')}`) : null;
|
|
422
|
+
const pathBits = pathSummary(paths, result.pages?.length ?? 0);
|
|
423
|
+
const pathsLine = pathBits.length ? chalk.dim(` Paths: ${pathBits.join(' ')}`) : null;
|
|
424
|
+
if (opts.jsonOnly) {
|
|
425
|
+
console.log = originalConsoleLog;
|
|
426
|
+
// Attach the drift report to the JSON stream (only here, so --save-output
|
|
427
|
+
// and baseline files stay pure extractions). Lets consumers — e.g. a CI
|
|
428
|
+
// gate posting a PR comment — read the per-token changes machine-readably
|
|
429
|
+
// instead of scraping the HTML report.
|
|
430
|
+
const jsonOut = driftReport ? { ...outputData, drift: driftReport } : outputData;
|
|
431
|
+
console.log(JSON.stringify(jsonOut, null, 2));
|
|
432
|
+
console.error(summaryLine);
|
|
433
|
+
if (pathsLine)
|
|
434
|
+
console.error(pathsLine);
|
|
435
|
+
if (flagsLine)
|
|
436
|
+
console.error(flagsLine);
|
|
437
|
+
for (const notice of savedNotices)
|
|
438
|
+
console.error(notice);
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
console.log();
|
|
442
|
+
displayResults(result);
|
|
443
|
+
console.log();
|
|
444
|
+
console.log(summaryLine);
|
|
445
|
+
if (pathsLine)
|
|
446
|
+
console.log(pathsLine);
|
|
447
|
+
if (flagsLine)
|
|
448
|
+
console.log(flagsLine);
|
|
449
|
+
for (const notice of savedNotices)
|
|
450
|
+
console.log(notice);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
catch (err) {
|
|
454
|
+
const { code, exit } = classifyError(err);
|
|
455
|
+
spinner.fail("Failed");
|
|
456
|
+
if (opts.jsonOnly) {
|
|
457
|
+
console.log = originalConsoleLog;
|
|
458
|
+
console.log(JSON.stringify({ url, error: { code, message: err.message } }, null, 2));
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
console.error(chalk.red("\n✗ Extraction failed"));
|
|
462
|
+
console.error(chalk.red(` Error [${code}]: ${err.message}`));
|
|
463
|
+
console.error(chalk.dim(` URL: ${url}`));
|
|
464
|
+
if (exit === EXIT.TIMEOUT)
|
|
465
|
+
console.error(chalk.dim(" Hint: retry with --slow"));
|
|
466
|
+
}
|
|
467
|
+
process.exit(exit);
|
|
468
|
+
}
|
|
469
|
+
finally {
|
|
470
|
+
if (browser)
|
|
471
|
+
await browser.close();
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
// Grouped --help for the root command. Commander 11 has no native option groups,
|
|
475
|
+
// so render them via a custom formatHelp. Subcommands keep a single flat list.
|
|
476
|
+
const OPTION_GROUPS = [
|
|
477
|
+
["Extraction", ["--dark-mode", "--mobile", "--slow", "--crawl", "--sitemap", "--browser"]],
|
|
478
|
+
["Output & export", ["--json-only", "--save-output", "--dtcg", "--brand-guide", "--design-md", "--html", "--screenshot", "--raw-colors"]],
|
|
479
|
+
["Analysis", ["--wcag", "--compare", "--approve"]],
|
|
480
|
+
["Network & auth", ["--cookie", "--header", "--user-agent", "--locale", "--timezone", "--accept-language", "--screen-size"]],
|
|
481
|
+
["Anti-detection", ["--stealth", "--no-sandbox"]],
|
|
482
|
+
];
|
|
483
|
+
program.configureHelp({
|
|
484
|
+
formatHelp(cmd, helper) {
|
|
485
|
+
const helpWidth = helper.helpWidth ?? 80;
|
|
486
|
+
const termWidth = helper.padWidth(cmd, helper);
|
|
487
|
+
const indent = 2;
|
|
488
|
+
const item = (term, desc) => {
|
|
489
|
+
if (!desc)
|
|
490
|
+
return term;
|
|
491
|
+
const full = `${term.padEnd(termWidth + 2)}${desc}`;
|
|
492
|
+
return helper.wrap(full, helpWidth - indent, termWidth + 2);
|
|
493
|
+
};
|
|
494
|
+
const block = (lines) => lines.map((l) => " ".repeat(indent) + l).join("\n");
|
|
495
|
+
const out = [`Usage: ${helper.commandUsage(cmd)}`, ""];
|
|
496
|
+
const description = helper.commandDescription(cmd);
|
|
497
|
+
if (description)
|
|
498
|
+
out.push(description, "");
|
|
499
|
+
const args = helper.visibleArguments(cmd);
|
|
500
|
+
if (args.length) {
|
|
501
|
+
out.push("Arguments:", block(args.map((a) => item(helper.argumentTerm(a), helper.argumentDescription(a)))), "");
|
|
502
|
+
}
|
|
503
|
+
const options = helper.visibleOptions(cmd);
|
|
504
|
+
if (options.length) {
|
|
505
|
+
if (cmd.parent) {
|
|
506
|
+
out.push("Options:", block(options.map((o) => item(helper.optionTerm(o), helper.optionDescription(o)))), "");
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
const byLong = new Map(options.map((o) => [o.long ?? o.short, o]));
|
|
510
|
+
const used = new Set();
|
|
511
|
+
for (const [title, flags] of OPTION_GROUPS) {
|
|
512
|
+
const groupOpts = flags.map((f) => byLong.get(f)).filter(Boolean);
|
|
513
|
+
if (!groupOpts.length)
|
|
514
|
+
continue;
|
|
515
|
+
groupOpts.forEach((o) => used.add(o));
|
|
516
|
+
out.push(`${title}:`, block(groupOpts.map((o) => item(helper.optionTerm(o), helper.optionDescription(o)))), "");
|
|
517
|
+
}
|
|
518
|
+
const rest = options.filter((o) => !used.has(o));
|
|
519
|
+
if (rest.length) {
|
|
520
|
+
out.push("General:", block(rest.map((o) => item(helper.optionTerm(o), helper.optionDescription(o)))), "");
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
const commands = helper.visibleCommands(cmd);
|
|
525
|
+
if (commands.length) {
|
|
526
|
+
out.push("Commands:", block(commands.map((c) => item(helper.subcommandTerm(c), helper.subcommandDescription(c)))), "");
|
|
527
|
+
}
|
|
528
|
+
return out.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd() + "\n";
|
|
529
|
+
},
|
|
530
|
+
});
|
|
531
|
+
program.parse();
|
|
532
|
+
//# 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,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy loader for the playwright-core browser engines.
|
|
3
|
+
*
|
|
4
|
+
* playwright-core (the driver, ~10MB, no browser download) is a regular
|
|
5
|
+
* dependency, so the import resolves on a plain install without pulling the
|
|
6
|
+
* ~150MB browser binaries onto every consumer — library-only importers
|
|
7
|
+
* (drift, types, normalize, dtcg) and Vercel/CI installs stay lean. The actual
|
|
8
|
+
* browser binary is fetched on demand (`npx playwright install chromium` or
|
|
9
|
+
* `npm run install-browser`), so only callers that really extract pay for it.
|
|
10
|
+
* The import is still routed through here and guarded so a missing engine
|
|
11
|
+
* surfaces a clear instruction; dynamic `import()` defers resolution to use.
|
|
12
|
+
*/
|
|
13
|
+
export declare class PlaywrightMissingError extends Error {
|
|
14
|
+
constructor();
|
|
15
|
+
}
|
|
16
|
+
export declare function loadBrowserEngines(): Promise<typeof import('playwright-core')>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy loader for the playwright-core browser engines.
|
|
3
|
+
*
|
|
4
|
+
* playwright-core (the driver, ~10MB, no browser download) is a regular
|
|
5
|
+
* dependency, so the import resolves on a plain install without pulling the
|
|
6
|
+
* ~150MB browser binaries onto every consumer — library-only importers
|
|
7
|
+
* (drift, types, normalize, dtcg) and Vercel/CI installs stay lean. The actual
|
|
8
|
+
* browser binary is fetched on demand (`npx playwright install chromium` or
|
|
9
|
+
* `npm run install-browser`), so only callers that really extract pay for it.
|
|
10
|
+
* The import is still routed through here and guarded so a missing engine
|
|
11
|
+
* surfaces a clear instruction; dynamic `import()` defers resolution to use.
|
|
12
|
+
*/
|
|
13
|
+
export class PlaywrightMissingError extends Error {
|
|
14
|
+
constructor() {
|
|
15
|
+
super('browser engine not available, run: npx playwright install chromium');
|
|
16
|
+
this.name = 'PlaywrightMissingError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function loadBrowserEngines() {
|
|
20
|
+
try {
|
|
21
|
+
return await import('playwright-core');
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
throw new PlaywrightMissingError();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../lib/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C;QACE,KAAK,CAAC,oEAAoE,CAAC,CAAC;QAC5E,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"}
|