design-brain-memory 0.9.2 → 0.9.4
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 +273 -0
- package/dist/agentBrowser.js +1 -1
- package/dist/agentBrowser.js.map +1 -1
- package/dist/aggregate.d.ts +9 -0
- package/dist/aggregate.js +53 -0
- package/dist/aggregate.js.map +1 -0
- package/dist/batch.d.ts +16 -0
- package/dist/batch.js +44 -0
- package/dist/batch.js.map +1 -0
- package/dist/cli.js +250 -216
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts +60 -1
- package/dist/commands.js +323 -10
- package/dist/commands.js.map +1 -1
- package/dist/compare.d.ts +33 -0
- package/dist/compare.js +83 -0
- package/dist/compare.js.map +1 -0
- package/dist/componentGraph.d.ts +22 -0
- package/dist/componentGraph.js +106 -0
- package/dist/componentGraph.js.map +1 -0
- package/dist/contextLayer.d.ts +12 -0
- package/dist/contextLayer.js +263 -0
- package/dist/contextLayer.js.map +1 -0
- package/dist/cssInJs.d.ts +9 -0
- package/dist/cssInJs.js +124 -0
- package/dist/cssInJs.js.map +1 -0
- package/dist/extractFromUrl.d.ts +8 -0
- package/dist/extractFromUrl.js +104 -355
- package/dist/extractFromUrl.js.map +1 -1
- package/dist/graphView.d.ts +21 -0
- package/dist/graphView.js +492 -0
- package/dist/graphView.js.map +1 -0
- package/dist/index.d.ts +26 -11
- package/dist/index.js +17 -10
- package/dist/index.js.map +1 -1
- package/dist/knowledge.d.ts +20 -0
- package/dist/knowledge.js +208 -0
- package/dist/knowledge.js.map +1 -0
- package/dist/liveView.d.ts +15 -0
- package/dist/liveView.js +475 -0
- package/dist/liveView.js.map +1 -0
- package/dist/llm.js +1 -9
- package/dist/llm.js.map +1 -1
- package/dist/moodboard.d.ts +3 -0
- package/dist/moodboard.js +152 -0
- package/dist/moodboard.js.map +1 -0
- package/dist/persona.d.ts +2 -2
- package/dist/persona.js +82 -210
- package/dist/persona.js.map +1 -1
- package/dist/query.js +1 -6
- package/dist/query.js.map +1 -1
- package/dist/render.d.ts +2 -10
- package/dist/render.js +80 -175
- package/dist/render.js.map +1 -1
- package/dist/reviewChecklist.d.ts +17 -0
- package/dist/reviewChecklist.js +126 -0
- package/dist/reviewChecklist.js.map +1 -0
- package/dist/scan.d.ts +19 -7
- package/dist/scan.js +132 -374
- package/dist/scan.js.map +1 -1
- package/dist/scorecard.d.ts +53 -0
- package/dist/scorecard.js +325 -0
- package/dist/scorecard.js.map +1 -0
- package/dist/skillPrompt.d.ts +1 -3
- package/dist/skillPrompt.js +22 -148
- package/dist/skillPrompt.js.map +1 -1
- package/dist/store.d.ts +2 -2
- package/dist/store.js +7 -9
- package/dist/store.js.map +1 -1
- package/dist/styleDictionary.d.ts +16 -0
- package/dist/styleDictionary.js +89 -0
- package/dist/styleDictionary.js.map +1 -0
- package/dist/svg.d.ts +5 -0
- package/dist/svg.js +162 -0
- package/dist/svg.js.map +1 -0
- package/dist/systemDiff.d.ts +28 -0
- package/dist/systemDiff.js +107 -0
- package/dist/systemDiff.js.map +1 -0
- package/dist/tailwind.d.ts +2 -0
- package/dist/tailwind.js +122 -0
- package/dist/tailwind.js.map +1 -0
- package/dist/taste.d.ts +3 -2
- package/dist/taste.js +349 -536
- package/dist/taste.js.map +1 -1
- package/dist/tasteRenderer.d.ts +2 -3
- package/dist/tasteRenderer.js +123 -119
- package/dist/tasteRenderer.js.map +1 -1
- package/dist/tokenNaming.d.ts +5 -0
- package/dist/tokenNaming.js +229 -0
- package/dist/tokenNaming.js.map +1 -0
- package/dist/tokens.d.ts +17 -0
- package/dist/tokens.js +44 -0
- package/dist/tokens.js.map +1 -0
- package/dist/trends.d.ts +12 -0
- package/dist/trends.js +178 -0
- package/dist/trends.js.map +1 -0
- package/dist/types.d.ts +47 -101
- package/dist/wiki.d.ts +10 -0
- package/dist/wiki.js +346 -0
- package/dist/wiki.js.map +1 -0
- package/dist/writingStyle.d.ts +38 -0
- package/dist/writingStyle.js +224 -0
- package/dist/writingStyle.js.map +1 -0
- package/package.json +5 -4
- package/dist/classify.d.ts +0 -21
- package/dist/classify.js +0 -205
- package/dist/classify.js.map +0 -1
- package/dist/scanRenderer.d.ts +0 -2
- package/dist/scanRenderer.js +0 -155
- package/dist/scanRenderer.js.map +0 -1
- package/dist/tasteDiff.d.ts +0 -19
- package/dist/tasteDiff.js +0 -340
- package/dist/tasteDiff.js.map +0 -1
- package/dist/tasteGenerate.d.ts +0 -12
- package/dist/tasteGenerate.js +0 -140
- package/dist/tasteGenerate.js.map +0 -1
- package/dist/tasteRefine.d.ts +0 -13
- package/dist/tasteRefine.js +0 -351
- package/dist/tasteRefine.js.map +0 -1
- package/dist/theatrical.d.ts +0 -5
- package/dist/theatrical.js +0 -258
- package/dist/theatrical.js.map +0 -1
- package/skills/SKILL.md +0 -36
- package/skills/design-brain/SKILL.md +0 -77
package/dist/extractFromUrl.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import fs from 'fs-extra';
|
|
3
3
|
import { runAgentBrowserJson } from './agentBrowser.js';
|
|
4
|
-
import { classifyMotionIntent, detectPhysics, detectAnimationGroups, classifyGsapEasing } from './classify.js';
|
|
5
4
|
const DEFAULT_VIEWPORTS = [
|
|
6
5
|
{ label: 'desktop', width: 1440, height: 1200 },
|
|
7
6
|
{ label: 'tablet', width: 1024, height: 1366 },
|
|
@@ -208,6 +207,7 @@ const EXTRACTION_SCRIPT = String.raw `(() => {
|
|
|
208
207
|
selector,
|
|
209
208
|
text: normalizeWhitespace(el.textContent || '').slice(0, 90),
|
|
210
209
|
className: typeof el.className === 'string' ? normalizeWhitespace(el.className) : '',
|
|
210
|
+
html: el.outerHTML.slice(0, 2048),
|
|
211
211
|
styles: {
|
|
212
212
|
color: style.color,
|
|
213
213
|
backgroundColor: style.backgroundColor,
|
|
@@ -227,12 +227,46 @@ const EXTRACTION_SCRIPT = String.raw `(() => {
|
|
|
227
227
|
const hasTransform = style.transform && style.transform !== 'none';
|
|
228
228
|
|
|
229
229
|
if ((hasTransition || hasAnimation || hasTransform) && motionList.length < maxMotion) {
|
|
230
|
-
|
|
230
|
+
const motionEntry = {
|
|
231
231
|
selector,
|
|
232
232
|
transition: style.transition,
|
|
233
233
|
animation: style.animation,
|
|
234
234
|
transform: style.transform,
|
|
235
|
-
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
if (hasTransition) {
|
|
238
|
+
const props = style.transitionProperty.split(',').map(s => s.trim());
|
|
239
|
+
const durs = style.transitionDuration.split(',').map(s => s.trim());
|
|
240
|
+
const funcs = style.transitionTimingFunction.split(',').map(s => s.trim());
|
|
241
|
+
const delays = style.transitionDelay.split(',').map(s => s.trim());
|
|
242
|
+
motionEntry.transitions = props.map((p, i) => ({
|
|
243
|
+
property: p,
|
|
244
|
+
duration: durs[i % durs.length] || '0s',
|
|
245
|
+
timingFunction: funcs[i % funcs.length] || 'ease',
|
|
246
|
+
delay: delays[i % delays.length] || '0s',
|
|
247
|
+
}));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (hasAnimation) {
|
|
251
|
+
const names = style.animationName.split(',').map(s => s.trim());
|
|
252
|
+
const durs = style.animationDuration.split(',').map(s => s.trim());
|
|
253
|
+
const funcs = style.animationTimingFunction.split(',').map(s => s.trim());
|
|
254
|
+
const delays = style.animationDelay.split(',').map(s => s.trim());
|
|
255
|
+
const iters = style.animationIterationCount.split(',').map(s => s.trim());
|
|
256
|
+
const dirs = style.animationDirection.split(',').map(s => s.trim());
|
|
257
|
+
const fills = style.animationFillMode.split(',').map(s => s.trim());
|
|
258
|
+
motionEntry.animations = names.map((n, i) => ({
|
|
259
|
+
name: n,
|
|
260
|
+
duration: durs[i % durs.length] || '0s',
|
|
261
|
+
timingFunction: funcs[i % funcs.length] || 'ease',
|
|
262
|
+
delay: delays[i % delays.length] || '0s',
|
|
263
|
+
iterationCount: iters[i % iters.length] || '1',
|
|
264
|
+
direction: dirs[i % dirs.length] || 'normal',
|
|
265
|
+
fillMode: fills[i % fills.length] || 'none',
|
|
266
|
+
}));
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
motionList.push(motionEntry);
|
|
236
270
|
}
|
|
237
271
|
});
|
|
238
272
|
|
|
@@ -296,6 +330,35 @@ const EXTRACTION_SCRIPT = String.raw `(() => {
|
|
|
296
330
|
|
|
297
331
|
addPseudoStateStyles();
|
|
298
332
|
|
|
333
|
+
const keyframeList = [];
|
|
334
|
+
const seenKeyframes = new Set();
|
|
335
|
+
const maxKeyframes = 60;
|
|
336
|
+
|
|
337
|
+
for (const sheet of Array.from(document.styleSheets)) {
|
|
338
|
+
let rules;
|
|
339
|
+
try { rules = sheet.cssRules; } catch { continue; }
|
|
340
|
+
if (!rules) continue;
|
|
341
|
+
|
|
342
|
+
for (const rule of Array.from(rules)) {
|
|
343
|
+
if (rule.constructor.name !== 'CSSKeyframesRule') continue;
|
|
344
|
+
const kfRule = rule;
|
|
345
|
+
const name = kfRule.name;
|
|
346
|
+
if (seenKeyframes.has(name) || keyframeList.length >= maxKeyframes) continue;
|
|
347
|
+
seenKeyframes.add(name);
|
|
348
|
+
|
|
349
|
+
const steps = [];
|
|
350
|
+
for (const kf of Array.from(kfRule.cssRules)) {
|
|
351
|
+
const declarations = {};
|
|
352
|
+
for (let i = 0; i < kf.style.length; i++) {
|
|
353
|
+
const prop = kf.style[i];
|
|
354
|
+
declarations[prop] = kf.style.getPropertyValue(prop);
|
|
355
|
+
}
|
|
356
|
+
steps.push({ offset: kf.keyText, declarations });
|
|
357
|
+
}
|
|
358
|
+
keyframeList.push({ name, steps });
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
299
362
|
const colors = Array.from(colorMap.values()).sort((a, b) => b.count - a.count).slice(0, 70);
|
|
300
363
|
const typography = Array.from(typographyMap.values()).sort((a, b) => b.count - a.count).slice(0, 90);
|
|
301
364
|
|
|
@@ -310,6 +373,7 @@ const EXTRACTION_SCRIPT = String.raw `(() => {
|
|
|
310
373
|
typography,
|
|
311
374
|
components: componentList,
|
|
312
375
|
motion: motionList,
|
|
376
|
+
keyframes: keyframeList,
|
|
313
377
|
layout: layoutList,
|
|
314
378
|
cssVariables: variableMap,
|
|
315
379
|
stateStyles: stateStyleList,
|
|
@@ -325,312 +389,6 @@ const PAGE_SUMMARY_SCRIPT = String.raw `(() => {
|
|
|
325
389
|
summary: [h1, 'nav-links:' + navCount, 'ctas:' + ctaCount].filter(Boolean).join(' | '),
|
|
326
390
|
};
|
|
327
391
|
})();`;
|
|
328
|
-
const ANIMATION_OBSERVER_SCRIPT = String.raw `(() => {
|
|
329
|
-
const maxAnimations = 200;
|
|
330
|
-
const result = {
|
|
331
|
-
libraries: [],
|
|
332
|
-
webAnimations: [],
|
|
333
|
-
gsapTweens: [],
|
|
334
|
-
lottiePlayers: [],
|
|
335
|
-
scrollBindings: {
|
|
336
|
-
hasScrollTrigger: false,
|
|
337
|
-
hasIntersectionObserver: false,
|
|
338
|
-
scrollTriggers: [],
|
|
339
|
-
hasScrollSnap: false,
|
|
340
|
-
hasScrollTimeline: false,
|
|
341
|
-
},
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
function buildSelector(el) {
|
|
345
|
-
if (!el || !el.tagName) return 'unknown';
|
|
346
|
-
const tag = el.tagName.toLowerCase();
|
|
347
|
-
if (el.id) return tag + '#' + el.id;
|
|
348
|
-
if (typeof el.className === 'string' && el.className.trim()) {
|
|
349
|
-
const firstClass = el.className.trim().split(/\s+/).slice(0, 2).join('.');
|
|
350
|
-
if (firstClass) return tag + '.' + firstClass;
|
|
351
|
-
}
|
|
352
|
-
return tag;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
/* Layer 1: Library Detection */
|
|
356
|
-
try {
|
|
357
|
-
if (typeof gsap !== 'undefined') {
|
|
358
|
-
result.libraries.push({ name: 'gsap', version: typeof gsap.version === 'string' ? gsap.version : 'unknown' });
|
|
359
|
-
}
|
|
360
|
-
if (typeof ScrollTrigger !== 'undefined') {
|
|
361
|
-
result.libraries.push({ name: 'scrolltrigger', version: 'detected' });
|
|
362
|
-
result.scrollBindings.hasScrollTrigger = true;
|
|
363
|
-
}
|
|
364
|
-
if (typeof lottie !== 'undefined' || typeof bodymovin !== 'undefined') {
|
|
365
|
-
result.libraries.push({ name: 'lottie', version: 'detected' });
|
|
366
|
-
}
|
|
367
|
-
if (document.querySelector('lottie-player, dotlottie-player')) {
|
|
368
|
-
if (!result.libraries.some(function(l) { return l.name === 'lottie'; })) {
|
|
369
|
-
result.libraries.push({ name: 'lottie', version: 'web-component' });
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
if (document.querySelector('[data-framer-name], [data-framer-component-type]')) {
|
|
373
|
-
result.libraries.push({ name: 'framer-motion', version: 'detected' });
|
|
374
|
-
}
|
|
375
|
-
} catch(e) {}
|
|
376
|
-
|
|
377
|
-
/* Layer 2: Web Animations API */
|
|
378
|
-
try {
|
|
379
|
-
var animations = document.getAnimations();
|
|
380
|
-
for (var ai = 0; ai < Math.min(animations.length, maxAnimations); ai++) {
|
|
381
|
-
var anim = animations[ai];
|
|
382
|
-
var effect = anim.effect;
|
|
383
|
-
if (!effect || !effect.target) continue;
|
|
384
|
-
|
|
385
|
-
var target = effect.target;
|
|
386
|
-
var selector = buildSelector(target);
|
|
387
|
-
|
|
388
|
-
var keyframes = [];
|
|
389
|
-
try { keyframes = effect.getKeyframes(); } catch(e) {}
|
|
390
|
-
|
|
391
|
-
var computedTiming = {};
|
|
392
|
-
try { computedTiming = effect.getComputedTiming(); } catch(e) {}
|
|
393
|
-
|
|
394
|
-
var timelineType = 'document';
|
|
395
|
-
try {
|
|
396
|
-
if (anim.timeline && anim.timeline.constructor) {
|
|
397
|
-
var tlName = anim.timeline.constructor.name;
|
|
398
|
-
if (tlName === 'ScrollTimeline') timelineType = 'scroll';
|
|
399
|
-
else if (tlName === 'ViewTimeline') timelineType = 'view';
|
|
400
|
-
}
|
|
401
|
-
} catch(e) {}
|
|
402
|
-
|
|
403
|
-
if (timelineType !== 'document') {
|
|
404
|
-
result.scrollBindings.hasScrollTimeline = true;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
result.webAnimations.push({
|
|
408
|
-
selector: selector,
|
|
409
|
-
playState: anim.playState,
|
|
410
|
-
animationName: anim.animationName || anim.id || '',
|
|
411
|
-
keyframes: keyframes.map(function(kf) {
|
|
412
|
-
var props = {};
|
|
413
|
-
for (var k in kf) {
|
|
414
|
-
if (k !== 'offset' && k !== 'computedOffset' && k !== 'easing' && k !== 'composite') {
|
|
415
|
-
props[k] = String(kf[k]);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
return {
|
|
419
|
-
offset: kf.computedOffset != null ? kf.computedOffset : (kf.offset || 0),
|
|
420
|
-
properties: props,
|
|
421
|
-
easing: kf.easing || 'linear',
|
|
422
|
-
};
|
|
423
|
-
}),
|
|
424
|
-
timing: {
|
|
425
|
-
duration: typeof computedTiming.duration === 'number' ? computedTiming.duration : 0,
|
|
426
|
-
delay: computedTiming.delay || 0,
|
|
427
|
-
easing: computedTiming.easing || 'linear',
|
|
428
|
-
iterations: computedTiming.iterations != null ? computedTiming.iterations : 1,
|
|
429
|
-
direction: computedTiming.direction || 'normal',
|
|
430
|
-
fillMode: computedTiming.fill || 'none',
|
|
431
|
-
},
|
|
432
|
-
timelineType: timelineType,
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
} catch(e) {}
|
|
436
|
-
|
|
437
|
-
/* Layer 3: GSAP Introspection */
|
|
438
|
-
try {
|
|
439
|
-
if (typeof gsap !== 'undefined' && gsap.globalTimeline) {
|
|
440
|
-
var children = gsap.globalTimeline.getChildren(true, true, false);
|
|
441
|
-
for (var gi = 0; gi < Math.min(children.length, maxAnimations); gi++) {
|
|
442
|
-
var tween = children[gi];
|
|
443
|
-
var targets = tween.targets ? tween.targets() : [];
|
|
444
|
-
if (targets.length === 0) continue;
|
|
445
|
-
|
|
446
|
-
var gsSelector = buildSelector(targets[0]);
|
|
447
|
-
var vars = {};
|
|
448
|
-
if (tween.vars) {
|
|
449
|
-
for (var vk in tween.vars) {
|
|
450
|
-
var vv = tween.vars[vk];
|
|
451
|
-
if (typeof vv === 'number' || typeof vv === 'string') {
|
|
452
|
-
vars[vk] = vv;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
result.gsapTweens.push({
|
|
458
|
-
selector: gsSelector,
|
|
459
|
-
duration: typeof tween.duration === 'function' ? tween.duration() : 0,
|
|
460
|
-
delay: typeof tween.delay === 'function' ? tween.delay() : 0,
|
|
461
|
-
ease: tween.vars && tween.vars.ease ? tween.vars.ease : 'power1.out',
|
|
462
|
-
vars: vars,
|
|
463
|
-
startTime: typeof tween.startTime === 'function' ? tween.startTime() : 0,
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
} catch(e) {}
|
|
468
|
-
|
|
469
|
-
/* Layer 4: Lottie Extraction */
|
|
470
|
-
try {
|
|
471
|
-
var lottieRef = (typeof lottie !== 'undefined') ? lottie : ((typeof bodymovin !== 'undefined') ? bodymovin : null);
|
|
472
|
-
if (lottieRef && typeof lottieRef.getRegisteredAnimations === 'function') {
|
|
473
|
-
var registered = lottieRef.getRegisteredAnimations();
|
|
474
|
-
for (var li = 0; li < Math.min(registered.length, 20); li++) {
|
|
475
|
-
var la = registered[li];
|
|
476
|
-
var container = la.wrapper || la.container;
|
|
477
|
-
result.lottiePlayers.push({
|
|
478
|
-
selector: container ? buildSelector(container) : 'lottie-unknown',
|
|
479
|
-
frameRate: la.frameRate || (la.animationData && la.animationData.fr) || 0,
|
|
480
|
-
totalFrames: la.totalFrames || (la.animationData && la.animationData.op) || 0,
|
|
481
|
-
duration: typeof la.getDuration === 'function' ? la.getDuration(false) : 0,
|
|
482
|
-
});
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
var players = document.querySelectorAll('lottie-player, dotlottie-player');
|
|
487
|
-
for (var pi = 0; pi < Math.min(players.length, 20); pi++) {
|
|
488
|
-
var pSelector = buildSelector(players[pi]);
|
|
489
|
-
if (!result.lottiePlayers.some(function(l) { return l.selector === pSelector; })) {
|
|
490
|
-
result.lottiePlayers.push({ selector: pSelector, frameRate: 0, totalFrames: 0, duration: 0 });
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
} catch(e) {}
|
|
494
|
-
|
|
495
|
-
/* Layer 5: Passive Scroll Detection */
|
|
496
|
-
try {
|
|
497
|
-
if (typeof ScrollTrigger !== 'undefined' && typeof ScrollTrigger.getAll === 'function') {
|
|
498
|
-
var triggers = ScrollTrigger.getAll();
|
|
499
|
-
for (var si = 0; si < Math.min(triggers.length, 50); si++) {
|
|
500
|
-
var st = triggers[si];
|
|
501
|
-
result.scrollBindings.scrollTriggers.push({
|
|
502
|
-
triggerSelector: st.trigger ? buildSelector(st.trigger) : '',
|
|
503
|
-
isActive: !!st.isActive,
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
} catch(e) {}
|
|
508
|
-
|
|
509
|
-
try {
|
|
510
|
-
var scrollSnap = window.getComputedStyle(document.documentElement).scrollSnapType;
|
|
511
|
-
if (scrollSnap && scrollSnap !== 'none') {
|
|
512
|
-
result.scrollBindings.hasScrollSnap = true;
|
|
513
|
-
}
|
|
514
|
-
} catch(e) {}
|
|
515
|
-
|
|
516
|
-
return result;
|
|
517
|
-
})();`;
|
|
518
|
-
function convertObserverResult(raw) {
|
|
519
|
-
const tokens = [];
|
|
520
|
-
const libraryNames = new Set(raw.libraries.map((l) => l.name));
|
|
521
|
-
// Convert Web Animations API results
|
|
522
|
-
for (const wa of raw.webAnimations) {
|
|
523
|
-
const intent = classifyMotionIntent(wa.keyframes);
|
|
524
|
-
let library = 'css';
|
|
525
|
-
if (libraryNames.has('framer-motion')) {
|
|
526
|
-
library = 'framer-motion';
|
|
527
|
-
}
|
|
528
|
-
const token = {
|
|
529
|
-
selector: wa.selector,
|
|
530
|
-
library,
|
|
531
|
-
motionIntent: intent,
|
|
532
|
-
timing: {
|
|
533
|
-
duration: wa.timing.duration,
|
|
534
|
-
delay: wa.timing.delay,
|
|
535
|
-
easing: wa.timing.easing,
|
|
536
|
-
iterations: wa.timing.iterations === Infinity ? Infinity : wa.timing.iterations,
|
|
537
|
-
direction: wa.timing.direction,
|
|
538
|
-
fillMode: wa.timing.fillMode,
|
|
539
|
-
},
|
|
540
|
-
keyframes: wa.keyframes,
|
|
541
|
-
trigger: wa.timelineType === 'scroll' || wa.timelineType === 'view' ? 'scroll' : 'load',
|
|
542
|
-
};
|
|
543
|
-
if (wa.timelineType !== 'document') {
|
|
544
|
-
token.scrollBinding = {
|
|
545
|
-
hasScrollTrigger: false,
|
|
546
|
-
hasIntersectionObserver: false,
|
|
547
|
-
scrollTimelineAxis: 'block',
|
|
548
|
-
};
|
|
549
|
-
}
|
|
550
|
-
// Detect physics from keyframes
|
|
551
|
-
const allProps = new Set();
|
|
552
|
-
for (const kf of wa.keyframes) {
|
|
553
|
-
for (const prop of Object.keys(kf.properties))
|
|
554
|
-
allProps.add(prop);
|
|
555
|
-
}
|
|
556
|
-
if (allProps.has('transform')) {
|
|
557
|
-
for (const fnName of ['translateX', 'translateY', 'scale', 'rotate']) {
|
|
558
|
-
const physics = detectPhysics(wa.keyframes, fnName);
|
|
559
|
-
if (physics) {
|
|
560
|
-
token.physics = physics;
|
|
561
|
-
token.motionIntent = physics.type === 'spring' ? 'spring' : 'bounce';
|
|
562
|
-
break;
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
tokens.push(token);
|
|
567
|
-
}
|
|
568
|
-
// Convert GSAP tweens
|
|
569
|
-
for (const tween of raw.gsapTweens) {
|
|
570
|
-
const token = {
|
|
571
|
-
selector: tween.selector,
|
|
572
|
-
library: 'gsap',
|
|
573
|
-
motionIntent: 'complex',
|
|
574
|
-
timing: {
|
|
575
|
-
duration: tween.duration * 1000,
|
|
576
|
-
delay: tween.delay * 1000,
|
|
577
|
-
easing: tween.ease || 'power1.out',
|
|
578
|
-
iterations: 1,
|
|
579
|
-
direction: 'normal',
|
|
580
|
-
fillMode: 'none',
|
|
581
|
-
},
|
|
582
|
-
trigger: 'load',
|
|
583
|
-
gsapVars: tween.vars,
|
|
584
|
-
};
|
|
585
|
-
const physics = classifyGsapEasing(tween.ease);
|
|
586
|
-
if (physics) {
|
|
587
|
-
token.physics = physics;
|
|
588
|
-
token.motionIntent = physics.type === 'spring' ? 'spring' : 'bounce';
|
|
589
|
-
}
|
|
590
|
-
else {
|
|
591
|
-
const varKeys = Object.keys(tween.vars);
|
|
592
|
-
if (varKeys.some((k) => ['x', 'y', 'xPercent', 'yPercent'].includes(k))) {
|
|
593
|
-
token.motionIntent = 'slide';
|
|
594
|
-
}
|
|
595
|
-
else if (varKeys.some((k) => ['scale', 'scaleX', 'scaleY'].includes(k))) {
|
|
596
|
-
token.motionIntent = 'scale';
|
|
597
|
-
}
|
|
598
|
-
else if (varKeys.some((k) => ['rotation', 'rotationX', 'rotationY'].includes(k))) {
|
|
599
|
-
token.motionIntent = 'rotate';
|
|
600
|
-
}
|
|
601
|
-
else if (varKeys.includes('opacity')) {
|
|
602
|
-
token.motionIntent = 'fade';
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
if (raw.scrollBindings.hasScrollTrigger) {
|
|
606
|
-
const matchingTrigger = raw.scrollBindings.scrollTriggers.find((st) => st.triggerSelector === tween.selector);
|
|
607
|
-
if (matchingTrigger) {
|
|
608
|
-
token.trigger = 'scroll';
|
|
609
|
-
token.scrollBinding = {
|
|
610
|
-
triggerSelector: matchingTrigger.triggerSelector,
|
|
611
|
-
hasScrollTrigger: true,
|
|
612
|
-
hasIntersectionObserver: false,
|
|
613
|
-
};
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
tokens.push(token);
|
|
617
|
-
}
|
|
618
|
-
// Convert Lottie players
|
|
619
|
-
for (const lp of raw.lottiePlayers) {
|
|
620
|
-
tokens.push({
|
|
621
|
-
selector: lp.selector,
|
|
622
|
-
library: 'lottie',
|
|
623
|
-
motionIntent: 'complex',
|
|
624
|
-
trigger: 'load',
|
|
625
|
-
lottieMetadata: {
|
|
626
|
-
frameRate: lp.frameRate,
|
|
627
|
-
totalFrames: lp.totalFrames,
|
|
628
|
-
duration: lp.duration,
|
|
629
|
-
},
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
return tokens;
|
|
633
|
-
}
|
|
634
392
|
function normalizeResult(result) {
|
|
635
393
|
return {
|
|
636
394
|
pageTitle: result.pageTitle ?? undefined,
|
|
@@ -640,6 +398,7 @@ function normalizeResult(result) {
|
|
|
640
398
|
typography: result.typography ?? [],
|
|
641
399
|
components: result.components ?? [],
|
|
642
400
|
motion: result.motion ?? [],
|
|
401
|
+
keyframes: result.keyframes ?? [],
|
|
643
402
|
layout: result.layout ?? [],
|
|
644
403
|
cssVariables: result.cssVariables ?? {},
|
|
645
404
|
stateStyles: result.stateStyles ?? [],
|
|
@@ -678,6 +437,7 @@ function mergeAnalysis(all) {
|
|
|
678
437
|
}
|
|
679
438
|
const componentMap = new Map();
|
|
680
439
|
const motionMap = new Map();
|
|
440
|
+
const keyframeMap = new Map();
|
|
681
441
|
const layoutMap = new Map();
|
|
682
442
|
const stateMap = new Map();
|
|
683
443
|
const cssVariables = {};
|
|
@@ -690,13 +450,16 @@ function mergeAnalysis(all) {
|
|
|
690
450
|
}
|
|
691
451
|
}
|
|
692
452
|
for (const motion of entry.motion) {
|
|
693
|
-
const key =
|
|
694
|
-
? `${motion.selector}|${motion.library}|${motion.motionIntent}`
|
|
695
|
-
: `${motion.selector}|${motion.transition}|${motion.animation}|${motion.transform}`;
|
|
453
|
+
const key = `${motion.selector}|${motion.transition}|${motion.animation}|${motion.transform}`;
|
|
696
454
|
if (!motionMap.has(key)) {
|
|
697
455
|
motionMap.set(key, motion);
|
|
698
456
|
}
|
|
699
457
|
}
|
|
458
|
+
for (const kf of entry.keyframes ?? []) {
|
|
459
|
+
if (!keyframeMap.has(kf.name)) {
|
|
460
|
+
keyframeMap.set(kf.name, kf);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
700
463
|
for (const layout of entry.layout) {
|
|
701
464
|
const key = `${layout.tag}|${layout.selector}|${layout.role}`;
|
|
702
465
|
if (!layoutMap.has(key)) {
|
|
@@ -718,6 +481,7 @@ function mergeAnalysis(all) {
|
|
|
718
481
|
typography: [...typographyMap.values()].sort((a, b) => b.count - a.count).slice(0, 120),
|
|
719
482
|
components: [...componentMap.values()].slice(0, 260),
|
|
720
483
|
motion: [...motionMap.values()].slice(0, 260),
|
|
484
|
+
keyframes: [...keyframeMap.values()].slice(0, 80),
|
|
721
485
|
layout: [...layoutMap.values()].slice(0, 220),
|
|
722
486
|
cssVariables,
|
|
723
487
|
stateStyles: [...stateMap.values()].slice(0, 300),
|
|
@@ -740,6 +504,7 @@ async function collectInteractiveStateStyles(params) {
|
|
|
740
504
|
const snapshot = await runAgentBrowserJson(['snapshot', '-i', '-d', '2'], {
|
|
741
505
|
session: params.sessionName,
|
|
742
506
|
cwd: params.workingDir,
|
|
507
|
+
headed: params.headed,
|
|
743
508
|
});
|
|
744
509
|
const refs = (snapshot.data.refs ?? {});
|
|
745
510
|
const refIds = Object.keys(refs).slice(0, 8);
|
|
@@ -748,10 +513,12 @@ async function collectInteractiveStateStyles(params) {
|
|
|
748
513
|
await runAgentBrowserJson(['hover', ref], {
|
|
749
514
|
session: params.sessionName,
|
|
750
515
|
cwd: params.workingDir,
|
|
516
|
+
headed: params.headed,
|
|
751
517
|
}).catch(() => undefined);
|
|
752
518
|
const hoverStyles = await runAgentBrowserJson(['get', 'styles', ref], {
|
|
753
519
|
session: params.sessionName,
|
|
754
520
|
cwd: params.workingDir,
|
|
521
|
+
headed: params.headed,
|
|
755
522
|
}).catch(() => undefined);
|
|
756
523
|
if (hoverStyles?.success) {
|
|
757
524
|
const declarations = parseStylesFromGetStyles(hoverStyles.data);
|
|
@@ -762,10 +529,12 @@ async function collectInteractiveStateStyles(params) {
|
|
|
762
529
|
await runAgentBrowserJson(['focus', ref], {
|
|
763
530
|
session: params.sessionName,
|
|
764
531
|
cwd: params.workingDir,
|
|
532
|
+
headed: params.headed,
|
|
765
533
|
}).catch(() => undefined);
|
|
766
534
|
const focusStyles = await runAgentBrowserJson(['get', 'styles', ref], {
|
|
767
535
|
session: params.sessionName,
|
|
768
536
|
cwd: params.workingDir,
|
|
537
|
+
headed: params.headed,
|
|
769
538
|
}).catch(() => undefined);
|
|
770
539
|
if (focusStyles?.success) {
|
|
771
540
|
const declarations = parseStylesFromGetStyles(focusStyles.data);
|
|
@@ -791,6 +560,7 @@ async function getCurrentUrl(params) {
|
|
|
791
560
|
const response = await runAgentBrowserJson(['get', 'url'], {
|
|
792
561
|
session: params.sessionName,
|
|
793
562
|
cwd: params.workingDir,
|
|
563
|
+
headed: params.headed,
|
|
794
564
|
}).catch(() => undefined);
|
|
795
565
|
return response?.success ? response.data.url : undefined;
|
|
796
566
|
}
|
|
@@ -802,6 +572,7 @@ async function collectJourney(params) {
|
|
|
802
572
|
const snapshot = await runAgentBrowserJson(['snapshot', '-i', '-d', '2'], {
|
|
803
573
|
session: params.sessionName,
|
|
804
574
|
cwd: params.workingDir,
|
|
575
|
+
headed: params.headed,
|
|
805
576
|
});
|
|
806
577
|
const refs = (snapshot.data.refs ?? {});
|
|
807
578
|
const clickable = Object.entries(refs)
|
|
@@ -814,6 +585,7 @@ async function collectJourney(params) {
|
|
|
814
585
|
const clickResult = await runAgentBrowserJson(['click', ref], {
|
|
815
586
|
session: params.sessionName,
|
|
816
587
|
cwd: params.workingDir,
|
|
588
|
+
headed: params.headed,
|
|
817
589
|
}).catch(() => undefined);
|
|
818
590
|
if (!clickResult?.success) {
|
|
819
591
|
continue;
|
|
@@ -821,10 +593,12 @@ async function collectJourney(params) {
|
|
|
821
593
|
await runAgentBrowserJson(['wait', '1200'], {
|
|
822
594
|
session: params.sessionName,
|
|
823
595
|
cwd: params.workingDir,
|
|
596
|
+
headed: params.headed,
|
|
824
597
|
}).catch(() => undefined);
|
|
825
598
|
const summaryResult = await runAgentBrowserJson(['eval', PAGE_SUMMARY_SCRIPT], {
|
|
826
599
|
session: params.sessionName,
|
|
827
600
|
cwd: params.workingDir,
|
|
601
|
+
headed: params.headed,
|
|
828
602
|
}).catch(() => undefined);
|
|
829
603
|
const summaryData = summaryResult?.data.result ?? {};
|
|
830
604
|
const toUrl = summaryData.url ?? (await getCurrentUrl(params));
|
|
@@ -837,22 +611,25 @@ async function collectJourney(params) {
|
|
|
837
611
|
title: summaryData.title,
|
|
838
612
|
summary: summaryData.summary,
|
|
839
613
|
});
|
|
614
|
+
params.onStep?.(i + 1, toUrl);
|
|
840
615
|
await runAgentBrowserJson(['back'], {
|
|
841
616
|
session: params.sessionName,
|
|
842
617
|
cwd: params.workingDir,
|
|
618
|
+
headed: params.headed,
|
|
843
619
|
}).catch(() => undefined);
|
|
844
620
|
await runAgentBrowserJson(['wait', '900'], {
|
|
845
621
|
session: params.sessionName,
|
|
846
622
|
cwd: params.workingDir,
|
|
623
|
+
headed: params.headed,
|
|
847
624
|
}).catch(() => undefined);
|
|
848
625
|
}
|
|
849
626
|
}
|
|
850
627
|
return steps;
|
|
851
628
|
}
|
|
852
629
|
export async function captureDesignFromUrl(params) {
|
|
853
|
-
const { url, sessionName, screenshotPath, workingDir, journeySteps = 3, responsiveViewports = DEFAULT_VIEWPORTS, } = params;
|
|
630
|
+
const { url, sessionName, screenshotPath, workingDir, headed = false, journeySteps = 3, responsiveViewports = DEFAULT_VIEWPORTS, callbacks, } = params;
|
|
854
631
|
await fs.ensureDir(path.dirname(screenshotPath));
|
|
855
|
-
await runAgentBrowserJson(['open', url], { session: sessionName, cwd: workingDir });
|
|
632
|
+
await runAgentBrowserJson(['open', url], { session: sessionName, cwd: workingDir, headed });
|
|
856
633
|
try {
|
|
857
634
|
const captures = [];
|
|
858
635
|
const responsiveSnapshots = [];
|
|
@@ -860,14 +637,17 @@ export async function captureDesignFromUrl(params) {
|
|
|
860
637
|
await runAgentBrowserJson(['set', 'viewport', String(viewport.width), String(viewport.height)], {
|
|
861
638
|
session: sessionName,
|
|
862
639
|
cwd: workingDir,
|
|
640
|
+
headed,
|
|
863
641
|
});
|
|
864
642
|
await runAgentBrowserJson(['wait', '900'], {
|
|
865
643
|
session: sessionName,
|
|
866
644
|
cwd: workingDir,
|
|
645
|
+
headed,
|
|
867
646
|
});
|
|
868
647
|
const extraction = await runAgentBrowserJson(['eval', EXTRACTION_SCRIPT], {
|
|
869
648
|
session: sessionName,
|
|
870
649
|
cwd: workingDir,
|
|
650
|
+
headed,
|
|
871
651
|
});
|
|
872
652
|
if (!extraction.success) {
|
|
873
653
|
throw new Error(`Extraction failed: ${extraction.error ?? 'Unknown error'}`);
|
|
@@ -875,72 +655,41 @@ export async function captureDesignFromUrl(params) {
|
|
|
875
655
|
const normalized = normalizeResult(extraction.data.result ?? {});
|
|
876
656
|
captures.push(normalized);
|
|
877
657
|
responsiveSnapshots.push(toResponsiveSnapshot(viewport.label, normalized));
|
|
658
|
+
callbacks?.onViewportExtracted?.(viewport.label, normalized);
|
|
878
659
|
}
|
|
879
660
|
await runAgentBrowserJson(['set', 'viewport', '1440', '1200'], {
|
|
880
661
|
session: sessionName,
|
|
881
662
|
cwd: workingDir,
|
|
663
|
+
headed,
|
|
882
664
|
}).catch(() => undefined);
|
|
883
|
-
// Scroll through the page to trigger lazy-loaded animation libraries (GSAP, ScrollTrigger, etc.)
|
|
884
|
-
try {
|
|
885
|
-
const pageInfo = await runAgentBrowserJson(['eval',
|
|
886
|
-
`({ height: Math.max(document.body.scrollHeight, document.documentElement.scrollHeight), vh: window.innerHeight })`
|
|
887
|
-
], { session: sessionName, cwd: workingDir });
|
|
888
|
-
const { height = 5000, vh = 800 } = pageInfo.data.result ?? {};
|
|
889
|
-
const scrollSteps = Math.min(Math.ceil(height / vh), 15);
|
|
890
|
-
const stepSize = Math.ceil(height / scrollSteps);
|
|
891
|
-
for (let i = 1; i <= scrollSteps; i++) {
|
|
892
|
-
await runAgentBrowserJson(['eval', `window.scrollTo({top:${i * stepSize},behavior:"instant"});true`], { session: sessionName, cwd: workingDir });
|
|
893
|
-
await runAgentBrowserJson(['wait', '200'], { session: sessionName, cwd: workingDir });
|
|
894
|
-
}
|
|
895
|
-
await runAgentBrowserJson(['eval', 'window.scrollTo({top:0,behavior:"instant"});true'], { session: sessionName, cwd: workingDir });
|
|
896
|
-
await runAgentBrowserJson(['wait', '1500'], { session: sessionName, cwd: workingDir });
|
|
897
|
-
}
|
|
898
|
-
catch {
|
|
899
|
-
// Scroll is best-effort; continue to animation capture
|
|
900
|
-
}
|
|
901
|
-
// Run animation observer script (once, at desktop viewport)
|
|
902
|
-
let animationTokens = [];
|
|
903
|
-
try {
|
|
904
|
-
const animResult = await runAgentBrowserJson(['eval', ANIMATION_OBSERVER_SCRIPT], {
|
|
905
|
-
session: sessionName,
|
|
906
|
-
cwd: workingDir,
|
|
907
|
-
});
|
|
908
|
-
if (animResult.success && animResult.data.result) {
|
|
909
|
-
const rawAnimData = animResult.data.result;
|
|
910
|
-
animationTokens = convertObserverResult(rawAnimData);
|
|
911
|
-
animationTokens = detectAnimationGroups(animationTokens);
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
catch {
|
|
915
|
-
// Animation capture is best-effort; don't fail the whole extraction
|
|
916
|
-
}
|
|
917
665
|
const snapshotResult = await runAgentBrowserJson(['snapshot', '-c', '-d', '3'], {
|
|
918
666
|
session: sessionName,
|
|
919
667
|
cwd: workingDir,
|
|
668
|
+
headed,
|
|
920
669
|
});
|
|
921
670
|
const interactiveStates = await collectInteractiveStateStyles({
|
|
922
671
|
sessionName,
|
|
923
672
|
workingDir,
|
|
673
|
+
headed,
|
|
924
674
|
});
|
|
675
|
+
callbacks?.onInteractiveStates?.(interactiveStates.length);
|
|
925
676
|
const journey = await collectJourney({
|
|
926
677
|
sessionName,
|
|
927
678
|
workingDir,
|
|
679
|
+
headed,
|
|
928
680
|
maxSteps: journeySteps,
|
|
681
|
+
onStep: callbacks?.onJourneyStep,
|
|
929
682
|
});
|
|
930
683
|
await runAgentBrowserJson(['screenshot', screenshotPath, '--full'], {
|
|
931
684
|
session: sessionName,
|
|
932
685
|
cwd: workingDir,
|
|
686
|
+
headed,
|
|
933
687
|
});
|
|
934
688
|
const merged = mergeAnalysis(captures);
|
|
689
|
+
callbacks?.onMerged?.(merged);
|
|
935
690
|
const stateStyles = [...(merged.stateStyles ?? []), ...interactiveStates].slice(0, 400);
|
|
936
|
-
// Merge: prefer new AnimationTokens, fall back to legacy MotionTokens
|
|
937
|
-
const mergedMotion = [
|
|
938
|
-
...animationTokens,
|
|
939
|
-
...merged.motion.filter((legacyToken) => !animationTokens.some((at) => at.selector === legacyToken.selector)),
|
|
940
|
-
];
|
|
941
691
|
return {
|
|
942
692
|
...merged,
|
|
943
|
-
motion: mergedMotion,
|
|
944
693
|
accessibilitySnapshot: snapshotResult.data.snapshot ?? undefined,
|
|
945
694
|
responsiveSnapshots,
|
|
946
695
|
stateStyles,
|
|
@@ -948,7 +697,7 @@ export async function captureDesignFromUrl(params) {
|
|
|
948
697
|
};
|
|
949
698
|
}
|
|
950
699
|
finally {
|
|
951
|
-
await runAgentBrowserJson(['close'], { session: sessionName, cwd: workingDir }).catch(() => undefined);
|
|
700
|
+
await runAgentBrowserJson(['close'], { session: sessionName, cwd: workingDir, headed }).catch(() => undefined);
|
|
952
701
|
}
|
|
953
702
|
}
|
|
954
703
|
//# sourceMappingURL=extractFromUrl.js.map
|