@beatzball/create-litro 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/CHANGELOG.md +133 -0
- package/dist/recipes/fullstack/template/app.ts +11 -8
- package/dist/recipes/fullstack/template/pages/blog/[slug].ts +4 -5
- package/dist/recipes/fullstack/template/pages/index.ts +4 -5
- package/dist/recipes/starlight/recipe.config.d.ts +4 -0
- package/dist/recipes/starlight/recipe.config.d.ts.map +1 -0
- package/dist/recipes/starlight/recipe.config.js +9 -0
- package/dist/recipes/starlight/recipe.config.js.map +1 -0
- package/dist/recipes/starlight/recipe.config.ts +11 -0
- package/dist/recipes/starlight/template/_data/metadata.js +10 -0
- package/dist/recipes/starlight/template/app.ts +18 -0
- package/dist/recipes/starlight/template/content/blog/.11tydata.json +1 -0
- package/dist/recipes/starlight/template/content/blog/release-notes.md +44 -0
- package/dist/recipes/starlight/template/content/blog/welcome.md +44 -0
- package/dist/recipes/starlight/template/content/docs/.11tydata.json +1 -0
- package/dist/recipes/starlight/template/content/docs/configuration.md +77 -0
- package/dist/recipes/starlight/template/content/docs/getting-started.md +53 -0
- package/dist/recipes/starlight/template/content/docs/guides-deploying.md +79 -0
- package/dist/recipes/starlight/template/content/docs/guides-first-page.md +64 -0
- package/dist/recipes/starlight/template/content/docs/installation.md +54 -0
- package/dist/recipes/starlight/template/litro.recipe.json +7 -0
- package/dist/recipes/starlight/template/nitro.config.ts +57 -0
- package/dist/recipes/starlight/template/package.json +26 -0
- package/dist/recipes/starlight/template/pages/blog/[slug].ts +125 -0
- package/dist/recipes/starlight/template/pages/blog/index.ts +114 -0
- package/dist/recipes/starlight/template/pages/blog/tags/[tag].ts +110 -0
- package/dist/recipes/starlight/template/pages/docs/[slug].ts +147 -0
- package/dist/recipes/starlight/template/pages/index.ts +135 -0
- package/dist/recipes/starlight/template/public/styles/starlight.css +215 -0
- package/dist/recipes/starlight/template/server/middleware/vite-dev.ts +29 -0
- package/dist/recipes/starlight/template/server/routes/[...].ts +57 -0
- package/dist/recipes/starlight/template/server/starlight.config.js +29 -0
- package/dist/recipes/starlight/template/src/components/sl-aside.ts +91 -0
- package/dist/recipes/starlight/template/src/components/sl-badge.ts +76 -0
- package/dist/recipes/starlight/template/src/components/sl-card-grid.ts +34 -0
- package/dist/recipes/starlight/template/src/components/sl-card.ts +91 -0
- package/dist/recipes/starlight/template/src/components/sl-tab-item.ts +35 -0
- package/dist/recipes/starlight/template/src/components/sl-tabs.ts +108 -0
- package/dist/recipes/starlight/template/src/components/starlight-header.ts +152 -0
- package/dist/recipes/starlight/template/src/components/starlight-page.ts +168 -0
- package/dist/recipes/starlight/template/src/components/starlight-sidebar.ts +125 -0
- package/dist/recipes/starlight/template/src/components/starlight-toc.ts +133 -0
- package/dist/recipes/starlight/template/src/date-utils.ts +20 -0
- package/dist/recipes/starlight/template/src/extract-headings.ts +68 -0
- package/dist/recipes/starlight/template/src/route-meta.ts +16 -0
- package/dist/recipes/starlight/template/tsconfig.json +14 -0
- package/dist/recipes/starlight/template/vite.config.ts +19 -0
- package/dist/src/scaffold.test.js +134 -0
- package/dist/src/scaffold.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/recipes/fullstack/template/app.ts +11 -8
- package/recipes/fullstack/template/pages/blog/[slug].ts +4 -5
- package/recipes/fullstack/template/pages/index.ts +4 -5
- package/recipes/starlight/recipe.config.ts +11 -0
- package/recipes/starlight/template/_data/metadata.js +10 -0
- package/recipes/starlight/template/app.ts +18 -0
- package/recipes/starlight/template/content/blog/.11tydata.json +1 -0
- package/recipes/starlight/template/content/blog/release-notes.md +44 -0
- package/recipes/starlight/template/content/blog/welcome.md +44 -0
- package/recipes/starlight/template/content/docs/.11tydata.json +1 -0
- package/recipes/starlight/template/content/docs/configuration.md +77 -0
- package/recipes/starlight/template/content/docs/getting-started.md +53 -0
- package/recipes/starlight/template/content/docs/guides-deploying.md +79 -0
- package/recipes/starlight/template/content/docs/guides-first-page.md +64 -0
- package/recipes/starlight/template/content/docs/installation.md +54 -0
- package/recipes/starlight/template/litro.recipe.json +7 -0
- package/recipes/starlight/template/nitro.config.ts +57 -0
- package/recipes/starlight/template/package.json +26 -0
- package/recipes/starlight/template/pages/blog/[slug].ts +125 -0
- package/recipes/starlight/template/pages/blog/index.ts +114 -0
- package/recipes/starlight/template/pages/blog/tags/[tag].ts +110 -0
- package/recipes/starlight/template/pages/docs/[slug].ts +147 -0
- package/recipes/starlight/template/pages/index.ts +135 -0
- package/recipes/starlight/template/public/styles/starlight.css +215 -0
- package/recipes/starlight/template/server/middleware/vite-dev.ts +29 -0
- package/recipes/starlight/template/server/routes/[...].ts +57 -0
- package/recipes/starlight/template/server/starlight.config.js +29 -0
- package/recipes/starlight/template/src/components/sl-aside.ts +91 -0
- package/recipes/starlight/template/src/components/sl-badge.ts +76 -0
- package/recipes/starlight/template/src/components/sl-card-grid.ts +34 -0
- package/recipes/starlight/template/src/components/sl-card.ts +91 -0
- package/recipes/starlight/template/src/components/sl-tab-item.ts +35 -0
- package/recipes/starlight/template/src/components/sl-tabs.ts +108 -0
- package/recipes/starlight/template/src/components/starlight-header.ts +152 -0
- package/recipes/starlight/template/src/components/starlight-page.ts +168 -0
- package/recipes/starlight/template/src/components/starlight-sidebar.ts +125 -0
- package/recipes/starlight/template/src/components/starlight-toc.ts +133 -0
- package/recipes/starlight/template/src/date-utils.ts +20 -0
- package/recipes/starlight/template/src/extract-headings.ts +68 -0
- package/recipes/starlight/template/src/route-meta.ts +16 -0
- package/recipes/starlight/template/tsconfig.json +14 -0
- package/recipes/starlight/template/vite.config.ts +19 -0
- package/src/scaffold.test.ts +148 -0
package/src/scaffold.test.ts
CHANGED
|
@@ -225,4 +225,152 @@ describe('scaffold', () => {
|
|
|
225
225
|
.rejects.toThrow();
|
|
226
226
|
});
|
|
227
227
|
});
|
|
228
|
+
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
// starlight recipe
|
|
231
|
+
// ---------------------------------------------------------------------------
|
|
232
|
+
|
|
233
|
+
it('starlight recipe writes litro.recipe.json with ssg mode', async () => {
|
|
234
|
+
await withTmpDir(async (dir) => {
|
|
235
|
+
const targetDir = join(dir, 'my-docs');
|
|
236
|
+
await scaffold('starlight', { projectName: 'my-docs', mode: 'ssg' }, targetDir);
|
|
237
|
+
|
|
238
|
+
const { existsSync } = await import('node:fs');
|
|
239
|
+
expect(existsSync(join(targetDir, 'litro.recipe.json'))).toBe(true);
|
|
240
|
+
|
|
241
|
+
const manifest = JSON.parse(await readFile(join(targetDir, 'litro.recipe.json'), 'utf-8')) as Record<string, unknown>;
|
|
242
|
+
expect(manifest.recipe).toBe('starlight');
|
|
243
|
+
expect(manifest.mode).toBe('ssg');
|
|
244
|
+
expect(manifest.contentDir).toBe('content');
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('starlight recipe writes all expected files', async () => {
|
|
249
|
+
await withTmpDir(async (dir) => {
|
|
250
|
+
const targetDir = join(dir, 'my-docs');
|
|
251
|
+
await scaffold('starlight', { projectName: 'my-docs', mode: 'ssg' }, targetDir);
|
|
252
|
+
|
|
253
|
+
const { existsSync } = await import('node:fs');
|
|
254
|
+
// Core config
|
|
255
|
+
expect(existsSync(join(targetDir, 'package.json'))).toBe(true);
|
|
256
|
+
expect(existsSync(join(targetDir, 'tsconfig.json'))).toBe(true);
|
|
257
|
+
expect(existsSync(join(targetDir, 'nitro.config.ts'))).toBe(true);
|
|
258
|
+
expect(existsSync(join(targetDir, 'vite.config.ts'))).toBe(true);
|
|
259
|
+
expect(existsSync(join(targetDir, 'app.ts'))).toBe(true);
|
|
260
|
+
expect(existsSync(join(targetDir, '.gitignore'))).toBe(true);
|
|
261
|
+
expect(existsSync(join(targetDir, 'litro.recipe.json'))).toBe(true);
|
|
262
|
+
// Server
|
|
263
|
+
expect(existsSync(join(targetDir, 'server/starlight.config.js'))).toBe(true);
|
|
264
|
+
expect(existsSync(join(targetDir, 'server/routes/[...].ts'))).toBe(true);
|
|
265
|
+
expect(existsSync(join(targetDir, 'server/middleware/vite-dev.ts'))).toBe(true);
|
|
266
|
+
expect(existsSync(join(targetDir, 'server/stubs/page-manifest.ts'))).toBe(true);
|
|
267
|
+
// Pages
|
|
268
|
+
expect(existsSync(join(targetDir, 'pages/index.ts'))).toBe(true);
|
|
269
|
+
expect(existsSync(join(targetDir, 'pages/docs/[slug].ts'))).toBe(true);
|
|
270
|
+
expect(existsSync(join(targetDir, 'pages/blog/index.ts'))).toBe(true);
|
|
271
|
+
expect(existsSync(join(targetDir, 'pages/blog/[slug].ts'))).toBe(true);
|
|
272
|
+
expect(existsSync(join(targetDir, 'pages/blog/tags/[tag].ts'))).toBe(true);
|
|
273
|
+
// Utilities
|
|
274
|
+
expect(existsSync(join(targetDir, 'src/extract-headings.ts'))).toBe(true);
|
|
275
|
+
expect(existsSync(join(targetDir, 'src/date-utils.ts'))).toBe(true);
|
|
276
|
+
expect(existsSync(join(targetDir, 'src/route-meta.ts'))).toBe(true);
|
|
277
|
+
// Components
|
|
278
|
+
expect(existsSync(join(targetDir, 'src/components/starlight-page.ts'))).toBe(true);
|
|
279
|
+
expect(existsSync(join(targetDir, 'src/components/starlight-header.ts'))).toBe(true);
|
|
280
|
+
expect(existsSync(join(targetDir, 'src/components/starlight-sidebar.ts'))).toBe(true);
|
|
281
|
+
expect(existsSync(join(targetDir, 'src/components/starlight-toc.ts'))).toBe(true);
|
|
282
|
+
expect(existsSync(join(targetDir, 'src/components/sl-card.ts'))).toBe(true);
|
|
283
|
+
expect(existsSync(join(targetDir, 'src/components/sl-card-grid.ts'))).toBe(true);
|
|
284
|
+
expect(existsSync(join(targetDir, 'src/components/sl-badge.ts'))).toBe(true);
|
|
285
|
+
expect(existsSync(join(targetDir, 'src/components/sl-aside.ts'))).toBe(true);
|
|
286
|
+
expect(existsSync(join(targetDir, 'src/components/sl-tabs.ts'))).toBe(true);
|
|
287
|
+
expect(existsSync(join(targetDir, 'src/components/sl-tab-item.ts'))).toBe(true);
|
|
288
|
+
// Content
|
|
289
|
+
expect(existsSync(join(targetDir, 'content/docs/.11tydata.json'))).toBe(true);
|
|
290
|
+
expect(existsSync(join(targetDir, 'content/docs/getting-started.md'))).toBe(true);
|
|
291
|
+
expect(existsSync(join(targetDir, 'content/blog/.11tydata.json'))).toBe(true);
|
|
292
|
+
expect(existsSync(join(targetDir, 'content/blog/welcome.md'))).toBe(true);
|
|
293
|
+
// Public
|
|
294
|
+
expect(existsSync(join(targetDir, 'public/styles/starlight.css'))).toBe(true);
|
|
295
|
+
// Data
|
|
296
|
+
expect(existsSync(join(targetDir, '_data/metadata.js'))).toBe(true);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('starlight recipe interpolates {{projectName}} in package.json', async () => {
|
|
301
|
+
await withTmpDir(async (dir) => {
|
|
302
|
+
const targetDir = join(dir, 'awesome-docs');
|
|
303
|
+
await scaffold('starlight', { projectName: 'awesome-docs', mode: 'ssg' }, targetDir);
|
|
304
|
+
|
|
305
|
+
const pkg = JSON.parse(await readFile(join(targetDir, 'package.json'), 'utf-8')) as Record<string, unknown>;
|
|
306
|
+
expect(pkg.name).toBe('awesome-docs');
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it('starlight recipe interpolates {{projectName}} in server/starlight.config.js', async () => {
|
|
311
|
+
await withTmpDir(async (dir) => {
|
|
312
|
+
const targetDir = join(dir, 'my-docs-site');
|
|
313
|
+
await scaffold('starlight', { projectName: 'my-docs-site', mode: 'ssg' }, targetDir);
|
|
314
|
+
|
|
315
|
+
const config = await readFile(join(targetDir, 'server/starlight.config.js'), 'utf-8');
|
|
316
|
+
expect(config).toContain('my-docs-site');
|
|
317
|
+
expect(config).not.toContain('{{projectName}}');
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it('starlight recipe has no un-interpolated {{ }} in any output file', async () => {
|
|
322
|
+
await withTmpDir(async (dir) => {
|
|
323
|
+
const targetDir = join(dir, 'my-docs');
|
|
324
|
+
await scaffold('starlight', { projectName: 'my-docs', mode: 'ssg' }, targetDir);
|
|
325
|
+
|
|
326
|
+
const binaryExts = new Set(['.png', '.jpg', '.jpeg', '.gif', '.ico', '.webp', '.svg',
|
|
327
|
+
'.woff', '.woff2', '.ttf', '.eot', '.otf', '.pdf', '.zip', '.gz', '.tar', '.gitkeep']);
|
|
328
|
+
|
|
329
|
+
async function collectFiles(d: string): Promise<string[]> {
|
|
330
|
+
const { readdir: rd } = await import('node:fs/promises');
|
|
331
|
+
const entries = await rd(d, { withFileTypes: true });
|
|
332
|
+
const results: string[] = [];
|
|
333
|
+
for (const e of entries) {
|
|
334
|
+
const p = join(d, e.name);
|
|
335
|
+
if (e.isDirectory()) results.push(...(await collectFiles(p)));
|
|
336
|
+
else results.push(p);
|
|
337
|
+
}
|
|
338
|
+
return results;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const files = await collectFiles(targetDir);
|
|
342
|
+
for (const file of files) {
|
|
343
|
+
const extPart = file.includes('.') ? `.${file.split('.').pop()}` : '';
|
|
344
|
+
if (binaryExts.has(extPart.toLowerCase())) continue;
|
|
345
|
+
const content = await readFile(file, 'utf-8');
|
|
346
|
+
const matches = content.match(/\{\{[^}]+\}\}/g);
|
|
347
|
+
if (matches) {
|
|
348
|
+
throw new Error(`Un-interpolated placeholder in ${file}: ${matches.join(', ')}`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
it('starlight recipe page files use plain <a> tags, not <litro-link>', async () => {
|
|
355
|
+
// SSG pages must use <a> for full-page-reload navigation so each pre-rendered
|
|
356
|
+
// page loads its own __litro_data__. <litro-link> triggers SPA navigation which
|
|
357
|
+
// leaves serverData=null on the navigated page (no __litro_data__ in DOM).
|
|
358
|
+
await withTmpDir(async (dir) => {
|
|
359
|
+
const targetDir = join(dir, 'my-docs');
|
|
360
|
+
await scaffold('starlight', { projectName: 'my-docs', mode: 'ssg' }, targetDir);
|
|
361
|
+
|
|
362
|
+
const pageFiles = [
|
|
363
|
+
join(targetDir, 'pages/index.ts'),
|
|
364
|
+
join(targetDir, 'pages/docs/[slug].ts'),
|
|
365
|
+
join(targetDir, 'pages/blog/index.ts'),
|
|
366
|
+
join(targetDir, 'pages/blog/[slug].ts'),
|
|
367
|
+
join(targetDir, 'pages/blog/tags/[tag].ts'),
|
|
368
|
+
];
|
|
369
|
+
|
|
370
|
+
for (const file of pageFiles) {
|
|
371
|
+
const content = await readFile(file, 'utf-8');
|
|
372
|
+
expect(content, `${file} should not contain <litro-link>`).not.toContain('litro-link');
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
});
|
|
228
376
|
});
|