@birdapi/velinstyle 1.2.2 → 1.3.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.
- package/README.de.md +18 -4
- package/README.md +42 -7
- package/cli/cli-manifest.json +441 -174
- package/cli/docgen/extract-cli.js +2 -1
- package/cli/docs-generate.js +9 -0
- package/cli/experience.js +173 -0
- package/cli/index.js +1294 -417
- package/cli/motion.js +738 -0
- package/cli/production/extract.js +46 -6
- package/cli/production/report.js +104 -14
- package/cli/production/run.js +44 -1
- package/cli/security.js +190 -0
- package/cli/skills.js +53 -10
- package/cli/transparency.js +140 -41
- package/cli/workflow.js +32 -17
- package/components/velin-theme-toggle.js +15 -1
- package/core/a11y/component-contracts.json +391 -274
- package/core/attributes/registry.js +1 -1
- package/core/motion/analyze.js +38 -0
- package/core/motion/blueprint.js +51 -0
- package/core/motion/composer.js +114 -0
- package/core/motion/data/registry.json +352 -0
- package/core/motion/effects.js +17 -1
- package/core/motion/index.js +112 -9
- package/core/motion/optimize.js +44 -0
- package/core/motion/policy.js +77 -0
- package/core/motion/registry.js +131 -0
- package/core/motion/review.js +59 -0
- package/core/motion/scan.js +150 -0
- package/core/motion/timeline.js +68 -0
- package/core/motion/transitions.js +49 -0
- package/core/motion/triggers.js +168 -0
- package/core/security/checks/fs.js +92 -0
- package/core/security/detect.js +35 -0
- package/core/security/engine.js +116 -0
- package/core/security/index.js +18 -0
- package/core/security/registry.js +85 -0
- package/core/security/report/report.js +113 -0
- package/core/security/rules/ci/index.js +146 -0
- package/core/security/rules/consumer/index.js +174 -0
- package/core/security/rules/deps/index.js +182 -0
- package/core/security/rules/index.js +24 -0
- package/core/security/rules/publish/index.js +230 -0
- package/core/security/rules/repo/index.js +143 -0
- package/core/security/rules/secrets/index.js +133 -0
- package/core/security/score/dependency-health.js +53 -0
- package/core/security/score/release-health.js +66 -0
- package/core/security/score/score.js +102 -0
- package/core/security/timeline/timeline.js +76 -0
- package/dist/chunks/attributes-HK7VIOLA.js +1080 -0
- package/dist/chunks/attributes-VRHHVNDO.js +1080 -0
- package/dist/chunks/chunk-MYKUI364.js +116 -0
- package/dist/chunks/chunk-NEVBPD5T.js +116 -0
- package/dist/chunks/runtime-entry.js +1 -1
- package/dist/chunks/velin-theme-toggle-J2NHC7IM.js +304 -0
- package/dist/llms.txt +2 -2
- package/dist/search-index.json +166 -2
- package/dist/velin-agent.json +156 -32
- package/dist/velinstyle-components.iife.js +862 -17
- package/dist/velinstyle-components.js +862 -17
- package/dist/velinstyle-components.min.js +126 -126
- package/dist/velinstyle.css +42 -7
- package/dist/velinstyle.min.css +1 -1
- package/package.json +158 -143
- package/packages/velinstyle-cli-core/package.json +11 -0
- package/packages/velinstyle-cli-core/src/config.js +84 -0
- package/packages/velinstyle-cli-core/src/contract.js +56 -0
- package/packages/velinstyle-cli-core/src/event-bus.js +50 -0
- package/packages/velinstyle-cli-core/src/index.js +18 -0
- package/packages/velinstyle-cli-core/src/lifecycle.js +33 -0
- package/packages/velinstyle-cli-core/src/runner.js +129 -0
- package/packages/velinstyle-cli-registry/data/commands.json +1216 -0
- package/packages/velinstyle-cli-registry/data/layouts.json +33 -0
- package/packages/velinstyle-cli-registry/data/widgets.json +35 -0
- package/packages/velinstyle-cli-registry/package.json +13 -0
- package/packages/velinstyle-cli-registry/src/index.js +88 -0
- package/packages/velinstyle-cli-renderer/package.json +8 -0
- package/packages/velinstyle-cli-renderer/src/index.js +286 -0
- package/packages/velinstyle-cli-theme/package.json +8 -0
- package/packages/velinstyle-cli-theme/src/index.js +84 -0
- package/packages/velinstyle-cli-ui/package.json +8 -0
- package/packages/velinstyle-cli-ui/src/index.js +34 -0
- package/packages/velinstyle-motion/README.md +81 -0
- package/packages/velinstyle-motion/package.json +37 -0
- package/packages/velinstyle-motion/src/ai/mini-prompt.js +119 -0
- package/packages/velinstyle-motion/src/ai/provider.js +59 -0
- package/packages/velinstyle-motion/src/ai/providers/pixverse-setup.js +402 -0
- package/packages/velinstyle-motion/src/ai/providers/pixverse.js +245 -0
- package/packages/velinstyle-motion/src/config.js +257 -0
- package/packages/velinstyle-motion/src/export/html-clip.js +141 -0
- package/packages/velinstyle-motion/src/index.js +304 -0
- package/packages/velinstyle-motion/src/jobs/cache.js +30 -0
- package/packages/velinstyle-motion/src/jobs/queue.js +69 -0
- package/packages/velinstyle-motion/src/jobs/usage.js +53 -0
- package/packages/velinstyle-motion/src/local/effects.js +139 -0
- package/packages/velinstyle-motion/src/local/engine.js +96 -0
- package/packages/velinstyle-motion/src/providers-catalog.js +44 -0
- package/packages/velinstyle-motion/src/registry/presets.js +25 -0
- package/packages/velinstyle-motion/src/registry/presets.json +85 -0
- package/packages/velinstyle-motion/src/ux/cost-gate.js +37 -0
- package/packages/velinstyle-motion/src/ux/pixverse-gate.js +153 -0
- package/packages/velinstyle-motion/src/ux/wizard.js +171 -0
- package/packages/velinstyle-motion/src/validate-image.js +91 -0
- package/packages/velinstyle-skills/catalog.json +1 -1
- package/packages/velinstyle-skills/registry.json +1 -142
- package/packages/velinstyle-skills/skills/velin-motion-reduced-safe/SKILL.md +1 -1
- package/packages/velinstyle-skills/skills/velin-motion-reveal-feedback/SKILL.md +1 -1
- package/src/tokens/motion.css +7 -0
- package/src/utilities/scroll-animation.css +66 -0
package/cli/transparency.js
CHANGED
|
@@ -44,10 +44,10 @@ function printScores(scores, C) {
|
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* @param {string[]} args process.argv slice after "transparency"
|
|
47
|
-
* @param {{ C: object, getArg: Function, hasFlag: Function }} util
|
|
47
|
+
* @param {{ C: object, getArg: Function, hasFlag: Function, emitExperience?: Function }} util
|
|
48
48
|
*/
|
|
49
49
|
export async function transparencyCmd(args, util) {
|
|
50
|
-
const { C, getArg, hasFlag } = util;
|
|
50
|
+
const { C, getArg, hasFlag, emitExperience } = util;
|
|
51
51
|
const sub = args[0] || 'doctor';
|
|
52
52
|
const rest = args.slice(1);
|
|
53
53
|
const target = rest.find((a) => !a.startsWith('-')) || '.';
|
|
@@ -55,32 +55,55 @@ export async function transparencyCmd(args, util) {
|
|
|
55
55
|
const policy = loadPolicy(policyPath);
|
|
56
56
|
const asJson = hasFlag('--json');
|
|
57
57
|
const engine = createTransparencyEngine({ policy });
|
|
58
|
+
const present = emitExperience
|
|
59
|
+
? async (payload) => emitExperience('transparency', payload)
|
|
60
|
+
: null;
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
62
|
+
try {
|
|
63
|
+
if (sub === 'scan') {
|
|
64
|
+
return await runDoctor(target, engine, { asJson, C, present });
|
|
65
|
+
}
|
|
66
|
+
if (sub === 'doctor') {
|
|
67
|
+
return await runDoctor(target, engine, { asJson, C, present });
|
|
68
|
+
}
|
|
69
|
+
if (sub === 'validate') {
|
|
70
|
+
return await runValidate(target, engine, { asJson, C, present });
|
|
71
|
+
}
|
|
72
|
+
if (sub === 'report') {
|
|
73
|
+
return await runReport(target, engine, { C, getArg, present });
|
|
74
|
+
}
|
|
75
|
+
if (sub === 'export') {
|
|
76
|
+
return await runExport(target, engine, { C, getArg, present });
|
|
77
|
+
}
|
|
78
|
+
if (sub === 'migrate') {
|
|
79
|
+
return await runMigrate(target, engine, { C, hasFlag, getArg, present });
|
|
80
|
+
}
|
|
81
|
+
if (sub === 'suggest') {
|
|
82
|
+
return await runMigrate(target, engine, { C, hasFlag, getArg, present, forceDry: true });
|
|
83
|
+
}
|
|
84
|
+
if (sub === 'apply') {
|
|
85
|
+
return await runMigrate(target, engine, { C, hasFlag, getArg, present, forceApply: true });
|
|
86
|
+
}
|
|
87
|
+
} catch (e) {
|
|
88
|
+
const message = /** @type {Error} */ (e).message || String(e);
|
|
89
|
+
if (present) {
|
|
90
|
+
await present({ status: 'ERROR', message, exitCode: 1 });
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
console.log(C.red(message));
|
|
94
|
+
process.exitCode = 1;
|
|
95
|
+
return;
|
|
82
96
|
}
|
|
83
97
|
|
|
98
|
+
if (present) {
|
|
99
|
+
await present({
|
|
100
|
+
status: 'ERROR',
|
|
101
|
+
message: `Unknown transparency subcommand: ${sub}`,
|
|
102
|
+
suggestions: [{ text: 'velinstyle transparency doctor|validate|report|export|migrate|scan [path]' }],
|
|
103
|
+
exitCode: 1,
|
|
104
|
+
});
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
84
107
|
console.log(`Unknown transparency subcommand: ${sub}
|
|
85
108
|
Usage:
|
|
86
109
|
velinstyle transparency doctor|validate|report|export|migrate|scan [path]
|
|
@@ -88,9 +111,13 @@ Usage:
|
|
|
88
111
|
process.exitCode = 1;
|
|
89
112
|
}
|
|
90
113
|
|
|
91
|
-
async function runDoctor(target, engine, { asJson, C }) {
|
|
114
|
+
async function runDoctor(target, engine, { asJson, C, present }) {
|
|
92
115
|
const files = collectHtmlFiles(target);
|
|
93
116
|
if (!files.length) {
|
|
117
|
+
if (present) {
|
|
118
|
+
await present({ status: 'WARNING', message: 'No HTML files found.', exitCode: 1 });
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
94
121
|
console.log(C.yellow('No HTML files found.'));
|
|
95
122
|
process.exitCode = 1;
|
|
96
123
|
return;
|
|
@@ -102,7 +129,7 @@ async function runDoctor(target, engine, { asJson, C }) {
|
|
|
102
129
|
const report = await engine.doctor(html, { file });
|
|
103
130
|
reports.push(report);
|
|
104
131
|
if (!report.ok) failed += 1;
|
|
105
|
-
if (!asJson) {
|
|
132
|
+
if (!asJson && !present) {
|
|
106
133
|
console.log(C.bold(`\n── ${basename(file)} ──`));
|
|
107
134
|
console.log(report.ok ? C.green('PASS') : C.red('FAIL'));
|
|
108
135
|
console.log(`disclosures=${report.summary.disclosures} errors=${report.summary.errors} warnings=${report.summary.warnings}`);
|
|
@@ -116,6 +143,30 @@ async function runDoctor(target, engine, { asJson, C }) {
|
|
|
116
143
|
}
|
|
117
144
|
if (asJson) {
|
|
118
145
|
console.log(JSON.stringify(files.length === 1 ? reports[0] : { reports }, null, 2));
|
|
146
|
+
} else if (present) {
|
|
147
|
+
const findings = reports.flatMap((r) =>
|
|
148
|
+
(r.findings || []).slice(0, 10).map((f) => [
|
|
149
|
+
basename(r.file || '') || 'file',
|
|
150
|
+
f.severity,
|
|
151
|
+
f.code,
|
|
152
|
+
String(f.message || '').slice(0, 40),
|
|
153
|
+
]),
|
|
154
|
+
);
|
|
155
|
+
const lastScores = reports[reports.length - 1]?.scores || {};
|
|
156
|
+
await present({
|
|
157
|
+
subtitle: 'doctor',
|
|
158
|
+
status: failed ? 'ERROR' : 'PASS',
|
|
159
|
+
message: failed ? `transparency doctor: ${failed} file(s) failed` : 'transparency doctor: ok',
|
|
160
|
+
items: [
|
|
161
|
+
{ label: 'Files', value: String(files.length) },
|
|
162
|
+
{ label: 'Failed', value: String(failed) },
|
|
163
|
+
...Object.entries(lastScores).map(([k, v]) => ({ label: k, value: `${v}%` })),
|
|
164
|
+
],
|
|
165
|
+
table: findings.length
|
|
166
|
+
? { columns: ['File', 'Sev', 'Code', 'Message'], rows: findings.slice(0, 25) }
|
|
167
|
+
: null,
|
|
168
|
+
exitCode: failed ? 1 : undefined,
|
|
169
|
+
});
|
|
119
170
|
} else {
|
|
120
171
|
console.log(failed ? C.red(`\ntransparency doctor: ${failed} file(s) failed`) : C.green('\ntransparency doctor: ok'));
|
|
121
172
|
}
|
|
@@ -123,7 +174,7 @@ async function runDoctor(target, engine, { asJson, C }) {
|
|
|
123
174
|
return reports;
|
|
124
175
|
}
|
|
125
176
|
|
|
126
|
-
async function runValidate(target, engine, { asJson, C }) {
|
|
177
|
+
async function runValidate(target, engine, { asJson, C, present }) {
|
|
127
178
|
const files = collectHtmlFiles(target);
|
|
128
179
|
const all = [];
|
|
129
180
|
let failed = 0;
|
|
@@ -132,15 +183,28 @@ async function runValidate(target, engine, { asJson, C }) {
|
|
|
132
183
|
const result = await engine.validate(html, { file });
|
|
133
184
|
all.push({ file, ...result });
|
|
134
185
|
if (!result.ok) failed += 1;
|
|
135
|
-
if (!asJson) {
|
|
186
|
+
if (!asJson && !present) {
|
|
136
187
|
console.log(`${basename(file)}: ${result.ok ? C.green('valid') : C.red('invalid')} (${result.findings.length} findings)`);
|
|
137
188
|
}
|
|
138
189
|
}
|
|
139
|
-
if (asJson)
|
|
190
|
+
if (asJson) {
|
|
191
|
+
console.log(JSON.stringify(all, null, 2));
|
|
192
|
+
} else if (present) {
|
|
193
|
+
await present({
|
|
194
|
+
subtitle: 'validate',
|
|
195
|
+
status: failed ? 'ERROR' : 'PASS',
|
|
196
|
+
message: failed ? `${failed} file(s) invalid` : 'All files valid',
|
|
197
|
+
table: {
|
|
198
|
+
columns: ['File', 'Status', 'Findings'],
|
|
199
|
+
rows: all.map((r) => [basename(r.file), r.ok ? 'valid' : 'invalid', String(r.findings?.length || 0)]),
|
|
200
|
+
},
|
|
201
|
+
exitCode: failed ? 1 : undefined,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
140
204
|
if (failed) process.exitCode = 1;
|
|
141
205
|
}
|
|
142
206
|
|
|
143
|
-
async function runReport(target, engine, { C, getArg }) {
|
|
207
|
+
async function runReport(target, engine, { C, getArg, present }) {
|
|
144
208
|
const outDir = resolve(getArg('--out') || 'transparency-report');
|
|
145
209
|
mkdirSync(outDir, { recursive: true });
|
|
146
210
|
const files = collectHtmlFiles(target);
|
|
@@ -155,10 +219,21 @@ async function runReport(target, engine, { C, getArg }) {
|
|
|
155
219
|
combined.files.push({ file, scores: artifacts.json.scores, ok: artifacts.json.ok });
|
|
156
220
|
}
|
|
157
221
|
writeFileSync(join(outDir, 'index.json'), JSON.stringify(combined, null, 2));
|
|
158
|
-
|
|
222
|
+
if (present) {
|
|
223
|
+
await present({
|
|
224
|
+
subtitle: 'report',
|
|
225
|
+
message: `Wrote transparency reports to ${outDir}`,
|
|
226
|
+
items: [
|
|
227
|
+
{ label: 'Files', value: String(files.length) },
|
|
228
|
+
{ label: 'Out', value: outDir },
|
|
229
|
+
],
|
|
230
|
+
});
|
|
231
|
+
} else {
|
|
232
|
+
console.log(C.green(`Wrote transparency reports to ${outDir}`));
|
|
233
|
+
}
|
|
159
234
|
}
|
|
160
235
|
|
|
161
|
-
async function runExport(target, engine, { C, getArg }) {
|
|
236
|
+
async function runExport(target, engine, { C, getArg, present }) {
|
|
162
237
|
const format = getArg('--format') || 'json';
|
|
163
238
|
const out = getArg('--output') || getArg('-o');
|
|
164
239
|
const files = collectHtmlFiles(target);
|
|
@@ -171,32 +246,56 @@ async function runExport(target, engine, { C, getArg }) {
|
|
|
171
246
|
const body = fresh.export(format);
|
|
172
247
|
if (out) {
|
|
173
248
|
writeFileSync(resolve(out), body);
|
|
174
|
-
|
|
249
|
+
if (present) {
|
|
250
|
+
await present({
|
|
251
|
+
subtitle: 'export',
|
|
252
|
+
message: `Exported ${format} → ${out}`,
|
|
253
|
+
items: [{ label: 'Format', value: format }, { label: 'Out', value: out }],
|
|
254
|
+
});
|
|
255
|
+
} else {
|
|
256
|
+
console.log(C.green(`Exported ${format} → ${out}`));
|
|
257
|
+
}
|
|
175
258
|
} else {
|
|
176
259
|
console.log(body);
|
|
177
260
|
}
|
|
178
261
|
}
|
|
179
262
|
|
|
180
|
-
async function runMigrate(target, engine, { C, hasFlag, getArg, forceDry, forceApply }) {
|
|
263
|
+
async function runMigrate(target, engine, { C, hasFlag, getArg, present, forceDry, forceApply }) {
|
|
181
264
|
const apply = forceApply || hasFlag('--apply') || hasFlag('--write');
|
|
182
265
|
const dryRun = forceDry || (!apply);
|
|
183
266
|
const files = collectHtmlFiles(target);
|
|
184
267
|
let total = 0;
|
|
268
|
+
const rows = [];
|
|
185
269
|
for (const file of files) {
|
|
186
270
|
const html = readFileSync(file, 'utf-8');
|
|
187
271
|
const result = await engine.migrate(html, { file, apply: apply && !dryRun, dryRun });
|
|
188
272
|
total += result.suggestions.length;
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
273
|
+
if (!present) {
|
|
274
|
+
console.log(C.bold(`\n── ${basename(file)} ──`));
|
|
275
|
+
console.log(`${result.suggestions.length} suggestion(s)${apply && !dryRun ? `, applied ${result.applied}` : ' (dry-run)'}`);
|
|
276
|
+
for (const s of result.suggestions.slice(0, 30)) {
|
|
277
|
+
console.log(C.dim(` • ${s.id || s.field || s.kind}: ${s.reason}`));
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
for (const s of result.suggestions.slice(0, 15)) {
|
|
281
|
+
rows.push([basename(file), s.id || s.field || s.kind || '—', String(s.reason || '').slice(0, 40)]);
|
|
193
282
|
}
|
|
194
283
|
if (apply && !dryRun && result.applied) {
|
|
195
284
|
writeFileSync(file, result.html);
|
|
196
|
-
console.log(C.green(` wrote ${file}`));
|
|
285
|
+
if (!present) console.log(C.green(` wrote ${file}`));
|
|
197
286
|
}
|
|
198
287
|
}
|
|
199
|
-
if (
|
|
288
|
+
if (present) {
|
|
289
|
+
await present({
|
|
290
|
+
subtitle: apply && !dryRun ? 'apply' : 'migrate',
|
|
291
|
+
message: total
|
|
292
|
+
? `${total} suggestion(s)${apply && !dryRun ? ' applied' : ' (dry-run)'}`
|
|
293
|
+
: 'No migration suggestions',
|
|
294
|
+
table: rows.length ? { columns: ['File', 'Id', 'Reason'], rows: rows.slice(0, 30) } : null,
|
|
295
|
+
});
|
|
296
|
+
} else if (!total) {
|
|
297
|
+
console.log(C.green('\nNo migration suggestions.'));
|
|
298
|
+
}
|
|
200
299
|
}
|
|
201
300
|
|
|
202
301
|
/**
|
package/cli/workflow.js
CHANGED
|
@@ -5,38 +5,53 @@ function hasFlag(argv, flag) {
|
|
|
5
5
|
return argv.includes(flag);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
velinstyle workflow landingpage
|
|
15
|
-
velinstyle workflow project:marketing-site --json
|
|
16
|
-
`);
|
|
17
|
-
process.exit(0);
|
|
18
|
-
}
|
|
8
|
+
/**
|
|
9
|
+
* Resolve a workflow graph or project workflow without printing.
|
|
10
|
+
* @param {string} workflowId
|
|
11
|
+
* @returns {{ ok: true, data: object } | { ok: false, error: string, issues?: string[] }}
|
|
12
|
+
*/
|
|
13
|
+
export function workflowResolve(workflowId) {
|
|
19
14
|
const registry = loadRegistry(getRegistryPathForMeta());
|
|
20
15
|
let resolved;
|
|
21
16
|
if (workflowId.startsWith('project:')) {
|
|
22
17
|
const projectId = workflowId.replace('project:', '');
|
|
23
18
|
const project = (registry.projects || []).find((item) => item.id === projectId);
|
|
24
19
|
if (!project) {
|
|
25
|
-
|
|
26
|
-
process.exit(1);
|
|
20
|
+
return { ok: false, error: `Unknown project: ${projectId}` };
|
|
27
21
|
}
|
|
28
22
|
resolved = resolveWorkflowGraph(registry, project.workflowGraph);
|
|
29
23
|
} else {
|
|
30
24
|
resolved = resolveWorkflowGraph(registry, workflowId);
|
|
31
25
|
}
|
|
32
26
|
if (resolved.issues.length) {
|
|
33
|
-
|
|
27
|
+
return { ok: false, error: 'Workflow resolve failed', issues: resolved.issues };
|
|
28
|
+
}
|
|
29
|
+
return { ok: true, data: resolved };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function workflowCommand(argv = []) {
|
|
33
|
+
const workflowId = argv[0];
|
|
34
|
+
if (!workflowId || workflowId === '--help' || workflowId === '-h') {
|
|
35
|
+
console.log(`Usage: velinstyle workflow <graph-id|project:id> [--json]
|
|
36
|
+
|
|
37
|
+
Examples:
|
|
38
|
+
velinstyle workflow landingpage
|
|
39
|
+
velinstyle workflow project:marketing-site --json
|
|
40
|
+
`);
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
const resolved = workflowResolve(workflowId);
|
|
44
|
+
if (!resolved.ok) {
|
|
45
|
+
console.error(resolved.error);
|
|
46
|
+
if (resolved.issues) {
|
|
47
|
+
for (const issue of resolved.issues) console.error(issue);
|
|
48
|
+
}
|
|
34
49
|
process.exit(1);
|
|
35
50
|
}
|
|
36
51
|
if (hasFlag(argv, '--json')) {
|
|
37
|
-
console.log(JSON.stringify(resolved, null, 2));
|
|
52
|
+
console.log(JSON.stringify(resolved.data, null, 2));
|
|
38
53
|
return;
|
|
39
54
|
}
|
|
40
|
-
console.log(`Workflow steps (${resolved.orderedSteps.length}):`);
|
|
41
|
-
for (const step of resolved.orderedSteps) console.log(`- ${step}`);
|
|
55
|
+
console.log(`Workflow steps (${resolved.data.orderedSteps.length}):`);
|
|
56
|
+
for (const step of resolved.data.orderedSteps) console.log(`- ${step}`);
|
|
42
57
|
}
|
|
@@ -17,9 +17,18 @@ const THEMES = [
|
|
|
17
17
|
];
|
|
18
18
|
|
|
19
19
|
const BUILTIN_THEMES = new Set(['', 'dark']);
|
|
20
|
+
const DARK_THEME_SLUGS = new Set(['dark', 'midnight', 'neon']);
|
|
20
21
|
|
|
21
22
|
const loadedThemeStylesheets = new Set();
|
|
22
23
|
|
|
24
|
+
function applyColorScheme(target, slug) {
|
|
25
|
+
const dark = DARK_THEME_SLUGS.has(slug);
|
|
26
|
+
if (target === document.documentElement || target === document.body) {
|
|
27
|
+
target.style.colorScheme = dark ? 'dark' : 'light';
|
|
28
|
+
}
|
|
29
|
+
target.setAttribute('data-velin-color-scheme', dark ? 'dark' : 'light');
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
function ensureThemeStylesheet(slug, base) {
|
|
24
33
|
if (!slug || BUILTIN_THEMES.has(slug)) return;
|
|
25
34
|
if (loadedThemeStylesheets.has(slug)) return;
|
|
@@ -288,6 +297,7 @@ class VelinThemeToggle extends HTMLElement {
|
|
|
288
297
|
this.setAttribute('theme', normalized === 'dark' ? 'dark' : normalized);
|
|
289
298
|
ensureThemeStylesheet(normalized, this._themesBase);
|
|
290
299
|
}
|
|
300
|
+
applyColorScheme(this._target, normalized);
|
|
291
301
|
if (persist) {
|
|
292
302
|
if (!normalized) localStorage.removeItem('velin-theme');
|
|
293
303
|
else localStorage.setItem('velin-theme', normalized);
|
|
@@ -295,7 +305,11 @@ class VelinThemeToggle extends HTMLElement {
|
|
|
295
305
|
this._highlightActive();
|
|
296
306
|
this.dispatchEvent(new CustomEvent('velin-theme-change', {
|
|
297
307
|
bubbles: true,
|
|
298
|
-
detail: {
|
|
308
|
+
detail: {
|
|
309
|
+
theme: normalized || 'light',
|
|
310
|
+
dark: DARK_THEME_SLUGS.has(normalized),
|
|
311
|
+
slug: normalized,
|
|
312
|
+
},
|
|
299
313
|
}));
|
|
300
314
|
}
|
|
301
315
|
|