@glw907/cairn-cms 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/components/ConceptList.svelte +8 -4
  2. package/dist/components/ConceptList.svelte.d.ts.map +1 -1
  3. package/dist/content/compose.d.ts +2 -2
  4. package/dist/content/compose.d.ts.map +1 -1
  5. package/dist/content/compose.js +2 -2
  6. package/dist/content/concepts.d.ts +7 -6
  7. package/dist/content/concepts.d.ts.map +1 -1
  8. package/dist/content/concepts.js +9 -6
  9. package/dist/content/ids.d.ts +14 -0
  10. package/dist/content/ids.d.ts.map +1 -1
  11. package/dist/content/ids.js +40 -0
  12. package/dist/content/permalink.d.ts +1 -0
  13. package/dist/content/permalink.d.ts.map +1 -1
  14. package/dist/content/permalink.js +1 -1
  15. package/dist/content/types.d.ts +12 -6
  16. package/dist/content/types.d.ts.map +1 -1
  17. package/dist/delivery/content-index.d.ts +1 -0
  18. package/dist/delivery/content-index.d.ts.map +1 -1
  19. package/dist/delivery/content-index.js +4 -2
  20. package/dist/delivery/site-index.d.ts +28 -0
  21. package/dist/delivery/site-index.d.ts.map +1 -0
  22. package/dist/delivery/site-index.js +38 -0
  23. package/dist/index.d.ts +6 -3
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +3 -2
  26. package/dist/nav/site-config.d.ts +5 -0
  27. package/dist/nav/site-config.d.ts.map +1 -1
  28. package/dist/nav/site-config.js +4 -0
  29. package/dist/sveltekit/content-routes.d.ts.map +1 -1
  30. package/dist/sveltekit/content-routes.js +18 -8
  31. package/dist/sveltekit/public-routes.d.ts +11 -12
  32. package/dist/sveltekit/public-routes.d.ts.map +1 -1
  33. package/dist/sveltekit/public-routes.js +36 -35
  34. package/package.json +1 -1
  35. package/src/lib/components/ConceptList.svelte +8 -4
  36. package/src/lib/content/compose.ts +3 -2
  37. package/src/lib/content/concepts.ts +10 -6
  38. package/src/lib/content/ids.ts +44 -0
  39. package/src/lib/content/permalink.ts +2 -2
  40. package/src/lib/content/types.ts +13 -6
  41. package/src/lib/delivery/content-index.ts +5 -2
  42. package/src/lib/delivery/site-index.ts +68 -0
  43. package/src/lib/index.ts +13 -1
  44. package/src/lib/nav/site-config.ts +8 -0
  45. package/src/lib/sveltekit/content-routes.ts +17 -7
  46. package/src/lib/sveltekit/public-routes.ts +38 -36
@@ -1,13 +1,15 @@
1
- // cairn-cms: public route loaders (public-delivery design, decision 6). A factory closes over
2
- // a concept's index, the runtime render, and the origin, and returns thin load functions plus
3
- // entries() for prerender. A site route file stays a one-line shim. The index is built in site
4
- // code from a glob, so it stays in the prerender graph and out of the runtime Worker.
1
+ // cairn-cms: public route loaders (dated-slug design). The factory closes over the site-level
2
+ // index, the runtime render, and the origin. entryLoad and entries are site-wide: one catch-all
3
+ // `[...path]` route resolves any concept by request path through `byPermalink`. The archive, tag,
4
+ // and tag-index loaders stay concept-scoped, keyed by concept id. The index is built in site code
5
+ // from globs, so it stays in the prerender graph and out of the runtime Worker.
5
6
  import { error } from '@sveltejs/kit';
6
- import type { ContentIndex, ContentSummary, ContentEntry } from '../delivery/content-index.js';
7
+ import type { ContentSummary, ContentEntry } from '../delivery/content-index.js';
8
+ import type { SiteIndex } from '../delivery/site-index.js';
7
9
 
8
10
  /** Injected dependencies for the public loaders. */
9
11
  export interface PublicRoutesDeps {
10
- index: ContentIndex;
12
+ site: SiteIndex;
11
13
  render: (md: string, opts?: { stagger?: boolean }) => string | Promise<string>;
12
14
  origin: string;
13
15
  }
@@ -36,46 +38,46 @@ export interface EntryData {
36
38
  older?: ContentSummary;
37
39
  }
38
40
 
39
- /** Build the public loaders for one concept's index. */
41
+ /** Build the public loaders for a site's unified index. */
40
42
  export function createPublicRoutes(deps: PublicRoutesDeps) {
41
- const { index, render, origin } = deps;
43
+ const { site, render, origin } = deps;
42
44
 
43
- /** The chronological archive: every non-draft summary, newest-first. */
44
- function archiveLoad(): ListData {
45
- return { entries: index.all() };
45
+ /** Resolve one concept's index by id, or a 404 (the route names an unconfigured concept). */
46
+ function indexOf(conceptId: string) {
47
+ const index = site.concept(conceptId);
48
+ if (!index) throw error(404, `Unknown content type: ${conceptId}`);
49
+ return index;
46
50
  }
47
51
 
48
- /** All tags with counts, for a tag index page. */
49
- function tagIndexLoad(): TagIndexData {
50
- return { tags: index.allTags() };
52
+ /** One entry by request path, rendered through the site renderer, or a 404. */
53
+ async function entryLoad(event: { url: URL }): Promise<EntryData> {
54
+ const entry = site.byPermalink(event.url.pathname);
55
+ if (!entry) throw error(404, `Not found: ${event.url.pathname}`);
56
+ const { newer, older } = site.adjacent(entry);
57
+ return { entry, html: await render(entry.body, { stagger: true }), canonicalUrl: origin + entry.permalink, newer, older };
51
58
  }
52
59
 
53
- /** One tag's entries, or a 404 when the tag has none. */
54
- function tagLoad(event: { params: { tag: string } }): TagData {
55
- const tag = event.params.tag;
56
- const entries = index.byTag(tag);
57
- if (entries.length === 0) throw error(404, `No entries tagged "${tag}"`);
58
- return { tag, entries };
60
+ /** The chronological archive for one concept: every non-draft summary, newest-first. */
61
+ function archiveLoad(conceptId: string): ListData {
62
+ return { entries: indexOf(conceptId).all() };
59
63
  }
60
64
 
61
- /** One entry by slug, rendered through the site renderer, or a 404. */
62
- async function entryLoad(event: { params: { slug: string } }): Promise<EntryData> {
63
- const entry = index.byId(event.params.slug);
64
- if (!entry) throw error(404, `Not found: ${event.params.slug}`);
65
- const { newer, older } = index.adjacent(entry.id);
66
- return {
67
- entry,
68
- html: await render(entry.body, { stagger: true }),
69
- canonicalUrl: origin + entry.permalink,
70
- newer,
71
- older,
72
- };
65
+ /** All tags with counts for one concept, for a tag index page. */
66
+ function tagIndexLoad(conceptId: string): TagIndexData {
67
+ return { tags: indexOf(conceptId).allTags() };
73
68
  }
74
69
 
75
- /** Prerender enumeration: one `{ slug }` per non-draft entry. */
76
- function entries(): { slug: string }[] {
77
- return index.all().map((entry) => ({ slug: entry.id }));
70
+ /** One tag's entries for one concept, or a 404 when the tag has none. */
71
+ function tagLoad(conceptId: string, event: { params: { tag: string } }): TagData {
72
+ const entries = indexOf(conceptId).byTag(event.params.tag);
73
+ if (entries.length === 0) throw error(404, `No entries tagged "${event.params.tag}"`);
74
+ return { tag: event.params.tag, entries };
78
75
  }
79
76
 
80
- return { archiveLoad, tagIndexLoad, tagLoad, entryLoad, entries };
77
+ /** Prerender enumeration: one `{ path }` per entry across every concept. */
78
+ function entries(): { path: string }[] {
79
+ return site.entries();
80
+ }
81
+
82
+ return { entryLoad, archiveLoad, tagIndexLoad, tagLoad, entries };
81
83
  }