@pro-vi/designer 0.3.1 → 0.3.3
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/dist/cli.js +7 -4
- package/dist/designer-controller.js +12 -6
- package/dist/setup.js +2 -6
- package/dist/ui-anchors.js +39 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -488,14 +488,17 @@ async function runDoctor() {
|
|
|
488
488
|
return out;
|
|
489
489
|
}
|
|
490
490
|
function checkDeps() {
|
|
491
|
+
const rootLock = path.join(REPO_ROOT, 'package-lock.json');
|
|
492
|
+
if (!fs.existsSync(rootLock)) {
|
|
493
|
+
return { name: 'dependencies installed', status: 'ok', detail: 'installed-mode' };
|
|
494
|
+
}
|
|
491
495
|
const nm = path.join(REPO_ROOT, 'node_modules');
|
|
492
496
|
if (!fs.existsSync(nm)) {
|
|
493
|
-
return { name: 'dependencies installed', status: 'fail', detail: 'node_modules missing — run `
|
|
497
|
+
return { name: 'dependencies installed', status: 'fail', detail: 'node_modules missing — run `npm install`' };
|
|
494
498
|
}
|
|
495
|
-
const rootLock = path.join(REPO_ROOT, 'package-lock.json');
|
|
496
499
|
const innerLock = path.join(nm, '.package-lock.json');
|
|
497
|
-
if (!fs.existsSync(
|
|
498
|
-
return { name: 'dependencies installed', status: 'ok', detail: 'node_modules present (no lockfile
|
|
500
|
+
if (!fs.existsSync(innerLock)) {
|
|
501
|
+
return { name: 'dependencies installed', status: 'ok', detail: 'node_modules present (no inner lockfile)' };
|
|
499
502
|
}
|
|
500
503
|
const h = (p) => createHash('sha1').update(fs.readFileSync(p)).digest('hex');
|
|
501
504
|
if (h(rootLock) !== h(innerLock)) {
|
|
@@ -329,17 +329,23 @@ export class DesignerController {
|
|
|
329
329
|
})()`).catch(() => null);
|
|
330
330
|
await new Promise((r) => setTimeout(r, 600));
|
|
331
331
|
const result = await this.browser.evalValue(`(() => {
|
|
332
|
-
|
|
332
|
+
// Walk all text nodes — Claude's file panel wraps filenames in styled-
|
|
333
|
+
// component <div>s whose class hashes change across deploys. Tag-based
|
|
334
|
+
// scraping misses them; text-node walking is resilient.
|
|
333
335
|
const seen = new Set();
|
|
334
336
|
const files = [];
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
337
|
+
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
|
|
338
|
+
let node;
|
|
339
|
+
while ((node = walker.nextNode())) {
|
|
340
|
+
const t = (node.textContent || '').trim();
|
|
341
|
+
if (!/^[A-Za-z0-9 _.()\\-]+\\.(html|js|css|jsx|tsx|ts|md|json|svg)$/i.test(t)) continue;
|
|
342
|
+
if (t.length > 80 || seen.has(t)) continue;
|
|
339
343
|
seen.add(t);
|
|
340
344
|
files.push(t);
|
|
341
345
|
}
|
|
342
|
-
// Folders: rows whose sibling text is 'Folder' (a Claude-side label)
|
|
346
|
+
// Folders: rows whose sibling text is 'Folder' (a Claude-side label).
|
|
347
|
+
// Still tag-based since folder rows are structurally different —
|
|
348
|
+
// revisit if this breaks.
|
|
343
349
|
const folderSet = new Set();
|
|
344
350
|
const divs = Array.from(document.querySelectorAll('div'));
|
|
345
351
|
for (const d of divs) {
|
package/dist/setup.js
CHANGED
|
@@ -92,12 +92,8 @@ async function step1NpmInstall() {
|
|
|
92
92
|
const rootLock = path.join(REPO_ROOT, 'package-lock.json');
|
|
93
93
|
const innerLock = path.join(nm, '.package-lock.json');
|
|
94
94
|
if (!fs.existsSync(rootLock)) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
log('deps', 'fail', 'no package-lock.json and no node_modules — reinstall the package');
|
|
100
|
-
return false;
|
|
95
|
+
log('deps', 'ok', 'installed-mode');
|
|
96
|
+
return true;
|
|
101
97
|
}
|
|
102
98
|
if (fs.existsSync(nm)) {
|
|
103
99
|
const a = lockfileHash(rootLock);
|
package/dist/ui-anchors.js
CHANGED
|
@@ -153,6 +153,45 @@ export const UI_ANCHORS = [
|
|
|
153
153
|
const ok = /[?&]file=/.test(url);
|
|
154
154
|
return { ok: true, detail: ok ? 'file param present' : '(no file open — not a regression)' };
|
|
155
155
|
}
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
id: 'session.fileListScrape',
|
|
159
|
+
category: 'session',
|
|
160
|
+
description: 'filename text nodes detectable (listFiles scrape still works)',
|
|
161
|
+
requires: 'session',
|
|
162
|
+
check: async (b, url) => {
|
|
163
|
+
const result = await b
|
|
164
|
+
.evalValue(`(() => {
|
|
165
|
+
const seen = new Set();
|
|
166
|
+
const files = [];
|
|
167
|
+
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
|
|
168
|
+
let node;
|
|
169
|
+
while ((node = walker.nextNode())) {
|
|
170
|
+
const t = (node.textContent || '').trim();
|
|
171
|
+
if (!/^[A-Za-z0-9 _.()\\-]+\\.(html|js|css|jsx|tsx|ts|md|json|svg)$/i.test(t)) continue;
|
|
172
|
+
if (t.length > 80 || seen.has(t)) continue;
|
|
173
|
+
seen.add(t);
|
|
174
|
+
files.push(t);
|
|
175
|
+
}
|
|
176
|
+
return { files };
|
|
177
|
+
})()`)
|
|
178
|
+
.catch(() => ({ files: [] }));
|
|
179
|
+
const files = Array.isArray(result.files) ? result.files : [];
|
|
180
|
+
if (files.length === 0) {
|
|
181
|
+
return { ok: false, detail: 'found 0 filenames — scraper regex or DOM layout regressed' };
|
|
182
|
+
}
|
|
183
|
+
const match = url.match(/[?&]file=([^&]+)/);
|
|
184
|
+
if (match && match[1]) {
|
|
185
|
+
const activeFile = decodeURIComponent(match[1]);
|
|
186
|
+
if (!files.includes(activeFile)) {
|
|
187
|
+
return {
|
|
188
|
+
ok: false,
|
|
189
|
+
detail: `active file "${activeFile}" not in scrape ([${files.slice(0, 3).join(', ')}...]) — scraper missing files`
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return { ok: true, detail: `${files.length} file(s) detected` };
|
|
194
|
+
}
|
|
156
195
|
}
|
|
157
196
|
];
|
|
158
197
|
export async function runHealth(browser, opts = {}) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pro-vi/designer",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "MCP + CLI for autonomous iteration of claude.ai/design — drives the design surface via agent-browser, downloads handoff bundles, and exposes a tasting harness for full-viewport variant comparison.",
|
|
6
6
|
"license": "MIT",
|