@12ui/design 0.2.29 → 0.2.30
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 +31 -6
- package/SKILL.md +1 -1
- package/dist/branch-execution-types.d.ts +2 -0
- package/dist/branch-execution-types.d.ts.map +1 -1
- package/dist/branch-execution.d.ts.map +1 -1
- package/dist/branch-execution.js +3 -0
- package/dist/branch-execution.js.map +1 -1
- package/dist/branch-run-record.d.ts +1 -0
- package/dist/branch-run-record.d.ts.map +1 -1
- package/dist/branch-run-record.js.map +1 -1
- package/dist/cli-arguments.d.ts.map +1 -1
- package/dist/cli-arguments.js +1 -0
- package/dist/cli-arguments.js.map +1 -1
- package/dist/cli-branch-command.d.ts +4 -0
- package/dist/cli-branch-command.d.ts.map +1 -1
- package/dist/cli-branch-command.js +30 -3
- package/dist/cli-branch-command.js.map +1 -1
- package/dist/cli-capabilities.d.ts +9 -0
- package/dist/cli-capabilities.d.ts.map +1 -1
- package/dist/cli-capabilities.js +9 -0
- package/dist/cli-capabilities.js.map +1 -1
- package/dist/cli-help/design.d.ts +8 -1
- package/dist/cli-help/design.d.ts.map +1 -1
- package/dist/cli-help/design.js +12 -0
- package/dist/cli-help/design.js.map +1 -1
- package/dist/cli-help/index.d.ts +8 -1
- package/dist/cli-help/index.d.ts.map +1 -1
- package/dist/cli-prototype-command.d.ts +12 -0
- package/dist/cli-prototype-command.d.ts.map +1 -0
- package/dist/cli-prototype-command.js +29 -0
- package/dist/cli-prototype-command.js.map +1 -0
- package/dist/cli-review-command.d.ts.map +1 -1
- package/dist/cli-review-command.js +20 -1
- package/dist/cli-review-command.js.map +1 -1
- package/dist/cli-run.d.ts.map +1 -1
- package/dist/cli-run.js +8 -0
- package/dist/cli-run.js.map +1 -1
- package/dist/cli-usage.d.ts.map +1 -1
- package/dist/cli-usage.js +6 -1
- package/dist/cli-usage.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/legacy-skill-catalog.d.ts.map +1 -1
- package/dist/legacy-skill-catalog.js +8 -0
- package/dist/legacy-skill-catalog.js.map +1 -1
- package/dist/prototype-gap-html.d.ts +10 -0
- package/dist/prototype-gap-html.d.ts.map +1 -0
- package/dist/prototype-gap-html.js +55 -0
- package/dist/prototype-gap-html.js.map +1 -0
- package/dist/prototype-gap-source.d.ts +14 -0
- package/dist/prototype-gap-source.d.ts.map +1 -0
- package/dist/prototype-gap-source.js +87 -0
- package/dist/prototype-gap-source.js.map +1 -0
- package/dist/prototype-gates.d.ts +24 -0
- package/dist/prototype-gates.d.ts.map +1 -0
- package/dist/prototype-gates.js +76 -0
- package/dist/prototype-gates.js.map +1 -0
- package/dist/prototype-label-client.d.ts +51 -0
- package/dist/prototype-label-client.d.ts.map +1 -0
- package/dist/prototype-label-client.js +53 -0
- package/dist/prototype-label-client.js.map +1 -0
- package/dist/prototype-label-score.d.ts +26 -0
- package/dist/prototype-label-score.d.ts.map +1 -0
- package/dist/prototype-label-score.js +51 -0
- package/dist/prototype-label-score.js.map +1 -0
- package/dist/prototype-process.d.ts +13 -0
- package/dist/prototype-process.d.ts.map +1 -0
- package/dist/prototype-process.js +26 -0
- package/dist/prototype-process.js.map +1 -0
- package/dist/prototype-requests.d.ts +29 -0
- package/dist/prototype-requests.d.ts.map +1 -0
- package/dist/prototype-requests.js +34 -0
- package/dist/prototype-requests.js.map +1 -0
- package/dist/prototype-runner.d.ts +22 -0
- package/dist/prototype-runner.d.ts.map +1 -0
- package/dist/prototype-runner.js +159 -0
- package/dist/prototype-runner.js.map +1 -0
- package/dist/prototype-source.d.ts +9 -0
- package/dist/prototype-source.d.ts.map +1 -0
- package/dist/prototype-source.js +48 -0
- package/dist/prototype-source.js.map +1 -0
- package/dist/review-discovery.d.ts +1 -0
- package/dist/review-discovery.d.ts.map +1 -1
- package/dist/review-discovery.js +49 -3
- package/dist/review-discovery.js.map +1 -1
- package/dist/review-page-assets.d.ts +2 -2
- package/dist/review-page-assets.d.ts.map +1 -1
- package/dist/review-page-assets.js +20 -1
- package/dist/review-page-assets.js.map +1 -1
- package/dist/review-page.d.ts.map +1 -1
- package/dist/review-page.js +38 -0
- package/dist/review-page.js.map +1 -1
- package/dist/review-prototype-gap.d.ts +48 -0
- package/dist/review-prototype-gap.d.ts.map +1 -0
- package/dist/review-prototype-gap.js +192 -0
- package/dist/review-prototype-gap.js.map +1 -0
- package/dist/review-server.d.ts +7 -0
- package/dist/review-server.d.ts.map +1 -1
- package/dist/review-server.js +64 -0
- package/dist/review-server.js.map +1 -1
- package/dist/review-types.d.ts +12 -0
- package/dist/review-types.d.ts.map +1 -1
- package/dist/run-journal-commands.d.ts.map +1 -1
- package/dist/run-journal-commands.js +13 -0
- package/dist/run-journal-commands.js.map +1 -1
- package/open-design.json +2 -2
- package/package.json +7 -1
- package/prototype-kit/analyze.mjs +275 -0
- package/prototype-kit/build.mjs +393 -0
- package/prototype-kit/inventory.mjs +104 -0
- package/prototype-kit/label-briefs.mjs +47 -0
- package/prototype-kit/lib/actions.mjs +15 -0
- package/prototype-kit/lib/navigation.mjs +33 -0
- package/prototype-kit/lib/runtime-check.mjs +126 -0
- package/prototype-kit/lib/shells.mjs +68 -0
- package/prototype-kit/lib/static-server.mjs +40 -0
- package/prototype-kit/lib/text.mjs +20 -0
- package/prototype-kit/runtime/proto.css +46 -0
- package/prototype-kit/runtime/proto.js +173 -0
- package/prototype-kit/score-labels.mjs +42 -0
- package/prototype-kit/tests/README.md +28 -0
- package/prototype-kit/tests/adversarial-runtime.mjs +90 -0
- package/prototype-kit/tests/discover-runs.mjs +29 -0
- package/prototype-kit/tests/fixtures/no-semantic/branch.plan.json +7 -0
- package/prototype-kit/tests/fixtures/no-semantic/pages/legacy.html +1 -0
- package/prototype-kit/tests/fixtures/partial-plan/branch.plan.json +5 -0
- package/prototype-kit/tests/fixtures/partial-plan/pages/orphan.html +4 -0
- package/prototype-kit/tests/fixtures/runtime/double.html +5 -0
- package/prototype-kit/tests/fixtures/runtime/history-destination.html +1 -0
- package/prototype-kit/tests/fixtures/runtime/history.html +6 -0
- package/prototype-kit/tests/fixtures/runtime/hover-stack.html +15 -0
- package/prototype-kit/tests/fixtures/runtime/invalid-dropdown.html +6 -0
- package/prototype-kit/tests/fixtures/runtime/nested.html +7 -0
- package/prototype-kit/tests/fixtures/three-shell/branch.plan.json +30 -0
- package/prototype-kit/tests/fixtures/three-shell/pages/p0-home.html +11 -0
- package/prototype-kit/tests/fixtures/three-shell/pages/p1-reports.html +11 -0
- package/prototype-kit/tests/lib/run-discovery.mjs +87 -0
- package/prototype-kit/tests/lib/run-process.mjs +49 -0
- package/prototype-kit/tests/offline-check.mjs +41 -0
- package/prototype-kit/tests/population-sweep.mjs +94 -0
- package/prototype-kit/tests/rules-check.mjs +50 -0
- package/prototype-kit/verify-runtime.mjs +36 -0
- package/skills/12ui-design/SKILL.md +8 -2
|
@@ -49,6 +49,12 @@ const branchDirectory = async (command, flags) => {
|
|
|
49
49
|
});
|
|
50
50
|
return directory.branchDir;
|
|
51
51
|
};
|
|
52
|
+
const prototypeDirectory = async (command) => {
|
|
53
|
+
const positional = command[1]?.trim();
|
|
54
|
+
if (!positional)
|
|
55
|
+
return undefined;
|
|
56
|
+
return (await resolveBranchDirectory({ runDirArgument: positional })).branchDir;
|
|
57
|
+
};
|
|
52
58
|
const is = (...tokens) => (command) => (tokens.every((token, index) => command[index] === token));
|
|
53
59
|
/**
|
|
54
60
|
* The MCP server's one paid tool, under the name its journal lines carry.
|
|
@@ -143,6 +149,13 @@ export const RUN_JOURNAL_COMMANDS = [
|
|
|
143
149
|
skip: 'An unrecognized branch action, and the retired `branch status`, refuse before they'
|
|
144
150
|
+ ' resolve a directory.',
|
|
145
151
|
},
|
|
152
|
+
{
|
|
153
|
+
cmd: 'prototype',
|
|
154
|
+
matches: is('prototype'),
|
|
155
|
+
paid: true,
|
|
156
|
+
terminalOnSuccess: true,
|
|
157
|
+
workspace: prototypeDirectory,
|
|
158
|
+
},
|
|
146
159
|
{
|
|
147
160
|
// One reader for every run shape, so its journal line is the one that can
|
|
148
161
|
// settle whether the run this workspace holds is over.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-journal-commands.js","sourceRoot":"","sources":["../src/run-journal-commands.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run-journal-commands.js","sourceRoot":"","sources":["../src/run-journal-commands.ts"],"names":[],"mappings":"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"}
|
package/open-design.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"specVersion": "1.0.0",
|
|
4
4
|
"name": "12ui-design",
|
|
5
5
|
"title": "12UI Design",
|
|
6
|
-
"version": "0.2.
|
|
6
|
+
"version": "0.2.30",
|
|
7
7
|
"description": "Explore corpus-grounded interface directions, choose one, and convert it into production-ready responsive or native artifacts with 12UI.",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "Just Every",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"command": "npx",
|
|
50
50
|
"args": [
|
|
51
51
|
"-y",
|
|
52
|
-
"@12ui/design@0.2.
|
|
52
|
+
"@12ui/design@0.2.30",
|
|
53
53
|
"mcp"
|
|
54
54
|
]
|
|
55
55
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@12ui/design",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.30",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The canonical 12ui CLI, SDK, MCP server, and visual interface design skills",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist/**/*",
|
|
13
|
+
"prototype-kit/**/*",
|
|
13
14
|
"skills/**/*",
|
|
14
15
|
"SKILL.md",
|
|
15
16
|
"open-design.json",
|
|
@@ -22,14 +23,19 @@
|
|
|
22
23
|
"start": "node dist/cli.js",
|
|
23
24
|
"test": "vitest",
|
|
24
25
|
"test:run": "vitest run",
|
|
26
|
+
"test:prototype": "node prototype-kit/tests/rules-check.mjs && node prototype-kit/tests/offline-check.mjs && node prototype-kit/tests/adversarial-runtime.mjs --assert",
|
|
25
27
|
"typecheck": "tsc --noEmit && tsc -p tsconfig.type-tests.json",
|
|
26
28
|
"prepublishOnly": "npm run build"
|
|
27
29
|
},
|
|
28
30
|
"dependencies": {
|
|
29
31
|
"@just-every/ensemble": "0.2.274",
|
|
30
32
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
33
|
+
"linkedom": "^0.18.12",
|
|
31
34
|
"sharp": "^0.35.3"
|
|
32
35
|
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"@playwright/test": "1.59.1"
|
|
38
|
+
},
|
|
33
39
|
"devDependencies": {
|
|
34
40
|
"@types/node": "^22.19.17",
|
|
35
41
|
"typescript": "^5.9.3",
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
// Deterministic analysis of an inventory: states, shared shell, nav items, dropdowns, rows, buttons, link-like texts.
|
|
2
|
+
// Usage: node analyze.mjs <inventory.json> <model.json>
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import { matchPlannedPage } from './lib/navigation.mjs';
|
|
5
|
+
import { compareCanonicalShells, isWithinShell, qualifiesShellCandidate, selectOneShellPerRegion } from './lib/shells.mjs';
|
|
6
|
+
import { normalizeText as norm, slugText as slug } from './lib/text.mjs';
|
|
7
|
+
|
|
8
|
+
const [invFile, outFile] = process.argv.slice(2);
|
|
9
|
+
const inv = JSON.parse(fs.readFileSync(invFile, 'utf8'));
|
|
10
|
+
const W = 1536, H = 1024;
|
|
11
|
+
const planScreens = Array.isArray(inv.plan?.screens) ? inv.plan.screens : [];
|
|
12
|
+
const chevronDown = (l) => /\b(down|caret down|chevron down|expand)\b/.test(norm(l)) && /chevron|caret|arrow|down/.test(norm(l));
|
|
13
|
+
const chevronRight = (l) => /right/.test(norm(l)) && /chevron|arrow|caret/.test(norm(l));
|
|
14
|
+
const linkVerb = /^(view|open|see|manage|clear|add|run|export|download|learn|read|sign|get|start|try|book|browse|explore|edit|approve|defer|review|show|load|invite|create|upgrade|contact|subscribe|join|buy|shop|reserve|rsvp|register|continue|back|cancel|save|send|submit|apply|filter|sort|search|show)\b/;
|
|
15
|
+
|
|
16
|
+
// ---- states
|
|
17
|
+
const states = [];
|
|
18
|
+
for (const p of inv.pages) {
|
|
19
|
+
p.sections.forEach((s, i) => {
|
|
20
|
+
const slotMatch = s.sectionId.match(/^viewport-(\d+)-(\w+)$/);
|
|
21
|
+
const slot = slotMatch ? slotMatch[2] : String(i);
|
|
22
|
+
const screen = planScreens.find((x) => x.slot === slot);
|
|
23
|
+
const ordinal = i + 1;
|
|
24
|
+
const base = p.pageId.replace(/^p\d+-/, '');
|
|
25
|
+
states.push({
|
|
26
|
+
stateId: ordinal === 1 ? base : `${base}-${ordinal}`,
|
|
27
|
+
pageId: p.pageId,
|
|
28
|
+
pageIndex: p.planPage?.index ?? null,
|
|
29
|
+
file: p.file,
|
|
30
|
+
sectionId: s.sectionId,
|
|
31
|
+
slot,
|
|
32
|
+
ordinal,
|
|
33
|
+
title: p.planPage?.title || base.replace(/-/g, ' ').replace(/\b\p{L}/gu, (letter) => letter.toUpperCase()),
|
|
34
|
+
purpose: p.planPage?.purpose || '',
|
|
35
|
+
surfaceType: p.planPage?.surfaceType || '',
|
|
36
|
+
direction: screen?.direction || '',
|
|
37
|
+
content: screen?.content || '',
|
|
38
|
+
dependsOnSlot: screen?.dependsOnSlot || null,
|
|
39
|
+
isSource: !!p.planPage?.startsFromWinner && ordinal === 1,
|
|
40
|
+
items: s.items,
|
|
41
|
+
containers: s.containers,
|
|
42
|
+
height: s.height,
|
|
43
|
+
scriptDirection: s.scriptDirection,
|
|
44
|
+
writingMode: s.writingMode,
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (!states.length) throw new Error('Prototype input error: no semantic viewport sections found; exports require section ids shaped like viewport-<ordinal>-<slot>');
|
|
49
|
+
const byId = Object.fromEntries(states.map((s) => [s.stateId, s]));
|
|
50
|
+
const slotToState = Object.fromEntries(states.map((s) => [s.slot, s.stateId]));
|
|
51
|
+
|
|
52
|
+
// ---- shell: elements repeated (same text/label, bbox within tol) across >= 60% of states
|
|
53
|
+
const key = (it) => (it.text ? 't:' + norm(it.text) : it.label ? 'l:' + norm(it.label) : null);
|
|
54
|
+
const TOL = 40;
|
|
55
|
+
const minStates = Math.max(2, Math.ceil(states.length * 0.4));
|
|
56
|
+
function repeatedKeys() {
|
|
57
|
+
const map = new Map();
|
|
58
|
+
for (const s of states) {
|
|
59
|
+
const seen = new Set();
|
|
60
|
+
for (const it of s.items) {
|
|
61
|
+
const k = key(it); if (!k || seen.has(k)) continue;
|
|
62
|
+
seen.add(k);
|
|
63
|
+
(map.get(k) || map.set(k, []).get(k)).push({ state: s.stateId, x: it.x, y: it.y, yb: s.height - it.y, w: it.w, h: it.h, id: it.id });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const rep = new Map();
|
|
67
|
+
for (const [k, occ] of map) {
|
|
68
|
+
if (occ.length < minStates) continue;
|
|
69
|
+
// cluster by position: count occurrences within TOL of the median
|
|
70
|
+
const mx = median(occ.map((o) => o.x)), my = median(occ.map((o) => o.y)), myb = median(occ.map((o) => o.yb));
|
|
71
|
+
const near = occ.filter((o) => Math.abs(o.x - mx) <= TOL && (Math.abs(o.y - my) <= TOL || Math.abs(o.yb - myb) <= TOL));
|
|
72
|
+
if (near.length >= minStates) rep.set(k, { x: mx, y: my, occ: near });
|
|
73
|
+
}
|
|
74
|
+
return rep;
|
|
75
|
+
}
|
|
76
|
+
function median(a) { const b = [...a].sort((x, y) => x - y); return b[Math.floor(b.length / 2)]; }
|
|
77
|
+
const repeated = repeatedKeys();
|
|
78
|
+
|
|
79
|
+
// top-level containers per state and their shell share
|
|
80
|
+
function topContainers(s) {
|
|
81
|
+
const pre = s.sectionId + '-';
|
|
82
|
+
return s.containers.filter((c) => c.id.startsWith(pre) && !c.id.slice(pre.length).includes('-') && c.children > 0);
|
|
83
|
+
}
|
|
84
|
+
function regionOf(c) {
|
|
85
|
+
if (c.w <= 0.3 * W && c.h >= 0.7 * H && c.x <= 0.05 * W) return 'sidebar';
|
|
86
|
+
if (c.w >= 0.15 * W && c.h <= 0.2 * H && c.y <= 0.08 * H) return 'header';
|
|
87
|
+
if (c.w >= 0.6 * W && c.h <= 0.45 * H && c.y + c.h >= 0.9 * H) return 'footer';
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const rejectedShellsByState = new Map();
|
|
91
|
+
for (const s of states) {
|
|
92
|
+
s.shell = [];
|
|
93
|
+
const rejected = [];
|
|
94
|
+
for (const c of topContainers(s)) {
|
|
95
|
+
const inside = s.items.filter((it) => it.chain.includes(c.id) || it.id === c.id);
|
|
96
|
+
if (inside.length < 2) continue;
|
|
97
|
+
const shellCount = inside.filter((it) => { const k = key(it); return k && repeated.has(k) && repeated.get(k).occ.some((o) => o.state === s.stateId); }).length;
|
|
98
|
+
const share = shellCount / inside.length;
|
|
99
|
+
const region = regionOf(c);
|
|
100
|
+
const semantic = ['aside', 'header', 'footer', 'nav'].includes(c.tag) || /-(sidebar|nav|navbar|header|footer|topbar|sidenav)$/.test(c.id);
|
|
101
|
+
const shell = { containerId: c.id, region, share: +share.toFixed(2), semantic, items: inside.length, box: [c.x, c.y, c.w, c.h] };
|
|
102
|
+
const hasShellEvidence = region && (share >= 0.5 || (semantic && region === 'sidebar' && inside.length >= 3));
|
|
103
|
+
if (!hasShellEvidence) continue;
|
|
104
|
+
if (qualifiesShellCandidate(shell, W)) s.shell.push(shell);
|
|
105
|
+
else rejected.push(shell);
|
|
106
|
+
}
|
|
107
|
+
rejectedShellsByState.set(s.stateId, rejected);
|
|
108
|
+
}
|
|
109
|
+
const shellAmbiguities = [];
|
|
110
|
+
for (const state of states) {
|
|
111
|
+
const { selected, dropped } = selectOneShellPerRegion(state.shell);
|
|
112
|
+
state.shell = selected;
|
|
113
|
+
for (const shell of [...dropped, ...(rejectedShellsByState.get(state.stateId) || [])]) {
|
|
114
|
+
const kept = selected.find((candidate) => candidate.region === shell.region);
|
|
115
|
+
if (!kept) continue;
|
|
116
|
+
shellAmbiguities.push({
|
|
117
|
+
state: state.stateId,
|
|
118
|
+
region: shell.region,
|
|
119
|
+
dropped: shell.containerId,
|
|
120
|
+
droppedBox: shell.box,
|
|
121
|
+
kept: kept?.containerId || null,
|
|
122
|
+
keptBox: kept?.box || null,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// canonical shell per region: prefer the source state, else the state whose container has the highest share*items
|
|
127
|
+
let regions = [...new Set(states.flatMap((s) => s.shell.map((x) => x.region)))];
|
|
128
|
+
const canonical = {};
|
|
129
|
+
// how many short texts inside a container match a planned page title (used to rank competing shells)
|
|
130
|
+
function pageMatches(s, cid) {
|
|
131
|
+
return s.items.filter((it) => it.text && it.text.length <= 32 && it.chain.includes(cid)).map((it) => matchPage(it.text)).filter(Boolean).length;
|
|
132
|
+
}
|
|
133
|
+
for (const r of regions) {
|
|
134
|
+
const cands = states.flatMap((s) => s.shell.filter((x) => x.region === r).map((x) => ({ ...x, stateId: s.stateId, isSource: s.isSource, matches: pageMatches(s, x.containerId) })));
|
|
135
|
+
if (cands.length < 2) { for (const s of states) s.shell = s.shell.filter((x) => x.region !== r); continue; }
|
|
136
|
+
cands.sort(compareCanonicalShells);
|
|
137
|
+
canonical[r] = { stateId: cands[0].stateId, containerId: cands[0].containerId, box: cands[0].box, presentIn: cands.map((c) => c.stateId), ranking: cands.map((c) => `${c.stateId}:${c.matches}m/${c.items}i/${c.share}`) };
|
|
138
|
+
}
|
|
139
|
+
regions = Object.keys(canonical);
|
|
140
|
+
|
|
141
|
+
// ---- nav items: texts inside a canonical shell container that repeat, font >= 12, excluding long copy
|
|
142
|
+
const nav = [];
|
|
143
|
+
for (const r of regions) {
|
|
144
|
+
const can = canonical[r]; const s = byId[can.stateId];
|
|
145
|
+
const texts = s.items.filter((it) => it.text && it.chain.includes(can.containerId) && it.fontSize >= 12 && it.text.length <= 32 && !it.inButton && !/\d/.test(it.text));
|
|
146
|
+
// a nav list = >= 3 texts sharing the same x (vertical list) or same y (horizontal list)
|
|
147
|
+
const groups = new Map();
|
|
148
|
+
for (const t of texts) {
|
|
149
|
+
const gx = 'x' + Math.round(t.x / 6), gy = 'y' + Math.round(t.y / 6);
|
|
150
|
+
(groups.get(gx) || groups.set(gx, []).get(gx)).push(t);
|
|
151
|
+
(groups.get(gy) || groups.set(gy, []).get(gy)).push(t);
|
|
152
|
+
}
|
|
153
|
+
const best = [...groups.values()].sort((a, b) => b.length - a.length)[0] || [];
|
|
154
|
+
if (best.length >= 3) for (const t of best) nav.push({ region: r, id: t.id, text: t.text, x: t.x, y: t.y, w: t.w, h: t.h, fontSize: t.fontSize, color: t.color, fontWeight: t.fontWeight });
|
|
155
|
+
}
|
|
156
|
+
// match nav text -> page (first state of that page) by token overlap with title / pageId
|
|
157
|
+
function matchPage(text) {
|
|
158
|
+
return matchPlannedPage(text, states.filter((state) => state.ordinal === 1))?.stateId || null;
|
|
159
|
+
}
|
|
160
|
+
for (const n of nav) { n.target = matchPage(n.text); }
|
|
161
|
+
{ const first = nav.find((n) => n.region !== 'footer'); const home = states.find((s) => s.isSource) || states[0];
|
|
162
|
+
if (first && !first.target && /^(home|overview|dashboard|start)$/.test(norm(first.text))) { first.target = home.stateId; first.fallback = 'home'; } }
|
|
163
|
+
for (const n of nav) n.holding = n.target ? null : 'holding-' + slug(n.text);
|
|
164
|
+
|
|
165
|
+
// ---- per-state interactive candidates
|
|
166
|
+
function smallestCommon(s, ids) {
|
|
167
|
+
const chains = ids.map((id) => { const it = s.items.find((x) => x.id === id); return it ? [it.id, ...it.chain] : []; });
|
|
168
|
+
for (const c of chains[0]) if (chains.every((ch) => ch.includes(c))) return c;
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
function containerItems(s, cid) { return s.items.filter((it) => it.id === cid || it.chain.includes(cid)); }
|
|
172
|
+
for (const s of states) {
|
|
173
|
+
const shellIds = new Set(s.shell.map((x) => x.containerId));
|
|
174
|
+
const inShell = (it) => it.chain.some((c) => shellIds.has(c));
|
|
175
|
+
const cands = [];
|
|
176
|
+
// buttons
|
|
177
|
+
const btnMap = new Map();
|
|
178
|
+
for (const it of s.items) if (it.inButton && it.text) btnMap.set(it.buttonId, ((btnMap.get(it.buttonId) || '') + ' ' + it.text).trim());
|
|
179
|
+
for (const [bid, text] of btnMap) {
|
|
180
|
+
const c = s.containers.find((x) => x.id === bid);
|
|
181
|
+
cands.push({ id: bid, kind: 'button', text, box: c ? [c.x, c.y, c.w, c.h] : null, inShell: !!c && [...shellIds].some((sh) => s.items.find((it) => it.buttonId === bid)?.chain.includes(sh)) });
|
|
182
|
+
}
|
|
183
|
+
// dropdown triggers: a down-chevron icon whose smallest container with a text sibling
|
|
184
|
+
for (const ic of s.items.filter((it) => (it.cls.includes('icon') || it.tag === 'img') && chevronDown(it.label))) {
|
|
185
|
+
// find nearest text to the left on the same line
|
|
186
|
+
// prefer an enclosing input/select-like container; else the nearest text to the left on the same line
|
|
187
|
+
const fieldCid = ic.chain.find((cid) => /(input|select|filter|sort|dropdown|picker|menu)(-|$)/.test(cid) && (s.containers.find((x) => x.id === cid)?.w || 0) <= 420);
|
|
188
|
+
let near = fieldCid ? containerItems(s, fieldCid).filter((t) => t.text).sort((a, b) => a.x - b.x)[0] : null;
|
|
189
|
+
if (!near) near = s.items.filter((t) => t.text && Math.abs((t.y + t.h / 2) - (ic.y + ic.h / 2)) <= Math.max(8, t.h) && t.x + t.w <= ic.x + 4 && ic.x - (t.x + t.w) <= 260).sort((a, b) => (ic.x - (a.x + a.w)) - (ic.x - (b.x + b.w)))[0];
|
|
190
|
+
if (!near) continue;
|
|
191
|
+
const cid = fieldCid || smallestCommon(s, [ic.id, near.id]);
|
|
192
|
+
const c = s.containers.find((x) => x.id === cid);
|
|
193
|
+
if (cands.some((x) => x.id === (cid || near.id))) { const ex = cands.find((x) => x.id === (cid || near.id)); ex.kind = 'dropdown'; ex.textId = near.id; continue; }
|
|
194
|
+
cands.push({ id: cid || near.id, kind: 'dropdown', text: near.text, textId: near.id, iconId: ic.id, box: c ? [c.x, c.y, c.w, c.h] : [near.x, near.y, ic.x + ic.w - near.x, Math.max(near.h, ic.h)], inShell: inShell(near) });
|
|
195
|
+
}
|
|
196
|
+
// rows: right-chevron icon -> its row container (smallest container wider than 200px holding the icon and >=1 text)
|
|
197
|
+
for (const ic of s.items.filter((it) => (it.cls.includes('icon') || it.tag === 'img') && chevronRight(it.label))) {
|
|
198
|
+
// the full row = the widest ancestor that is still row-shaped (<= 140px tall)
|
|
199
|
+
let row = null;
|
|
200
|
+
for (const cid of ic.chain) { const c = s.containers.find((x) => x.id === cid); if (c && c.h <= 140 && c.w >= 200 && containerItems(s, cid).some((t) => t.text) && (!row || c.w * c.h >= row.w * row.h)) row = c; }
|
|
201
|
+
if (!row || shellIds.has(row.id) || isWithinShell(ic.chain, shellIds)) continue;
|
|
202
|
+
if (cands.some((x) => x.id === row.id)) continue;
|
|
203
|
+
const texts = containerItems(s, row.id).filter((t) => t.text).sort((a, b) => b.fontSize - a.fontSize);
|
|
204
|
+
cands.push({ id: row.id, kind: 'row', text: texts.slice(0, 2).map((t) => t.text).join(' — '), box: [row.x, row.y, row.w, row.h], inShell: false });
|
|
205
|
+
}
|
|
206
|
+
// link-like texts
|
|
207
|
+
for (const t of s.items) {
|
|
208
|
+
if (!t.text || t.inButton || t.text.length > 40) continue;
|
|
209
|
+
if (cands.some((c) => c.id === t.id || c.textId === t.id)) continue;
|
|
210
|
+
const isNav = inShell(t) && nav.some((n) => norm(n.text) === norm(t.text));
|
|
211
|
+
if (isNav) { cands.push({ id: t.id, kind: 'nav', text: t.text, box: [t.x, t.y, t.w, t.h], inShell: true }); continue; }
|
|
212
|
+
if (linkVerb.test(norm(t.text)) && t.text.split(' ').length <= 5) cands.push({ id: t.id, kind: 'link', text: t.text, box: [t.x, t.y, t.w, t.h], inShell: inShell(t) });
|
|
213
|
+
}
|
|
214
|
+
// card titles: prominent texts inside a sizeable card container (not the page title, not chrome)
|
|
215
|
+
const pageTitleY = Math.min(...s.items.filter((t) => t.text && t.fontSize >= 24 && !inShell(t)).map((t) => t.y), 1e9);
|
|
216
|
+
for (const t of s.items) {
|
|
217
|
+
if (!t.text || t.inButton || inShell(t) || t.fontSize < 17 || t.text.length > 48 || t.y <= pageTitleY + 4) continue;
|
|
218
|
+
if (cands.some((c) => c.id === t.id || c.textId === t.id || t.chain.includes(c.id))) continue;
|
|
219
|
+
const card = t.chain.map((cid) => s.containers.find((x) => x.id === cid)).find((c) => c && c.w >= 240 && c.h >= 80 && c.h <= 600 && c.bg && c.bg !== 'rgba(0, 0, 0, 0)');
|
|
220
|
+
if (!card) continue;
|
|
221
|
+
cands.push({ id: card.id, kind: 'card', text: t.text, textId: t.id, box: [card.x, card.y, card.w, card.h], inShell: false });
|
|
222
|
+
}
|
|
223
|
+
// search / bell / avatar icons in header: utility
|
|
224
|
+
for (const ic of s.items.filter((it) => (it.cls.includes('icon') || it.tag === 'img') && /search|magnif|bell|notification|avatar|profile|menu|hamburger|user/.test(norm(it.label)) && !it.inButton)) {
|
|
225
|
+
if (cands.some((c) => c.id === ic.id)) continue;
|
|
226
|
+
cands.push({ id: ic.id, kind: 'utility', text: ic.label, box: [ic.x, ic.y, ic.w, ic.h], inShell: inShell(ic) });
|
|
227
|
+
}
|
|
228
|
+
s.candidates = cands;
|
|
229
|
+
// form fields: containers whose id mentions input/field/composer/search and have a text child (placeholder)
|
|
230
|
+
s.fields = s.containers.filter((c) => /(input|field|composer|search|textarea|prompt)(-|$)/.test(c.id) && c.w >= 120 && c.h >= 28 && c.h <= 160 && !cands.some((x) => x.id === c.id)).map((c) => {
|
|
231
|
+
const texts = containerItems(s, c.id).filter((t) => t.text);
|
|
232
|
+
return { id: c.id, placeholder: texts[0]?.text || '', box: [c.x, c.y, c.w, c.h] };
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// ---- style tokens from the source (or first) state
|
|
237
|
+
const src = states.find((s) => s.isSource) || states[0];
|
|
238
|
+
function mode(arr) { const m = new Map(); for (const a of arr) if (a) m.set(a, (m.get(a) || 0) + 1); return [...m.entries()].sort((a, b) => b[1] - a[1])[0]?.[0]; }
|
|
239
|
+
const bodyTexts = src.items.filter((t) => t.text && t.fontSize >= 12 && t.fontSize <= 16);
|
|
240
|
+
const heading = src.items.filter((t) => t.text).sort((a, b) => b.fontSize - a.fontSize)[0];
|
|
241
|
+
const btnBgs = states.flatMap((s) => s.containers.filter((c) => c.tag === 'button' && c.bg && c.bg !== 'rgba(0, 0, 0, 0)').map((c) => c.bg));
|
|
242
|
+
const accentText = mode(src.items.filter((t) => t.text && t.fontWeight >= 500 && !/rgb\((\d+), \1, \1\)/.test(t.color) && t.color !== 'rgb(0, 0, 0)').map((t) => t.color));
|
|
243
|
+
const tokens = {
|
|
244
|
+
bodyFont: mode(bodyTexts.map((t) => t.fontFamily)),
|
|
245
|
+
bodySize: mode(bodyTexts.map((t) => Math.round(t.fontSize))),
|
|
246
|
+
bodyColor: mode(bodyTexts.map((t) => t.color)),
|
|
247
|
+
mutedColor: mode(src.items.filter((t) => t.text && t.fontSize < 13).map((t) => t.color)),
|
|
248
|
+
headingFont: heading?.fontFamily, headingSize: heading?.fontSize, headingColor: heading?.color, headingWeight: heading?.fontWeight,
|
|
249
|
+
accent: accentText,
|
|
250
|
+
buttonBg: mode(btnBgs),
|
|
251
|
+
cardRadius: mode(src.containers.filter((c) => c.w > 200 && c.h > 80 && c.radius !== '0px').map((c) => c.radius)),
|
|
252
|
+
cardBorder: mode(src.containers.filter((c) => c.w > 200 && c.h > 80 && !c.border.startsWith('0px')).map((c) => c.border)),
|
|
253
|
+
pageBg: src.containers.find((c) => c.x === 0 && c.y === 0 && c.w >= W - 1 && c.h >= H - 1)?.bg,
|
|
254
|
+
surfaceBg: mode(src.containers.filter((c) => c.w > 300 && c.h > 100 && c.bg !== 'rgba(0, 0, 0, 0)').map((c) => c.bg)),
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const model = {
|
|
258
|
+
run: inv.runDir,
|
|
259
|
+
plan: { concept: typeof inv.plan?.concept === 'string' ? inv.plan.concept : '', sitePurpose: typeof inv.plan?.sitePurpose === 'string' ? inv.plan.sitePurpose : '', scope: inv.plan?.scope || null },
|
|
260
|
+
tokens,
|
|
261
|
+
canonicalShell: canonical,
|
|
262
|
+
shellAmbiguities,
|
|
263
|
+
nav,
|
|
264
|
+
states: states.map((s) => ({
|
|
265
|
+
stateId: s.stateId, pageId: s.pageId, file: s.file, sectionId: s.sectionId, slot: s.slot, ordinal: s.ordinal, title: s.title, purpose: s.purpose,
|
|
266
|
+
surfaceType: s.surfaceType, direction: s.direction, content: s.content, dependsOn: s.dependsOnSlot ? slotToState[s.dependsOnSlot] : null, isSource: s.isSource,
|
|
267
|
+
shell: s.shell, candidates: s.candidates, fields: s.fields, scriptDirection: s.scriptDirection, writingMode: s.writingMode,
|
|
268
|
+
texts: s.items.filter((t) => t.text).map((t) => ({ id: t.id, text: t.text })).length,
|
|
269
|
+
})),
|
|
270
|
+
};
|
|
271
|
+
fs.writeFileSync(outFile, JSON.stringify(model, null, 1));
|
|
272
|
+
// summary
|
|
273
|
+
console.error(`states: ${states.length}; shell regions: ${regions.join(',') || 'none'}; nav items: ${nav.length} (${nav.filter((n) => n.target).length} matched to pages)`);
|
|
274
|
+
for (const s of model.states) console.error(` ${s.stateId.padEnd(28)} shell=${s.shell.map((x) => x.region).join('+') || '-'} cands=${s.candidates.length} [${['button', 'dropdown', 'row', 'link', 'nav', 'utility', 'card'].map((k) => k[0] + s.candidates.filter((c) => c.kind === k).length).join(' ')}] fields=${s.fields.length}`);
|
|
275
|
+
console.error('tokens', JSON.stringify(tokens));
|