skillui 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.js +202 -0
  3. package/dist/extractors/components.d.ts +11 -0
  4. package/dist/extractors/components.js +455 -0
  5. package/dist/extractors/framework.d.ts +4 -0
  6. package/dist/extractors/framework.js +126 -0
  7. package/dist/extractors/tokens/computed.d.ts +7 -0
  8. package/dist/extractors/tokens/computed.js +249 -0
  9. package/dist/extractors/tokens/css.d.ts +3 -0
  10. package/dist/extractors/tokens/css.js +510 -0
  11. package/dist/extractors/tokens/http-css.d.ts +14 -0
  12. package/dist/extractors/tokens/http-css.js +1689 -0
  13. package/dist/extractors/tokens/tailwind.d.ts +3 -0
  14. package/dist/extractors/tokens/tailwind.js +353 -0
  15. package/dist/extractors/tokens/tokens-file.d.ts +3 -0
  16. package/dist/extractors/tokens/tokens-file.js +229 -0
  17. package/dist/extractors/ultra/animations.d.ts +21 -0
  18. package/dist/extractors/ultra/animations.js +530 -0
  19. package/dist/extractors/ultra/components-dom.d.ts +13 -0
  20. package/dist/extractors/ultra/components-dom.js +152 -0
  21. package/dist/extractors/ultra/interactions.d.ts +14 -0
  22. package/dist/extractors/ultra/interactions.js +225 -0
  23. package/dist/extractors/ultra/layout.d.ts +14 -0
  24. package/dist/extractors/ultra/layout.js +126 -0
  25. package/dist/extractors/ultra/pages.d.ts +16 -0
  26. package/dist/extractors/ultra/pages.js +231 -0
  27. package/dist/font-resolver.d.ts +10 -0
  28. package/dist/font-resolver.js +280 -0
  29. package/dist/modes/dir.d.ts +6 -0
  30. package/dist/modes/dir.js +213 -0
  31. package/dist/modes/repo.d.ts +6 -0
  32. package/dist/modes/repo.js +76 -0
  33. package/dist/modes/ultra.d.ts +22 -0
  34. package/dist/modes/ultra.js +285 -0
  35. package/dist/modes/url.d.ts +14 -0
  36. package/dist/modes/url.js +161 -0
  37. package/dist/normalizer.d.ts +11 -0
  38. package/dist/normalizer.js +867 -0
  39. package/dist/screenshot.d.ts +9 -0
  40. package/dist/screenshot.js +94 -0
  41. package/dist/types-ultra.d.ts +157 -0
  42. package/dist/types-ultra.js +4 -0
  43. package/dist/types.d.ts +182 -0
  44. package/dist/types.js +4 -0
  45. package/dist/writers/animations-md.d.ts +17 -0
  46. package/dist/writers/animations-md.js +313 -0
  47. package/dist/writers/components-md.d.ts +8 -0
  48. package/dist/writers/components-md.js +151 -0
  49. package/dist/writers/design-md.d.ts +7 -0
  50. package/dist/writers/design-md.js +704 -0
  51. package/dist/writers/interactions-md.d.ts +8 -0
  52. package/dist/writers/interactions-md.js +146 -0
  53. package/dist/writers/layout-md.d.ts +8 -0
  54. package/dist/writers/layout-md.js +120 -0
  55. package/dist/writers/skill.d.ts +12 -0
  56. package/dist/writers/skill.js +1006 -0
  57. package/dist/writers/tokens-json.d.ts +11 -0
  58. package/dist/writers/tokens-json.js +164 -0
  59. package/package.json +78 -0
@@ -0,0 +1,126 @@
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.detectFrameworks = detectFrameworks;
37
+ exports.getProjectName = getProjectName;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const DEP_MAP = [
41
+ { pkg: 'tailwindcss', id: 'tailwind', name: 'Tailwind CSS' },
42
+ { pkg: 'react', id: 'react', name: 'React' },
43
+ { pkg: 'vue', id: 'vue', name: 'Vue' },
44
+ { pkg: 'next', id: 'next', name: 'Next.js' },
45
+ { pkg: 'nuxt', id: 'nuxt', name: 'Nuxt' },
46
+ { pkg: 'svelte', id: 'svelte', name: 'Svelte' },
47
+ { pkg: '@angular/core', id: 'angular', name: 'Angular' },
48
+ { pkg: 'styled-components', id: 'css-in-js', name: 'CSS-in-JS (styled-components)' },
49
+ { pkg: '@emotion/react', id: 'css-in-js', name: 'CSS-in-JS (Emotion)' },
50
+ { pkg: '@emotion/styled', id: 'css-in-js', name: 'CSS-in-JS (Emotion)' },
51
+ ];
52
+ function detectFrameworks(projectDir) {
53
+ const frameworks = [];
54
+ const seen = new Set();
55
+ // Read package.json
56
+ const pkgPath = path.join(projectDir, 'package.json');
57
+ if (fs.existsSync(pkgPath)) {
58
+ try {
59
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
60
+ const allDeps = {
61
+ ...pkg.dependencies,
62
+ ...pkg.devDependencies,
63
+ };
64
+ for (const mapping of DEP_MAP) {
65
+ if (allDeps[mapping.pkg] && !seen.has(mapping.id)) {
66
+ seen.add(mapping.id);
67
+ frameworks.push({
68
+ id: mapping.id,
69
+ name: mapping.name,
70
+ version: allDeps[mapping.pkg].replace(/[\^~>=<]/g, ''),
71
+ });
72
+ }
73
+ }
74
+ }
75
+ catch {
76
+ // Ignore malformed package.json
77
+ }
78
+ }
79
+ // Check for CSS Modules
80
+ if (!seen.has('css-modules')) {
81
+ if (hasCSSModules(projectDir)) {
82
+ seen.add('css-modules');
83
+ frameworks.push({ id: 'css-modules', name: 'CSS Modules' });
84
+ }
85
+ }
86
+ return frameworks;
87
+ }
88
+ function hasCSSModules(dir, depth = 0) {
89
+ if (depth > 4)
90
+ return false;
91
+ try {
92
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
93
+ for (const entry of entries) {
94
+ if (entry.name === 'node_modules' || entry.name === '.git')
95
+ continue;
96
+ if (entry.isFile() && /\.module\.(css|scss|less)$/.test(entry.name)) {
97
+ return true;
98
+ }
99
+ if (entry.isDirectory() && depth < 4) {
100
+ if (hasCSSModules(path.join(dir, entry.name), depth + 1))
101
+ return true;
102
+ }
103
+ }
104
+ }
105
+ catch {
106
+ // Permission errors etc.
107
+ }
108
+ return false;
109
+ }
110
+ function getProjectName(projectDir, overrideName) {
111
+ if (overrideName)
112
+ return overrideName;
113
+ const pkgPath = path.join(projectDir, 'package.json');
114
+ if (fs.existsSync(pkgPath)) {
115
+ try {
116
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
117
+ if (pkg.name)
118
+ return pkg.name;
119
+ }
120
+ catch {
121
+ // Ignore
122
+ }
123
+ }
124
+ return path.basename(path.resolve(projectDir));
125
+ }
126
+ //# sourceMappingURL=framework.js.map
@@ -0,0 +1,7 @@
1
+ import { RawTokens } from '../../types';
2
+ /**
3
+ * URL mode: Extract computed styles from live DOM using Playwright.
4
+ * Playwright is an optional peer dependency.
5
+ */
6
+ export declare function extractComputedTokens(url: string, maxPages?: number): Promise<RawTokens>;
7
+ //# sourceMappingURL=computed.d.ts.map
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractComputedTokens = extractComputedTokens;
4
+ /**
5
+ * URL mode: Extract computed styles from live DOM using Playwright.
6
+ * Playwright is an optional peer dependency.
7
+ */
8
+ async function extractComputedTokens(url, maxPages = 5) {
9
+ const tokens = {
10
+ colors: [],
11
+ fonts: [],
12
+ spacingValues: [],
13
+ shadows: [],
14
+ cssVariables: [],
15
+ breakpoints: [],
16
+ borderRadii: [],
17
+ gradients: [],
18
+ fontVarMap: {},
19
+ animations: [],
20
+ darkModeVars: [],
21
+ zIndexValues: [],
22
+ containerMaxWidth: null,
23
+ fontSources: [],
24
+ pageSections: [],
25
+ transitionDurations: [],
26
+ transitionEasings: [],
27
+ };
28
+ let playwright;
29
+ try {
30
+ playwright = require('playwright');
31
+ }
32
+ catch {
33
+ // Playwright not installed — caller should handle this
34
+ return tokens;
35
+ }
36
+ const browser = await playwright.chromium.launch({ headless: true });
37
+ const context = await browser.newContext({
38
+ viewport: { width: 1440, height: 900 },
39
+ userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
40
+ });
41
+ try {
42
+ const visited = new Set();
43
+ const toVisit = [url];
44
+ while (toVisit.length > 0 && visited.size < maxPages) {
45
+ const currentUrl = toVisit.shift();
46
+ if (visited.has(currentUrl))
47
+ continue;
48
+ visited.add(currentUrl);
49
+ try {
50
+ const page = await context.newPage();
51
+ await page.goto(currentUrl, { waitUntil: 'networkidle', timeout: 20000 });
52
+ // Wait a moment for any JS-rendered content
53
+ await page.waitForTimeout(1500);
54
+ // Extract comprehensive styles from the page
55
+ const pageTokens = await page.evaluate(() => {
56
+ const colors = [];
57
+ const fonts = [];
58
+ const spacingValues = [];
59
+ const shadows = [];
60
+ const cssVars = [];
61
+ const borderRadii = [];
62
+ // ── Extract CSS custom properties from all stylesheets ──
63
+ try {
64
+ const sheets = document.styleSheets;
65
+ for (let i = 0; i < sheets.length; i++) {
66
+ try {
67
+ const rules = sheets[i].cssRules;
68
+ for (let j = 0; j < rules.length; j++) {
69
+ const rule = rules[j];
70
+ if (rule instanceof CSSStyleRule) {
71
+ // Get CSS variables from :root, body, html, .dark, etc.
72
+ if (/^(:root|html|body|\.dark)/.test(rule.selectorText)) {
73
+ for (let k = 0; k < rule.style.length; k++) {
74
+ const prop = rule.style[k];
75
+ if (prop.startsWith('--')) {
76
+ cssVars.push({
77
+ name: prop,
78
+ value: rule.style.getPropertyValue(prop).trim(),
79
+ });
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ catch {
87
+ // Cross-origin stylesheets
88
+ }
89
+ }
90
+ }
91
+ catch {
92
+ // Ignore
93
+ }
94
+ // ── Sample elements for computed styles ──
95
+ // Target semantically meaningful elements
96
+ const selectors = [
97
+ 'body',
98
+ 'header', 'nav', 'main', 'footer', 'aside',
99
+ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
100
+ 'p', 'a', 'span',
101
+ 'button', 'input', 'select', 'textarea',
102
+ 'table', 'th', 'td',
103
+ 'img', 'svg',
104
+ '[class*="card"]', '[class*="modal"]', '[class*="dialog"]',
105
+ '[class*="badge"]', '[class*="chip"]', '[class*="tag"]',
106
+ '[class*="btn"]', '[class*="button"]',
107
+ '[class*="nav"]', '[class*="menu"]',
108
+ '[class*="hero"]', '[class*="banner"]',
109
+ '[class*="container"]', '[class*="wrapper"]',
110
+ 'section', 'article', 'div',
111
+ ];
112
+ const allElements = new Set();
113
+ for (const sel of selectors) {
114
+ try {
115
+ const els = document.querySelectorAll(sel);
116
+ els.forEach(el => allElements.add(el));
117
+ }
118
+ catch {
119
+ // Invalid selector
120
+ }
121
+ }
122
+ const colorMap = new Map();
123
+ const fontMap = new Map();
124
+ const sampleSize = Math.min(allElements.size, 500);
125
+ let count = 0;
126
+ for (const el of allElements) {
127
+ if (count++ >= sampleSize)
128
+ break;
129
+ const style = getComputedStyle(el);
130
+ // ── Colors ──
131
+ for (const prop of ['color', 'backgroundColor', 'borderColor', 'outlineColor']) {
132
+ const val = style[prop];
133
+ if (val && val !== 'rgba(0, 0, 0, 0)' && val !== 'transparent' && val !== 'inherit') {
134
+ colorMap.set(val, (colorMap.get(val) || 0) + 1);
135
+ }
136
+ }
137
+ // ── Fonts ──
138
+ const family = style.fontFamily.split(',')[0].replace(/["']/g, '').trim();
139
+ if (family && family !== 'inherit') {
140
+ if (!fontMap.has(family)) {
141
+ fontMap.set(family, {
142
+ size: style.fontSize,
143
+ weight: style.fontWeight,
144
+ });
145
+ }
146
+ }
147
+ // ── Spacing ──
148
+ for (const prop of [
149
+ 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight',
150
+ 'marginTop', 'marginBottom', 'marginLeft', 'marginRight',
151
+ 'gap', 'rowGap', 'columnGap',
152
+ ]) {
153
+ const val = parseFloat(style[prop]);
154
+ if (val > 0 && val <= 200)
155
+ spacingValues.push(Math.round(val));
156
+ }
157
+ // ── Shadows ──
158
+ const shadow = style.boxShadow;
159
+ if (shadow && shadow !== 'none') {
160
+ shadows.push({ value: shadow });
161
+ }
162
+ // ── Border Radius ──
163
+ const radius = style.borderRadius;
164
+ if (radius && radius !== '0px') {
165
+ borderRadii.push(radius);
166
+ }
167
+ }
168
+ // Convert color map
169
+ for (const [val, freq] of colorMap.entries()) {
170
+ colors.push({ value: val, frequency: freq });
171
+ }
172
+ // Convert font map
173
+ for (const [family, info] of fontMap.entries()) {
174
+ fonts.push({ family, size: info.size, weight: info.weight });
175
+ }
176
+ return { colors, fonts, spacingValues, shadows, cssVars, borderRadii };
177
+ });
178
+ // Convert rgb() colors to hex
179
+ for (const color of pageTokens.colors) {
180
+ const hex = rgbStringToHex(color.value);
181
+ if (hex) {
182
+ const existing = tokens.colors.find(c => c.value === hex);
183
+ if (existing) {
184
+ existing.frequency += color.frequency;
185
+ }
186
+ else {
187
+ tokens.colors.push({ value: hex, frequency: color.frequency, source: 'computed' });
188
+ }
189
+ }
190
+ }
191
+ for (const font of pageTokens.fonts) {
192
+ if (font.family && !tokens.fonts.find(f => f.family === font.family)) {
193
+ tokens.fonts.push({ ...font, source: 'computed' });
194
+ }
195
+ }
196
+ tokens.spacingValues.push(...pageTokens.spacingValues);
197
+ for (const shadow of pageTokens.shadows) {
198
+ if (!tokens.shadows.find(s => s.value === shadow.value)) {
199
+ tokens.shadows.push(shadow);
200
+ }
201
+ }
202
+ for (const cssVar of pageTokens.cssVars) {
203
+ if (!tokens.cssVariables.find(v => v.name === cssVar.name)) {
204
+ tokens.cssVariables.push({ name: cssVar.name, value: cssVar.value });
205
+ }
206
+ }
207
+ for (const radius of pageTokens.borderRadii) {
208
+ if (!tokens.borderRadii.includes(radius)) {
209
+ tokens.borderRadii.push(radius);
210
+ }
211
+ }
212
+ // Find links for crawling
213
+ const links = await page.evaluate((baseUrl) => {
214
+ const origin = new URL(baseUrl).origin;
215
+ return Array.from(document.querySelectorAll('a[href]'))
216
+ .map(a => {
217
+ try {
218
+ return new URL(a.href, baseUrl).href;
219
+ }
220
+ catch {
221
+ return '';
222
+ }
223
+ })
224
+ .filter(href => href.startsWith(origin) && !href.includes('#'));
225
+ }, currentUrl);
226
+ for (const link of links.slice(0, 10)) {
227
+ if (!visited.has(link))
228
+ toVisit.push(link);
229
+ }
230
+ await page.close();
231
+ }
232
+ catch {
233
+ // Skip pages that fail to load
234
+ }
235
+ }
236
+ }
237
+ finally {
238
+ await browser.close();
239
+ }
240
+ return tokens;
241
+ }
242
+ function rgbStringToHex(rgb) {
243
+ const match = rgb.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);
244
+ if (!match)
245
+ return null;
246
+ const [, r, g, b] = match;
247
+ return '#' + [r, g, b].map(c => parseInt(c).toString(16).padStart(2, '0')).join('').toLowerCase();
248
+ }
249
+ //# sourceMappingURL=computed.js.map
@@ -0,0 +1,3 @@
1
+ import { RawTokens } from '../../types';
2
+ export declare function extractCSSTokens(projectDir: string): RawTokens;
3
+ //# sourceMappingURL=css.d.ts.map