@glw907/cairn-cms 0.26.0 → 0.33.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 (234) hide show
  1. package/CHANGELOG.md +143 -0
  2. package/dist/auth/crypto.d.ts +0 -1
  3. package/dist/auth/store.d.ts +0 -1
  4. package/dist/auth/types.d.ts +0 -1
  5. package/dist/components/AdminLayout.svelte +372 -44
  6. package/dist/components/AdminLayout.svelte.d.ts +5 -5
  7. package/dist/components/CairnLogo.svelte +28 -0
  8. package/dist/components/CairnLogo.svelte.d.ts +15 -0
  9. package/dist/components/ComponentForm.svelte +1 -1
  10. package/dist/components/ComponentForm.svelte.d.ts +0 -1
  11. package/dist/components/ComponentInsertDialog.svelte.d.ts +0 -1
  12. package/dist/components/ConceptList.svelte +240 -45
  13. package/dist/components/ConceptList.svelte.d.ts +12 -3
  14. package/dist/components/ConfirmPage.svelte +20 -3
  15. package/dist/components/ConfirmPage.svelte.d.ts +0 -1
  16. package/dist/components/DeleteDialog.svelte.d.ts +0 -1
  17. package/dist/components/EditPage.svelte +12 -7
  18. package/dist/components/EditPage.svelte.d.ts +0 -1
  19. package/dist/components/EditorToolbar.svelte.d.ts +0 -1
  20. package/dist/components/IconPicker.svelte.d.ts +0 -1
  21. package/dist/components/LinkPicker.svelte.d.ts +0 -1
  22. package/dist/components/LoginPage.svelte +27 -5
  23. package/dist/components/LoginPage.svelte.d.ts +0 -1
  24. package/dist/components/ManageEditors.svelte +8 -5
  25. package/dist/components/ManageEditors.svelte.d.ts +0 -1
  26. package/dist/components/MarkdownEditor.svelte.d.ts +0 -1
  27. package/dist/components/NavTree.svelte +2 -2
  28. package/dist/components/NavTree.svelte.d.ts +0 -1
  29. package/dist/components/RenameDialog.svelte.d.ts +0 -1
  30. package/dist/components/admin-icons.d.ts +13 -0
  31. package/dist/components/admin-icons.js +15 -0
  32. package/dist/components/cairn-admin.css +5516 -37
  33. package/dist/components/cairn-favicon.d.ts +2 -0
  34. package/dist/components/cairn-favicon.js +7 -0
  35. package/dist/components/chrome-guard.d.ts +9 -0
  36. package/dist/components/chrome-guard.js +55 -0
  37. package/dist/components/fonts/BricolageGrotesque-OFL.txt +93 -0
  38. package/dist/components/fonts/Figtree-OFL.txt +93 -0
  39. package/dist/components/fonts/bricolage-grotesque.woff2 +0 -0
  40. package/dist/components/fonts/figtree.woff2 +0 -0
  41. package/dist/components/index.d.ts +0 -1
  42. package/dist/components/link-completion.d.ts +0 -1
  43. package/dist/components/markdown-format.d.ts +0 -1
  44. package/dist/content/adapter.d.ts +0 -1
  45. package/dist/content/compose.d.ts +1 -2
  46. package/dist/content/compose.js +2 -3
  47. package/dist/content/concepts.d.ts +7 -1
  48. package/dist/content/concepts.js +49 -1
  49. package/dist/content/frontmatter.d.ts +0 -1
  50. package/dist/content/identity.d.ts +23 -0
  51. package/dist/content/identity.js +43 -0
  52. package/dist/content/ids.d.ts +0 -1
  53. package/dist/content/links.d.ts +0 -1
  54. package/dist/content/manifest.d.ts +3 -2
  55. package/dist/content/manifest.js +6 -26
  56. package/dist/content/permalink.d.ts +0 -1
  57. package/dist/content/schema.d.ts +0 -1
  58. package/dist/content/types.d.ts +0 -1
  59. package/dist/content/validate.d.ts +0 -1
  60. package/dist/delivery/CairnHead.svelte.d.ts +0 -1
  61. package/dist/delivery/content-index.d.ts +0 -1
  62. package/dist/delivery/content-index.js +8 -25
  63. package/dist/delivery/data.d.ts +0 -1
  64. package/dist/delivery/excerpt.d.ts +0 -1
  65. package/dist/delivery/feeds.d.ts +0 -1
  66. package/dist/delivery/head.d.ts +0 -1
  67. package/dist/delivery/index.d.ts +0 -1
  68. package/dist/delivery/json-ld.d.ts +0 -1
  69. package/dist/delivery/manifest.d.ts +0 -1
  70. package/dist/delivery/paginate.d.ts +0 -1
  71. package/dist/delivery/responses.d.ts +0 -1
  72. package/dist/delivery/robots.d.ts +0 -1
  73. package/dist/delivery/seo-fields.d.ts +0 -1
  74. package/dist/delivery/seo.d.ts +0 -1
  75. package/dist/delivery/site-descriptors.d.ts +0 -1
  76. package/dist/delivery/site-descriptors.js +5 -6
  77. package/dist/delivery/site-index.d.ts +0 -1
  78. package/dist/delivery/site-indexes.d.ts +0 -1
  79. package/dist/delivery/sitemap.d.ts +0 -1
  80. package/dist/email.d.ts +0 -1
  81. package/dist/env.d.ts +0 -1
  82. package/dist/github/credentials.d.ts +0 -1
  83. package/dist/github/repo.d.ts +0 -1
  84. package/dist/github/signing.d.ts +0 -1
  85. package/dist/github/types.d.ts +0 -1
  86. package/dist/index.d.ts +0 -29
  87. package/dist/index.js +4 -23
  88. package/dist/nav/site-config.d.ts +0 -1
  89. package/dist/render/authoring.d.ts +3 -0
  90. package/dist/render/authoring.js +5 -0
  91. package/dist/render/component-grammar.d.ts +0 -1
  92. package/dist/render/component-insert.d.ts +0 -1
  93. package/dist/render/component-reference.d.ts +0 -1
  94. package/dist/render/component-validate.d.ts +0 -1
  95. package/dist/render/glyph.d.ts +0 -1
  96. package/dist/render/index.d.ts +0 -1
  97. package/dist/render/pipeline.d.ts +0 -1
  98. package/dist/render/pipeline.js +5 -1
  99. package/dist/render/registry.d.ts +2 -1
  100. package/dist/render/registry.js +15 -0
  101. package/dist/render/rehype-dispatch.d.ts +9 -7
  102. package/dist/render/rehype-dispatch.js +12 -6
  103. package/dist/render/remark-directives.d.ts +0 -1
  104. package/dist/render/remark-directives.js +1 -1
  105. package/dist/render/resolve-links.d.ts +0 -1
  106. package/dist/render/sanitize-schema.d.ts +14 -1
  107. package/dist/render/sanitize-schema.js +96 -0
  108. package/dist/sveltekit/auth-routes.d.ts +0 -1
  109. package/dist/sveltekit/content-routes.d.ts +12 -2
  110. package/dist/sveltekit/content-routes.js +37 -13
  111. package/dist/sveltekit/editors-routes.d.ts +0 -1
  112. package/dist/sveltekit/guard.d.ts +0 -1
  113. package/dist/sveltekit/health.d.ts +0 -1
  114. package/dist/sveltekit/index.d.ts +1 -3
  115. package/dist/sveltekit/index.js +0 -1
  116. package/dist/sveltekit/nav-routes.d.ts +0 -1
  117. package/dist/sveltekit/public-routes.d.ts +0 -1
  118. package/dist/sveltekit/types.d.ts +0 -1
  119. package/dist/vite/bin.d.ts +0 -1
  120. package/dist/vite/index.d.ts +0 -1
  121. package/package.json +16 -2
  122. package/src/lib/components/AdminLayout.svelte +372 -44
  123. package/src/lib/components/CairnLogo.svelte +28 -0
  124. package/src/lib/components/ComponentForm.svelte +1 -1
  125. package/src/lib/components/ConceptList.svelte +240 -45
  126. package/src/lib/components/ConfirmPage.svelte +20 -3
  127. package/src/lib/components/EditPage.svelte +12 -7
  128. package/src/lib/components/LoginPage.svelte +27 -5
  129. package/src/lib/components/ManageEditors.svelte +8 -5
  130. package/src/lib/components/NavTree.svelte +2 -2
  131. package/src/lib/components/admin-icons.ts +15 -0
  132. package/src/lib/components/cairn-admin.css +162 -7
  133. package/src/lib/components/cairn-favicon.ts +9 -0
  134. package/src/lib/components/chrome-guard.ts +62 -0
  135. package/src/lib/components/fonts/BricolageGrotesque-OFL.txt +93 -0
  136. package/src/lib/components/fonts/Figtree-OFL.txt +93 -0
  137. package/src/lib/components/fonts/bricolage-grotesque.woff2 +0 -0
  138. package/src/lib/components/fonts/figtree.woff2 +0 -0
  139. package/src/lib/content/compose.ts +3 -3
  140. package/src/lib/content/concepts.ts +61 -1
  141. package/src/lib/content/identity.ts +60 -0
  142. package/src/lib/content/manifest.ts +6 -27
  143. package/src/lib/delivery/content-index.ts +8 -27
  144. package/src/lib/delivery/site-descriptors.ts +5 -6
  145. package/src/lib/index.ts +4 -57
  146. package/src/lib/render/authoring.ts +7 -0
  147. package/src/lib/render/pipeline.ts +4 -1
  148. package/src/lib/render/registry.ts +20 -0
  149. package/src/lib/render/rehype-dispatch.ts +13 -6
  150. package/src/lib/render/remark-directives.ts +1 -1
  151. package/src/lib/render/sanitize-schema.ts +97 -0
  152. package/src/lib/sveltekit/content-routes.ts +51 -14
  153. package/src/lib/sveltekit/index.ts +2 -8
  154. package/dist/auth/crypto.d.ts.map +0 -1
  155. package/dist/auth/store.d.ts.map +0 -1
  156. package/dist/auth/types.d.ts.map +0 -1
  157. package/dist/components/AdminLayout.svelte.d.ts.map +0 -1
  158. package/dist/components/ComponentForm.svelte.d.ts.map +0 -1
  159. package/dist/components/ComponentInsertDialog.svelte.d.ts.map +0 -1
  160. package/dist/components/ConceptList.svelte.d.ts.map +0 -1
  161. package/dist/components/ConfirmPage.svelte.d.ts.map +0 -1
  162. package/dist/components/DeleteDialog.svelte.d.ts.map +0 -1
  163. package/dist/components/EditPage.svelte.d.ts.map +0 -1
  164. package/dist/components/EditorToolbar.svelte.d.ts.map +0 -1
  165. package/dist/components/IconPicker.svelte.d.ts.map +0 -1
  166. package/dist/components/LinkPicker.svelte.d.ts.map +0 -1
  167. package/dist/components/LoginPage.svelte.d.ts.map +0 -1
  168. package/dist/components/ManageEditors.svelte.d.ts.map +0 -1
  169. package/dist/components/MarkdownEditor.svelte.d.ts.map +0 -1
  170. package/dist/components/NavTree.svelte.d.ts.map +0 -1
  171. package/dist/components/RenameDialog.svelte.d.ts.map +0 -1
  172. package/dist/components/index.d.ts.map +0 -1
  173. package/dist/components/link-completion.d.ts.map +0 -1
  174. package/dist/components/markdown-format.d.ts.map +0 -1
  175. package/dist/content/adapter.d.ts.map +0 -1
  176. package/dist/content/compose.d.ts.map +0 -1
  177. package/dist/content/concepts.d.ts.map +0 -1
  178. package/dist/content/frontmatter.d.ts.map +0 -1
  179. package/dist/content/ids.d.ts.map +0 -1
  180. package/dist/content/links.d.ts.map +0 -1
  181. package/dist/content/manifest.d.ts.map +0 -1
  182. package/dist/content/permalink.d.ts.map +0 -1
  183. package/dist/content/schema.d.ts.map +0 -1
  184. package/dist/content/types.d.ts.map +0 -1
  185. package/dist/content/validate.d.ts.map +0 -1
  186. package/dist/delivery/CairnHead.svelte.d.ts.map +0 -1
  187. package/dist/delivery/content-index.d.ts.map +0 -1
  188. package/dist/delivery/data.d.ts.map +0 -1
  189. package/dist/delivery/excerpt.d.ts.map +0 -1
  190. package/dist/delivery/feeds.d.ts.map +0 -1
  191. package/dist/delivery/head.d.ts.map +0 -1
  192. package/dist/delivery/index.d.ts.map +0 -1
  193. package/dist/delivery/json-ld.d.ts.map +0 -1
  194. package/dist/delivery/manifest.d.ts.map +0 -1
  195. package/dist/delivery/paginate.d.ts.map +0 -1
  196. package/dist/delivery/responses.d.ts.map +0 -1
  197. package/dist/delivery/robots.d.ts.map +0 -1
  198. package/dist/delivery/seo-fields.d.ts.map +0 -1
  199. package/dist/delivery/seo.d.ts.map +0 -1
  200. package/dist/delivery/site-descriptors.d.ts.map +0 -1
  201. package/dist/delivery/site-index.d.ts.map +0 -1
  202. package/dist/delivery/site-indexes.d.ts.map +0 -1
  203. package/dist/delivery/sitemap.d.ts.map +0 -1
  204. package/dist/email.d.ts.map +0 -1
  205. package/dist/env.d.ts.map +0 -1
  206. package/dist/github/credentials.d.ts.map +0 -1
  207. package/dist/github/repo.d.ts.map +0 -1
  208. package/dist/github/signing.d.ts.map +0 -1
  209. package/dist/github/types.d.ts.map +0 -1
  210. package/dist/index.d.ts.map +0 -1
  211. package/dist/nav/site-config.d.ts.map +0 -1
  212. package/dist/render/component-grammar.d.ts.map +0 -1
  213. package/dist/render/component-insert.d.ts.map +0 -1
  214. package/dist/render/component-reference.d.ts.map +0 -1
  215. package/dist/render/component-validate.d.ts.map +0 -1
  216. package/dist/render/glyph.d.ts.map +0 -1
  217. package/dist/render/index.d.ts.map +0 -1
  218. package/dist/render/pipeline.d.ts.map +0 -1
  219. package/dist/render/registry.d.ts.map +0 -1
  220. package/dist/render/rehype-dispatch.d.ts.map +0 -1
  221. package/dist/render/remark-directives.d.ts.map +0 -1
  222. package/dist/render/resolve-links.d.ts.map +0 -1
  223. package/dist/render/sanitize-schema.d.ts.map +0 -1
  224. package/dist/sveltekit/auth-routes.d.ts.map +0 -1
  225. package/dist/sveltekit/content-routes.d.ts.map +0 -1
  226. package/dist/sveltekit/editors-routes.d.ts.map +0 -1
  227. package/dist/sveltekit/guard.d.ts.map +0 -1
  228. package/dist/sveltekit/health.d.ts.map +0 -1
  229. package/dist/sveltekit/index.d.ts.map +0 -1
  230. package/dist/sveltekit/nav-routes.d.ts.map +0 -1
  231. package/dist/sveltekit/public-routes.d.ts.map +0 -1
  232. package/dist/sveltekit/types.d.ts.map +0 -1
  233. package/dist/vite/bin.d.ts.map +0 -1
  234. package/dist/vite/index.d.ts.map +0 -1
@@ -0,0 +1,2 @@
1
+ /** The cairn mark as a `data:image/svg+xml` URL, for a `<link rel="icon">` on the admin pages. */
2
+ export declare const cairnFaviconHref: string;
@@ -0,0 +1,7 @@
1
+ // The cairn mark as an inline SVG data URL, so an admin browser tab carries Cairn's brand. The fill
2
+ // is a fixed violet near the admin primary, since a favicon cannot read a CSS variable. The path is
3
+ // the same public-domain Temaki cairn used by CairnLogo.svelte.
4
+ const svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15" fill="#7c3aed">' +
5
+ '<path d="M6.28 14C5.56 14 1 13.89 1 12.91C1 11.46 2.16 11.07 3.2 10.81C4.36 10.51 13.18 9.77 13.76 10.07C14.46 10.43 13.52 12.49 12.44 12.77C11.28 13.07 10.21 14 8.48 14C7.05 14 9.69 14 6.28 14ZM6.92 4.5C6.67 4.5 5 4.43 5 3.88C5 3.07 5.75 2.51 5.96 2.35C6.36 2.03 6.32 1.62 6.54 1.27C6.84 0.79 7.61 0.5 7.88 0.5C8.1 0.5 8.75 0.9 9.23 1.42C9.45 1.66 10 2.77 10 3.12C10 4.22 9.36 4.5 8.85 4.5C8.33 4.5 8.15 4.5 6.92 4.5ZM3.68 8.22C3 7.73 3.67 6.86 4.57 6.21C5.38 5.63 5.92 5.96 6.79 5.7C8.33 5.24 9.02 5.72 9.02 5.72L10.9 6.82C12.03 7.63 10.99 7.67 10.38 8.56C9.79 9.42 8.18 9.11 7.42 9.33C6.78 9.53 5.75 9.71 4.62 8.9L3.68 8.22Z"/></svg>';
6
+ /** The cairn mark as a `data:image/svg+xml` URL, for a `<link rel="icon">` on the admin pages. */
7
+ export const cairnFaviconHref = `data:image/svg+xml,${encodeURIComponent(svg)}`;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Inspect the admin root's ancestor chain for host chrome. Returns a diagnostic when a
3
+ * width-constraining ancestor sits between the root and <body>, else null. Pure over the DOM so a
4
+ * test can build either shape. The sibling signal (host elements outside the admin subtree) is folded
5
+ * into the message as context rather than raised on its own, because it is the noisier of the two.
6
+ */
7
+ export declare function detectChromeWrap(root: HTMLElement): string | null;
8
+ /** Run the check in dev and log one error when host chrome is detected. A no-op in production. */
9
+ export declare function warnIfChromeWrapped(root: HTMLElement): void;
@@ -0,0 +1,55 @@
1
+ // Dev-only structural check that catches a host mounting the admin inside its own chrome. Every admin
2
+ // rule is scoped and the admin self-styles, but a host whose root layout wraps the admin in a
3
+ // width-constraining container (a `<main class="container">`) or renders its nav and footer around it
4
+ // breaks the full-bleed admin shell. The engine cannot prevent that layout mistake, so it names it.
5
+ // The check walks the ancestor chain once on mount and emits one console.error that points at the
6
+ // route-structure doc. The public entry runs only under import.meta.env.DEV, never throws, and changes
7
+ // no rendering.
8
+ const DOC = 'docs/admin-route-structure.md';
9
+ // max-width values that do not actually constrain the admin below the viewport. A host that sets a
10
+ // defensive `max-width: 100%` or `100vw` on a wrapper is not chrome, so skip those to avoid a spurious
11
+ // dev error. A real constraining container uses an absolute length (`64rem`, `1280px`) or a sub-100
12
+ // percentage, both of which still trip the guard.
13
+ const NON_CONSTRAINING = new Set(['none', '100%', '100vw']);
14
+ function describe(el) {
15
+ const tag = el.tagName.toLowerCase();
16
+ const cls = el.getAttribute('class');
17
+ return cls ? `<${tag} class="${cls}">` : `<${tag}>`;
18
+ }
19
+ /**
20
+ * Inspect the admin root's ancestor chain for host chrome. Returns a diagnostic when a
21
+ * width-constraining ancestor sits between the root and <body>, else null. Pure over the DOM so a
22
+ * test can build either shape. The sibling signal (host elements outside the admin subtree) is folded
23
+ * into the message as context rather than raised on its own, because it is the noisier of the two.
24
+ */
25
+ export function detectChromeWrap(root) {
26
+ const body = root.ownerDocument.body;
27
+ let constrainer = null;
28
+ let maxWidth = '';
29
+ for (let el = root.parentElement; el && el !== body; el = el.parentElement) {
30
+ const elMaxWidth = getComputedStyle(el).maxWidth;
31
+ if (elMaxWidth && !NON_CONSTRAINING.has(elMaxWidth)) {
32
+ constrainer = el;
33
+ maxWidth = elMaxWidth;
34
+ break;
35
+ }
36
+ }
37
+ if (!constrainer)
38
+ return null;
39
+ const siblings = [...body.children].filter((el) => !el.contains(root) && !root.contains(el) && el !== root);
40
+ const siblingNote = siblings.length
41
+ ? ` Host elements also sit beside the admin in <body> (${siblings.map(describe).join(', ')}).`
42
+ : '';
43
+ return (`[cairn-cms] The admin is rendering inside host chrome. A width-constraining ancestor ` +
44
+ `${describe(constrainer)} (max-width: ${maxWidth}) sits between the admin root and <body>, so the ` +
45
+ `admin shell cannot fill the viewport.${siblingNote} Keep the host root layout chrome-free and move ` +
46
+ `your nav, footer, and app.css into a (site) route group. See ${DOC}.`);
47
+ }
48
+ /** Run the check in dev and log one error when host chrome is detected. A no-op in production. */
49
+ export function warnIfChromeWrapped(root) {
50
+ if (!import.meta.env.DEV)
51
+ return;
52
+ const problem = detectChromeWrap(root);
53
+ if (problem)
54
+ console.error(problem);
55
+ }
@@ -0,0 +1,93 @@
1
+ Copyright 2022 The Bricolage Grotesque Project Authors (https://github.com/ateliertriay/bricolage)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ https://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
1
+ Copyright 2022 The Figtree Project Authors (https://github.com/erikdkennedy/figtree)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -12,4 +12,3 @@ export { default as NavTree } from './NavTree.svelte';
12
12
  export { default as LinkPicker } from './LinkPicker.svelte';
13
13
  export { default as DeleteDialog } from './DeleteDialog.svelte';
14
14
  export { default as RenameDialog } from './RenameDialog.svelte';
15
- //# sourceMappingURL=index.d.ts.map
@@ -13,4 +13,3 @@ export declare function linkCompletions(targets: LinkTarget[], query: string): C
13
13
  * whole `[[query` with the chosen link, and sets filter:false because linkCompletions already
14
14
  * filtered by the query (CodeMirror would otherwise re-filter against the literal `[[query`). */
15
15
  export declare function cairnLinkCompletionSource(targets: LinkTarget[]): CompletionSource;
16
- //# sourceMappingURL=link-completion.d.ts.map
@@ -30,4 +30,3 @@ export declare function unwrapCairnLink(doc: string, href: string): string;
30
30
  * last to first, replacing only the `](oldHref` run so the label and title stay exact.
31
31
  */
32
32
  export declare function rewriteCairnLink(doc: string, oldHref: string, newHref: string): string;
33
- //# sourceMappingURL=markdown-format.d.ts.map
@@ -1,4 +1,3 @@
1
1
  import type { CairnAdapter } from './types.js';
2
2
  /** Declare a site's adapter while preserving each concept's concrete schema type for typed reads. */
3
3
  export declare function defineAdapter<const A extends CairnAdapter>(adapter: A): A;
4
- //# sourceMappingURL=adapter.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import type { CairnAdapter, CairnExtension, CairnRuntime } from './types.js';
2
- import { type SiteConfig } from '../nav/site-config.js';
2
+ import type { SiteConfig } from '../nav/site-config.js';
3
3
  /** The input to {@link composeRuntime}. `siteConfig` is required so the per-concept URL policy is
4
4
  * always derived from one source and can never be silently dropped. `extensions` fold in after the
5
5
  * adapter's concepts. */
@@ -15,4 +15,3 @@ export interface ComposeInput {
15
15
  * (seam 4) passes through untouched.
16
16
  */
17
17
  export declare function composeRuntime({ adapter, siteConfig, extensions }: ComposeInput): CairnRuntime;
18
- //# sourceMappingURL=compose.d.ts.map
@@ -1,5 +1,4 @@
1
- import { normalizeConcepts } from './concepts.js';
2
- import { urlPolicyFrom } from '../nav/site-config.js';
1
+ import { resolveConcepts } from './concepts.js';
3
2
  /**
4
3
  * Fold an adapter and any extensions into the composed runtime (seam 2). The per-concept URL policy
5
4
  * is derived from the site config, the same source the delivery path uses, so the runtime and
@@ -24,7 +23,7 @@ export function composeRuntime({ adapter, siteConfig, extensions = [] }) {
24
23
  }
25
24
  return {
26
25
  siteName: adapter.siteName,
27
- concepts: normalizeConcepts(content, urlPolicyFrom(siteConfig)),
26
+ concepts: resolveConcepts(content, siteConfig),
28
27
  backend: adapter.backend,
29
28
  sender: adapter.sender,
30
29
  render: adapter.render,
@@ -1,4 +1,5 @@
1
1
  import type { ConceptConfig, ConceptDescriptor, ConceptUrlPolicy, RoutingRule } from './types.js';
2
+ import { type SiteConfig } from '../nav/site-config.js';
2
3
  /**
3
4
  * Concept-fixed routing, keyed by concept id (spec §7.2). Posts are dated feed entries;
4
5
  * pages are plain navigable structure. Not in adapter config. A future Fragments adds one
@@ -13,6 +14,11 @@ export declare const CONCEPT_ROUTING: Readonly<Record<string, RoutingRule>>;
13
14
  * a new concept attaches additively; production passes the default `CONCEPT_ROUTING`.
14
15
  */
15
16
  export declare function normalizeConcepts(content: Record<string, ConceptConfig | undefined>, urlPolicy?: Record<string, ConceptUrlPolicy | undefined>, routing?: Readonly<Record<string, RoutingRule>>): ConceptDescriptor[];
17
+ /**
18
+ * Resolve a site's concept descriptors from its content map and parsed site config. The admin runtime
19
+ * (composeRuntime) and the delivery layer (siteDescriptors) both call this, so the per-concept URL
20
+ * policy is derived once from the YAML and the runtime and delivery permalinks cannot diverge.
21
+ */
22
+ export declare function resolveConcepts(content: Record<string, ConceptConfig | undefined>, siteConfig: SiteConfig): ConceptDescriptor[];
16
23
  /** Look up a normalized concept by id, or undefined when the site does not enable it. */
17
24
  export declare function findConcept(concepts: ConceptDescriptor[], id: string): ConceptDescriptor | undefined;
18
- //# sourceMappingURL=concepts.d.ts.map
@@ -1,3 +1,4 @@
1
+ import { urlPolicyFrom } from '../nav/site-config.js';
1
2
  /**
2
3
  * Concept-fixed routing, keyed by concept id (spec §7.2). Posts are dated feed entries;
3
4
  * pages are plain navigable structure. Not in adapter config. A future Fragments adds one
@@ -17,6 +18,37 @@ function defaultLabel(id) {
17
18
  function defaultPermalink(id) {
18
19
  return id === 'pages' ? '/:slug' : `/${id}/:slug`;
19
20
  }
21
+ /** Permalink tokens the resolver understands. */
22
+ const KNOWN_TOKENS = new Set(['slug', 'year', 'month', 'day']);
23
+ /** The date-bearing tokens; valid only for a dated concept. */
24
+ const DATE_TOKENS = new Set(['year', 'month', 'day']);
25
+ /** The valid date-prefix granularities. A runtime check, since the YAML is untyped. */
26
+ const DATE_PREFIXES = new Set(['year', 'month', 'day']);
27
+ /**
28
+ * Validate one concept's URL policy at build, so a misconfigured permalink or datePrefix fails loudly
29
+ * here rather than emitting a wrong or defaulted URL at render. The permalink must be root-relative and
30
+ * use only known tokens, a date token requires a dated concept, and the datePrefix must be in range.
31
+ */
32
+ function validateUrlPolicy(id, policy, dated) {
33
+ if (policy.permalink !== undefined) {
34
+ const pattern = policy.permalink;
35
+ if (!pattern.startsWith('/')) {
36
+ throw new Error(`cairn: concept "${id}" permalink "${pattern}" must start with "/"`);
37
+ }
38
+ for (const match of pattern.matchAll(/:(\w+)/g)) {
39
+ const token = match[1];
40
+ if (!KNOWN_TOKENS.has(token)) {
41
+ throw new Error(`cairn: concept "${id}" permalink "${pattern}" uses unknown token ":${token}"`);
42
+ }
43
+ if (DATE_TOKENS.has(token) && !dated) {
44
+ throw new Error(`cairn: concept "${id}" is not dated, so permalink "${pattern}" cannot use the date token ":${token}"`);
45
+ }
46
+ }
47
+ }
48
+ if (policy.datePrefix !== undefined && !DATE_PREFIXES.has(policy.datePrefix)) {
49
+ throw new Error(`cairn: concept "${id}" datePrefix "${policy.datePrefix}" must be one of year, month, day`);
50
+ }
51
+ }
20
52
  /**
21
53
  * Normalize an adapter's declared concepts into uniform descriptors (seam 1). URL policy
22
54
  * (`permalink`, `datePrefix`) comes from the YAML site-config, passed here as `urlPolicy` keyed by
@@ -26,6 +58,12 @@ function defaultPermalink(id) {
26
58
  */
27
59
  export function normalizeConcepts(content, urlPolicy = {}, routing = CONCEPT_ROUTING) {
28
60
  const descriptors = [];
61
+ const declaredConcepts = new Set(Object.keys(content).filter((key) => content[key] !== undefined));
62
+ for (const key of Object.keys(urlPolicy)) {
63
+ if (!declaredConcepts.has(key)) {
64
+ throw new Error(`cairn: URL policy names concept "${key}", which is not declared under content`);
65
+ }
66
+ }
29
67
  for (const [id, config] of Object.entries(content)) {
30
68
  if (!config)
31
69
  continue;
@@ -35,12 +73,14 @@ export function normalizeConcepts(content, urlPolicy = {}, routing = CONCEPT_ROU
35
73
  if (undeclared !== undefined) {
36
74
  throw new Error(`cairn: concept "${id}" summaryFields key "${undeclared}" is not a declared field`);
37
75
  }
76
+ const conceptRouting = routing[id] ?? DEFAULT_ROUTING;
38
77
  const policy = urlPolicy[id] ?? {};
78
+ validateUrlPolicy(id, policy, conceptRouting.dated);
39
79
  descriptors.push({
40
80
  id,
41
81
  label: config.label ?? defaultLabel(id),
42
82
  dir: config.dir,
43
- routing: routing[id] ?? DEFAULT_ROUTING,
83
+ routing: conceptRouting,
44
84
  permalink: policy.permalink ?? defaultPermalink(id),
45
85
  datePrefix: policy.datePrefix ?? 'day',
46
86
  fields: config.schema.fields,
@@ -50,6 +90,14 @@ export function normalizeConcepts(content, urlPolicy = {}, routing = CONCEPT_ROU
50
90
  }
51
91
  return descriptors;
52
92
  }
93
+ /**
94
+ * Resolve a site's concept descriptors from its content map and parsed site config. The admin runtime
95
+ * (composeRuntime) and the delivery layer (siteDescriptors) both call this, so the per-concept URL
96
+ * policy is derived once from the YAML and the runtime and delivery permalinks cannot diverge.
97
+ */
98
+ export function resolveConcepts(content, siteConfig) {
99
+ return normalizeConcepts(content, urlPolicyFrom(siteConfig));
100
+ }
53
101
  /** Look up a normalized concept by id, or undefined when the site does not enable it. */
54
102
  export function findConcept(concepts, id) {
55
103
  return concepts.find((concept) => concept.id === id);
@@ -23,4 +23,3 @@ export declare function parseMarkdown(source: string): {
23
23
  frontmatter: Record<string, unknown>;
24
24
  body: string;
25
25
  };
26
- //# sourceMappingURL=frontmatter.d.ts.map
@@ -0,0 +1,23 @@
1
+ import type { ConceptDescriptor } from './types.js';
2
+ /** A content entry's resolved URL identity. */
3
+ export interface EntryIdentity {
4
+ id: string;
5
+ slug: string;
6
+ date?: string;
7
+ permalink: string;
8
+ }
9
+ /** A present, non-empty string, else undefined. The read-model string coercion. */
10
+ export declare function asString(value: unknown): string | undefined;
11
+ /** A YYYY-MM-DD date. An unquoted YAML date parses as a JS Date; a string is sliced to its date head. */
12
+ export declare function asDate(value: unknown): string | undefined;
13
+ /** Tags as an array, empty when the file declares none. */
14
+ export declare function asTags(value: unknown): string[];
15
+ /** A content entry's id: its filename stem (the date prefix is part of a dated id). */
16
+ export declare function entryId(path: string): string;
17
+ /**
18
+ * Resolve a content entry's URL identity from its concept descriptor, its file path, and its parsed
19
+ * frontmatter. The slug strips the leading date prefix for a dated concept and is the id verbatim for
20
+ * an undated one. The permalink is the one resolver every reader shares. The caller parses the markdown
21
+ * once and passes the frontmatter, so there is no second parse here.
22
+ */
23
+ export declare function entryIdentity(descriptor: ConceptDescriptor, path: string, frontmatter: Record<string, unknown>): EntryIdentity;
@@ -0,0 +1,43 @@
1
+ // cairn-cms: a content entry's URL identity in one place (engine-hardening pass 3). The id, the
2
+ // slug, the date, and the permalink are computed here, so the content index and the manifest cannot
3
+ // drift on what an entry's URL is. A cairn: link resolves through the manifest in the admin preview
4
+ // and through the content index in the public build, so the two must agree by construction.
5
+ import { idFromFilename, slugFromId } from './ids.js';
6
+ import { permalink } from './permalink.js';
7
+ /** The basename of a glob path: the segment after the last slash, or the whole path. */
8
+ function basename(path) {
9
+ const slash = path.lastIndexOf('/');
10
+ return slash >= 0 ? path.slice(slash + 1) : path;
11
+ }
12
+ /** A present, non-empty string, else undefined. The read-model string coercion. */
13
+ export function asString(value) {
14
+ return typeof value === 'string' && value.trim() ? value : undefined;
15
+ }
16
+ /** A YYYY-MM-DD date. An unquoted YAML date parses as a JS Date; a string is sliced to its date head. */
17
+ export function asDate(value) {
18
+ if (value instanceof Date)
19
+ return Number.isNaN(value.getTime()) ? undefined : value.toISOString().slice(0, 10);
20
+ if (typeof value === 'string')
21
+ return value.match(/^\d{4}-\d{2}-\d{2}/)?.[0];
22
+ return undefined;
23
+ }
24
+ /** Tags as an array, empty when the file declares none. */
25
+ export function asTags(value) {
26
+ return Array.isArray(value) ? value.map(String) : [];
27
+ }
28
+ /** A content entry's id: its filename stem (the date prefix is part of a dated id). */
29
+ export function entryId(path) {
30
+ return idFromFilename(basename(path));
31
+ }
32
+ /**
33
+ * Resolve a content entry's URL identity from its concept descriptor, its file path, and its parsed
34
+ * frontmatter. The slug strips the leading date prefix for a dated concept and is the id verbatim for
35
+ * an undated one. The permalink is the one resolver every reader shares. The caller parses the markdown
36
+ * once and passes the frontmatter, so there is no second parse here.
37
+ */
38
+ export function entryIdentity(descriptor, path, frontmatter) {
39
+ const id = entryId(path);
40
+ const slug = slugFromId(id, descriptor.routing.dated ? descriptor.datePrefix : null);
41
+ const date = asDate(frontmatter.date);
42
+ return { id, slug, date, permalink: permalink(descriptor, { id, slug, date }) };
43
+ }
@@ -35,4 +35,3 @@ export declare function composeDatedId(date: string, slug: string, datePrefix: D
35
35
  * newSlug. The caller validates newSlug with isValidId first.
36
36
  */
37
37
  export declare function renameId(oldId: string, newSlug: string, datePrefix: DatePrefix | null): string;
38
- //# sourceMappingURL=ids.d.ts.map
@@ -18,4 +18,3 @@ export declare function escapeLinkText(text: string): string;
18
18
  /** The cairn links a markdown body points at, in first-occurrence order, deduped by concept/id.
19
19
  * Parses the body as mdast, so a token inside a code span or fence is never matched. */
20
20
  export declare function extractCairnLinks(body: string): CairnRef[];
21
- //# sourceMappingURL=links.d.ts.map
@@ -24,7 +24,9 @@ export interface LinkTarget {
24
24
  date?: string;
25
25
  draft: boolean;
26
26
  }
27
- /** Build one manifest entry from a content file. Drafts are included and flagged. */
27
+ /** Build one manifest entry from a content file. Drafts are included and flagged. The id, date, and
28
+ * permalink come from entryIdentity, the same source content-index uses, so a cairn: link resolves to
29
+ * one URL whether the admin preview reads the manifest or the public build reads the content index. */
28
30
  export declare function manifestEntryFromFile(descriptor: ConceptDescriptor, file: {
29
31
  path: string;
30
32
  raw: string;
@@ -83,4 +85,3 @@ export declare function manifestLinkResolver(targets: {
83
85
  id: string;
84
86
  permalink: string;
85
87
  }[]): LinkResolve;
86
- //# sourceMappingURL=manifest.d.ts.map
@@ -3,41 +3,21 @@
3
3
  // code reads the content graph without an N+1 GitHub crawl. The build regenerates and verifies
4
4
  // it; the save path patches one entry and commits it with the content in one commit. Each entry
5
5
  // carries its identity and its outbound cairn: edges, so the manifest is the link graph.
6
- import { idFromFilename, slugFromId } from './ids.js';
7
6
  import { parseMarkdown } from './frontmatter.js';
8
- import { permalink } from './permalink.js';
7
+ import { entryIdentity, asString } from './identity.js';
9
8
  import { extractCairnLinks } from './links.js';
10
- function basename(path) {
11
- const slash = path.lastIndexOf('/');
12
- return slash >= 0 ? path.slice(slash + 1) : path;
13
- }
14
- /** Mirror content-index's frontmatter coercion: a present non-empty string, else undefined. */
15
- function asString(value) {
16
- return typeof value === 'string' && value.trim() ? value : undefined;
17
- }
18
- /** Mirror content-index's date coercion: an unquoted YAML date is a JS Date, a string is sliced. */
19
- function asDate(value) {
20
- if (value instanceof Date)
21
- return Number.isNaN(value.getTime()) ? undefined : value.toISOString().slice(0, 10);
22
- if (typeof value === 'string')
23
- return value.match(/^\d{4}-\d{2}-\d{2}/)?.[0];
24
- return undefined;
25
- }
26
- /** Build one manifest entry from a content file. Drafts are included and flagged. */
9
+ /** Build one manifest entry from a content file. Drafts are included and flagged. The id, date, and
10
+ * permalink come from entryIdentity, the same source content-index uses, so a cairn: link resolves to
11
+ * one URL whether the admin preview reads the manifest or the public build reads the content index. */
27
12
  export function manifestEntryFromFile(descriptor, file) {
28
- const id = idFromFilename(basename(file.path));
29
- // Use the same slug rule content-index uses, so the manifest's permalink for an entry always
30
- // equals content-index's permalink for it. A cairn link must resolve to one URL whether the
31
- // admin preview reads the manifest or the public build reads the content index.
32
- const slug = slugFromId(id, descriptor.routing.dated ? descriptor.datePrefix : null);
33
13
  const { frontmatter, body } = parseMarkdown(file.raw);
34
- const date = asDate(frontmatter.date);
14
+ const { id, date, permalink } = entryIdentity(descriptor, file.path, frontmatter);
35
15
  return {
36
16
  id,
37
17
  concept: descriptor.id,
38
18
  title: asString(frontmatter.title) ?? id,
39
19
  date,
40
- permalink: permalink(descriptor, { id, slug, date }),
20
+ permalink,
41
21
  draft: frontmatter.draft === true,
42
22
  links: extractCairnLinks(body),
43
23
  };
@@ -9,4 +9,3 @@ export declare function permalink(descriptor: ConceptDescriptor, entry: {
9
9
  slug: string;
10
10
  date?: string;
11
11
  }): string;
12
- //# sourceMappingURL=permalink.d.ts.map
@@ -72,4 +72,3 @@ export interface DefineFieldsOptions<F extends readonly FrontmatterField[]> {
72
72
  /** Declare a concept's fields once. Returns the schema's faces derived from that one declaration. */
73
73
  export declare function defineFields<const F extends readonly FrontmatterField[]>(fields: F, options?: DefineFieldsOptions<F>): ConceptSchema<F>;
74
74
  export {};
75
- //# sourceMappingURL=schema.d.ts.map
@@ -270,4 +270,3 @@ export interface CairnRuntime {
270
270
  fieldTypes?: FieldTypeDef[];
271
271
  }
272
272
  export {};
273
- //# sourceMappingURL=types.d.ts.map
@@ -15,4 +15,3 @@ import type { FrontmatterField, ValidationResult } from './types.js';
15
15
  * `Date` to `YYYY-MM-DD` so a valid parsed date is not mistaken for an empty one.
16
16
  */
17
17
  export declare function validateFields(fields: FrontmatterField[], frontmatter: Record<string, unknown>): ValidationResult;
18
- //# sourceMappingURL=validate.d.ts.map
@@ -12,4 +12,3 @@ type $$ComponentProps = {
12
12
  declare const CairnHead: import("svelte").Component<$$ComponentProps, {}, "">;
13
13
  type CairnHead = ReturnType<typeof CairnHead>;
14
14
  export default CairnHead;
15
- //# sourceMappingURL=CairnHead.svelte.d.ts.map
@@ -65,4 +65,3 @@ export interface ContentIndex<F = Record<string, unknown>> {
65
65
  export declare function fromGlob(record: Record<string, string>): RawFile[];
66
66
  /** Build a concept's index from its raw files and normalized descriptor. */
67
67
  export declare function createContentIndex<F = Record<string, unknown>>(files: RawFile[], descriptor: ConceptDescriptor): ContentIndex<F>;
68
- //# sourceMappingURL=content-index.d.ts.map