@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.
Files changed (139) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +408 -0
  3. package/dist/index.d.ts +8 -0
  4. package/dist/index.js +532 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/lib/browser.d.ts +16 -0
  7. package/dist/lib/browser.js +27 -0
  8. package/dist/lib/browser.js.map +1 -0
  9. package/dist/lib/colors.d.ts +101 -0
  10. package/dist/lib/colors.js +405 -0
  11. package/dist/lib/colors.js.map +1 -0
  12. package/dist/lib/compare.d.ts +31 -0
  13. package/dist/lib/compare.js +46 -0
  14. package/dist/lib/compare.js.map +1 -0
  15. package/dist/lib/discovery.d.ts +31 -0
  16. package/dist/lib/discovery.js +243 -0
  17. package/dist/lib/discovery.js.map +1 -0
  18. package/dist/lib/drift.d.ts +64 -0
  19. package/dist/lib/drift.js +383 -0
  20. package/dist/lib/drift.js.map +1 -0
  21. package/dist/lib/dtcg/validate.d.ts +51 -0
  22. package/dist/lib/dtcg/validate.js +1403 -0
  23. package/dist/lib/dtcg/validate.js.map +1 -0
  24. package/dist/lib/exit-codes.d.ts +29 -0
  25. package/dist/lib/exit-codes.js +26 -0
  26. package/dist/lib/exit-codes.js.map +1 -0
  27. package/dist/lib/extractors/breakpoints.d.ts +5 -0
  28. package/dist/lib/extractors/breakpoints.js +450 -0
  29. package/dist/lib/extractors/breakpoints.js.map +1 -0
  30. package/dist/lib/extractors/colors.d.ts +2 -0
  31. package/dist/lib/extractors/colors.js +657 -0
  32. package/dist/lib/extractors/colors.js.map +1 -0
  33. package/dist/lib/extractors/components.d.ts +4 -0
  34. package/dist/lib/extractors/components.js +370 -0
  35. package/dist/lib/extractors/components.js.map +1 -0
  36. package/dist/lib/extractors/index.d.ts +9 -0
  37. package/dist/lib/extractors/index.js +1257 -0
  38. package/dist/lib/extractors/index.js.map +1 -0
  39. package/dist/lib/extractors/logo.d.ts +2 -0
  40. package/dist/lib/extractors/logo.js +626 -0
  41. package/dist/lib/extractors/logo.js.map +1 -0
  42. package/dist/lib/extractors/spacing.d.ts +4 -0
  43. package/dist/lib/extractors/spacing.js +163 -0
  44. package/dist/lib/extractors/spacing.js.map +1 -0
  45. package/dist/lib/extractors/teach.d.ts +1 -0
  46. package/dist/lib/extractors/teach.js +66 -0
  47. package/dist/lib/extractors/teach.js.map +1 -0
  48. package/dist/lib/extractors/typography.d.ts +1 -0
  49. package/dist/lib/extractors/typography.js +163 -0
  50. package/dist/lib/extractors/typography.js.map +1 -0
  51. package/dist/lib/findings.d.ts +34 -0
  52. package/dist/lib/findings.js +166 -0
  53. package/dist/lib/findings.js.map +1 -0
  54. package/dist/lib/formatters/dtcg.d.ts +10 -0
  55. package/dist/lib/formatters/dtcg.js +416 -0
  56. package/dist/lib/formatters/dtcg.js.map +1 -0
  57. package/dist/lib/formatters/html.d.ts +25 -0
  58. package/dist/lib/formatters/html.js +479 -0
  59. package/dist/lib/formatters/html.js.map +1 -0
  60. package/dist/lib/formatters/markdown.d.ts +5 -0
  61. package/dist/lib/formatters/markdown.js +568 -0
  62. package/dist/lib/formatters/markdown.js.map +1 -0
  63. package/dist/lib/formatters/pdf.d.ts +12 -0
  64. package/dist/lib/formatters/pdf.js +1121 -0
  65. package/dist/lib/formatters/pdf.js.map +1 -0
  66. package/dist/lib/formatters/terminal.d.ts +6 -0
  67. package/dist/lib/formatters/terminal.js +954 -0
  68. package/dist/lib/formatters/terminal.js.map +1 -0
  69. package/dist/lib/formatters/theme.d.ts +35 -0
  70. package/dist/lib/formatters/theme.js +37 -0
  71. package/dist/lib/formatters/theme.js.map +1 -0
  72. package/dist/lib/merger.d.ts +14 -0
  73. package/dist/lib/merger.js +362 -0
  74. package/dist/lib/merger.js.map +1 -0
  75. package/dist/lib/normalize.d.ts +29 -0
  76. package/dist/lib/normalize.js +59 -0
  77. package/dist/lib/normalize.js.map +1 -0
  78. package/dist/lib/robots.d.ts +12 -0
  79. package/dist/lib/robots.js +110 -0
  80. package/dist/lib/robots.js.map +1 -0
  81. package/dist/lib/run-summary.d.ts +40 -0
  82. package/dist/lib/run-summary.js +64 -0
  83. package/dist/lib/run-summary.js.map +1 -0
  84. package/dist/lib/types.d.ts +329 -0
  85. package/dist/lib/types.js +7 -0
  86. package/dist/lib/types.js.map +1 -0
  87. package/dist/lib/version.d.ts +134 -0
  88. package/dist/lib/version.js +153 -0
  89. package/dist/lib/version.js.map +1 -0
  90. package/dist/mcp-server.d.ts +11 -0
  91. package/dist/mcp-server.js +311 -0
  92. package/dist/mcp-server.js.map +1 -0
  93. package/dist/package.json +106 -0
  94. package/dist/test/_vitest-shim.d.ts +13 -0
  95. package/dist/test/_vitest-shim.js +23 -0
  96. package/dist/test/_vitest-shim.js.map +1 -0
  97. package/dist/test/cli.test.d.ts +1 -0
  98. package/dist/test/cli.test.js +24 -0
  99. package/dist/test/cli.test.js.map +1 -0
  100. package/dist/test/colors.test.d.ts +1 -0
  101. package/dist/test/colors.test.js +64 -0
  102. package/dist/test/colors.test.js.map +1 -0
  103. package/dist/test/compare.test.d.ts +1 -0
  104. package/dist/test/compare.test.js +57 -0
  105. package/dist/test/compare.test.js.map +1 -0
  106. package/dist/test/drift.test.d.ts +1 -0
  107. package/dist/test/drift.test.js +53 -0
  108. package/dist/test/drift.test.js.map +1 -0
  109. package/dist/test/dtcg-formatter.test.d.ts +1 -0
  110. package/dist/test/dtcg-formatter.test.js +48 -0
  111. package/dist/test/dtcg-formatter.test.js.map +1 -0
  112. package/dist/test/dtcg-validate.test.d.ts +1 -0
  113. package/dist/test/dtcg-validate.test.js +2129 -0
  114. package/dist/test/dtcg-validate.test.js.map +1 -0
  115. package/dist/test/exit-codes.test.d.ts +1 -0
  116. package/dist/test/exit-codes.test.js +53 -0
  117. package/dist/test/exit-codes.test.js.map +1 -0
  118. package/dist/test/findings.test.d.ts +1 -0
  119. package/dist/test/findings.test.js +77 -0
  120. package/dist/test/findings.test.js.map +1 -0
  121. package/dist/test/html.test.d.ts +1 -0
  122. package/dist/test/html.test.js +95 -0
  123. package/dist/test/html.test.js.map +1 -0
  124. package/dist/test/markdown.test.d.ts +1 -0
  125. package/dist/test/markdown.test.js +145 -0
  126. package/dist/test/markdown.test.js.map +1 -0
  127. package/dist/test/merger.test.d.ts +1 -0
  128. package/dist/test/merger.test.js +98 -0
  129. package/dist/test/merger.test.js.map +1 -0
  130. package/dist/test/normalize.test.d.ts +1 -0
  131. package/dist/test/normalize.test.js +47 -0
  132. package/dist/test/normalize.test.js.map +1 -0
  133. package/dist/test/run-summary.test.d.ts +1 -0
  134. package/dist/test/run-summary.test.js +45 -0
  135. package/dist/test/run-summary.test.js.map +1 -0
  136. package/dist/test/version.test.d.ts +1 -0
  137. package/dist/test/version.test.js +73 -0
  138. package/dist/test/version.test.js.map +1 -0
  139. package/package.json +106 -0
@@ -0,0 +1,98 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { mergeResults } from '../lib/merger.js';
4
+ /**
5
+ * mergeResults feeds both the terminal display and the DTCG formatter. It is a
6
+ * pure function, so it is tested directly with synthetic extraction results
7
+ * rather than live pages. These assertions pin the union invariants: perceptual
8
+ * dedup, pageCount, count summation, multi-page confidence boost, homepage-wins
9
+ * semantics, and the pages provenance array.
10
+ */
11
+ function page(url, overrides = {}) {
12
+ return {
13
+ url,
14
+ extractedAt: `${url}-time`,
15
+ siteName: 'Test',
16
+ logo: { url: 'logo.svg' },
17
+ favicons: [],
18
+ colors: { palette: [], semantic: {}, cssVariables: {} },
19
+ typography: { styles: [], sources: {} },
20
+ spacing: { commonValues: [] },
21
+ borderRadius: { values: [] },
22
+ borders: { combinations: [] },
23
+ shadows: [],
24
+ gradients: [],
25
+ motion: { durations: [], easings: [], animations: [], contexts: {}, interactiveDeltas: [] },
26
+ components: { buttons: [], inputs: {}, links: [], badges: {} },
27
+ breakpoints: [],
28
+ iconSystem: [],
29
+ frameworks: [],
30
+ ...overrides,
31
+ };
32
+ }
33
+ const color = (hex, count, confidence) => ({ normalized: hex, color: hex, count, confidence });
34
+ test('mergeResults throws on empty input', () => {
35
+ assert.throws(() => mergeResults([]), /No results to merge/);
36
+ });
37
+ test('mergeResults returns a single result unchanged', () => {
38
+ const only = page('https://a.test');
39
+ assert.equal(mergeResults([only]), only);
40
+ });
41
+ test('mergeResults unions palette with perceptual dedup, pageCount and count', () => {
42
+ const home = page('https://a.test', {
43
+ colors: {
44
+ palette: [color('#0066cc', 10, 'high'), color('#777777', 2, 'low')],
45
+ semantic: { primary: '#0066cc' },
46
+ cssVariables: {},
47
+ },
48
+ });
49
+ const second = page('https://a.test/pricing', {
50
+ colors: {
51
+ // #0166cc is within deltaE 15 of #0066cc -> collapses.
52
+ // #777777 repeats -> low confidence boosted by multi-page presence.
53
+ // #cc0000 is page-only.
54
+ palette: [color('#0166cc', 6, 'high'), color('#777777', 3, 'low'), color('#cc0000', 4, 'low')],
55
+ semantic: { primary: '#cc0000', secondary: '#00aa00' },
56
+ cssVariables: {},
57
+ },
58
+ });
59
+ const merged = mergeResults([home, second]);
60
+ const pal = merged.colors.palette;
61
+ const blue = pal.find((c) => c.normalized === '#0066cc');
62
+ assert.ok(blue, 'near-duplicate blues collapse to the higher-count canonical');
63
+ assert.equal(blue.pageCount, 2);
64
+ assert.equal(blue.count, 16);
65
+ assert.equal(pal.some((c) => c.normalized === '#0166cc'), false);
66
+ const gray = pal.find((c) => c.normalized === '#777777');
67
+ assert.equal(gray.pageCount, 2);
68
+ assert.equal(gray.count, 5);
69
+ assert.equal(gray.confidence, 'medium'); // low -> medium because pageCount > 1
70
+ const red = pal.find((c) => c.normalized === '#cc0000');
71
+ assert.equal(red.pageCount, 1);
72
+ assert.equal(red.confidence, 'low');
73
+ // Homepage semantic wins; missing keys are filled from later pages.
74
+ assert.equal(merged.colors.semantic.primary, '#0066cc');
75
+ assert.equal(merged.colors.semantic.secondary, '#00aa00');
76
+ });
77
+ test('mergeResults dedupes typography by family/size/weight and sums spacing', () => {
78
+ const style = (family, size, weight) => ({ family, size, weight });
79
+ const home = page('https://a.test', {
80
+ typography: { styles: [style('Inter', '16px', '400')], sources: {} },
81
+ spacing: { commonValues: [{ px: '8px', count: 5 }] },
82
+ });
83
+ const second = page('https://a.test/x', {
84
+ typography: { styles: [style('Inter', '16px', '400'), style('Inter', '24px', '700')], sources: {} },
85
+ spacing: { commonValues: [{ px: '8px', count: 3 }, { px: '16px', count: 2 }] },
86
+ });
87
+ const merged = mergeResults([home, second]);
88
+ assert.equal(merged.typography.styles.length, 2);
89
+ const eight = merged.spacing.commonValues.find((v) => v.px === '8px');
90
+ assert.equal(eight.count, 8);
91
+ assert.ok(merged.spacing.commonValues.find((v) => v.px === '16px'));
92
+ });
93
+ test('mergeResults records per-page provenance in the pages array', () => {
94
+ const merged = mergeResults([page('https://a.test'), page('https://a.test/pricing')]);
95
+ assert.equal(merged.pages.length, 2);
96
+ assert.deepEqual(merged.pages.map((p) => p.url), ['https://a.test', 'https://a.test/pricing']);
97
+ });
98
+ //# sourceMappingURL=merger.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merger.test.js","sourceRoot":"","sources":["../../test/merger.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Ingest hardening: transients never persist, and loose unions canonicalize so
3
+ * the drift engine never compares a string weight against a number weight.
4
+ */
5
+ import { test } from 'node:test';
6
+ import assert from 'node:assert/strict';
7
+ import { stripTransient, normalizeExtraction } from '../lib/normalize.js';
8
+ const base = {
9
+ url: 'https://x.com/',
10
+ extractedAt: '2026-01-01T00:00:00.000Z',
11
+ meta: { dembrandtVersion: '0.16.0', schemaVersion: '1.0.0' },
12
+ colors: { palette: [], semantic: {}, cssVariables: {} },
13
+ typography: {
14
+ styles: [{ context: 'body', family: 'Inter', size: '16px', weight: '700' }],
15
+ sources: { adobeFonts: false },
16
+ },
17
+ spacing: { scaleType: 'base-8', commonValues: [{ px: '16px' }, { px: 24 }] },
18
+ borderRadius: { values: [] },
19
+ borders: {},
20
+ shadows: [],
21
+ components: { buttons: [], inputs: { text: [] }, links: [], badges: { all: [] } },
22
+ breakpoints: [],
23
+ iconSystem: [],
24
+ frameworks: [],
25
+ };
26
+ test('stripTransient removes internal crawl fields and does not mutate input', () => {
27
+ const input = { ...base, _discoveredLinks: [1], _extractedUrls: [2], _pageResults: [3] };
28
+ const out = stripTransient(input);
29
+ assert.strictEqual(out._discoveredLinks, undefined);
30
+ assert.strictEqual(out._extractedUrls, undefined);
31
+ assert.strictEqual(out._pageResults, undefined);
32
+ // input untouched
33
+ assert.deepStrictEqual(input._discoveredLinks, [1]);
34
+ });
35
+ test('normalizeExtraction canonicalizes loose unions for diffing', () => {
36
+ const out = normalizeExtraction({ ...base, _pageResults: [9] });
37
+ assert.strictEqual(out.typography.styles[0].weight, 700); // string -> number
38
+ assert.strictEqual(out.spacing.commonValues[0].px, 16); // "16px" -> 16
39
+ assert.strictEqual(out.spacing.commonValues[1].px, 24); // already number
40
+ assert.strictEqual(out.spacing.commonValues[0].display, '16px'); // display backfilled
41
+ assert.strictEqual(out.spacing.commonValues[1].display, '24px'); // backfilled from number
42
+ assert.deepStrictEqual(out.typography.sources.adobeFonts, []); // false -> []
43
+ assert.ok(Array.isArray(out.components.inputs)); // object -> array
44
+ assert.ok(Array.isArray(out.components.badges));
45
+ assert.strictEqual(out._pageResults, undefined); // also stripped
46
+ });
47
+ //# sourceMappingURL=normalize.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.test.js","sourceRoot":"","sources":["../../test/normalize.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,45 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { activeFlags, pathSummary } from '../lib/run-summary.js';
4
+ /**
5
+ * The closing-summary "what shaped this run" lines (DEM-99): which flags were
6
+ * active and which paths were merged. Pinned here so the summary stays honest
7
+ * as flags are added.
8
+ */
9
+ test('activeFlags: no flags -> empty (no line printed)', () => {
10
+ assert.deepEqual(activeFlags({}), []);
11
+ assert.deepEqual(activeFlags(), []);
12
+ });
13
+ test('activeFlags: behaviour-only flags are surfaced (they write no file)', () => {
14
+ assert.deepEqual(activeFlags({ darkMode: true, wcag: true, mobile: true, slow: true, stealth: true }), ['--dark-mode', '--mobile', '--slow', '--stealth', '--wcag']);
15
+ });
16
+ test('activeFlags: artifact flags included alongside behaviour flags', () => {
17
+ assert.deepEqual(activeFlags({ dtcg: true, saveOutput: true, html: '/tmp/r.html', compare: 'base.json', brandGuide: true, designMd: true, screenshot: '/tmp/s.png' }), ['--dtcg', '--save-output', '--html', '--compare', '--brand-guide', '--design-md', '--screenshot']);
18
+ });
19
+ test('activeFlags: --html present with no value (true) still counts', () => {
20
+ assert.deepEqual(activeFlags({ html: true }), ['--html']);
21
+ });
22
+ test('activeFlags: --crawl renders its count, bare flag has none', () => {
23
+ assert.deepEqual(activeFlags({ crawl: 5 }), ['--crawl 5']);
24
+ assert.deepEqual(activeFlags({ crawl: true }), ['--crawl']);
25
+ assert.deepEqual(activeFlags({ crawl: null }), []);
26
+ assert.deepEqual(activeFlags({ crawl: false }), []);
27
+ });
28
+ test('activeFlags: --browser only when non-default; --no-sandbox only when false', () => {
29
+ assert.deepEqual(activeFlags({ browser: 'chromium' }), []);
30
+ assert.deepEqual(activeFlags({ browser: 'firefox' }), ['--browser firefox']);
31
+ assert.deepEqual(activeFlags({ sandbox: false }), ['--no-sandbox']);
32
+ assert.deepEqual(activeFlags({ sandbox: true }), []);
33
+ });
34
+ test('pathSummary: explicit paths are listed (they are positional, not flags)', () => {
35
+ assert.deepEqual(pathSummary(['/recipes', '/pricing'], 3), ['/recipes', '/pricing', '(3 pages merged)']);
36
+ });
37
+ test('pathSummary: crawl/sitemap have no explicit paths, just the merged count', () => {
38
+ assert.deepEqual(pathSummary([], 2), ['(2 pages merged)']);
39
+ assert.deepEqual(pathSummary(undefined, 4), ['(4 pages merged)']);
40
+ });
41
+ test('pathSummary: single page -> nothing (no merge happened)', () => {
42
+ assert.deepEqual(pathSummary(undefined, 1), []);
43
+ assert.deepEqual(pathSummary([], 0), []);
44
+ });
45
+ //# sourceMappingURL=run-summary.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-summary.test.js","sourceRoot":"","sources":["../../test/run-summary.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Locks the output version contract: the three independent version axes and the
3
+ * DTCG $extensions key shape that consumers (dembrandt-next, MCP, skills, drift)
4
+ * depend on.
5
+ */
6
+ import { test } from 'node:test';
7
+ import assert from 'node:assert/strict';
8
+ import { buildDembrandtProvenance, checkSchemaCompatibility, formatCompatibilityNotice, SCHEMA_VERSION, EXTENSION_KEY, DTCG_SPEC_VERSION, } from '../lib/version.js';
9
+ test('buildDembrandtProvenance carries the three version axes', () => {
10
+ const ext = buildDembrandtProvenance({
11
+ url: 'https://www.acme.com/pricing',
12
+ extractedAt: '2026-01-01T00:00:00.000Z',
13
+ meta: { dembrandtVersion: '9.9.9' },
14
+ });
15
+ assert.strictEqual(ext.schemaVersion, SCHEMA_VERSION);
16
+ assert.strictEqual(ext.toolVersion, '9.9.9');
17
+ assert.strictEqual(ext.specVersion, DTCG_SPEC_VERSION);
18
+ assert.strictEqual(ext.generator, 'dembrandt');
19
+ assert.strictEqual(ext.source.domain, 'acme.com');
20
+ assert.strictEqual(ext.source.url, 'https://www.acme.com/pricing');
21
+ });
22
+ test('EXTENSION_KEY is reverse-domain; SCHEMA_VERSION is semver', () => {
23
+ assert.strictEqual(EXTENSION_KEY, 'com.dembrandt');
24
+ assert.match(SCHEMA_VERSION, /^\d+\.\d+\.\d+$/);
25
+ });
26
+ test('missing tool version degrades to null and domain to "unknown", never throws', () => {
27
+ const ext = buildDembrandtProvenance({});
28
+ assert.strictEqual(ext.toolVersion, null);
29
+ assert.strictEqual(ext.source.domain, 'unknown');
30
+ assert.strictEqual(ext.source.url, null);
31
+ });
32
+ test('compatibility compares the schema contract, not the churning tool version', () => {
33
+ // The exact bug behind "unknown vs v0.14.0": a refactor-only release bumps the
34
+ // tool version but leaves the contract alone. Must read as fully compatible.
35
+ const current = checkSchemaCompatibility({
36
+ meta: { schemaVersion: SCHEMA_VERSION, dembrandtVersion: '99.0.0' },
37
+ });
38
+ assert.strictEqual(current.status, 'current');
39
+ assert.strictEqual(current.compatible, true);
40
+ assert.strictEqual(formatCompatibilityNotice(current), null);
41
+ // Same major, additive minor/patch drift either direction stays compatible.
42
+ const minorDrift = checkSchemaCompatibility({ meta: { schemaVersion: '1.4.2' } });
43
+ assert.strictEqual(minorDrift.status, 'compatible');
44
+ assert.strictEqual(minorDrift.compatible, true);
45
+ assert.strictEqual(formatCompatibilityNotice(minorDrift), null);
46
+ });
47
+ test('compatibility flags breaking major drift in both directions', () => {
48
+ const outdated = checkSchemaCompatibility({ meta: { schemaVersion: '0.9.0' } });
49
+ assert.strictEqual(outdated.status, 'outdated');
50
+ assert.strictEqual(outdated.compatible, false);
51
+ assert.match(formatCompatibilityNotice(outdated), /Re-extract recommended/);
52
+ const ahead = checkSchemaCompatibility({ meta: { schemaVersion: '2.0.0' } });
53
+ assert.strictEqual(ahead.status, 'ahead');
54
+ assert.strictEqual(ahead.compatible, false);
55
+ assert.match(formatCompatibilityNotice(ahead), /Upgrade dembrandt/);
56
+ });
57
+ test('compatibility degrades legacy and unknown extractions without throwing', () => {
58
+ // Pre-1.0 tallenne: has a tool version, no schemaVersion. This is the case the
59
+ // old viewer mislabelled "unknown vs v0.14.0".
60
+ const legacy = checkSchemaCompatibility({ meta: { dembrandtVersion: '0.14.0' } });
61
+ assert.strictEqual(legacy.status, 'legacy');
62
+ assert.strictEqual(legacy.compatible, false);
63
+ assert.strictEqual(legacy.found, null);
64
+ assert.match(legacy.message, /v0\.14\.0/);
65
+ const unknown = checkSchemaCompatibility({});
66
+ assert.strictEqual(unknown.status, 'unknown');
67
+ assert.strictEqual(unknown.compatible, false);
68
+ assert.strictEqual(unknown.toolVersion, null);
69
+ // Malformed version string must not throw; falls back to unknown/legacy.
70
+ const garbage = checkSchemaCompatibility({ meta: { schemaVersion: 'not-a-version' } });
71
+ assert.strictEqual(garbage.compatible, false);
72
+ });
73
+ //# sourceMappingURL=version.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.test.js","sourceRoot":"","sources":["../../test/version.test.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,106 @@
1
+ {
2
+ "name": "@mseep/dembrandt",
3
+ "version": "0.19.5",
4
+ "description": "Extract design tokens and publicly visible CSS information from any website",
5
+ "mcpName": "io.github.dembrandt/dembrandt",
6
+ "main": "dist/index.js",
7
+ "type": "module",
8
+ "bin": {
9
+ "dembrandt": "dist/index.js",
10
+ "dembrandt-mcp": "dist/mcp-server.js"
11
+ },
12
+ "exports": {
13
+ ".": "./dist/index.js",
14
+ "./dtcg": "./dist/lib/dtcg/validate.js",
15
+ "./drift": {
16
+ "types": "./dist/lib/drift.d.ts",
17
+ "default": "./dist/lib/drift.js"
18
+ },
19
+ "./report": {
20
+ "types": "./dist/lib/formatters/html.d.ts",
21
+ "default": "./dist/lib/formatters/html.js"
22
+ },
23
+ "./normalize": "./dist/lib/normalize.js",
24
+ "./types": {
25
+ "types": "./dist/lib/types.d.ts",
26
+ "default": "./dist/lib/types.js"
27
+ }
28
+ },
29
+ "files": [
30
+ "dist/"
31
+ ],
32
+ "scripts": {
33
+ "start": "node dist/index.js",
34
+ "prepublishOnly": "npm run build",
35
+ "test": "npm run build && node --test dist/test/*.test.js",
36
+ "install-browser": "node tools/install-browser.mjs",
37
+ "qa:baseline": "npm run build && node test/qa.mjs --baseline",
38
+ "qa:diff": "npm run build && node test/qa.mjs --diff",
39
+ "qa:site": "npm run build && node test/qa.mjs --site",
40
+ "gold:label": "npm run build && node tools/gold-label.mjs",
41
+ "gold:run": "npm run build && node tools/gold-run.mjs",
42
+ "gold:judge": "npm run build && node tools/gold-ai-judge.mjs",
43
+ "gold:tune": "node tools/gold-tune.mjs",
44
+ "gold:cluster": "node tools/gold-cluster.mjs",
45
+ "gold:analyze": "node tools/gold-analyze.mjs",
46
+ "build": "tsc && cp package.json dist/package.json",
47
+ "lint": "eslint ."
48
+ },
49
+ "keywords": [
50
+ "design-tokens",
51
+ "design-system",
52
+ "branding",
53
+ "css-analysis",
54
+ "cli",
55
+ "playwright",
56
+ "mseep",
57
+ "mcp-server"
58
+ ],
59
+ "repository": {
60
+ "type": "git",
61
+ "url": "git+https://github.com/dembrandt/dembrandt.git"
62
+ },
63
+ "bugs": {
64
+ "url": "https://github.com/dembrandt/dembrandt/issues"
65
+ },
66
+ "homepage": "https://dembrandt.com",
67
+ "author": "thevangelist <info@esajuhana.com>",
68
+ "license": "MIT",
69
+ "dependencies": {
70
+ "chalk": "^5.3.0",
71
+ "commander": "^11.1.0",
72
+ "ora": "^7.0.1",
73
+ "playwright-core": "^1.60.0"
74
+ },
75
+ "peerDependencies": {
76
+ "@modelcontextprotocol/sdk": "1.29.0",
77
+ "playwright": "^1.60.0",
78
+ "zod": "4.3.6"
79
+ },
80
+ "peerDependenciesMeta": {
81
+ "@modelcontextprotocol/sdk": {
82
+ "optional": true
83
+ },
84
+ "zod": {
85
+ "optional": true
86
+ },
87
+ "playwright": {
88
+ "optional": true
89
+ }
90
+ },
91
+ "engines": {
92
+ "node": ">=18.0.0"
93
+ },
94
+ "devDependencies": {
95
+ "@eslint/js": "10.0.1",
96
+ "@modelcontextprotocol/sdk": "1.29.0",
97
+ "@types/node": "25.9.2",
98
+ "eslint": "10.4.1",
99
+ "playwright": "^1.57.0",
100
+ "playwright-core": "1.60.0",
101
+ "typescript": "6.0.3",
102
+ "typescript-eslint": "8.60.1",
103
+ "zod": "4.3.6"
104
+ },
105
+ "publisher": "mseep"
106
+ }