create-supaslidev 0.1.3 → 0.2.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.md +1 -0
- package/dist/cli.js +164 -196
- package/dist/index.js +166 -199
- package/package.json +2 -2
- package/templates/default/gitignore.ejs +0 -1
- package/templates/default/nuxt.config.ts.ejs +3 -0
- package/templates/default/package.json.ejs +5 -2
- package/templates/default/pnpm-workspace.yaml.ejs +24 -3
- package/templates/default/npmrc.ejs +0 -1
- package/templates/default/tsconfig.json.ejs +0 -17
- package/templates/default/turbo.json.ejs +0 -24
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ pnpm create supaslidev --name my-slides --presentation intro-deck
|
|
|
43
43
|
| `--install` / `--no-install` | Run pnpm install | `true` |
|
|
44
44
|
|
|
45
45
|
The wizard creates a pnpm workspace with:
|
|
46
|
+
|
|
46
47
|
- A `presentations/` directory for your decks
|
|
47
48
|
- A `packages/shared/` directory with reusable components, layouts, and styles (configured as a Slidev addon)
|
|
48
49
|
- Shared dependency management via pnpm catalog
|
package/dist/cli.js
CHANGED
|
@@ -10,8 +10,86 @@ import ejs from "ejs";
|
|
|
10
10
|
import pc from "picocolors";
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
12
12
|
|
|
13
|
+
//#region src/version.ts
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
|
|
16
|
+
const CLI_VERSION = pkg.version;
|
|
17
|
+
const PACKAGE_NAME = "@supaslidev/cli";
|
|
18
|
+
const CACHE_DIR = join(tmpdir(), "supaslidev-cli");
|
|
19
|
+
const CACHE_FILE = join(CACHE_DIR, "version-cache.json");
|
|
20
|
+
const CACHE_TTL_MS = 1440 * 60 * 1e3;
|
|
21
|
+
function compareVersions(current, latest) {
|
|
22
|
+
const parseVersion = (v) => v.replace(/^v/, "").split(".").map((n) => parseInt(n, 10) || 0);
|
|
23
|
+
const currentParts = parseVersion(current);
|
|
24
|
+
const latestParts = parseVersion(latest);
|
|
25
|
+
for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
|
|
26
|
+
const curr = currentParts[i] ?? 0;
|
|
27
|
+
const lat = latestParts[i] ?? 0;
|
|
28
|
+
if (lat > curr) return true;
|
|
29
|
+
if (lat < curr) return false;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
function readCache() {
|
|
34
|
+
try {
|
|
35
|
+
if (!existsSync(CACHE_FILE)) return null;
|
|
36
|
+
const data = JSON.parse(readFileSync(CACHE_FILE, "utf-8"));
|
|
37
|
+
if (Date.now() - data.checkedAt > CACHE_TTL_MS) return null;
|
|
38
|
+
return data;
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function writeCache(latestVersion) {
|
|
44
|
+
try {
|
|
45
|
+
if (!existsSync(CACHE_DIR)) mkdirSync(CACHE_DIR, { recursive: true });
|
|
46
|
+
const cache = {
|
|
47
|
+
latestVersion,
|
|
48
|
+
checkedAt: Date.now()
|
|
49
|
+
};
|
|
50
|
+
writeFileSync(CACHE_FILE, JSON.stringify(cache));
|
|
51
|
+
} catch {}
|
|
52
|
+
}
|
|
53
|
+
async function fetchLatestPackageVersion(packageName) {
|
|
54
|
+
try {
|
|
55
|
+
const controller = new AbortController();
|
|
56
|
+
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
57
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}`, { signal: controller.signal });
|
|
58
|
+
clearTimeout(timeoutId);
|
|
59
|
+
if (!response.ok) return null;
|
|
60
|
+
return (await response.json())["dist-tags"].latest;
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function fetchLatestVersion() {
|
|
66
|
+
const version = await fetchLatestPackageVersion(PACKAGE_NAME);
|
|
67
|
+
if (version) writeCache(version);
|
|
68
|
+
return version;
|
|
69
|
+
}
|
|
70
|
+
function getCachedLatestVersion() {
|
|
71
|
+
return readCache()?.latestVersion ?? null;
|
|
72
|
+
}
|
|
73
|
+
async function checkForUpdates() {
|
|
74
|
+
const latestVersion = await fetchLatestVersion();
|
|
75
|
+
return {
|
|
76
|
+
currentVersion: CLI_VERSION,
|
|
77
|
+
latestVersion,
|
|
78
|
+
updateAvailable: latestVersion ? compareVersions(CLI_VERSION, latestVersion) : false
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function checkForUpdatesCached() {
|
|
82
|
+
const latestVersion = getCachedLatestVersion();
|
|
83
|
+
return {
|
|
84
|
+
currentVersion: CLI_VERSION,
|
|
85
|
+
latestVersion,
|
|
86
|
+
updateAvailable: latestVersion ? compareVersions(CLI_VERSION, latestVersion) : false
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
//#endregion
|
|
13
91
|
//#region src/create.ts
|
|
14
|
-
const
|
|
92
|
+
const SUPASLIDEV_FALLBACK_VERSION = "0.1.4";
|
|
15
93
|
function createSafeSpinner() {
|
|
16
94
|
if (process.stdout.isTTY && process.stdin.isTTY) {
|
|
17
95
|
const spinner = p.spinner();
|
|
@@ -80,11 +158,7 @@ async function renderTemplatesRecursively(sourceDir, targetDir, data) {
|
|
|
80
158
|
}
|
|
81
159
|
}
|
|
82
160
|
function createDirectoryStructure(targetDir) {
|
|
83
|
-
for (const dir of [
|
|
84
|
-
"presentations",
|
|
85
|
-
"packages",
|
|
86
|
-
"scripts"
|
|
87
|
-
]) {
|
|
161
|
+
for (const dir of ["presentations", "packages"]) {
|
|
88
162
|
const fullPath = join(targetDir, dir);
|
|
89
163
|
mkdirSync(fullPath, { recursive: true });
|
|
90
164
|
trackPath(fullPath);
|
|
@@ -143,90 +217,7 @@ Add your content here
|
|
|
143
217
|
[Slidev Documentation](https://sli.dev/)
|
|
144
218
|
`;
|
|
145
219
|
writeFileSync(join(presentationDir, "slides.md"), slidesContent, "utf-8");
|
|
146
|
-
writeFileSync(join(presentationDir, ".gitignore"), "node_modules\ndist\n.
|
|
147
|
-
writeFileSync(join(presentationDir, ".npmrc"), "shamefully-hoist=true\n", "utf-8");
|
|
148
|
-
}
|
|
149
|
-
function createScripts(targetDir) {
|
|
150
|
-
writeFileSync(join(join(targetDir, "scripts"), "dev-presentation.mjs"), `#!/usr/bin/env node
|
|
151
|
-
|
|
152
|
-
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
153
|
-
import { join, dirname } from 'node:path';
|
|
154
|
-
import { fileURLToPath } from 'node:url';
|
|
155
|
-
import { spawn } from 'node:child_process';
|
|
156
|
-
|
|
157
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
158
|
-
const rootDir = join(__dirname, '..');
|
|
159
|
-
const presentationsDir = join(rootDir, 'presentations');
|
|
160
|
-
|
|
161
|
-
function getPresentations() {
|
|
162
|
-
if (!existsSync(presentationsDir)) {
|
|
163
|
-
return [];
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return readdirSync(presentationsDir)
|
|
167
|
-
.filter((name) => {
|
|
168
|
-
const fullPath = join(presentationsDir, name);
|
|
169
|
-
return statSync(fullPath).isDirectory() && existsSync(join(fullPath, 'slides.md'));
|
|
170
|
-
})
|
|
171
|
-
.sort();
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function printUsage(presentations) {
|
|
175
|
-
console.error('Usage: pnpm dev <presentation-name>');
|
|
176
|
-
console.error('\\nAvailable presentations:');
|
|
177
|
-
|
|
178
|
-
if (presentations.length === 0) {
|
|
179
|
-
console.error(' No presentations found');
|
|
180
|
-
} else {
|
|
181
|
-
presentations.forEach((name) => {
|
|
182
|
-
console.error(\` \${name}\`);
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function runDev(name) {
|
|
188
|
-
const packageName = \`@supaslidev/\${name}\`;
|
|
189
|
-
|
|
190
|
-
console.log(\`\\nStarting dev server for \${name}...\\n\`);
|
|
191
|
-
|
|
192
|
-
const pnpm = spawn('pnpm', ['--filter', packageName, 'dev'], {
|
|
193
|
-
cwd: rootDir,
|
|
194
|
-
stdio: 'inherit',
|
|
195
|
-
shell: true,
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
pnpm.on('error', (err) => {
|
|
199
|
-
console.error(\`Failed to start dev server: \${err.message}\`);
|
|
200
|
-
process.exit(1);
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
pnpm.on('close', (code) => {
|
|
204
|
-
process.exit(code ?? 0);
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function main() {
|
|
209
|
-
const args = process.argv.slice(2);
|
|
210
|
-
const name = args[0];
|
|
211
|
-
const presentations = getPresentations();
|
|
212
|
-
|
|
213
|
-
if (!name) {
|
|
214
|
-
console.error('Error: Presentation name is required');
|
|
215
|
-
printUsage(presentations);
|
|
216
|
-
process.exit(1);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (!presentations.includes(name)) {
|
|
220
|
-
console.error(\`Error: Presentation "\${name}" not found\`);
|
|
221
|
-
printUsage(presentations);
|
|
222
|
-
process.exit(1);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
runDev(name);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
main();
|
|
229
|
-
`, "utf-8");
|
|
220
|
+
writeFileSync(join(presentationDir, ".gitignore"), "node_modules\n.DS_Store\ndist\n*.local\n.vite-inspect\n.remote-assets\ncomponents.d.ts\n", "utf-8");
|
|
230
221
|
}
|
|
231
222
|
function createSharedPackage(targetDir) {
|
|
232
223
|
const sharedDir = join(targetDir, "packages", "shared");
|
|
@@ -248,49 +239,99 @@ function createSharedPackage(targetDir) {
|
|
|
248
239
|
keywords: ["slidev-addon", "slidev"],
|
|
249
240
|
dependencies: { vue: "catalog:" }
|
|
250
241
|
}, null, 2) + "\n", "utf-8");
|
|
251
|
-
writeFileSync(join(sharedDir, "components", "SharedBadge.vue"), `<
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
242
|
+
writeFileSync(join(sharedDir, "components", "SharedBadge.vue"), `<script setup lang="ts">
|
|
243
|
+
defineProps<{
|
|
244
|
+
text?: string;
|
|
245
|
+
}>();
|
|
246
|
+
<\/script>
|
|
247
|
+
|
|
248
|
+
<template>
|
|
249
|
+
<span class="shared-badge">{{ text ?? 'Shared' }}</span>
|
|
255
250
|
</template>
|
|
256
251
|
|
|
257
252
|
<style scoped>
|
|
258
253
|
.shared-badge {
|
|
259
254
|
display: inline-block;
|
|
260
|
-
padding: 0.25rem 0.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
255
|
+
padding: 0.25rem 0.75rem;
|
|
256
|
+
font-size: 0.75rem;
|
|
257
|
+
font-weight: 600;
|
|
258
|
+
line-height: 1;
|
|
259
|
+
text-transform: uppercase;
|
|
260
|
+
letter-spacing: 0.05em;
|
|
261
|
+
color: #fff;
|
|
262
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
263
|
+
border-radius: 9999px;
|
|
266
264
|
}
|
|
267
265
|
</style>
|
|
268
266
|
`, "utf-8");
|
|
269
267
|
writeFileSync(join(sharedDir, "README.md"), `# @supaslidev/shared
|
|
270
268
|
|
|
271
|
-
|
|
269
|
+
A local Slidev addon for sharing components, layouts, and styles across all presentations in your workspace.
|
|
270
|
+
|
|
271
|
+
## How It Works
|
|
272
|
+
|
|
273
|
+
This package follows the [Slidev addon pattern](https://sli.dev/guide/write-addon). Slidev automatically discovers and imports resources from the following directories:
|
|
274
|
+
|
|
275
|
+
- **components/** - Vue components available in all slides
|
|
276
|
+
- **layouts/** - Custom slide layouts
|
|
277
|
+
- **styles/** - Shared CSS/SCSS styles
|
|
278
|
+
|
|
279
|
+
## Using This Addon
|
|
280
|
+
|
|
281
|
+
Add the addon to your presentation's frontmatter:
|
|
282
|
+
|
|
283
|
+
\`\`\`yaml
|
|
284
|
+
---
|
|
285
|
+
addons:
|
|
286
|
+
- '@supaslidev/shared'
|
|
287
|
+
---
|
|
288
|
+
\`\`\`
|
|
289
|
+
|
|
290
|
+
## Example: Using SharedBadge
|
|
272
291
|
|
|
273
|
-
|
|
292
|
+
The \`SharedBadge\` component is available globally once the addon is configured:
|
|
274
293
|
|
|
275
|
-
|
|
294
|
+
\`\`\`md
|
|
295
|
+
---
|
|
296
|
+
addons:
|
|
297
|
+
- '@supaslidev/shared'
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
# My Slide
|
|
301
|
+
|
|
302
|
+
<SharedBadge text="New" />
|
|
303
|
+
\`\`\`
|
|
276
304
|
|
|
277
|
-
## Structure
|
|
305
|
+
## Directory Structure
|
|
306
|
+
|
|
307
|
+
\`\`\`
|
|
308
|
+
shared/
|
|
309
|
+
├── components/ # Vue components (auto-imported)
|
|
310
|
+
│ └── SharedBadge.vue
|
|
311
|
+
├── layouts/ # Custom layouts
|
|
312
|
+
├── styles/ # Shared styles
|
|
313
|
+
├── package.json
|
|
314
|
+
└── README.md
|
|
315
|
+
\`\`\`
|
|
316
|
+
|
|
317
|
+
## Adding New Components
|
|
318
|
+
|
|
319
|
+
Create a \`.vue\` file in \`components/\`:
|
|
320
|
+
|
|
321
|
+
\`\`\`vue
|
|
322
|
+
<script setup lang="ts">
|
|
323
|
+
defineProps<{
|
|
324
|
+
label: string;
|
|
325
|
+
}>();
|
|
326
|
+
<\/script>
|
|
327
|
+
|
|
328
|
+
<template>
|
|
329
|
+
<div class="my-component">{{ label }}</div>
|
|
330
|
+
</template>
|
|
331
|
+
\`\`\`
|
|
278
332
|
|
|
279
|
-
|
|
280
|
-
- \`layouts/\` - Custom slide layouts
|
|
281
|
-
- \`styles/\` - Global styles
|
|
333
|
+
The component is immediately available in all presentations using this addon.
|
|
282
334
|
`, "utf-8");
|
|
283
|
-
writeFileSync(join(sharedDir, "tsconfig.json"), JSON.stringify({
|
|
284
|
-
compilerOptions: {
|
|
285
|
-
target: "ESNext",
|
|
286
|
-
module: "ESNext",
|
|
287
|
-
moduleResolution: "bundler",
|
|
288
|
-
strict: true,
|
|
289
|
-
jsx: "preserve",
|
|
290
|
-
skipLibCheck: true
|
|
291
|
-
},
|
|
292
|
-
include: ["**/*.ts", "**/*.vue"]
|
|
293
|
-
}, null, 2) + "\n", "utf-8");
|
|
294
335
|
}
|
|
295
336
|
async function create(options = {}) {
|
|
296
337
|
const spinner = createSafeSpinner();
|
|
@@ -379,20 +420,20 @@ async function create(options = {}) {
|
|
|
379
420
|
trackPath(targetDir);
|
|
380
421
|
spinner.start("Creating workspace structure...");
|
|
381
422
|
createDirectoryStructure(targetDir);
|
|
423
|
+
const supaslidevVersion = `^${await fetchLatestPackageVersion("supaslidev") ?? SUPASLIDEV_FALLBACK_VERSION}`;
|
|
382
424
|
const templateData = {
|
|
383
425
|
projectName,
|
|
384
426
|
presentationName,
|
|
385
427
|
description: `${projectName} - Slidev presentations monorepo`,
|
|
386
|
-
cliVersion: CLI_VERSION
|
|
387
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
428
|
+
cliVersion: CLI_VERSION,
|
|
429
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
430
|
+
supaslidevVersion
|
|
388
431
|
};
|
|
389
432
|
await renderWorkspaceTemplates(targetDir, options.template ?? "default", templateData);
|
|
390
433
|
spinner.message("Creating presentation...");
|
|
391
434
|
await createPresentation(targetDir, presentationName);
|
|
392
435
|
spinner.message("Creating shared package...");
|
|
393
436
|
createSharedPackage(targetDir);
|
|
394
|
-
spinner.message("Creating scripts...");
|
|
395
|
-
createScripts(targetDir);
|
|
396
437
|
spinner.stop("Workspace structure created");
|
|
397
438
|
if (initGit) {
|
|
398
439
|
spinner.start("Initializing git repository...");
|
|
@@ -548,79 +589,6 @@ function getMigrationOrder(manifest) {
|
|
|
548
589
|
return order;
|
|
549
590
|
}
|
|
550
591
|
|
|
551
|
-
//#endregion
|
|
552
|
-
//#region src/version.ts
|
|
553
|
-
const CLI_VERSION = "0.1.0";
|
|
554
|
-
const PACKAGE_NAME = "@supaslidev/cli";
|
|
555
|
-
const CACHE_DIR = join(tmpdir(), "supaslidev-cli");
|
|
556
|
-
const CACHE_FILE = join(CACHE_DIR, "version-cache.json");
|
|
557
|
-
const CACHE_TTL_MS = 1440 * 60 * 1e3;
|
|
558
|
-
function compareVersions(current, latest) {
|
|
559
|
-
const parseVersion = (v) => v.replace(/^v/, "").split(".").map((n) => parseInt(n, 10) || 0);
|
|
560
|
-
const currentParts = parseVersion(current);
|
|
561
|
-
const latestParts = parseVersion(latest);
|
|
562
|
-
for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
|
|
563
|
-
const curr = currentParts[i] ?? 0;
|
|
564
|
-
const lat = latestParts[i] ?? 0;
|
|
565
|
-
if (lat > curr) return true;
|
|
566
|
-
if (lat < curr) return false;
|
|
567
|
-
}
|
|
568
|
-
return false;
|
|
569
|
-
}
|
|
570
|
-
function readCache() {
|
|
571
|
-
try {
|
|
572
|
-
if (!existsSync(CACHE_FILE)) return null;
|
|
573
|
-
const data = JSON.parse(readFileSync(CACHE_FILE, "utf-8"));
|
|
574
|
-
if (Date.now() - data.checkedAt > CACHE_TTL_MS) return null;
|
|
575
|
-
return data;
|
|
576
|
-
} catch {
|
|
577
|
-
return null;
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
function writeCache(latestVersion) {
|
|
581
|
-
try {
|
|
582
|
-
if (!existsSync(CACHE_DIR)) mkdirSync(CACHE_DIR, { recursive: true });
|
|
583
|
-
const cache = {
|
|
584
|
-
latestVersion,
|
|
585
|
-
checkedAt: Date.now()
|
|
586
|
-
};
|
|
587
|
-
writeFileSync(CACHE_FILE, JSON.stringify(cache));
|
|
588
|
-
} catch {}
|
|
589
|
-
}
|
|
590
|
-
async function fetchLatestVersion() {
|
|
591
|
-
try {
|
|
592
|
-
const controller = new AbortController();
|
|
593
|
-
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
594
|
-
const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}`, { signal: controller.signal });
|
|
595
|
-
clearTimeout(timeoutId);
|
|
596
|
-
if (!response.ok) return null;
|
|
597
|
-
const version = (await response.json())["dist-tags"].latest;
|
|
598
|
-
writeCache(version);
|
|
599
|
-
return version;
|
|
600
|
-
} catch {
|
|
601
|
-
return null;
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
function getCachedLatestVersion() {
|
|
605
|
-
return readCache()?.latestVersion ?? null;
|
|
606
|
-
}
|
|
607
|
-
async function checkForUpdates() {
|
|
608
|
-
const latestVersion = await fetchLatestVersion();
|
|
609
|
-
return {
|
|
610
|
-
currentVersion: CLI_VERSION,
|
|
611
|
-
latestVersion,
|
|
612
|
-
updateAvailable: latestVersion ? compareVersions(CLI_VERSION, latestVersion) : false
|
|
613
|
-
};
|
|
614
|
-
}
|
|
615
|
-
function checkForUpdatesCached() {
|
|
616
|
-
const latestVersion = getCachedLatestVersion();
|
|
617
|
-
return {
|
|
618
|
-
currentVersion: CLI_VERSION,
|
|
619
|
-
latestVersion,
|
|
620
|
-
updateAvailable: latestVersion ? compareVersions(CLI_VERSION, latestVersion) : false
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
|
|
624
592
|
//#endregion
|
|
625
593
|
//#region src/commands/status.ts
|
|
626
594
|
function getPendingMigrationsCount(workspaceDir) {
|
|
@@ -1252,7 +1220,7 @@ function printUpdateNotification(latestVersion) {
|
|
|
1252
1220
|
//#endregion
|
|
1253
1221
|
//#region src/cli.ts
|
|
1254
1222
|
const program = new Command();
|
|
1255
|
-
program.name("create-supaslidev").description("CLI tool for scaffolding Supaslidev presentations").version(
|
|
1223
|
+
program.name("create-supaslidev").description("CLI tool for scaffolding Supaslidev presentations").version(CLI_VERSION);
|
|
1256
1224
|
program.command("create", { isDefault: true }).description("Create a new Supaslidev workspace").option("-n, --name <name>", "Name of the workspace").option("-p, --presentation <name>", "Name of the first presentation").option("-t, --template <template>", "Template to use", "default").option("--git", "Initialize a git repository").option("--no-git", "Skip git initialization").option("--install", "Run pnpm install after scaffolding").option("--no-install", "Skip pnpm install").action(async (options) => {
|
|
1257
1225
|
await create(options);
|
|
1258
1226
|
});
|
package/dist/index.js
CHANGED
|
@@ -10,8 +10,86 @@ import { tmpdir } from "node:os";
|
|
|
10
10
|
import { parse, parseDocument, stringify } from "yaml";
|
|
11
11
|
import { IndentationText, Node, Project, SyntaxKind } from "ts-morph";
|
|
12
12
|
|
|
13
|
+
//#region src/version.ts
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
|
|
16
|
+
const CLI_VERSION = pkg.version;
|
|
17
|
+
const PACKAGE_NAME = "@supaslidev/cli";
|
|
18
|
+
const CACHE_DIR = join(tmpdir(), "supaslidev-cli");
|
|
19
|
+
const CACHE_FILE = join(CACHE_DIR, "version-cache.json");
|
|
20
|
+
const CACHE_TTL_MS = 1440 * 60 * 1e3;
|
|
21
|
+
function compareVersions(current, latest) {
|
|
22
|
+
const parseVersion = (v) => v.replace(/^v/, "").split(".").map((n) => parseInt(n, 10) || 0);
|
|
23
|
+
const currentParts = parseVersion(current);
|
|
24
|
+
const latestParts = parseVersion(latest);
|
|
25
|
+
for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
|
|
26
|
+
const curr = currentParts[i] ?? 0;
|
|
27
|
+
const lat = latestParts[i] ?? 0;
|
|
28
|
+
if (lat > curr) return true;
|
|
29
|
+
if (lat < curr) return false;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
function readCache() {
|
|
34
|
+
try {
|
|
35
|
+
if (!existsSync(CACHE_FILE)) return null;
|
|
36
|
+
const data = JSON.parse(readFileSync(CACHE_FILE, "utf-8"));
|
|
37
|
+
if (Date.now() - data.checkedAt > CACHE_TTL_MS) return null;
|
|
38
|
+
return data;
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function writeCache(latestVersion) {
|
|
44
|
+
try {
|
|
45
|
+
if (!existsSync(CACHE_DIR)) mkdirSync(CACHE_DIR, { recursive: true });
|
|
46
|
+
const cache = {
|
|
47
|
+
latestVersion,
|
|
48
|
+
checkedAt: Date.now()
|
|
49
|
+
};
|
|
50
|
+
writeFileSync(CACHE_FILE, JSON.stringify(cache));
|
|
51
|
+
} catch {}
|
|
52
|
+
}
|
|
53
|
+
async function fetchLatestPackageVersion(packageName) {
|
|
54
|
+
try {
|
|
55
|
+
const controller = new AbortController();
|
|
56
|
+
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
57
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}`, { signal: controller.signal });
|
|
58
|
+
clearTimeout(timeoutId);
|
|
59
|
+
if (!response.ok) return null;
|
|
60
|
+
return (await response.json())["dist-tags"].latest;
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function fetchLatestVersion() {
|
|
66
|
+
const version = await fetchLatestPackageVersion(PACKAGE_NAME);
|
|
67
|
+
if (version) writeCache(version);
|
|
68
|
+
return version;
|
|
69
|
+
}
|
|
70
|
+
function getCachedLatestVersion() {
|
|
71
|
+
return readCache()?.latestVersion ?? null;
|
|
72
|
+
}
|
|
73
|
+
async function checkForUpdates() {
|
|
74
|
+
const latestVersion = await fetchLatestVersion();
|
|
75
|
+
return {
|
|
76
|
+
currentVersion: CLI_VERSION,
|
|
77
|
+
latestVersion,
|
|
78
|
+
updateAvailable: latestVersion ? compareVersions(CLI_VERSION, latestVersion) : false
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function checkForUpdatesCached() {
|
|
82
|
+
const latestVersion = getCachedLatestVersion();
|
|
83
|
+
return {
|
|
84
|
+
currentVersion: CLI_VERSION,
|
|
85
|
+
latestVersion,
|
|
86
|
+
updateAvailable: latestVersion ? compareVersions(CLI_VERSION, latestVersion) : false
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
//#endregion
|
|
13
91
|
//#region src/create.ts
|
|
14
|
-
const
|
|
92
|
+
const SUPASLIDEV_FALLBACK_VERSION = "0.1.4";
|
|
15
93
|
function createSafeSpinner() {
|
|
16
94
|
if (process.stdout.isTTY && process.stdin.isTTY) {
|
|
17
95
|
const spinner = p.spinner();
|
|
@@ -80,11 +158,7 @@ async function renderTemplatesRecursively(sourceDir, targetDir, data) {
|
|
|
80
158
|
}
|
|
81
159
|
}
|
|
82
160
|
function createDirectoryStructure(targetDir) {
|
|
83
|
-
for (const dir of [
|
|
84
|
-
"presentations",
|
|
85
|
-
"packages",
|
|
86
|
-
"scripts"
|
|
87
|
-
]) {
|
|
161
|
+
for (const dir of ["presentations", "packages"]) {
|
|
88
162
|
const fullPath = join(targetDir, dir);
|
|
89
163
|
mkdirSync(fullPath, { recursive: true });
|
|
90
164
|
trackPath(fullPath);
|
|
@@ -143,90 +217,7 @@ Add your content here
|
|
|
143
217
|
[Slidev Documentation](https://sli.dev/)
|
|
144
218
|
`;
|
|
145
219
|
writeFileSync(join(presentationDir, "slides.md"), slidesContent, "utf-8");
|
|
146
|
-
writeFileSync(join(presentationDir, ".gitignore"), "node_modules\ndist\n.
|
|
147
|
-
writeFileSync(join(presentationDir, ".npmrc"), "shamefully-hoist=true\n", "utf-8");
|
|
148
|
-
}
|
|
149
|
-
function createScripts(targetDir) {
|
|
150
|
-
writeFileSync(join(join(targetDir, "scripts"), "dev-presentation.mjs"), `#!/usr/bin/env node
|
|
151
|
-
|
|
152
|
-
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
153
|
-
import { join, dirname } from 'node:path';
|
|
154
|
-
import { fileURLToPath } from 'node:url';
|
|
155
|
-
import { spawn } from 'node:child_process';
|
|
156
|
-
|
|
157
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
158
|
-
const rootDir = join(__dirname, '..');
|
|
159
|
-
const presentationsDir = join(rootDir, 'presentations');
|
|
160
|
-
|
|
161
|
-
function getPresentations() {
|
|
162
|
-
if (!existsSync(presentationsDir)) {
|
|
163
|
-
return [];
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return readdirSync(presentationsDir)
|
|
167
|
-
.filter((name) => {
|
|
168
|
-
const fullPath = join(presentationsDir, name);
|
|
169
|
-
return statSync(fullPath).isDirectory() && existsSync(join(fullPath, 'slides.md'));
|
|
170
|
-
})
|
|
171
|
-
.sort();
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function printUsage(presentations) {
|
|
175
|
-
console.error('Usage: pnpm dev <presentation-name>');
|
|
176
|
-
console.error('\\nAvailable presentations:');
|
|
177
|
-
|
|
178
|
-
if (presentations.length === 0) {
|
|
179
|
-
console.error(' No presentations found');
|
|
180
|
-
} else {
|
|
181
|
-
presentations.forEach((name) => {
|
|
182
|
-
console.error(\` \${name}\`);
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function runDev(name) {
|
|
188
|
-
const packageName = \`@supaslidev/\${name}\`;
|
|
189
|
-
|
|
190
|
-
console.log(\`\\nStarting dev server for \${name}...\\n\`);
|
|
191
|
-
|
|
192
|
-
const pnpm = spawn('pnpm', ['--filter', packageName, 'dev'], {
|
|
193
|
-
cwd: rootDir,
|
|
194
|
-
stdio: 'inherit',
|
|
195
|
-
shell: true,
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
pnpm.on('error', (err) => {
|
|
199
|
-
console.error(\`Failed to start dev server: \${err.message}\`);
|
|
200
|
-
process.exit(1);
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
pnpm.on('close', (code) => {
|
|
204
|
-
process.exit(code ?? 0);
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function main() {
|
|
209
|
-
const args = process.argv.slice(2);
|
|
210
|
-
const name = args[0];
|
|
211
|
-
const presentations = getPresentations();
|
|
212
|
-
|
|
213
|
-
if (!name) {
|
|
214
|
-
console.error('Error: Presentation name is required');
|
|
215
|
-
printUsage(presentations);
|
|
216
|
-
process.exit(1);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (!presentations.includes(name)) {
|
|
220
|
-
console.error(\`Error: Presentation "\${name}" not found\`);
|
|
221
|
-
printUsage(presentations);
|
|
222
|
-
process.exit(1);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
runDev(name);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
main();
|
|
229
|
-
`, "utf-8");
|
|
220
|
+
writeFileSync(join(presentationDir, ".gitignore"), "node_modules\n.DS_Store\ndist\n*.local\n.vite-inspect\n.remote-assets\ncomponents.d.ts\n", "utf-8");
|
|
230
221
|
}
|
|
231
222
|
function createSharedPackage(targetDir) {
|
|
232
223
|
const sharedDir = join(targetDir, "packages", "shared");
|
|
@@ -248,49 +239,99 @@ function createSharedPackage(targetDir) {
|
|
|
248
239
|
keywords: ["slidev-addon", "slidev"],
|
|
249
240
|
dependencies: { vue: "catalog:" }
|
|
250
241
|
}, null, 2) + "\n", "utf-8");
|
|
251
|
-
writeFileSync(join(sharedDir, "components", "SharedBadge.vue"), `<
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
242
|
+
writeFileSync(join(sharedDir, "components", "SharedBadge.vue"), `<script setup lang="ts">
|
|
243
|
+
defineProps<{
|
|
244
|
+
text?: string;
|
|
245
|
+
}>();
|
|
246
|
+
<\/script>
|
|
247
|
+
|
|
248
|
+
<template>
|
|
249
|
+
<span class="shared-badge">{{ text ?? 'Shared' }}</span>
|
|
255
250
|
</template>
|
|
256
251
|
|
|
257
252
|
<style scoped>
|
|
258
253
|
.shared-badge {
|
|
259
254
|
display: inline-block;
|
|
260
|
-
padding: 0.25rem 0.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
255
|
+
padding: 0.25rem 0.75rem;
|
|
256
|
+
font-size: 0.75rem;
|
|
257
|
+
font-weight: 600;
|
|
258
|
+
line-height: 1;
|
|
259
|
+
text-transform: uppercase;
|
|
260
|
+
letter-spacing: 0.05em;
|
|
261
|
+
color: #fff;
|
|
262
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
263
|
+
border-radius: 9999px;
|
|
266
264
|
}
|
|
267
265
|
</style>
|
|
268
266
|
`, "utf-8");
|
|
269
267
|
writeFileSync(join(sharedDir, "README.md"), `# @supaslidev/shared
|
|
270
268
|
|
|
271
|
-
|
|
269
|
+
A local Slidev addon for sharing components, layouts, and styles across all presentations in your workspace.
|
|
272
270
|
|
|
273
|
-
##
|
|
271
|
+
## How It Works
|
|
274
272
|
|
|
275
|
-
This package
|
|
273
|
+
This package follows the [Slidev addon pattern](https://sli.dev/guide/write-addon). Slidev automatically discovers and imports resources from the following directories:
|
|
276
274
|
|
|
277
|
-
|
|
275
|
+
- **components/** - Vue components available in all slides
|
|
276
|
+
- **layouts/** - Custom slide layouts
|
|
277
|
+
- **styles/** - Shared CSS/SCSS styles
|
|
278
278
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
279
|
+
## Using This Addon
|
|
280
|
+
|
|
281
|
+
Add the addon to your presentation's frontmatter:
|
|
282
|
+
|
|
283
|
+
\`\`\`yaml
|
|
284
|
+
---
|
|
285
|
+
addons:
|
|
286
|
+
- '@supaslidev/shared'
|
|
287
|
+
---
|
|
288
|
+
\`\`\`
|
|
289
|
+
|
|
290
|
+
## Example: Using SharedBadge
|
|
291
|
+
|
|
292
|
+
The \`SharedBadge\` component is available globally once the addon is configured:
|
|
293
|
+
|
|
294
|
+
\`\`\`md
|
|
295
|
+
---
|
|
296
|
+
addons:
|
|
297
|
+
- '@supaslidev/shared'
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
# My Slide
|
|
301
|
+
|
|
302
|
+
<SharedBadge text="New" />
|
|
303
|
+
\`\`\`
|
|
304
|
+
|
|
305
|
+
## Directory Structure
|
|
306
|
+
|
|
307
|
+
\`\`\`
|
|
308
|
+
shared/
|
|
309
|
+
├── components/ # Vue components (auto-imported)
|
|
310
|
+
│ └── SharedBadge.vue
|
|
311
|
+
├── layouts/ # Custom layouts
|
|
312
|
+
├── styles/ # Shared styles
|
|
313
|
+
├── package.json
|
|
314
|
+
└── README.md
|
|
315
|
+
\`\`\`
|
|
316
|
+
|
|
317
|
+
## Adding New Components
|
|
318
|
+
|
|
319
|
+
Create a \`.vue\` file in \`components/\`:
|
|
320
|
+
|
|
321
|
+
\`\`\`vue
|
|
322
|
+
<script setup lang="ts">
|
|
323
|
+
defineProps<{
|
|
324
|
+
label: string;
|
|
325
|
+
}>();
|
|
326
|
+
<\/script>
|
|
327
|
+
|
|
328
|
+
<template>
|
|
329
|
+
<div class="my-component">{{ label }}</div>
|
|
330
|
+
</template>
|
|
331
|
+
\`\`\`
|
|
332
|
+
|
|
333
|
+
The component is immediately available in all presentations using this addon.
|
|
282
334
|
`, "utf-8");
|
|
283
|
-
writeFileSync(join(sharedDir, "tsconfig.json"), JSON.stringify({
|
|
284
|
-
compilerOptions: {
|
|
285
|
-
target: "ESNext",
|
|
286
|
-
module: "ESNext",
|
|
287
|
-
moduleResolution: "bundler",
|
|
288
|
-
strict: true,
|
|
289
|
-
jsx: "preserve",
|
|
290
|
-
skipLibCheck: true
|
|
291
|
-
},
|
|
292
|
-
include: ["**/*.ts", "**/*.vue"]
|
|
293
|
-
}, null, 2) + "\n", "utf-8");
|
|
294
335
|
}
|
|
295
336
|
async function create(options = {}) {
|
|
296
337
|
const spinner = createSafeSpinner();
|
|
@@ -379,20 +420,20 @@ async function create(options = {}) {
|
|
|
379
420
|
trackPath(targetDir);
|
|
380
421
|
spinner.start("Creating workspace structure...");
|
|
381
422
|
createDirectoryStructure(targetDir);
|
|
423
|
+
const supaslidevVersion = `^${await fetchLatestPackageVersion("supaslidev") ?? SUPASLIDEV_FALLBACK_VERSION}`;
|
|
382
424
|
const templateData = {
|
|
383
425
|
projectName,
|
|
384
426
|
presentationName,
|
|
385
427
|
description: `${projectName} - Slidev presentations monorepo`,
|
|
386
|
-
cliVersion: CLI_VERSION
|
|
387
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
428
|
+
cliVersion: CLI_VERSION,
|
|
429
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
430
|
+
supaslidevVersion
|
|
388
431
|
};
|
|
389
432
|
await renderWorkspaceTemplates(targetDir, options.template ?? "default", templateData);
|
|
390
433
|
spinner.message("Creating presentation...");
|
|
391
434
|
await createPresentation(targetDir, presentationName);
|
|
392
435
|
spinner.message("Creating shared package...");
|
|
393
436
|
createSharedPackage(targetDir);
|
|
394
|
-
spinner.message("Creating scripts...");
|
|
395
|
-
createScripts(targetDir);
|
|
396
437
|
spinner.stop("Workspace structure created");
|
|
397
438
|
if (initGit) {
|
|
398
439
|
spinner.start("Initializing git repository...");
|
|
@@ -437,7 +478,6 @@ async function create(options = {}) {
|
|
|
437
478
|
|
|
438
479
|
//#endregion
|
|
439
480
|
//#region src/state.ts
|
|
440
|
-
const CLI_VERSION$1 = "0.1.0";
|
|
441
481
|
const STATE_DIR = ".supaslidev";
|
|
442
482
|
const STATE_FILE = "state.json";
|
|
443
483
|
function getStatePath(workspaceDir) {
|
|
@@ -449,7 +489,7 @@ function getStateDir(workspaceDir) {
|
|
|
449
489
|
function createInitialState() {
|
|
450
490
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
451
491
|
return {
|
|
452
|
-
cliVersion: CLI_VERSION
|
|
492
|
+
cliVersion: CLI_VERSION,
|
|
453
493
|
createdAt: now,
|
|
454
494
|
lastUpdatedAt: now,
|
|
455
495
|
appliedMigrations: []
|
|
@@ -501,7 +541,7 @@ function hasMigration(workspaceDir, migrationId) {
|
|
|
501
541
|
function updateCliVersion(workspaceDir) {
|
|
502
542
|
const state = readState(workspaceDir);
|
|
503
543
|
if (!state) throw new Error("State file not found. Is this a Supaslidev workspace?");
|
|
504
|
-
state.cliVersion = CLI_VERSION
|
|
544
|
+
state.cliVersion = CLI_VERSION;
|
|
505
545
|
writeState(workspaceDir, state);
|
|
506
546
|
}
|
|
507
547
|
function findWorkspaceRoot(startDir = process.cwd()) {
|
|
@@ -594,79 +634,6 @@ function getMigrationOrder(manifest) {
|
|
|
594
634
|
return order;
|
|
595
635
|
}
|
|
596
636
|
|
|
597
|
-
//#endregion
|
|
598
|
-
//#region src/version.ts
|
|
599
|
-
const CLI_VERSION = "0.1.0";
|
|
600
|
-
const PACKAGE_NAME = "@supaslidev/cli";
|
|
601
|
-
const CACHE_DIR = join(tmpdir(), "supaslidev-cli");
|
|
602
|
-
const CACHE_FILE = join(CACHE_DIR, "version-cache.json");
|
|
603
|
-
const CACHE_TTL_MS = 1440 * 60 * 1e3;
|
|
604
|
-
function compareVersions(current, latest) {
|
|
605
|
-
const parseVersion = (v) => v.replace(/^v/, "").split(".").map((n) => parseInt(n, 10) || 0);
|
|
606
|
-
const currentParts = parseVersion(current);
|
|
607
|
-
const latestParts = parseVersion(latest);
|
|
608
|
-
for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
|
|
609
|
-
const curr = currentParts[i] ?? 0;
|
|
610
|
-
const lat = latestParts[i] ?? 0;
|
|
611
|
-
if (lat > curr) return true;
|
|
612
|
-
if (lat < curr) return false;
|
|
613
|
-
}
|
|
614
|
-
return false;
|
|
615
|
-
}
|
|
616
|
-
function readCache() {
|
|
617
|
-
try {
|
|
618
|
-
if (!existsSync(CACHE_FILE)) return null;
|
|
619
|
-
const data = JSON.parse(readFileSync(CACHE_FILE, "utf-8"));
|
|
620
|
-
if (Date.now() - data.checkedAt > CACHE_TTL_MS) return null;
|
|
621
|
-
return data;
|
|
622
|
-
} catch {
|
|
623
|
-
return null;
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
function writeCache(latestVersion) {
|
|
627
|
-
try {
|
|
628
|
-
if (!existsSync(CACHE_DIR)) mkdirSync(CACHE_DIR, { recursive: true });
|
|
629
|
-
const cache = {
|
|
630
|
-
latestVersion,
|
|
631
|
-
checkedAt: Date.now()
|
|
632
|
-
};
|
|
633
|
-
writeFileSync(CACHE_FILE, JSON.stringify(cache));
|
|
634
|
-
} catch {}
|
|
635
|
-
}
|
|
636
|
-
async function fetchLatestVersion() {
|
|
637
|
-
try {
|
|
638
|
-
const controller = new AbortController();
|
|
639
|
-
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
640
|
-
const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}`, { signal: controller.signal });
|
|
641
|
-
clearTimeout(timeoutId);
|
|
642
|
-
if (!response.ok) return null;
|
|
643
|
-
const version = (await response.json())["dist-tags"].latest;
|
|
644
|
-
writeCache(version);
|
|
645
|
-
return version;
|
|
646
|
-
} catch {
|
|
647
|
-
return null;
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
function getCachedLatestVersion() {
|
|
651
|
-
return readCache()?.latestVersion ?? null;
|
|
652
|
-
}
|
|
653
|
-
async function checkForUpdates() {
|
|
654
|
-
const latestVersion = await fetchLatestVersion();
|
|
655
|
-
return {
|
|
656
|
-
currentVersion: CLI_VERSION,
|
|
657
|
-
latestVersion,
|
|
658
|
-
updateAvailable: latestVersion ? compareVersions(CLI_VERSION, latestVersion) : false
|
|
659
|
-
};
|
|
660
|
-
}
|
|
661
|
-
function checkForUpdatesCached() {
|
|
662
|
-
const latestVersion = getCachedLatestVersion();
|
|
663
|
-
return {
|
|
664
|
-
currentVersion: CLI_VERSION,
|
|
665
|
-
latestVersion,
|
|
666
|
-
updateAvailable: latestVersion ? compareVersions(CLI_VERSION, latestVersion) : false
|
|
667
|
-
};
|
|
668
|
-
}
|
|
669
|
-
|
|
670
637
|
//#endregion
|
|
671
638
|
//#region src/commands/status.ts
|
|
672
639
|
function getPendingMigrationsCount(workspaceDir) {
|
|
@@ -1346,7 +1313,7 @@ function printUpdateNotification(latestVersion) {
|
|
|
1346
1313
|
//#endregion
|
|
1347
1314
|
//#region src/cli.ts
|
|
1348
1315
|
const program = new Command();
|
|
1349
|
-
program.name("create-supaslidev").description("CLI tool for scaffolding Supaslidev presentations").version(
|
|
1316
|
+
program.name("create-supaslidev").description("CLI tool for scaffolding Supaslidev presentations").version(CLI_VERSION);
|
|
1350
1317
|
program.command("create", { isDefault: true }).description("Create a new Supaslidev workspace").option("-n, --name <name>", "Name of the workspace").option("-p, --presentation <name>", "Name of the first presentation").option("-t, --template <template>", "Template to use", "default").option("--git", "Initialize a git repository").option("--no-git", "Skip git initialization").option("--install", "Run pnpm install after scaffolding").option("--no-install", "Skip pnpm install").action(async (options) => {
|
|
1351
1318
|
await create(options);
|
|
1352
1319
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-supaslidev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "CLI tool for scaffolding Supaslidev presentations",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"slidev",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"tsdown": "^0.12.5",
|
|
51
51
|
"tsx": "^4.19.0",
|
|
52
52
|
"typescript": "^5.3.3",
|
|
53
|
-
"vitest": "^
|
|
53
|
+
"vitest": "^4.0.0"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "tsdown",
|
|
@@ -9,10 +9,13 @@
|
|
|
9
9
|
"new": "supaslidev new",
|
|
10
10
|
"present": "supaslidev present",
|
|
11
11
|
"export": "supaslidev export",
|
|
12
|
-
"deploy": "supaslidev deploy"
|
|
12
|
+
"deploy": "supaslidev deploy",
|
|
13
|
+
"build": "pnpm --filter @supaslidev/* run build"
|
|
13
14
|
},
|
|
14
15
|
"devDependencies": {
|
|
15
|
-
"
|
|
16
|
+
"nuxt": "catalog:core",
|
|
17
|
+
"playwright-chromium": "catalog:",
|
|
18
|
+
"supaslidev": "<%= supaslidevVersion %>"
|
|
16
19
|
},
|
|
17
20
|
"engines": {
|
|
18
21
|
"node": ">=18.0.0"
|
|
@@ -8,6 +8,27 @@ catalog:
|
|
|
8
8
|
'@slidev/theme-seriph': latest
|
|
9
9
|
'@slidev/theme-apple-basic': latest
|
|
10
10
|
vue: ^3.5.26
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
playwright-chromium: ^1.58.2
|
|
12
|
+
|
|
13
|
+
catalogs:
|
|
14
|
+
core:
|
|
15
|
+
nuxt: ^4.4.2
|
|
16
|
+
'@vue/compiler-sfc': ^3.5.27
|
|
17
|
+
typescript: ^5.3.3
|
|
18
|
+
vue-tsc: ^2.0.0
|
|
19
|
+
|
|
20
|
+
catalogMode: prefer
|
|
21
|
+
|
|
22
|
+
linkWorkspacePackages: true
|
|
23
|
+
|
|
24
|
+
shellEmulator: true
|
|
25
|
+
|
|
26
|
+
trustPolicy: no-downgrade
|
|
27
|
+
|
|
28
|
+
trustPolicyExclude:
|
|
29
|
+
- axios
|
|
30
|
+
- chokidar
|
|
31
|
+
- semver
|
|
32
|
+
- undici
|
|
33
|
+
- undici-types
|
|
34
|
+
- vite
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
shamefully-hoist=true
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ESNext",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "bundler",
|
|
6
|
-
"strict": true,
|
|
7
|
-
"jsx": "preserve",
|
|
8
|
-
"resolveJsonModule": true,
|
|
9
|
-
"isolatedModules": true,
|
|
10
|
-
"esModuleInterop": true,
|
|
11
|
-
"lib": ["ESNext", "DOM"],
|
|
12
|
-
"skipLibCheck": true,
|
|
13
|
-
"noEmit": true
|
|
14
|
-
},
|
|
15
|
-
"include": ["packages/**/*.ts", "packages/**/*.vue"],
|
|
16
|
-
"exclude": ["node_modules", "**/dist"]
|
|
17
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://turbo.build/schema.json",
|
|
3
|
-
"tasks": {
|
|
4
|
-
"typecheck": {
|
|
5
|
-
"dependsOn": ["^typecheck"],
|
|
6
|
-
"inputs": ["**/*.ts", "**/*.tsx", "**/*.vue", "tsconfig.json"],
|
|
7
|
-
"outputs": []
|
|
8
|
-
},
|
|
9
|
-
"lint": {
|
|
10
|
-
"dependsOn": ["^lint"],
|
|
11
|
-
"inputs": ["**/*.ts", "**/*.tsx", "**/*.vue", "**/*.js", "**/*.mjs"],
|
|
12
|
-
"outputs": []
|
|
13
|
-
},
|
|
14
|
-
"build": {
|
|
15
|
-
"dependsOn": ["^build"],
|
|
16
|
-
"inputs": ["src/**", "**/*.ts", "**/*.vue", "package.json"],
|
|
17
|
-
"outputs": ["dist/**"]
|
|
18
|
-
},
|
|
19
|
-
"dev": {
|
|
20
|
-
"cache": false,
|
|
21
|
-
"persistent": true
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|