create-riebeckite 0.0.32 → 0.0.33

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 (62) hide show
  1. package/dist/src/arguments.d.ts +2 -0
  2. package/dist/src/index.js +379 -42
  3. package/dist/src/interactive.d.ts +7 -5
  4. package/dist/src/package-manager.d.ts +2 -1
  5. package/dist/src/publish.d.ts +2 -1
  6. package/dist/src/scaffold/deployment.d.ts +0 -1
  7. package/dist/src/scaffold/features.d.ts +12 -0
  8. package/dist/src/scaffold/index.d.ts +1 -0
  9. package/dist/src/scaffold/index.js +329 -36
  10. package/dist/src/scaffold/options.d.ts +2 -0
  11. package/dist/src/scaffold/presets.d.ts +9 -5
  12. package/dist/src/scaffold/readme_demos.d.ts +2 -1
  13. package/dist/src/scaffold/template_options.d.ts +1 -6
  14. package/dist/src/scaffold/utilities.d.ts +0 -1
  15. package/dist/src/scaffold/version.d.ts +1 -1
  16. package/dist/src/scaffold/wrangler-defaults.d.ts +0 -1
  17. package/package.json +3 -3
  18. package/templates/scaffold/presets/blog/app/components/article.tsx +33 -0
  19. package/templates/scaffold/presets/blog/app/components/site-header.tsx +37 -0
  20. package/templates/scaffold/presets/blog/app/routes/[slug{.+}].tsx +10 -0
  21. package/templates/scaffold/presets/blog/app/routes/_404.tsx +18 -0
  22. package/templates/scaffold/presets/blog/app/routes/_renderer.tsx +42 -0
  23. package/templates/scaffold/presets/blog/app/routes/index.tsx +10 -0
  24. package/templates/scaffold/presets/blog/app/style.css +152 -0
  25. package/templates/scaffold/presets/blog/content/index.md +8 -0
  26. package/templates/scaffold/presets/blog/content/posts/editing-before-publishing.md +12 -0
  27. package/templates/scaffold/presets/blog/content/posts/writing-a-useful-post.md +12 -0
  28. package/templates/scaffold/presets/digital-garden/app/components/article.tsx +31 -0
  29. package/templates/scaffold/presets/digital-garden/app/components/site-header.tsx +37 -0
  30. package/templates/scaffold/presets/digital-garden/app/routes/[slug{.+}].tsx +10 -0
  31. package/templates/scaffold/presets/digital-garden/app/routes/_404.tsx +18 -0
  32. package/templates/scaffold/presets/digital-garden/app/routes/_renderer.tsx +42 -0
  33. package/templates/scaffold/presets/digital-garden/app/routes/index.tsx +10 -0
  34. package/templates/scaffold/presets/digital-garden/app/style.css +152 -0
  35. package/templates/scaffold/presets/digital-garden/content/index.md +10 -0
  36. package/templates/scaffold/presets/digital-garden/content/notes/how-this-garden-works.md +11 -0
  37. package/templates/scaffold/presets/digital-garden/content/notes/seed-idea.md +9 -0
  38. package/templates/scaffold/presets/docs/app/components/article.tsx +26 -0
  39. package/templates/scaffold/presets/docs/app/components/site-header.tsx +37 -0
  40. package/templates/scaffold/presets/docs/app/routes/[slug{.+}].tsx +10 -0
  41. package/templates/scaffold/presets/docs/app/routes/_404.tsx +18 -0
  42. package/templates/scaffold/presets/docs/app/routes/_renderer.tsx +42 -0
  43. package/templates/scaffold/presets/docs/app/routes/index.tsx +10 -0
  44. package/templates/scaffold/presets/docs/app/style.css +169 -0
  45. package/templates/scaffold/presets/docs/content/docs/configuration.md +8 -0
  46. package/templates/scaffold/presets/docs/content/docs/getting-started.md +15 -0
  47. package/templates/scaffold/presets/docs/content/index.md +7 -0
  48. package/templates/scaffold/presets/portfolio/app/components/article.tsx +29 -0
  49. package/templates/scaffold/presets/portfolio/app/components/site-header.tsx +37 -0
  50. package/templates/scaffold/presets/portfolio/app/routes/[slug{.+}].tsx +10 -0
  51. package/templates/scaffold/presets/portfolio/app/routes/_404.tsx +18 -0
  52. package/templates/scaffold/presets/portfolio/app/routes/_renderer.tsx +42 -0
  53. package/templates/scaffold/presets/portfolio/app/routes/index.tsx +10 -0
  54. package/templates/scaffold/presets/portfolio/app/style.css +152 -0
  55. package/templates/scaffold/presets/portfolio/content/about.md +7 -0
  56. package/templates/scaffold/presets/portfolio/content/contact.md +7 -0
  57. package/templates/scaffold/presets/portfolio/content/index.en.md +18 -0
  58. package/templates/scaffold/presets/portfolio/content/projects/field-notes.md +20 -0
  59. package/templates/scaffold/presets/portfolio/content/projects/small-tools.md +10 -0
  60. package/templates/scaffold/presets/showcase/content/deck.md +24 -0
  61. package/templates/scaffold/presets/showcase/content/demo/planning.md +2 -1
  62. package/templates/scaffold/presets/showcase/content/demo/writing.md +4 -1
@@ -269,6 +269,10 @@ function defaultLanguageForLocale(locale) {
269
269
  }
270
270
  var SCAFFOLD_PRESET_NAMES = [
271
271
  "starter",
272
+ "digital-garden",
273
+ "blog",
274
+ "docs",
275
+ "portfolio",
272
276
  "minimal",
273
277
  "showcase",
274
278
  "empty"
@@ -285,7 +289,7 @@ var obsidianMarkdown = np(
285
289
  "@riebeckite/plugin-obsidian-markdown",
286
290
  "obsidianMarkdown"
287
291
  );
288
- var colorMode = np("@riebeckite/plugin-color-mode", "colorModePlugin");
292
+ var colorMode = np("@riebeckite/plugin-color-mode", "colorMode");
289
293
  var l10n = np("@riebeckite/plugin-l10n", "l10n", (context) => {
290
294
  const defaultLang = defaultLanguageForLocale(context.variables.locale);
291
295
  return `{ defaultLang: ${JSON.stringify(defaultLang)}, languages: ${JSON.stringify(context.languages)} }`;
@@ -295,7 +299,12 @@ var seo = np("@riebeckite/plugin-seo", "seo", {
295
299
  robots: { depth: 2, value: "true" },
296
300
  feed: { depth: 3, value: "{ rss: true, atom: true, json: true }" }
297
301
  });
298
- var toc = np("@riebeckite/plugin-toc", "tocPlugin");
302
+ var blogSeo = np(
303
+ "@riebeckite/plugin-seo",
304
+ "seo",
305
+ `{ sitemap: true, robots: true, feed: { rss: true, atom: true, json: true } }`
306
+ );
307
+ var toc = np("@riebeckite/plugin-toc", "toc");
299
308
  var properties = np("@riebeckite/plugin-properties", "properties", {
300
309
  include: { depth: 2, value: '["created", "modified", "tags", "status"]' },
301
310
  fields: {
@@ -303,7 +312,7 @@ var properties = np("@riebeckite/plugin-properties", "properties", {
303
312
  value: '{ created: { type: "date", format: "yyyy-MM-dd" }, modified: { type: "date", format: "yyyy-MM-dd" }, tags: { type: "tags", variant: "chips" }, status: { type: "badge", variants: { active: "success", draft: "warning", archived: "danger" } } }'
304
313
  }
305
314
  });
306
- var alias = np("@riebeckite/plugin-alias", "aliasPlugin", `{ status: 308 }`);
315
+ var alias = np("@riebeckite/plugin-alias", "alias", `{ status: 308 }`);
307
316
  var codeEnhance = np("@riebeckite/plugin-code-enhance", "codeEnhance", {
308
317
  lineNumbers: { depth: 1, value: "true" },
309
318
  copyButton: { depth: 1, value: "true" },
@@ -313,9 +322,9 @@ var codeEnhance = np("@riebeckite/plugin-code-enhance", "codeEnhance", {
313
322
  theme: { depth: 3, value: '{ light: "github-light", dark: "github-dark" }' },
314
323
  wrapToggle: { depth: 3, value: "true" }
315
324
  });
316
- var search = np("@riebeckite/plugin-search", "searchPlugin");
317
- var backlinks = np("@riebeckite/plugin-backlinks", "backlinksPlugin");
318
- var breadcrumbs = np("@riebeckite/plugin-breadcrumbs", "breadcrumbsPlugin");
325
+ var search = np("@riebeckite/plugin-search", "search");
326
+ var backlinks = np("@riebeckite/plugin-backlinks", "backlinks");
327
+ var breadcrumbs = np("@riebeckite/plugin-breadcrumbs", "breadcrumbs");
319
328
  var navigationStarter = np("@riebeckite/plugin-navigation", "navigation");
320
329
  var navigationShowcase = np(
321
330
  "@riebeckite/plugin-navigation",
@@ -338,7 +347,7 @@ var share = np("@riebeckite/plugin-share", "share", {
338
347
  },
339
348
  mastodonInstance: { depth: 3, value: '"mastodon.social"' }
340
349
  });
341
- var recentPosts = np("@riebeckite/plugin-recent-posts", "recentPostsPlugin");
350
+ var recentPosts = np("@riebeckite/plugin-recent-posts", "recentPosts");
342
351
  var changelog = np("@riebeckite/plugin-changelog", "changelog", {
343
352
  perNote: { depth: 2, value: "true" },
344
353
  lookbackDays: { depth: 3, value: "90" },
@@ -382,7 +391,7 @@ var responsiveImage = np(
382
391
  );
383
392
  var lightbox = np(
384
393
  "@riebeckite/plugin-lightbox",
385
- "lightboxPlugin",
394
+ "lightbox",
386
395
  `{ selectorClass: "rr-lightbox-trigger" }`
387
396
  );
388
397
  var highlight = np("@riebeckite/plugin-highlight", "highlight", {
@@ -418,10 +427,15 @@ var taxonomy = np("@riebeckite/plugin-taxonomy", "taxonomy", {
418
427
  feeds: { depth: 3, value: "{ rss: true, atom: true, json: true }" },
419
428
  relatedLimit: { depth: 3, value: "8" }
420
429
  });
421
- var folderPages = np("@riebeckite/plugin-folder-pages", "folderPagesPlugin");
430
+ var blogTaxonomy = np(
431
+ "@riebeckite/plugin-taxonomy",
432
+ "taxonomy",
433
+ `{ tags: true, folders: true, related: true, feeds: { rss: true, atom: true, json: true } }`
434
+ );
435
+ var folderPages = np("@riebeckite/plugin-folder-pages", "folderPages");
422
436
  var autoCardLink = np(
423
437
  "@riebeckite/plugin-autocardlink",
424
- "autoCardLinkPlugin",
438
+ "autoCardLink",
425
439
  `{ className: "rb-cardlink" }`
426
440
  );
427
441
  var richEmbed = np(
@@ -536,12 +550,12 @@ var bases = np("@riebeckite/plugin-bases", "bases", {
536
550
  className: { depth: 3, value: '"rb-bases"' },
537
551
  showFallback: { depth: 3, value: "true" }
538
552
  });
539
- var dataview = np("@riebeckite/plugin-dataview", "dataviewPlugin", {
553
+ var dataview = np("@riebeckite/plugin-dataview", "dataview", {
540
554
  limit: { depth: 2, value: "50" },
541
555
  className: { depth: 3, value: '"rb-dataview"' },
542
556
  hideFallback: { depth: 3, value: "false" }
543
557
  });
544
- var flashcards = np("@riebeckite/plugin-flashcards", "flashcardsPlugin", {
558
+ var flashcards = np("@riebeckite/plugin-flashcards", "flashcards", {
545
559
  shuffle: { depth: 2, value: "true" },
546
560
  fallback: { depth: 2, value: "true" },
547
561
  className: { depth: 3, value: '"rb-flashcards"' }
@@ -552,55 +566,67 @@ var kanban = np("@riebeckite/plugin-kanban", "kanban", {
552
566
  className: { depth: 3, value: '"rb-kanban"' },
553
567
  fallback: { depth: 3, value: "true" }
554
568
  });
555
- var query = np("@riebeckite/plugin-query", "queryPlugin", {
569
+ var query = np("@riebeckite/plugin-query", "query", {
556
570
  defaultFormat: { depth: 2, value: '"list"' },
557
571
  defaultLimit: { depth: 2, value: "50" },
558
572
  className: { depth: 3, value: '"rb-query"' },
559
573
  excludeSelf: { depth: 3, value: "true" }
560
574
  });
561
- var localGraph = np("@riebeckite/plugin-local-graph", "localGraphPlugin");
562
- var hoverPreview = np(
563
- "@riebeckite/plugin-hover-preview",
564
- "hoverPreviewPlugin",
565
- {
566
- delay: { depth: 2, value: "120" },
567
- excerptLength: { depth: 2, value: "160" },
568
- selector: { depth: 2, value: `'a[href^="/"]'` },
569
- includeTitles: { depth: 3, value: "true" }
570
- }
575
+ var localGraph = np("@riebeckite/plugin-local-graph", "localGraph");
576
+ var docs = np(
577
+ "@riebeckite/plugin-docs",
578
+ "docs",
579
+ `{ root: "docs", sidebar: { auto: true }, prevNext: true }`
571
580
  );
581
+ var readingPlugins = [
582
+ obsidianMarkdown,
583
+ colorMode,
584
+ toc,
585
+ codeEnhance,
586
+ search,
587
+ breadcrumbs,
588
+ navigationStarter
589
+ ];
590
+ var hoverPreview = np("@riebeckite/plugin-hover-preview", "hoverPreview", {
591
+ delay: { depth: 2, value: "120" },
592
+ excerptLength: { depth: 2, value: "160" },
593
+ selector: { depth: 2, value: `'a[href^="/"]'` },
594
+ includeTitles: { depth: 3, value: "true" }
595
+ });
572
596
  var gardenExplorer = np(
573
597
  "@riebeckite/plugin-garden-explorer",
574
- "gardenExplorerPlugin"
598
+ "gardenExplorer"
575
599
  );
576
- var ux = np("@riebeckite/plugin-ux", "uxPlugin", {
600
+ var glossary = np("@riebeckite/plugin-glossary", "glossary");
601
+ var ux = np("@riebeckite/plugin-ux", "ux", {
577
602
  progress: { depth: 2, value: "true" },
578
603
  backToTop: { depth: 2, value: "true" },
579
604
  tocScrollSpy: { depth: 2, value: "true" }
580
605
  });
581
606
  var dailyNotes = np(
582
607
  "@riebeckite/plugin-daily-notes",
583
- "dailyNotesPlugin",
608
+ "dailyNotes",
584
609
  `{ source: { directory: "Daily", pathPattern: "Daily/{YYYY}-{MM}-{DD}" }, extract: { frontmatter: "daily-summary", codeBlock: "daily-snippet" }, widget: { limit: 5 } }`
585
610
  );
586
611
  var rename = np(
587
612
  "@riebeckite/plugin-rename",
588
- "renamePlugin",
613
+ "rename",
589
614
  `{ enabled: true, status: 308, onUnexpectedRemoval: "warning" }`
590
615
  );
591
616
  var textFragment = np(
592
617
  "@riebeckite/plugin-text-fragment",
593
- "textFragmentPlugin",
618
+ "textFragment",
594
619
  (context) => `{ prefix: ${JSON.stringify(`${context.variables.title}: `)} }`
595
620
  );
621
+ var timeline = np("@riebeckite/plugin-timeline", "timeline");
596
622
  var quality = np(
597
623
  "@riebeckite/plugin-quality",
598
- "qualityPlugin",
624
+ "quality",
599
625
  `{ a11y: { enabled: true }, ignoreRules: [] }`
600
626
  );
601
627
  var deploy = np(
602
628
  "@riebeckite/plugin-deploy",
603
- "deployPlugin",
629
+ "deploy",
604
630
  `{ provider: "cloudflare-pages" }`
605
631
  );
606
632
  var diagnostics = np(
@@ -612,6 +638,22 @@ var defaultTheme = {
612
638
  package: "@riebeckite/theme-default",
613
639
  factory: "defaultTheme"
614
640
  };
641
+ var gardenTheme = {
642
+ package: "@riebeckite/theme-garden",
643
+ factory: "gardenTheme"
644
+ };
645
+ var editorialTheme = {
646
+ package: "@riebeckite/theme-editorial",
647
+ factory: "editorialTheme"
648
+ };
649
+ var technicalTheme = {
650
+ package: "@riebeckite/theme-technical",
651
+ factory: "technicalTheme"
652
+ };
653
+ var folioTheme = {
654
+ package: "@riebeckite/theme-folio",
655
+ factory: "folioTheme"
656
+ };
615
657
  var showCaseTheme = {
616
658
  package: "@riebeckite/theme-default",
617
659
  factory: "defaultTheme",
@@ -667,6 +709,75 @@ var starter = {
667
709
  contentPages: ["index", "guide", "examples"],
668
710
  readme: "standard"
669
711
  };
712
+ var digitalGarden = {
713
+ name: "digital-garden",
714
+ description: "An Obsidian-compatible digital garden with linked notes, backlinks, and a local graph.",
715
+ languages: ["en"],
716
+ theme: gardenTheme,
717
+ plugins: [
718
+ seo,
719
+ ...readingPlugins,
720
+ properties,
721
+ alias,
722
+ backlinks,
723
+ relatedPosts,
724
+ recentPosts,
725
+ taxonomy,
726
+ folderPages,
727
+ localGraph,
728
+ hoverPreview
729
+ ],
730
+ contentPages: [],
731
+ readme: "standard"
732
+ };
733
+ var blog = {
734
+ name: "blog",
735
+ description: "A publishing-focused blog with tags, series, related posts, sharing, and feeds.",
736
+ languages: ["en"],
737
+ theme: editorialTheme,
738
+ plugins: [
739
+ ...readingPlugins,
740
+ blogSeo,
741
+ properties,
742
+ relatedPosts,
743
+ share,
744
+ recentPosts,
745
+ series,
746
+ blogTaxonomy,
747
+ folderPages
748
+ ],
749
+ contentPages: [],
750
+ readme: "standard"
751
+ };
752
+ var documentation = {
753
+ name: "docs",
754
+ description: "A documentation site with an automatic sidebar, table of contents, and previous/next navigation.",
755
+ languages: ["en"],
756
+ theme: technicalTheme,
757
+ plugins: [seo, ...readingPlugins, docs],
758
+ contentPages: [],
759
+ readme: "standard"
760
+ };
761
+ var portfolio = {
762
+ name: "portfolio",
763
+ description: "A calm portfolio for projects and contact details, with image and media support when you add it.",
764
+ languages: ["en"],
765
+ theme: folioTheme,
766
+ plugins: [
767
+ ...readingPlugins,
768
+ seo,
769
+ properties,
770
+ backlinks,
771
+ relatedPosts,
772
+ recentPosts,
773
+ responsiveImage,
774
+ lightbox,
775
+ media,
776
+ gallery
777
+ ],
778
+ contentPages: [],
779
+ readme: "standard"
780
+ };
670
781
  var showcase = {
671
782
  name: "showcase",
672
783
  description: "A feature-rich example that demonstrates the Riebeckite plugin ecosystem with rendered samples and references.",
@@ -705,6 +816,7 @@ var showcase = {
705
816
  autoCardLink,
706
817
  richEmbed,
707
818
  gallery,
819
+ glossary,
708
820
  mermaidPele,
709
821
  graphviz,
710
822
  d2,
@@ -732,6 +844,7 @@ var showcase = {
732
844
  dailyNotes,
733
845
  rename,
734
846
  textFragment,
847
+ timeline,
735
848
  quality,
736
849
  deploy,
737
850
  diagnostics
@@ -747,22 +860,144 @@ var showcase = {
747
860
  ],
748
861
  readme: "rich"
749
862
  };
750
- var scaffoldPresets = { starter, minimal, showcase, empty };
863
+ var scaffoldPresets = {
864
+ starter,
865
+ "digital-garden": digitalGarden,
866
+ blog,
867
+ docs: documentation,
868
+ portfolio,
869
+ minimal,
870
+ showcase,
871
+ empty
872
+ };
751
873
  var SCAFFOLD_DEFAULT_PRESET = "starter";
752
874
  var SCAFFOLD_PRESETS = SCAFFOLD_PRESET_NAMES.map((name) => ({
753
875
  name,
754
876
  description: scaffoldPresets[name].description
755
877
  }));
756
878
  function resolveScaffoldPreset(value) {
757
- if (value === void 0) return scaffoldPresets[SCAFFOLD_DEFAULT_PRESET];
879
+ if (value === void 0) {
880
+ const preset2 = scaffoldPresets[SCAFFOLD_DEFAULT_PRESET];
881
+ validateScaffoldPreset(preset2);
882
+ return preset2;
883
+ }
758
884
  const preset = scaffoldPresets[value];
759
885
  if (!preset) {
760
886
  throw new Error(
761
887
  `Unknown scaffold preset: ${value}. Available presets: ${SCAFFOLD_PRESET_NAMES.join(", ")}.`
762
888
  );
763
889
  }
890
+ validateScaffoldPreset(preset);
764
891
  return preset;
765
892
  }
893
+ function validateScaffoldPreset(preset) {
894
+ const factories = /* @__PURE__ */ new Map();
895
+ const packages = /* @__PURE__ */ new Map();
896
+ for (const plugin of preset.plugins) {
897
+ if (plugin.package.trim() === "" || plugin.factory.trim() === "") {
898
+ throw new Error(`Invalid plugin declaration in preset "${preset.name}".`);
899
+ }
900
+ const factoryPackage = factories.get(plugin.factory);
901
+ if (factoryPackage !== void 0 && factoryPackage !== plugin.package) {
902
+ throw new Error(
903
+ `Preset "${preset.name}" imports "${plugin.factory}" from both "${factoryPackage}" and "${plugin.package}".`
904
+ );
905
+ }
906
+ const packageFactory = packages.get(plugin.package);
907
+ if (packageFactory === plugin.factory) {
908
+ throw new Error(
909
+ `Preset "${preset.name}" registers "${plugin.factory}" from "${plugin.package}" more than once.`
910
+ );
911
+ }
912
+ factories.set(plugin.factory, plugin.package);
913
+ packages.set(plugin.package, plugin.factory);
914
+ }
915
+ if (preset.theme && preset.plugins.some((plugin) => plugin.factory === preset.theme?.factory)) {
916
+ throw new Error(
917
+ `Preset "${preset.name}" reuses theme factory "${preset.theme.factory}" as a plugin import.`
918
+ );
919
+ }
920
+ }
921
+
922
+ // src/scaffold/features.ts
923
+ var feature = (package_, factory, options) => ({ package: package_, factory, options });
924
+ var featurePacks = {
925
+ knowledge: {
926
+ name: "knowledge",
927
+ description: "Link previews and a local graph for connected notes.",
928
+ plugins: [
929
+ feature("@riebeckite/plugin-hover-preview", "hoverPreview"),
930
+ feature("@riebeckite/plugin-local-graph", "localGraph")
931
+ ]
932
+ },
933
+ diagrams: {
934
+ name: "diagrams",
935
+ description: "Mermaid and Graphviz diagrams in Markdown.",
936
+ plugins: [
937
+ feature("@riebeckite/plugin-mermaid-pele", "mermaidPele"),
938
+ feature("@riebeckite/plugin-graphviz", "graphviz")
939
+ ]
940
+ },
941
+ media: {
942
+ name: "media",
943
+ description: "Embedded audio and video, responsive images, and lightbox.",
944
+ plugins: [
945
+ feature("@riebeckite/plugin-media", "media"),
946
+ feature("@riebeckite/plugin-responsive-image", "responsiveImage"),
947
+ feature("@riebeckite/plugin-lightbox", "lightbox")
948
+ ]
949
+ },
950
+ i18n: {
951
+ name: "i18n",
952
+ description: "English and Japanese localization support for content you add.",
953
+ plugins: [
954
+ feature(
955
+ "@riebeckite/plugin-l10n",
956
+ "l10n",
957
+ '{ defaultLang: "en", languages: ["en", "ja"] }'
958
+ )
959
+ ]
960
+ }
961
+ };
962
+ var SCAFFOLD_FEATURE_NAMES = [
963
+ "knowledge",
964
+ "diagrams",
965
+ "media",
966
+ "i18n"
967
+ ];
968
+ var SCAFFOLD_FEATURE_PACKS = SCAFFOLD_FEATURE_NAMES.map((name) => featurePacks[name]);
969
+ function isScaffoldFeatureName(value) {
970
+ return SCAFFOLD_FEATURE_NAMES.includes(value);
971
+ }
972
+ function parseScaffoldFeatures(value) {
973
+ if (value === "none") return [];
974
+ const names = value.split(",");
975
+ if (names.length === 0 || names.some((name) => !isScaffoldFeatureName(name))) {
976
+ throw new Error(
977
+ `Unknown feature: ${names.find((name) => !isScaffoldFeatureName(name)) ?? "(missing)"}. Available features: ${SCAFFOLD_FEATURE_NAMES.join(", ")}.`
978
+ );
979
+ }
980
+ if (new Set(names).size !== names.length) {
981
+ throw new Error("Features must not be repeated.");
982
+ }
983
+ return names;
984
+ }
985
+ function composeScaffoldPreset(preset, features) {
986
+ const selected = features.map((name) => featurePacks[name]);
987
+ const composed = {
988
+ ...preset,
989
+ languages: features.includes("i18n") ? ["en", "ja"] : preset.languages,
990
+ plugins: [...preset.plugins, ...selected.flatMap((pack) => pack.plugins)]
991
+ };
992
+ try {
993
+ validateScaffoldPreset(composed);
994
+ } catch (error) {
995
+ throw new Error(
996
+ `Feature packs cannot be combined with preset "${preset.name}": ${error instanceof Error ? error.message : String(error)}`
997
+ );
998
+ }
999
+ return composed;
1000
+ }
766
1001
 
767
1002
  // src/scaffold/readme_demos.ts
768
1003
  var README_DEMOS = {
@@ -1128,6 +1363,10 @@ var README_DEMO_ORDER = [
1128
1363
  // src/scaffold/template_options.ts
1129
1364
  var OPTION_DEPTH = {
1130
1365
  empty: 0,
1366
+ "digital-garden": 2,
1367
+ blog: 2,
1368
+ docs: 2,
1369
+ portfolio: 2,
1131
1370
  minimal: 0,
1132
1371
  starter: 2,
1133
1372
  showcase: 3
@@ -1325,7 +1564,7 @@ var PLUGIN_MARKDOWN_GUIDES = {
1325
1564
  },
1326
1565
  "@riebeckite/plugin-shortcodes": {
1327
1566
  summary: "Expands built-in shortcode syntax inside Markdown.",
1328
- markdown: '::youtube[id=dQw4w9WgXcQ]\n\n::figure[Demo image]{src="/images/demo.png"}'
1567
+ markdown: '::youtube{id=dQw4w9WgXcQ}\n\n::figure[Demo image]{src="/images/demo.png"}'
1329
1568
  },
1330
1569
  "@riebeckite/plugin-series": {
1331
1570
  summary: "Groups Markdown pages into a reading series using frontmatter.",
@@ -1913,6 +2152,18 @@ var PLUGIN_CATEGORIES = [
1913
2152
  ko: "Obsidian 스타일 마크다운: 위키링크, 임베드, 콜아웃, 태그."
1914
2153
  }
1915
2154
  },
2155
+ {
2156
+ slug: "glossary",
2157
+ desc: {
2158
+ en: "An alphabetical glossary page from marked term notes.",
2159
+ ja: "印を付けた用語ノートからアルファベット順の用語集ページを生成。",
2160
+ "zh-CN": "从标记的术语笔记生成按字母排序的术语表页面。",
2161
+ es: "Una página de glosario alfabético a partir de notas de términos marcadas.",
2162
+ de: "Eine alphabetische Glossarseite aus markierten Begriffnotizen.",
2163
+ fr: "Une page de glossaire alphabétique à partir de notes de termes marquées.",
2164
+ ko: "표시한 용어 노트에서 알파벳순 용어집 페이지를 생성."
2165
+ }
2166
+ },
1916
2167
  {
1917
2168
  slug: "attachment",
1918
2169
  desc: {
@@ -2135,6 +2386,18 @@ var PLUGIN_CATEGORIES = [
2135
2386
  ko: "노트 그래프와 검색을 탐색하는 대화형 뷰."
2136
2387
  }
2137
2388
  },
2389
+ {
2390
+ slug: "timeline",
2391
+ desc: {
2392
+ en: "A chronological page from marked, dated notes.",
2393
+ ja: "印を付けた日付付きノートから時系列ページを生成。",
2394
+ "zh-CN": "从标记且带日期的笔记生成时间线页面。",
2395
+ es: "Una página cronológica a partir de notas marcadas y fechadas.",
2396
+ de: "Eine chronologische Seite aus markierten, datierten Notizen.",
2397
+ fr: "Une page chronologique à partir de notes marquées et datées.",
2398
+ ko: "표시한 날짜가 있는 노트에서 시간순 페이지를 생성."
2399
+ }
2400
+ },
2138
2401
  {
2139
2402
  slug: "local-graph",
2140
2403
  desc: {
@@ -2359,6 +2622,10 @@ function pluginsContent(language) {
2359
2622
  function readSummary(text, language) {
2360
2623
  return language === "ja" ? text.ja ?? text.en : text.en;
2361
2624
  }
2625
+ var SHOWCASE_DECK_LINK = {
2626
+ en: "This preset also ships a whole-document Marp note. Open the [note](/deck/) or its [standalone slide page](/slides/deck/).",
2627
+ ja: "このプリセットには全文が Marp のノートも含まれます。[ノート](/deck/) または [スライド単体ページ](/slides/deck/) を開いてください。"
2628
+ };
2362
2629
  var EXAMPLES_COPY = {
2363
2630
  heading: {
2364
2631
  en: "Examples",
@@ -2460,6 +2727,9 @@ function examplesContent(preset, language) {
2460
2727
  lines.push(heading(2, readSummary(demo.title, language)), "");
2461
2728
  lines.push(readSummary(demo.intro, language), "");
2462
2729
  lines.push(demo.markdown, "");
2730
+ if (preset.name === "showcase" && key === "@riebeckite/plugin-marp") {
2731
+ lines.push(readSummary(SHOWCASE_DECK_LINK, language), "");
2732
+ }
2463
2733
  }
2464
2734
  if (preset.name === "showcase") {
2465
2735
  for (const packageName of SHOWCASE_GUIDE_DEMOS) {
@@ -2587,6 +2857,22 @@ var README_INTRO = {
2587
2857
  en: "Recommended default: a practical Markdown garden with search, navigation, and reading essentials.",
2588
2858
  ja: "大半のサイトにおすすめの既定構成です。検索・ナビゲーション・閲覧に必要な機能を備えた実用的な Markdown サイトを作れます。"
2589
2859
  },
2860
+ "digital-garden": {
2861
+ en: "An Obsidian-compatible digital garden with linked notes, backlinks, and a local graph.",
2862
+ ja: "Obsidian と互換性のあるデジタルガーデンです。ノート間リンク、バックリンク、ローカルグラフを備えます。"
2863
+ },
2864
+ blog: {
2865
+ en: "A publishing-focused blog with tags, series, related posts, sharing, and feeds.",
2866
+ ja: "タグ、シリーズ、関連記事、共有、フィードを備えた公開向けブログです。"
2867
+ },
2868
+ docs: {
2869
+ en: "A documentation site with an automatic sidebar, table of contents, and previous/next navigation.",
2870
+ ja: "自動サイドバー、目次、前後ページナビゲーションを備えたドキュメントサイトです。"
2871
+ },
2872
+ portfolio: {
2873
+ en: "A focused portfolio with pages for selected projects, an introduction, and contact details.",
2874
+ ja: "選んだプロジェクト、自己紹介、連絡先のページから始められる、要点を絞ったポートフォリオです。"
2875
+ },
2590
2876
  showcase: {
2591
2877
  en: "A feature-rich example that demonstrates the Riebeckite plugin ecosystem with rendered samples, reference pages, and local fixtures.",
2592
2878
  ja: "Riebeckite の Plugin エコシステムを実際に確認できる機能紹介用の構成です。描画例・リファレンスページ・ローカルのフィクスチャを含みます。"
@@ -2964,7 +3250,7 @@ function utilityTemplateFiles(utilities) {
2964
3250
  }
2965
3251
 
2966
3252
  // src/scaffold/version.ts
2967
- var RIEBECKITE_VERSION = "^0.0.32";
3253
+ var RIEBECKITE_VERSION = "^0.0.33";
2968
3254
 
2969
3255
  // src/scaffold/templates.ts
2970
3256
  function siteTemplateFiles(preset, variables, options = {}) {
@@ -3060,7 +3346,7 @@ function packageJson(preset, variables, options) {
3060
3346
  "@riebeckite/cli": RIEBECKITE_VERSION,
3061
3347
  "@types/node": "^24.5.2",
3062
3348
  typescript: "^5.0.0",
3063
- vite: "^8.0.9",
3349
+ vite: "^8.3.5",
3064
3350
  ...options.cloudflareWorkers ? { wrangler: WRANGLER_VERSION } : {}
3065
3351
  }
3066
3352
  },
@@ -3155,7 +3441,10 @@ function formatScaffoldNextSteps(relativeDirectory, options = {}) {
3155
3441
  var NO_DEPLOYMENT = { type: "none" };
3156
3442
  async function scaffoldRiebeckiteSite(options) {
3157
3443
  const targetDirectory = path3.resolve(options.targetDirectory);
3158
- const preset = resolveScaffoldPreset(options.preset);
3444
+ const preset = composeScaffoldPreset(
3445
+ resolveScaffoldPreset(options.preset),
3446
+ options.features ?? []
3447
+ );
3159
3448
  const deployment = options.deployment ?? NO_DEPLOYMENT;
3160
3449
  const externalContent = externalContentSource(deployment);
3161
3450
  if (externalContent !== void 0) {
@@ -3257,14 +3546,18 @@ export {
3257
3546
  GITHUB_ACTIONS_SECRETS,
3258
3547
  SCAFFOLD_DEFAULT_PRESET,
3259
3548
  SCAFFOLD_DEFAULT_UTILITIES,
3549
+ SCAFFOLD_FEATURE_NAMES,
3550
+ SCAFFOLD_FEATURE_PACKS,
3260
3551
  SCAFFOLD_PRESETS,
3261
3552
  SCAFFOLD_UTILITIES,
3262
3553
  SCAFFOLD_UTILITY_NAMES,
3263
3554
  ScaffoldSiteError,
3264
3555
  deploymentWorkflow,
3265
3556
  formatScaffoldNextSteps,
3557
+ isScaffoldFeatureName,
3266
3558
  isScaffoldPresetName,
3267
3559
  isScaffoldUtilityName,
3560
+ parseScaffoldFeatures,
3268
3561
  parseScaffoldUtilities,
3269
3562
  scaffoldDeploymentFromFlags,
3270
3563
  scaffoldRiebeckiteSite,
@@ -1,3 +1,4 @@
1
+ import type { ScaffoldFeatureName } from "./features.js";
1
2
  import type { ScaffoldPresetName } from "./presets.js";
2
3
  import type { ScaffoldUtilityName } from "./utilities.js";
3
4
  export type ScaffoldSiteMetadata = {
@@ -26,6 +27,7 @@ export type ScaffoldSiteOptions = {
26
27
  readonly name?: string;
27
28
  readonly site?: ScaffoldSiteMetadata;
28
29
  readonly preset?: ScaffoldPresetName;
30
+ readonly features?: readonly ScaffoldFeatureName[];
29
31
  readonly utilities?: readonly ScaffoldUtilityName[];
30
32
  readonly deployment?: ScaffoldDeployment;
31
33
  readonly overwrite?: boolean;
@@ -19,11 +19,11 @@
19
19
  export declare const SCAFFOLD_LANGUAGES: readonly ["en", "ja", "zh-CN", "es", "de", "fr", "ko"];
20
20
  export type ScaffoldLanguage = (typeof SCAFFOLD_LANGUAGES)[number];
21
21
  export declare function defaultLanguageForLocale(locale: string): string;
22
- export type ScaffoldPresetName = "starter" | "minimal" | "showcase" | "empty";
22
+ export type ScaffoldPresetName = "starter" | "digital-garden" | "blog" | "docs" | "portfolio" | "minimal" | "showcase" | "empty";
23
23
  export declare const SCAFFOLD_PRESET_NAMES: readonly ScaffoldPresetName[];
24
24
  export declare function isScaffoldPresetName(value: string): value is ScaffoldPresetName;
25
25
  /** How a theme factory is referenced in the generated config file. */
26
- export type ScaffoldThemeSpec = {
26
+ type ScaffoldThemeSpec = {
27
27
  /** Npm package, for example `@riebeckite/theme-minimal`. */
28
28
  readonly package: string;
29
29
  /** Factory/import name, for example `minimalTheme`. */
@@ -61,7 +61,7 @@ export type ScaffoldOptionContext = {
61
61
  /** A single option value: a literal, or a function of the scaffold context. */
62
62
  export type ScaffoldOptionValue = string | ((context: ScaffoldOptionContext) => string);
63
63
  /** A config field gated to a minimum preset depth. */
64
- export type ScaffoldOptionField = {
64
+ type ScaffoldOptionField = {
65
65
  /** The lowest `ScaffoldOptionContext.depth` that includes this field. */
66
66
  readonly depth: number;
67
67
  readonly value: ScaffoldOptionValue;
@@ -74,9 +74,9 @@ export type ScaffoldOptionField = {
74
74
  */
75
75
  export type ScaffoldOptions = string | ((context: ScaffoldOptionContext) => string) | Readonly<Record<string, ScaffoldOptionField>>;
76
76
  /** Content pages the scaffold can emit. */
77
- export type ScaffoldPageKey = "index" | "framework/plugins" | "framework/themes" | "guide" | "examples" | "reference/plugins" | "reference/themes";
77
+ type ScaffoldPageKey = "index" | "framework/plugins" | "framework/themes" | "guide" | "examples" | "reference/plugins" | "reference/themes";
78
78
  /** README verbosity. */
79
- export type ScaffoldReadmeLevel = "short" | "standard" | "rich";
79
+ type ScaffoldReadmeLevel = "short" | "standard" | "rich";
80
80
  export type ScaffoldPreset = {
81
81
  readonly name: ScaffoldPresetName;
82
82
  /** One-line human description, shown by `--list-presets`. */
@@ -91,6 +91,8 @@ export type ScaffoldPreset = {
91
91
  export declare const empty: ScaffoldPreset;
92
92
  export declare const minimal: ScaffoldPreset;
93
93
  export declare const starter: ScaffoldPreset;
94
+ export declare const blog: ScaffoldPreset;
95
+ export declare const portfolio: ScaffoldPreset;
94
96
  export declare const showcase: ScaffoldPreset;
95
97
  export declare const scaffoldPresets: Readonly<Record<ScaffoldPresetName, ScaffoldPreset>>;
96
98
  export declare const SCAFFOLD_DEFAULT_PRESET: ScaffoldPresetName;
@@ -100,3 +102,5 @@ export type ScaffoldPresetSummary = {
100
102
  };
101
103
  export declare const SCAFFOLD_PRESETS: readonly ScaffoldPresetSummary[];
102
104
  export declare function resolveScaffoldPreset(value: ScaffoldPresetName | undefined): ScaffoldPreset;
105
+ export declare function validateScaffoldPreset(preset: ScaffoldPreset): void;
106
+ export {};
@@ -1,5 +1,5 @@
1
1
  import type { ScaffoldPreset } from "./presets.js";
2
- export type ReadmeDemo = {
2
+ type ReadmeDemo = {
3
3
  readonly title: {
4
4
  readonly en: string;
5
5
  readonly ja: string;
@@ -25,3 +25,4 @@ export declare function hasPlugin(preset: ScaffoldPreset, packageName: string):
25
25
  */
26
26
  export declare function demoPackage(key: string): string;
27
27
  export declare const README_DEMO_ORDER: string[];
28
+ export {};
@@ -1,10 +1,5 @@
1
- import type { ScaffoldOptionContext, ScaffoldOptions, ScaffoldPreset } from "./presets.js";
1
+ import type { ScaffoldPreset } from "./presets.js";
2
2
  import type { SiteTemplateVariables } from "./template_types.js";
3
- /**
4
- * Resolve a plugin's options literal for the preset's depth, or `null` when
5
- * the plugin takes no options at that depth (and should be called bare).
6
- */
7
- export declare function renderOptions(options: ScaffoldOptions | undefined, context: ScaffoldOptionContext): string | null;
8
3
  export declare function pluginExpression(plugin: ScaffoldPreset["plugins"][number], preset: ScaffoldPreset, variables: SiteTemplateVariables): string;
9
4
  /**
10
5
  * The options object literal used for a plugin at this preset's depth, or