skillui 1.1.2 → 1.1.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 +20 -15
- package/dist/cli.js +105073 -194
- package/package.json +15 -6
- package/dist/cli.d.ts +0 -3
- package/dist/extractors/components.d.ts +0 -11
- package/dist/extractors/components.js +0 -455
- package/dist/extractors/framework.d.ts +0 -4
- package/dist/extractors/framework.js +0 -126
- package/dist/extractors/tokens/computed.d.ts +0 -7
- package/dist/extractors/tokens/computed.js +0 -249
- package/dist/extractors/tokens/css.d.ts +0 -3
- package/dist/extractors/tokens/css.js +0 -510
- package/dist/extractors/tokens/http-css.d.ts +0 -14
- package/dist/extractors/tokens/http-css.js +0 -1689
- package/dist/extractors/tokens/tailwind.d.ts +0 -3
- package/dist/extractors/tokens/tailwind.js +0 -353
- package/dist/extractors/tokens/tokens-file.d.ts +0 -3
- package/dist/extractors/tokens/tokens-file.js +0 -229
- package/dist/extractors/ultra/animations.d.ts +0 -21
- package/dist/extractors/ultra/animations.js +0 -527
- package/dist/extractors/ultra/components-dom.d.ts +0 -13
- package/dist/extractors/ultra/components-dom.js +0 -149
- package/dist/extractors/ultra/interactions.d.ts +0 -14
- package/dist/extractors/ultra/interactions.js +0 -222
- package/dist/extractors/ultra/layout.d.ts +0 -14
- package/dist/extractors/ultra/layout.js +0 -123
- package/dist/extractors/ultra/pages.d.ts +0 -16
- package/dist/extractors/ultra/pages.js +0 -228
- package/dist/font-resolver.d.ts +0 -10
- package/dist/font-resolver.js +0 -280
- package/dist/modes/dir.d.ts +0 -6
- package/dist/modes/dir.js +0 -213
- package/dist/modes/repo.d.ts +0 -6
- package/dist/modes/repo.js +0 -76
- package/dist/modes/ultra.d.ts +0 -22
- package/dist/modes/ultra.js +0 -281
- package/dist/modes/url.d.ts +0 -14
- package/dist/modes/url.js +0 -161
- package/dist/normalizer.d.ts +0 -11
- package/dist/normalizer.js +0 -867
- package/dist/playwright-loader.d.ts +0 -10
- package/dist/playwright-loader.js +0 -71
- package/dist/screenshot.d.ts +0 -9
- package/dist/screenshot.js +0 -94
- package/dist/types-ultra.d.ts +0 -157
- package/dist/types-ultra.js +0 -4
- package/dist/types.d.ts +0 -182
- package/dist/types.js +0 -4
- package/dist/writers/animations-md.d.ts +0 -17
- package/dist/writers/animations-md.js +0 -313
- package/dist/writers/components-md.d.ts +0 -8
- package/dist/writers/components-md.js +0 -151
- package/dist/writers/design-md.d.ts +0 -7
- package/dist/writers/design-md.js +0 -704
- package/dist/writers/interactions-md.d.ts +0 -8
- package/dist/writers/interactions-md.js +0 -146
- package/dist/writers/layout-md.d.ts +0 -8
- package/dist/writers/layout-md.js +0 -120
- package/dist/writers/skill.d.ts +0 -12
- package/dist/writers/skill.js +0 -1006
- package/dist/writers/tokens-json.d.ts +0 -11
- package/dist/writers/tokens-json.js +0 -164
package/dist/modes/dir.js
DELETED
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.runDirMode = runDirMode;
|
|
4
|
-
const framework_1 = require("../extractors/framework");
|
|
5
|
-
const tailwind_1 = require("../extractors/tokens/tailwind");
|
|
6
|
-
const css_1 = require("../extractors/tokens/css");
|
|
7
|
-
const tokens_file_1 = require("../extractors/tokens/tokens-file");
|
|
8
|
-
const components_1 = require("../extractors/components");
|
|
9
|
-
const normalizer_1 = require("../normalizer");
|
|
10
|
-
/**
|
|
11
|
-
* DIR mode: scan a local project directory and extract design tokens.
|
|
12
|
-
*/
|
|
13
|
-
async function runDirMode(projectDir, nameOverride) {
|
|
14
|
-
// Step 1: Detect frameworks
|
|
15
|
-
const frameworks = (0, framework_1.detectFrameworks)(projectDir);
|
|
16
|
-
const projectName = (0, framework_1.getProjectName)(projectDir, nameOverride);
|
|
17
|
-
// Step 2: Detect project libraries (icons, state, animations)
|
|
18
|
-
const libraries = (0, components_1.detectProjectLibraries)(projectDir);
|
|
19
|
-
// Step 3: Extract raw tokens from all sources (priority order)
|
|
20
|
-
const tailwindTokens = (0, tailwind_1.extractTailwindTokens)(projectDir);
|
|
21
|
-
const tokensFileTokens = (0, tokens_file_1.extractTokensFile)(projectDir);
|
|
22
|
-
const cssTokens = (0, css_1.extractCSSTokens)(projectDir);
|
|
23
|
-
// Merge all raw tokens
|
|
24
|
-
const merged = mergeRawTokens([tailwindTokens, tokensFileTokens, cssTokens]);
|
|
25
|
-
// Step 4: Extract components
|
|
26
|
-
const components = (0, components_1.extractComponents)(projectDir);
|
|
27
|
-
// Step 5: Scan component files for additional color/font tokens
|
|
28
|
-
for (const comp of components) {
|
|
29
|
-
extractComponentTokens(comp, merged);
|
|
30
|
-
}
|
|
31
|
-
// Step 6: Collect animation tokens from components
|
|
32
|
-
for (const comp of components) {
|
|
33
|
-
if (comp.hasAnimation) {
|
|
34
|
-
for (const detail of comp.animationDetails) {
|
|
35
|
-
if (detail.startsWith('framer-motion')) {
|
|
36
|
-
merged.animations.push({
|
|
37
|
-
name: 'framer-motion',
|
|
38
|
-
type: 'framer-motion',
|
|
39
|
-
value: detail,
|
|
40
|
-
source: comp.filePath,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
else if (detail.startsWith('spring:')) {
|
|
44
|
-
merged.animations.push({
|
|
45
|
-
name: 'spring-config',
|
|
46
|
-
type: 'spring',
|
|
47
|
-
value: detail.replace('spring: ', ''),
|
|
48
|
-
source: comp.filePath,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
else if (detail.startsWith('tw-animate-')) {
|
|
52
|
-
merged.animations.push({
|
|
53
|
-
name: detail.replace('tw-', ''),
|
|
54
|
-
type: 'css-keyframe',
|
|
55
|
-
value: detail,
|
|
56
|
-
source: comp.filePath,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
// Step 7: Normalize into clean DesignProfile
|
|
63
|
-
return (0, normalizer_1.normalize)(projectName, frameworks, merged, components, libraries);
|
|
64
|
-
}
|
|
65
|
-
function mergeRawTokens(sources) {
|
|
66
|
-
const merged = {
|
|
67
|
-
colors: [],
|
|
68
|
-
fonts: [],
|
|
69
|
-
spacingValues: [],
|
|
70
|
-
shadows: [],
|
|
71
|
-
cssVariables: [],
|
|
72
|
-
breakpoints: [],
|
|
73
|
-
borderRadii: [],
|
|
74
|
-
gradients: [],
|
|
75
|
-
fontVarMap: {},
|
|
76
|
-
animations: [],
|
|
77
|
-
darkModeVars: [],
|
|
78
|
-
zIndexValues: [],
|
|
79
|
-
containerMaxWidth: null,
|
|
80
|
-
fontSources: [],
|
|
81
|
-
pageSections: [],
|
|
82
|
-
transitionDurations: [],
|
|
83
|
-
transitionEasings: [],
|
|
84
|
-
};
|
|
85
|
-
for (const src of sources) {
|
|
86
|
-
// Merge colors, deduplicating by hex value
|
|
87
|
-
for (const color of src.colors) {
|
|
88
|
-
const existing = merged.colors.find(c => c.value === color.value);
|
|
89
|
-
if (existing) {
|
|
90
|
-
existing.frequency += color.frequency;
|
|
91
|
-
if (color.name && !existing.name)
|
|
92
|
-
existing.name = color.name;
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
merged.colors.push({ ...color });
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
// Merge fonts
|
|
99
|
-
for (const font of src.fonts) {
|
|
100
|
-
if (font.family && !merged.fonts.find(f => f.family === font.family && f.size === font.size)) {
|
|
101
|
-
merged.fonts.push({ ...font });
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
// Merge spacing
|
|
105
|
-
merged.spacingValues.push(...src.spacingValues);
|
|
106
|
-
// Merge shadows
|
|
107
|
-
for (const shadow of src.shadows) {
|
|
108
|
-
if (!merged.shadows.find(s => s.value === shadow.value)) {
|
|
109
|
-
merged.shadows.push({ ...shadow });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// Merge CSS variables
|
|
113
|
-
for (const v of src.cssVariables) {
|
|
114
|
-
if (!merged.cssVariables.find(cv => cv.name === v.name)) {
|
|
115
|
-
merged.cssVariables.push({ ...v });
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
// Merge breakpoints (prefer tailwind over css)
|
|
119
|
-
for (const bp of src.breakpoints) {
|
|
120
|
-
if (!merged.breakpoints.find(b => b.value === bp.value)) {
|
|
121
|
-
merged.breakpoints.push({ ...bp });
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
// Merge border radii
|
|
125
|
-
if (src.borderRadii) {
|
|
126
|
-
for (const r of src.borderRadii) {
|
|
127
|
-
if (!merged.borderRadii.includes(r))
|
|
128
|
-
merged.borderRadii.push(r);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
// Merge gradients
|
|
132
|
-
if (src.gradients) {
|
|
133
|
-
merged.gradients.push(...src.gradients);
|
|
134
|
-
}
|
|
135
|
-
// Merge font var map
|
|
136
|
-
if (src.fontVarMap) {
|
|
137
|
-
Object.assign(merged.fontVarMap, src.fontVarMap);
|
|
138
|
-
}
|
|
139
|
-
// Merge animations
|
|
140
|
-
if (src.animations) {
|
|
141
|
-
merged.animations.push(...src.animations);
|
|
142
|
-
}
|
|
143
|
-
// Merge dark mode vars
|
|
144
|
-
if (src.darkModeVars) {
|
|
145
|
-
for (const dmv of src.darkModeVars) {
|
|
146
|
-
if (!merged.darkModeVars.find(d => d.variable === dmv.variable)) {
|
|
147
|
-
merged.darkModeVars.push(dmv);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
// Merge z-index values
|
|
152
|
-
if (src.zIndexValues) {
|
|
153
|
-
for (const z of src.zIndexValues) {
|
|
154
|
-
if (!merged.zIndexValues.includes(z))
|
|
155
|
-
merged.zIndexValues.push(z);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
// Container max-width: prefer explicit
|
|
159
|
-
if (src.containerMaxWidth && !merged.containerMaxWidth) {
|
|
160
|
-
merged.containerMaxWidth = src.containerMaxWidth;
|
|
161
|
-
}
|
|
162
|
-
// Merge font sources
|
|
163
|
-
if (src.fontSources) {
|
|
164
|
-
for (const fs of src.fontSources) {
|
|
165
|
-
if (!merged.fontSources.find(f => f.family === fs.family && f.src === fs.src)) {
|
|
166
|
-
merged.fontSources.push(fs);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
// Merge page sections
|
|
171
|
-
if (src.pageSections) {
|
|
172
|
-
for (const ps of src.pageSections) {
|
|
173
|
-
if (!merged.pageSections.find(p => p.type === ps.type)) {
|
|
174
|
-
merged.pageSections.push(ps);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
// Merge transition durations/easings
|
|
179
|
-
if (src.transitionDurations) {
|
|
180
|
-
for (const d of src.transitionDurations) {
|
|
181
|
-
if (!merged.transitionDurations.includes(d))
|
|
182
|
-
merged.transitionDurations.push(d);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
if (src.transitionEasings) {
|
|
186
|
-
for (const e of src.transitionEasings) {
|
|
187
|
-
if (!merged.transitionEasings.includes(e))
|
|
188
|
-
merged.transitionEasings.push(e);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
return merged;
|
|
193
|
-
}
|
|
194
|
-
function extractComponentTokens(comp, tokens) {
|
|
195
|
-
if (comp.jsxSnippet) {
|
|
196
|
-
const hexMatches = comp.jsxSnippet.matchAll(/#([0-9a-fA-F]{3,6})\b/g);
|
|
197
|
-
for (const m of hexMatches) {
|
|
198
|
-
let hex = m[0].toLowerCase();
|
|
199
|
-
if (hex.length === 4) {
|
|
200
|
-
const [, r, g, b] = hex.split('');
|
|
201
|
-
hex = `#${r}${r}${g}${g}${b}${b}`;
|
|
202
|
-
}
|
|
203
|
-
const existing = tokens.colors.find(c => c.value === hex);
|
|
204
|
-
if (existing) {
|
|
205
|
-
existing.frequency++;
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
tokens.colors.push({ value: hex, frequency: 1, source: 'component' });
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
//# sourceMappingURL=dir.js.map
|
package/dist/modes/repo.d.ts
DELETED
package/dist/modes/repo.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.runRepoMode = runRepoMode;
|
|
37
|
-
const tmp = __importStar(require("tmp"));
|
|
38
|
-
const dir_1 = require("./dir");
|
|
39
|
-
/**
|
|
40
|
-
* REPO mode: clone a git repo into a temp directory, then run dir mode.
|
|
41
|
-
*/
|
|
42
|
-
async function runRepoMode(repoUrl, nameOverride) {
|
|
43
|
-
// Import simple-git
|
|
44
|
-
const { simpleGit } = await Promise.resolve().then(() => __importStar(require('simple-git')));
|
|
45
|
-
const git = simpleGit();
|
|
46
|
-
// Create temp directory
|
|
47
|
-
const tmpDir = tmp.dirSync({ unsafeCleanup: true, prefix: 'skillui-' });
|
|
48
|
-
const cloneDir = tmpDir.name;
|
|
49
|
-
try {
|
|
50
|
-
process.stdout.write(' Cloning...');
|
|
51
|
-
await git.clone(repoUrl, cloneDir, ['--depth', '1', '--single-branch']);
|
|
52
|
-
console.log(' \u2713');
|
|
53
|
-
// Derive project name from repo URL if not overridden
|
|
54
|
-
const derivedName = nameOverride || deriveRepoName(repoUrl);
|
|
55
|
-
// Run dir mode on the cloned repo
|
|
56
|
-
const profile = await (0, dir_1.runDirMode)(cloneDir, derivedName);
|
|
57
|
-
return profile;
|
|
58
|
-
}
|
|
59
|
-
finally {
|
|
60
|
-
// Cleanup temp directory
|
|
61
|
-
try {
|
|
62
|
-
tmpDir.removeCallback();
|
|
63
|
-
}
|
|
64
|
-
catch {
|
|
65
|
-
// Best effort cleanup
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
function deriveRepoName(url) {
|
|
70
|
-
// Handle GitHub URLs: https://github.com/org/repo or git@github.com:org/repo.git
|
|
71
|
-
const match = url.match(/\/([^\/]+?)(?:\.git)?$/);
|
|
72
|
-
if (match)
|
|
73
|
-
return match[1];
|
|
74
|
-
return 'project';
|
|
75
|
-
}
|
|
76
|
-
//# sourceMappingURL=repo.js.map
|
package/dist/modes/ultra.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { DesignProfile } from '../types';
|
|
2
|
-
import { UltraOptions, UltraResult } from '../types-ultra';
|
|
3
|
-
/**
|
|
4
|
-
* Ultra mode orchestrator.
|
|
5
|
-
*
|
|
6
|
-
* Runs AFTER the normal url mode pipeline. Adds:
|
|
7
|
-
* - screens/pages/ — full-page screenshots per crawled page
|
|
8
|
-
* - screens/sections/ — clipped section screenshots per page
|
|
9
|
-
* - screens/states/ — hover/focus state screenshots per interactive element
|
|
10
|
-
* - screens/scroll/ — 7 scroll-journey screenshots + video first frames
|
|
11
|
-
* - references/LAYOUT.md
|
|
12
|
-
* - references/INTERACTIONS.md
|
|
13
|
-
* - references/COMPONENTS.md
|
|
14
|
-
* - references/ANIMATIONS.md ← NEW: cinematic animation documentation
|
|
15
|
-
* - tokens/colors.json
|
|
16
|
-
* - tokens/spacing.json
|
|
17
|
-
* - tokens/typography.json
|
|
18
|
-
*
|
|
19
|
-
* All existing outputs remain untouched.
|
|
20
|
-
*/
|
|
21
|
-
export declare function runUltraMode(url: string, profile: DesignProfile, skillDir: string, opts: UltraOptions): Promise<UltraResult>;
|
|
22
|
-
//# sourceMappingURL=ultra.d.ts.map
|
package/dist/modes/ultra.js
DELETED
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.runUltraMode = runUltraMode;
|
|
37
|
-
const fs = __importStar(require("fs"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
|
-
const pages_1 = require("../extractors/ultra/pages");
|
|
40
|
-
const interactions_1 = require("../extractors/ultra/interactions");
|
|
41
|
-
const layout_1 = require("../extractors/ultra/layout");
|
|
42
|
-
const components_dom_1 = require("../extractors/ultra/components-dom");
|
|
43
|
-
const animations_1 = require("../extractors/ultra/animations");
|
|
44
|
-
const layout_md_1 = require("../writers/layout-md");
|
|
45
|
-
const interactions_md_1 = require("../writers/interactions-md");
|
|
46
|
-
const components_md_1 = require("../writers/components-md");
|
|
47
|
-
const animations_md_1 = require("../writers/animations-md");
|
|
48
|
-
const tokens_json_1 = require("../writers/tokens-json");
|
|
49
|
-
const playwright_loader_1 = require("../playwright-loader");
|
|
50
|
-
/**
|
|
51
|
-
* Ultra mode orchestrator.
|
|
52
|
-
*
|
|
53
|
-
* Runs AFTER the normal url mode pipeline. Adds:
|
|
54
|
-
* - screens/pages/ — full-page screenshots per crawled page
|
|
55
|
-
* - screens/sections/ — clipped section screenshots per page
|
|
56
|
-
* - screens/states/ — hover/focus state screenshots per interactive element
|
|
57
|
-
* - screens/scroll/ — 7 scroll-journey screenshots + video first frames
|
|
58
|
-
* - references/LAYOUT.md
|
|
59
|
-
* - references/INTERACTIONS.md
|
|
60
|
-
* - references/COMPONENTS.md
|
|
61
|
-
* - references/ANIMATIONS.md ← NEW: cinematic animation documentation
|
|
62
|
-
* - tokens/colors.json
|
|
63
|
-
* - tokens/spacing.json
|
|
64
|
-
* - tokens/typography.json
|
|
65
|
-
*
|
|
66
|
-
* All existing outputs remain untouched.
|
|
67
|
-
*/
|
|
68
|
-
async function runUltraMode(url, profile, skillDir, opts) {
|
|
69
|
-
// Ensure all output directories exist
|
|
70
|
-
fs.mkdirSync(path.join(skillDir, 'screens', 'pages'), { recursive: true });
|
|
71
|
-
fs.mkdirSync(path.join(skillDir, 'screens', 'sections'), { recursive: true });
|
|
72
|
-
fs.mkdirSync(path.join(skillDir, 'screens', 'states'), { recursive: true });
|
|
73
|
-
fs.mkdirSync(path.join(skillDir, 'screens', 'scroll'), { recursive: true });
|
|
74
|
-
fs.mkdirSync(path.join(skillDir, 'references'), { recursive: true });
|
|
75
|
-
fs.mkdirSync(path.join(skillDir, 'tokens'), { recursive: true });
|
|
76
|
-
const hasPlaywright = (0, playwright_loader_1.loadPlaywright)() !== null;
|
|
77
|
-
if (!hasPlaywright) {
|
|
78
|
-
process.stdout.write('\n ⚠ Playwright not found — ultra visual features skipped\n');
|
|
79
|
-
process.stdout.write(' Fix: npm install -g playwright && npx playwright install chromium\n\n');
|
|
80
|
-
(0, tokens_json_1.writeTokensJson)(profile, skillDir);
|
|
81
|
-
writeStubs(skillDir);
|
|
82
|
-
const emptyAnim = emptyAnimResult();
|
|
83
|
-
return { pageScreenshots: [], sectionScreenshots: [], interactions: [], layouts: [], domComponents: [], animations: emptyAnim };
|
|
84
|
-
}
|
|
85
|
-
// ── Step 1: Animation extraction (scroll journey + keyframes + libraries) ──
|
|
86
|
-
process.stdout.write(' Extracting animations & scroll journey...');
|
|
87
|
-
const animations = await (0, animations_1.captureAnimations)(url, skillDir);
|
|
88
|
-
console.log(` ✓ (${animations.keyframes.length} keyframes · ${animations.scrollFrames.length} scroll frames · ${animations.libraries.length} libs)`);
|
|
89
|
-
// ── Step 2: Multi-page screenshots + section clips ─────────────────────
|
|
90
|
-
process.stdout.write(` Crawling ${opts.screens} pages...`);
|
|
91
|
-
const { pages, sections } = await (0, pages_1.capturePageScreenshots)(url, skillDir, opts.screens);
|
|
92
|
-
console.log(` ✓ (${pages.length} pages · ${sections.length} sections)`);
|
|
93
|
-
// ── Step 3: Micro-interactions ────────────────────────────────────────
|
|
94
|
-
process.stdout.write(' Capturing interactions...');
|
|
95
|
-
const interactions = await (0, interactions_1.captureInteractions)(url, skillDir);
|
|
96
|
-
console.log(` ✓ (${interactions.length} components)`);
|
|
97
|
-
// ── Step 4: Layout extraction ──────────────────────────────────────────
|
|
98
|
-
process.stdout.write(' Extracting layout...');
|
|
99
|
-
const layouts = await (0, layout_1.extractLayouts)(url);
|
|
100
|
-
console.log(` ✓ (${layouts.length} containers)`);
|
|
101
|
-
// ── Step 5: DOM component detection ───────────────────────────────────
|
|
102
|
-
process.stdout.write(' Detecting DOM components...');
|
|
103
|
-
const domComponents = await (0, components_dom_1.detectDOMComponents)(url);
|
|
104
|
-
console.log(` ✓ (${domComponents.length} patterns)`);
|
|
105
|
-
// ── Step 6: Write all reference files ─────────────────────────────────
|
|
106
|
-
process.stdout.write(' Writing extended outputs...');
|
|
107
|
-
const refsDir = path.join(skillDir, 'references');
|
|
108
|
-
// ANIMATIONS.md — cinematic motion documentation
|
|
109
|
-
const animMd = (0, animations_md_1.generateAnimationsMd)(animations, profile);
|
|
110
|
-
fs.writeFileSync(path.join(refsDir, 'ANIMATIONS.md'), animMd, 'utf-8');
|
|
111
|
-
// LAYOUT.md
|
|
112
|
-
const layoutMd = (0, layout_md_1.generateLayoutMd)(layouts, profile);
|
|
113
|
-
fs.writeFileSync(path.join(refsDir, 'LAYOUT.md'), layoutMd, 'utf-8');
|
|
114
|
-
// INTERACTIONS.md
|
|
115
|
-
const interactionsMd = (0, interactions_md_1.generateInteractionsMd)(interactions, profile);
|
|
116
|
-
fs.writeFileSync(path.join(refsDir, 'INTERACTIONS.md'), interactionsMd, 'utf-8');
|
|
117
|
-
// COMPONENTS.md
|
|
118
|
-
const componentsMd = (0, components_md_1.generateComponentsMd)(domComponents, profile);
|
|
119
|
-
fs.writeFileSync(path.join(refsDir, 'COMPONENTS.md'), componentsMd, 'utf-8');
|
|
120
|
-
// Token JSON files
|
|
121
|
-
(0, tokens_json_1.writeTokensJson)(profile, skillDir);
|
|
122
|
-
// VISUAL_GUIDE.md — master visual reference embedding all screenshots
|
|
123
|
-
const visualGuideMd = generateVisualGuideMd(profile, pages, sections, animations);
|
|
124
|
-
fs.writeFileSync(path.join(refsDir, 'VISUAL_GUIDE.md'), visualGuideMd, 'utf-8');
|
|
125
|
-
// Ultra screenshot index
|
|
126
|
-
writeScreensIndex(pages, sections, animations, skillDir);
|
|
127
|
-
console.log(' ✓');
|
|
128
|
-
// ── Print ultra summary ────────────────────────────────────────────────
|
|
129
|
-
printUltraSummary(animations);
|
|
130
|
-
return { pageScreenshots: pages, sectionScreenshots: sections, interactions, layouts, domComponents, animations };
|
|
131
|
-
}
|
|
132
|
-
// ── Visual Guide Generator ────────────────────────────────────────────
|
|
133
|
-
function generateVisualGuideMd(profile, pages, sections, anim) {
|
|
134
|
-
let md = `# ${profile.projectName} — Visual Guide\n\n`;
|
|
135
|
-
md += `> Master visual reference. Study every screenshot carefully before implementing any UI.\n`;
|
|
136
|
-
md += `> Match colors, layout, typography, spacing, and motion states exactly.\n\n`;
|
|
137
|
-
// Animation stack summary
|
|
138
|
-
if (anim.libraries.length > 0) {
|
|
139
|
-
const libs = anim.libraries.map(l => `**${l.name}**`).join(', ');
|
|
140
|
-
md += `**Motion Stack:** ${libs}\n\n`;
|
|
141
|
-
}
|
|
142
|
-
if (anim.webglDetected) {
|
|
143
|
-
md += `**WebGL/3D:** Detected (${anim.canvasCount} canvas elements) — replicate with Three.js or CSS 3D transforms\n\n`;
|
|
144
|
-
}
|
|
145
|
-
// Scroll journey — most important section
|
|
146
|
-
if (anim.scrollFrames.length > 0) {
|
|
147
|
-
md += `## Scroll Journey\n\n`;
|
|
148
|
-
md += `The page has cinematic scroll animations. Each screenshot below shows the exact visual state at that scroll depth.\n`;
|
|
149
|
-
md += `**Replicate these transitions precisely** — the design changes dramatically as you scroll.\n\n`;
|
|
150
|
-
for (const frame of anim.scrollFrames) {
|
|
151
|
-
const relPath = `../screens/scroll/${path.basename(frame.filePath)}`;
|
|
152
|
-
const label = frame.scrollPercent === 0 ? 'Hero — Above the fold'
|
|
153
|
-
: frame.scrollPercent === 100 ? 'Footer — End of page'
|
|
154
|
-
: `${frame.scrollPercent}% scroll depth`;
|
|
155
|
-
md += `### ${label}\n\n`;
|
|
156
|
-
md += `*Scroll position: ${frame.scrollY}px of ${frame.pageHeight}px total*\n\n`;
|
|
157
|
-
md += `\n\n`;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
// Video backgrounds
|
|
161
|
-
if (anim.videos.some(v => v.firstFramePath)) {
|
|
162
|
-
md += `## Video Backgrounds\n\n`;
|
|
163
|
-
md += `These videos play as background elements. Use first-frame as poster image while video loads.\n\n`;
|
|
164
|
-
for (const v of anim.videos.filter(vv => vv.firstFramePath)) {
|
|
165
|
-
const relPath = `../screens/scroll/${path.basename(v.firstFramePath)}`;
|
|
166
|
-
md += `### Video ${v.index} (${v.role})\n\n`;
|
|
167
|
-
if (v.src)
|
|
168
|
-
md += `*Source: \`${v.src.slice(0, 80)}...\`*\n\n`;
|
|
169
|
-
md += `\n\n`;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
// Page screenshots
|
|
173
|
-
if (pages.length > 0) {
|
|
174
|
-
md += `## Full Page Screenshots\n\n`;
|
|
175
|
-
for (const p of pages) {
|
|
176
|
-
const relPath = `../screens/pages/${path.basename(p.filePath)}`;
|
|
177
|
-
md += `### ${p.title}\n\n`;
|
|
178
|
-
md += `*URL: \`${p.url}\`*\n\n`;
|
|
179
|
-
md += `\n\n`;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
// Section clips
|
|
183
|
-
if (sections.length > 0) {
|
|
184
|
-
md += `## Section Screenshots\n\n`;
|
|
185
|
-
md += `Clipped sections showing individual components in context.\n\n`;
|
|
186
|
-
for (const s of sections) {
|
|
187
|
-
const relPath = `../screens/sections/${path.basename(s.filePath)}`;
|
|
188
|
-
md += `### Section ${s.index} — \`${s.selector}\`\n\n`;
|
|
189
|
-
md += `*${s.width}×${s.height}px*\n\n`;
|
|
190
|
-
md += `\n\n`;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return md;
|
|
194
|
-
}
|
|
195
|
-
// ── Helpers ───────────────────────────────────────────────────────────
|
|
196
|
-
function printUltraSummary(anim) {
|
|
197
|
-
const libs = anim.libraries.map(l => l.name).join(', ') || 'none';
|
|
198
|
-
console.log('');
|
|
199
|
-
console.log(` Animation Stack: ${libs}`);
|
|
200
|
-
if (anim.webglDetected)
|
|
201
|
-
console.log(` WebGL/3D: detected (${anim.canvasCount} canvas elements)`);
|
|
202
|
-
if (anim.videos.length > 0) {
|
|
203
|
-
const bg = anim.videos.filter(v => v.role === 'background').length;
|
|
204
|
-
console.log(` Video: ${anim.videos.length} elements (${bg} background)`);
|
|
205
|
-
}
|
|
206
|
-
if (anim.lottieCount > 0)
|
|
207
|
-
console.log(` Lottie: ${anim.lottieCount} players`);
|
|
208
|
-
if (anim.keyframes.length > 0)
|
|
209
|
-
console.log(` Keyframes: ${anim.keyframes.length} extracted`);
|
|
210
|
-
if (anim.scrollPatterns.length > 0)
|
|
211
|
-
console.log(` Scroll patterns: ${anim.scrollPatterns.length} types`);
|
|
212
|
-
}
|
|
213
|
-
function writeScreensIndex(pages, sections, anim, skillDir) {
|
|
214
|
-
let md = `# Screenshot Index\n\n`;
|
|
215
|
-
// Scroll journey (most important for animation sites)
|
|
216
|
-
if (anim.scrollFrames.length > 0) {
|
|
217
|
-
md += `## Scroll Journey\n\n`;
|
|
218
|
-
md += `> Shows the cinematic state at each point of the page\n\n`;
|
|
219
|
-
md += `| Scroll | Y Position | File |\n`;
|
|
220
|
-
md += `|--------|-----------|------|\n`;
|
|
221
|
-
for (const f of anim.scrollFrames) {
|
|
222
|
-
md += `| ${f.scrollPercent}% | ${f.scrollY}px | \`${f.filePath}\` |\n`;
|
|
223
|
-
}
|
|
224
|
-
md += `\n`;
|
|
225
|
-
}
|
|
226
|
-
// Video frames
|
|
227
|
-
if (anim.videos.some(v => v.firstFramePath)) {
|
|
228
|
-
md += `## Video First Frames\n\n`;
|
|
229
|
-
for (const v of anim.videos) {
|
|
230
|
-
if (v.firstFramePath) {
|
|
231
|
-
md += `- Video ${v.index} (${v.role}): \`${v.firstFramePath}\`\n`;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
md += `\n`;
|
|
235
|
-
}
|
|
236
|
-
if (pages.length > 0) {
|
|
237
|
-
md += `## Pages\n\n`;
|
|
238
|
-
md += `| Page | URL | File |\n`;
|
|
239
|
-
md += `|------|-----|------|\n`;
|
|
240
|
-
for (const p of pages) {
|
|
241
|
-
md += `| ${p.title} | \`${p.url}\` | \`${p.filePath}\` |\n`;
|
|
242
|
-
}
|
|
243
|
-
md += `\n`;
|
|
244
|
-
}
|
|
245
|
-
if (sections.length > 0) {
|
|
246
|
-
md += `## Sections\n\n`;
|
|
247
|
-
md += `| Page | Section | File |\n`;
|
|
248
|
-
md += `|------|---------|------|\n`;
|
|
249
|
-
for (const s of sections) {
|
|
250
|
-
md += `| ${s.page} | #${s.index} (${s.selector}) | \`${s.filePath}\` |\n`;
|
|
251
|
-
}
|
|
252
|
-
md += `\n`;
|
|
253
|
-
}
|
|
254
|
-
fs.writeFileSync(path.join(skillDir, 'screens', 'INDEX.md'), md, 'utf-8');
|
|
255
|
-
}
|
|
256
|
-
function writeStubs(skillDir) {
|
|
257
|
-
const refsDir = path.join(skillDir, 'references');
|
|
258
|
-
const note = '> Install Playwright to enable: `npm install playwright && npx playwright install chromium`\n\nRun `skillui --url <url> --mode ultra` after installing.\n';
|
|
259
|
-
for (const file of ['ANIMATIONS.md', 'LAYOUT.md', 'INTERACTIONS.md', 'COMPONENTS.md']) {
|
|
260
|
-
const filePath = path.join(refsDir, file);
|
|
261
|
-
if (!fs.existsSync(filePath)) {
|
|
262
|
-
const title = file.replace('.md', '').replace(/-/g, ' ');
|
|
263
|
-
fs.writeFileSync(filePath, `# ${title} Reference\n\n${note}`, 'utf-8');
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
function emptyAnimResult() {
|
|
268
|
-
return {
|
|
269
|
-
keyframes: [],
|
|
270
|
-
scrollFrames: [],
|
|
271
|
-
libraries: [],
|
|
272
|
-
videos: [],
|
|
273
|
-
scrollPatterns: [],
|
|
274
|
-
animationVars: [],
|
|
275
|
-
globalTransitions: [],
|
|
276
|
-
canvasCount: 0,
|
|
277
|
-
webglDetected: false,
|
|
278
|
-
lottieCount: 0,
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
//# sourceMappingURL=ultra.js.map
|
package/dist/modes/url.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { DesignProfile } from '../types';
|
|
2
|
-
/**
|
|
3
|
-
* URL mode: crawl a live website and extract design tokens.
|
|
4
|
-
*
|
|
5
|
-
* Strategy:
|
|
6
|
-
* 1. ALWAYS fetch HTML + linked CSS via HTTP (no Playwright needed)
|
|
7
|
-
* 2. If Playwright is available, ALSO extract computed styles from live DOM
|
|
8
|
-
* 3. Merge both token sets for maximum coverage
|
|
9
|
-
*/
|
|
10
|
-
export declare function runUrlMode(url: string, nameOverride?: string, skillDir?: string): Promise<{
|
|
11
|
-
profile: DesignProfile;
|
|
12
|
-
screenshotPath: string | null;
|
|
13
|
-
}>;
|
|
14
|
-
//# sourceMappingURL=url.d.ts.map
|