dembrandt 0.14.0 → 0.15.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/README.md +4 -0
- package/index.js +9 -14
- package/mcp-server.js +4 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,6 +59,9 @@ Load extractions, track token drift, and compare snapshots. **[dembrandt.com/app
|
|
|
59
59
|
* **Copy tokens.** Paste values straight into Copilot, Claude, or Cursor.
|
|
60
60
|
* **No login.** Your data stays in the browser, nothing is sent to any server.
|
|
61
61
|
|
|
62
|
+
## Recipes
|
|
63
|
+
|
|
64
|
+
**[dembrandt.com/recipes](https://www.dembrandt.com/recipes)** — 38 ready-to-run workflows. Copy a command, paste a prompt, get a result. Covers competitor benchmarking, WCAG audits, CI/CD drift detection, Figma token push, and agentic design system builds. Filterable by role.
|
|
62
65
|
|
|
63
66
|
## What to expect from extraction?
|
|
64
67
|
|
|
@@ -84,6 +87,7 @@ dembrandt example.com --mobile # Use mobile viewport (390x844) for respo
|
|
|
84
87
|
dembrandt example.com --slow # 3x longer timeouts (24s hydration) for JavaScript-heavy sites
|
|
85
88
|
dembrandt example.com --brand-guide # Generate a brand guide PDF
|
|
86
89
|
dembrandt example.com --design-md # Generate a DESIGN.md file for AI agents
|
|
90
|
+
dembrandt example.com /pricing /docs # Extract specific paths and merge results into one output
|
|
87
91
|
dembrandt example.com --crawl 5 # Analyze 5 pages (homepage + 4 discovered pages), merges results
|
|
88
92
|
dembrandt example.com --sitemap # Discover pages from sitemap.xml instead of DOM links
|
|
89
93
|
dembrandt example.com --crawl 10 --sitemap # Combine: up to 10 pages discovered via sitemap
|
package/index.js
CHANGED
|
@@ -32,7 +32,7 @@ program
|
|
|
32
32
|
.description("Extract design tokens from any website")
|
|
33
33
|
.version(version)
|
|
34
34
|
.argument("<url>")
|
|
35
|
-
.argument("[paths...]", "Additional paths to extract and merge, e.g. /pricing /docs")
|
|
35
|
+
.argument("[paths...]", "Additional paths on the same domain to extract and merge, e.g. /pricing /docs")
|
|
36
36
|
.option("--browser <type>", "Browser to use (chromium|firefox); set BROWSER_CDP_ENDPOINT env var to connect to an existing Chromium instance via CDP", "chromium")
|
|
37
37
|
.option("--json-only", "Output raw JSON")
|
|
38
38
|
.option("--save-output", "Save JSON file to output folder")
|
|
@@ -44,24 +44,19 @@ program
|
|
|
44
44
|
.option("--design-md", "Export a DESIGN.md file")
|
|
45
45
|
.option("--no-sandbox", "Disable browser sandbox (needed for Docker/CI)")
|
|
46
46
|
.option("--raw-colors", "Include pre-filter raw colors in JSON output")
|
|
47
|
-
.option("--screenshot <path>", "Save a screenshot of the page")
|
|
47
|
+
.option("--screenshot <path>", "Save a viewport screenshot of the page (not full-page)")
|
|
48
48
|
.option("--wcag", "Analyze WCAG contrast ratios between palette colors")
|
|
49
|
-
.option("--crawl [n]", "Auto-discover and extract up to N pages via DOM links (default: 5)", (v) => {
|
|
49
|
+
.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) => {
|
|
50
50
|
if (v === undefined || v === true) return 5;
|
|
51
51
|
const n = parseInt(v, 10);
|
|
52
52
|
if (isNaN(n) || n < 1) throw new Error(`--crawl must be a positive integer, got: ${v}`);
|
|
53
53
|
return n;
|
|
54
54
|
})
|
|
55
|
-
.option("--
|
|
56
|
-
|
|
57
|
-
if (isNaN(n) || n < 1) throw new Error(`--pages must be a positive integer, got: ${v}`);
|
|
58
|
-
return n;
|
|
59
|
-
})
|
|
60
|
-
.option("--sitemap", "Discover pages from sitemap.xml instead of DOM links")
|
|
61
|
-
.option("--stealth", "Enable anti-detection scripts to bypass bot protection (use only when authorized)")
|
|
55
|
+
.option("--sitemap", "Discover pages from sitemap.xml instead of DOM links; use alone or combine with --crawl to set page limit")
|
|
56
|
+
.option("--stealth", "Enable anti-detection: navigator spoofing, human mouse simulation, randomized fingerprint (use only when authorized)")
|
|
62
57
|
.option("--user-agent <string>", "Custom user agent string")
|
|
63
|
-
.option("--locale <string>", "Browser locale, e.g. en-GB, fi-FI (default: en-US)")
|
|
64
|
-
.option("--timezone <string>", "Browser timezone, e.g. Europe/Helsinki (default: America/New_York)")
|
|
58
|
+
.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)")
|
|
59
|
+
.option("--timezone <string>", "Browser timezone for fingerprint, e.g. Europe/Helsinki; affects content only if the site reacts to timezone (default: America/New_York)")
|
|
65
60
|
.option("--accept-language <string>", "Custom Accept-Language header value")
|
|
66
61
|
.option("--screen-size <WxH>", "Physical screen resolution to report, e.g. 1920x1080 (default: 1920x1080)")
|
|
67
62
|
.action(async (input, paths, opts) => {
|
|
@@ -126,7 +121,7 @@ program
|
|
|
126
121
|
}
|
|
127
122
|
|
|
128
123
|
try {
|
|
129
|
-
const crawlN = opts.crawl ??
|
|
124
|
+
const crawlN = opts.crawl ?? null;
|
|
130
125
|
const isAutoCrawl = crawlN && !opts.sitemap && (!paths || paths.length === 0);
|
|
131
126
|
const hasExplicitPaths = paths && paths.length > 0;
|
|
132
127
|
|
|
@@ -265,7 +260,7 @@ program
|
|
|
265
260
|
mkdirSync(outputDir, { recursive: true });
|
|
266
261
|
|
|
267
262
|
const suffix = opts.dtcg ? '.tokens' : '';
|
|
268
|
-
const filename = `${timestamp}${suffix}.json`;
|
|
263
|
+
const filename = `${timestamp}_v${version}${suffix}.json`;
|
|
269
264
|
const filepath = join(outputDir, filename);
|
|
270
265
|
writeFileSync(filepath, JSON.stringify(outputData, null, 2));
|
|
271
266
|
|
package/mcp-server.js
CHANGED
|
@@ -15,9 +15,11 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
15
15
|
import { z } from "zod";
|
|
16
16
|
import { chromium } from "playwright-core";
|
|
17
17
|
import { readFileSync } from "node:fs";
|
|
18
|
-
import {
|
|
18
|
+
import { createRequire } from "node:module";
|
|
19
|
+
import { extractBranding } from "./lib/extractors/index.js";
|
|
19
20
|
|
|
20
21
|
const { version } = JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf8"));
|
|
22
|
+
const pwVersion = createRequire(import.meta.url)("playwright-core/package.json").version;
|
|
21
23
|
|
|
22
24
|
const server = new McpServer({
|
|
23
25
|
name: "dembrandt",
|
|
@@ -50,7 +52,7 @@ async function runExtraction(url, options = {}) {
|
|
|
50
52
|
} catch (err) {
|
|
51
53
|
return {
|
|
52
54
|
ok: false,
|
|
53
|
-
error: `Browser launch failed.
|
|
55
|
+
error: `Browser launch failed. Install the matching browser: npx playwright@${pwVersion} install chromium\n\n${err.message}`,
|
|
54
56
|
};
|
|
55
57
|
}
|
|
56
58
|
|