@glw907/cairn-cms 0.3.1 → 0.5.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 (99) hide show
  1. package/README.md +17 -9
  2. package/dist/adapter.d.ts +10 -1
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/auth/admins.d.ts +33 -0
  5. package/dist/auth/admins.d.ts.map +1 -0
  6. package/dist/auth/admins.js +90 -0
  7. package/dist/auth/config.d.ts +2097 -0
  8. package/dist/auth/config.d.ts.map +1 -0
  9. package/dist/auth/config.js +78 -0
  10. package/dist/auth/guard.d.ts +34 -0
  11. package/dist/auth/guard.d.ts.map +1 -0
  12. package/dist/auth/guard.js +47 -0
  13. package/dist/auth/index.d.ts +4 -0
  14. package/dist/auth/index.d.ts.map +1 -0
  15. package/dist/auth/index.js +6 -0
  16. package/dist/auth/schema.d.ts +750 -0
  17. package/dist/auth/schema.d.ts.map +1 -0
  18. package/dist/auth/schema.js +93 -0
  19. package/dist/carta.d.ts +1 -1
  20. package/dist/carta.d.ts.map +1 -1
  21. package/dist/components/AdminLayout.svelte +9 -9
  22. package/dist/components/AdminLayout.svelte.d.ts +2 -2
  23. package/dist/components/AdminLayout.svelte.d.ts.map +1 -1
  24. package/dist/components/AdminList.svelte +1 -1
  25. package/dist/components/ConfirmPage.svelte +31 -0
  26. package/dist/components/ConfirmPage.svelte.d.ts +11 -0
  27. package/dist/components/ConfirmPage.svelte.d.ts.map +1 -0
  28. package/dist/components/EditPage.svelte +5 -5
  29. package/dist/components/LoginPage.svelte +35 -18
  30. package/dist/components/LoginPage.svelte.d.ts +0 -2
  31. package/dist/components/LoginPage.svelte.d.ts.map +1 -1
  32. package/dist/components/ManageAdmins.svelte +1 -1
  33. package/dist/components/ManageAdmins.svelte.d.ts +1 -1
  34. package/dist/components/ManageAdmins.svelte.d.ts.map +1 -1
  35. package/dist/components/index.d.ts +1 -0
  36. package/dist/components/index.d.ts.map +1 -1
  37. package/dist/components/index.js +1 -0
  38. package/dist/email.d.ts.map +1 -1
  39. package/dist/email.js +19 -11
  40. package/dist/github.d.ts +22 -2
  41. package/dist/github.d.ts.map +1 -1
  42. package/dist/github.js +40 -5
  43. package/dist/index.d.ts +1 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +3 -2
  46. package/dist/render/glyph.d.ts +6 -0
  47. package/dist/render/glyph.d.ts.map +1 -0
  48. package/dist/render/glyph.js +5 -0
  49. package/dist/render/index.d.ts +6 -0
  50. package/dist/render/index.d.ts.map +1 -0
  51. package/dist/render/index.js +8 -0
  52. package/dist/render/pipeline.d.ts +16 -0
  53. package/dist/render/pipeline.d.ts.map +1 -0
  54. package/dist/render/pipeline.js +29 -0
  55. package/dist/render/registry.d.ts +28 -0
  56. package/dist/render/registry.d.ts.map +1 -0
  57. package/dist/render/registry.js +11 -0
  58. package/dist/render/rehype-dispatch.d.ts +24 -0
  59. package/dist/render/rehype-dispatch.d.ts.map +1 -0
  60. package/dist/render/rehype-dispatch.js +86 -0
  61. package/dist/render/remark-directives.d.ts +4 -0
  62. package/dist/render/remark-directives.d.ts.map +1 -0
  63. package/dist/render/remark-directives.js +74 -0
  64. package/dist/sveltekit/index.d.ts +20 -58
  65. package/dist/sveltekit/index.d.ts.map +1 -1
  66. package/dist/sveltekit/index.js +35 -152
  67. package/dist/utils.d.ts +1 -1
  68. package/dist/utils.d.ts.map +1 -1
  69. package/dist/utils.js +2 -2
  70. package/package.json +48 -6
  71. package/src/lib/adapter.ts +12 -3
  72. package/src/lib/auth/admins.ts +106 -0
  73. package/src/lib/auth/config.ts +108 -0
  74. package/src/lib/auth/guard.ts +60 -0
  75. package/src/lib/auth/index.ts +6 -0
  76. package/src/lib/auth/schema.ts +112 -0
  77. package/src/lib/carta.ts +2 -2
  78. package/src/lib/components/AdminLayout.svelte +9 -9
  79. package/src/lib/components/AdminList.svelte +1 -1
  80. package/src/lib/components/ConfirmPage.svelte +31 -0
  81. package/src/lib/components/EditPage.svelte +5 -5
  82. package/src/lib/components/LoginPage.svelte +35 -18
  83. package/src/lib/components/ManageAdmins.svelte +1 -1
  84. package/src/lib/components/index.ts +1 -0
  85. package/src/lib/email.ts +18 -11
  86. package/src/lib/github.ts +38 -6
  87. package/src/lib/index.ts +3 -2
  88. package/src/lib/render/glyph.ts +14 -0
  89. package/src/lib/render/index.ts +8 -0
  90. package/src/lib/render/pipeline.ts +37 -0
  91. package/src/lib/render/registry.ts +36 -0
  92. package/src/lib/render/rehype-dispatch.ts +97 -0
  93. package/src/lib/render/remark-directives.ts +71 -0
  94. package/src/lib/sveltekit/index.ts +59 -227
  95. package/src/lib/utils.ts +2 -2
  96. package/dist/auth.d.ts +0 -25
  97. package/dist/auth.d.ts.map +0 -1
  98. package/dist/auth.js +0 -132
  99. package/src/lib/auth.ts +0 -185
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
- // cairn-cms public API. Consumers import everything from 'cairn-cms'.
2
- export * from './auth';
1
+ // cairn-cms public API. Consumers import content/email/github/adapter from 'cairn-cms';
2
+ // auth (better-auth factory, guards, manage-editors) lives at the 'cairn-cms/auth' subpath.
3
3
  export * from './email';
4
4
  export * from './github';
5
5
  export * from './carta';
6
6
  export * from './content';
7
7
  export * from './adapter';
8
+ export * from './render';
@@ -0,0 +1,6 @@
1
+ import type { Element } from 'hast';
2
+ /** A glyph name → SVG path-data map (the site owns the icon set). */
3
+ export type IconSet = Record<string, string>;
4
+ /** Inline SVG glyph as a real hast node: class ec-glyph, 256 viewBox, currentColor fill. */
5
+ export declare function glyph(name: string, icons: IconSet): Element;
6
+ //# sourceMappingURL=glyph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glyph.d.ts","sourceRoot":"","sources":["../../src/lib/render/glyph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,qEAAqE;AACrE,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7C,4FAA4F;AAC5F,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAM3D"}
@@ -0,0 +1,5 @@
1
+ import { s } from 'hastscript';
2
+ /** Inline SVG glyph as a real hast node: class ec-glyph, 256 viewBox, currentColor fill. */
3
+ export function glyph(name, icons) {
4
+ return s('svg', { className: ['ec-glyph'], viewBox: '0 0 256 256', fill: 'currentColor', ariaHidden: 'true' }, [s('path', { d: icons[name] })]);
5
+ }
@@ -0,0 +1,6 @@
1
+ export * from './registry';
2
+ export * from './glyph';
3
+ export * from './remark-directives';
4
+ export * from './rehype-dispatch';
5
+ export * from './pipeline';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/render/index.ts"],"names":[],"mappings":"AAGA,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,8 @@
1
+ // cairn-cms render engine: a directive-driven markdown → HTML pipeline whose
2
+ // component vocabulary is supplied by a site's component registry. The site owns the
3
+ // component builders, class names, icon set, and CSS; the engine owns the machinery.
4
+ export * from './registry';
5
+ export * from './glyph';
6
+ export * from './remark-directives';
7
+ export * from './rehype-dispatch';
8
+ export * from './pipeline';
@@ -0,0 +1,16 @@
1
+ import { type PluggableList } from 'unified';
2
+ import type { ComponentRegistry } from './registry';
3
+ export interface RendererOptions {
4
+ /** A site's per-index motion formula for the top-level rise stagger
5
+ * (e.g. ecnordic's `(i) => '--rise:' + …`). Omit for no stagger. */
6
+ rise?: (idx: number) => string;
7
+ }
8
+ /** Compose a site's render pipeline from its component registry: directive syntax →
9
+ * stamped markers → registry-built hast. Returns `renderMarkdown` plus the remark/
10
+ * rehype plugin arrays (so the Carta editor preview can reuse the exact same set). */
11
+ export declare function createRenderer(registry: ComponentRegistry, options?: RendererOptions): {
12
+ remarkPlugins: PluggableList;
13
+ rehypePlugins: PluggableList;
14
+ renderMarkdown: (content: string) => Promise<string>;
15
+ };
16
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/lib/render/pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAUtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC/B;yEACqE;IACrE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/B;AAED;;uFAEuF;AACvF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAO,GAAE,eAAoB;;;8BAavD,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;EAEzD"}
@@ -0,0 +1,29 @@
1
+ import { unified } from 'unified';
2
+ import remarkParse from 'remark-parse';
3
+ import remarkGfm from 'remark-gfm';
4
+ import remarkDirective from 'remark-directive';
5
+ import remarkRehype from 'remark-rehype';
6
+ import rehypeRaw from 'rehype-raw';
7
+ import rehypeSlug from 'rehype-slug';
8
+ import rehypeStringify from 'rehype-stringify';
9
+ import { remarkDirectiveStamp } from './remark-directives';
10
+ import { rehypeDispatch } from './rehype-dispatch';
11
+ /** Compose a site's render pipeline from its component registry: directive syntax →
12
+ * stamped markers → registry-built hast. Returns `renderMarkdown` plus the remark/
13
+ * rehype plugin arrays (so the Carta editor preview can reuse the exact same set). */
14
+ export function createRenderer(registry, options = {}) {
15
+ const remarkPlugins = [remarkDirective, [remarkDirectiveStamp, registry]];
16
+ const rehypePlugins = [rehypeRaw, [rehypeDispatch, registry, options.rise], rehypeSlug];
17
+ const processor = unified()
18
+ .use(remarkParse)
19
+ .use(remarkGfm)
20
+ .use(remarkPlugins)
21
+ .use(remarkRehype, { allowDangerousHtml: true })
22
+ .use(rehypePlugins)
23
+ .use(rehypeStringify);
24
+ return {
25
+ remarkPlugins,
26
+ rehypePlugins,
27
+ renderMarkdown: async (content) => String(await processor.process(content)),
28
+ };
29
+ }
@@ -0,0 +1,28 @@
1
+ import type { Element } from 'hast';
2
+ /** A site component: how it inserts (editor) and how it renders (rehype). */
3
+ export interface ComponentDef {
4
+ /** Directive name, e.g. 'card' (matches `:::card`). */
5
+ name: string;
6
+ /** Palette label. */
7
+ label: string;
8
+ /** Palette description. */
9
+ description: string;
10
+ /** Markdown scaffold inserted at the cursor by the editor palette. */
11
+ insertTemplate: string;
12
+ /** Build the final hast element from the stamped directive element. */
13
+ build: (node: Element, rise?: string) => Element;
14
+ /** Optional role→default-icon (e.g. `{ caution: 'warning' }`). */
15
+ defaultIconByRole?: Record<string, string>;
16
+ }
17
+ export interface ComponentRegistry {
18
+ defs: ComponentDef[];
19
+ names: string[];
20
+ get(name: string): ComponentDef | undefined;
21
+ defaultIcon(name: string, role?: string): string | undefined;
22
+ }
23
+ /** Build a registry from a site's component definitions. The single source the
24
+ * render pipeline (directive stamp + rehype dispatch) and the editor palette read. */
25
+ export declare function defineRegistry(input: {
26
+ components: ComponentDef[];
27
+ }): ComponentRegistry;
28
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/lib/render/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC5B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,cAAc,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IACjD,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IAC5C,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAC7D;AAED;uFACuF;AACvF,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,UAAU,EAAE,YAAY,EAAE,CAAA;CAAE,GAAG,iBAAiB,CAQvF"}
@@ -0,0 +1,11 @@
1
+ /** Build a registry from a site's component definitions. The single source the
2
+ * render pipeline (directive stamp + rehype dispatch) and the editor palette read. */
3
+ export function defineRegistry(input) {
4
+ const byName = new Map(input.components.map((c) => [c.name, c]));
5
+ return {
6
+ defs: input.components,
7
+ names: input.components.map((c) => c.name),
8
+ get: (name) => byName.get(name),
9
+ defaultIcon: (name, role) => (role ? byName.get(name)?.defaultIconByRole?.[role] : undefined),
10
+ };
11
+ }
@@ -0,0 +1,24 @@
1
+ import type { Root, Element, ElementContent } from 'hast';
2
+ import type { ComponentRegistry } from './registry';
3
+ export declare function isElement(node: ElementContent | undefined): node is Element;
4
+ export declare function strProp(node: Element, name: string): string | undefined;
5
+ /** Wrap a pre-built glyph in an ec-icon span; secondary role adds the modifier. */
6
+ export declare function iconSpan(glyphEl: Element, role?: string): Element;
7
+ /** A site's icon factory: turn a stamped icon name + role into a hast element. */
8
+ export type MakeIcon = (name: string, role?: string) => Element;
9
+ export declare function splitHead(node: Element, makeIcon?: MakeIcon): {
10
+ head: Element;
11
+ rest: ElementContent[];
12
+ };
13
+ /** Section wrapper: `<section class=…><div class="card-body">…</div></section>`,
14
+ * with an optional inline rise style. */
15
+ export declare function cardShell(classes: string[], rise: string | undefined, body: ElementContent[]): Element;
16
+ /** Tag the first <ul> among children with `ec-grid` and strip its whitespace-only
17
+ * text nodes so the bare list serializes without newlines. Returns that <ul>. */
18
+ export declare function markFirstList(children: ElementContent[]): Element | undefined;
19
+ /** Rehype transformer: dispatch each stamped element through its registry `build`
20
+ * fn. Top-level primitives get a document-order rise stagger when `rise` is
21
+ * supplied (a site's per-index motion formula); nested ones don't. Non-primitive
22
+ * content (lede, intro paragraphs, the page-toc nav) passes through untouched. */
23
+ export declare function rehypeDispatch(registry: ComponentRegistry, rise?: (idx: number) => string): (tree: Root) => void;
24
+ //# sourceMappingURL=rehype-dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rehype-dispatch.d.ts","sourceRoot":"","sources":["../../src/lib/render/rehype-dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAc,MAAM,MAAM,CAAC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,wBAAgB,SAAS,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI,IAAI,OAAO,CAE3E;AAKD,wBAAgB,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGvE;AAED,mFAAmF;AACnF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAGjE;AAED,kFAAkF;AAClF,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;AAMhE,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,cAAc,EAAE,CAAA;CAAE,CAYvG;AAED;0CAC0C;AAC1C,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,OAAO,CAItG;AAED;kFACkF;AAClF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,OAAO,GAAG,SAAS,CAS7E;AAmBD;;;mFAGmF;AACnF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,IACjF,MAAM,IAAI,UAUlB"}
@@ -0,0 +1,86 @@
1
+ import { h } from 'hastscript';
2
+ export function isElement(node) {
3
+ return !!node && node.type === 'element';
4
+ }
5
+ // hast Properties values are PropertyValue (string | number | boolean | array | null).
6
+ // Directive markers (dataIcon/dataRole/dataPrimitive) are always stamped as strings;
7
+ // this reads them back with that guarantee instead of casting at each call site.
8
+ export function strProp(node, name) {
9
+ const value = node.properties?.[name];
10
+ return typeof value === 'string' ? value : undefined;
11
+ }
12
+ /** Wrap a pre-built glyph in an ec-icon span; secondary role adds the modifier. */
13
+ export function iconSpan(glyphEl, role) {
14
+ const className = role === 'secondary' ? ['ec-icon', 'ec-icon-secondary'] : ['ec-icon'];
15
+ return h('span', { className }, [glyphEl]);
16
+ }
17
+ // Pull the section's <h2> out, retag it .card-title, and build the .ec-head row
18
+ // (optional icon + heading). Returns the head plus the remaining body children.
19
+ // `makeIcon` (site-supplied) turns the stamped data-icon into an element; omit it
20
+ // for a head with no icon.
21
+ export function splitHead(node, makeIcon) {
22
+ const children = node.children;
23
+ const i = children.findIndex((c) => isElement(c) && c.tagName === 'h2');
24
+ const h2 = children[i];
25
+ h2.properties = { ...h2.properties, className: ['card-title'] };
26
+ const rest = children.filter((_, j) => j !== i);
27
+ const icon = strProp(node, 'dataIcon');
28
+ const role = strProp(node, 'dataRole');
29
+ const headKids = [];
30
+ if (makeIcon && icon)
31
+ headKids.push(makeIcon(icon, role));
32
+ headKids.push(h2);
33
+ return { head: h('div', { className: ['ec-head'] }, headKids), rest };
34
+ }
35
+ /** Section wrapper: `<section class=…><div class="card-body">…</div></section>`,
36
+ * with an optional inline rise style. */
37
+ export function cardShell(classes, rise, body) {
38
+ const properties = { className: classes };
39
+ if (rise)
40
+ properties.style = rise;
41
+ return h('section', properties, [h('div', { className: ['card-body'] }, body)]);
42
+ }
43
+ /** Tag the first <ul> among children with `ec-grid` and strip its whitespace-only
44
+ * text nodes so the bare list serializes without newlines. Returns that <ul>. */
45
+ export function markFirstList(children) {
46
+ const ul = children.find((c) => isElement(c) && c.tagName === 'ul');
47
+ if (ul) {
48
+ ul.properties = { ...ul.properties, className: ['ec-grid'] };
49
+ ul.children = ul.children.filter((c) => !(c.type === 'text' && /^\s*$/.test(c.value)));
50
+ }
51
+ return ul;
52
+ }
53
+ // Recurse into a node's children, transforming any nested primitive sections
54
+ // (a grid inside a card, panels inside a split) WITHOUT a rise stagger.
55
+ function transformChildren(children, registry) {
56
+ return children.map((c) => {
57
+ if (isElement(c) && c.properties?.dataPrimitive)
58
+ return transformNode(c, registry);
59
+ if (isElement(c))
60
+ c.children = transformChildren(c.children, registry);
61
+ return c;
62
+ });
63
+ }
64
+ function transformNode(node, registry, rise) {
65
+ node.children = transformChildren(node.children, registry);
66
+ const name = strProp(node, 'dataPrimitive');
67
+ const def = name ? registry.get(name) : undefined;
68
+ return def ? def.build(node, rise) : node;
69
+ }
70
+ /** Rehype transformer: dispatch each stamped element through its registry `build`
71
+ * fn. Top-level primitives get a document-order rise stagger when `rise` is
72
+ * supplied (a site's per-index motion formula); nested ones don't. Non-primitive
73
+ * content (lede, intro paragraphs, the page-toc nav) passes through untouched. */
74
+ export function rehypeDispatch(registry, rise) {
75
+ return (tree) => {
76
+ let idx = 0;
77
+ tree.children = tree.children.map((child) => {
78
+ if (isElement(child) && child.properties?.dataPrimitive) {
79
+ return transformNode(child, registry, rise ? rise(idx++) : undefined);
80
+ }
81
+ if (isElement(child))
82
+ child.children = transformChildren(child.children, registry);
83
+ return child;
84
+ });
85
+ };
86
+ }
@@ -0,0 +1,4 @@
1
+ import type { Root } from 'mdast';
2
+ import type { ComponentRegistry } from './registry';
3
+ export declare function remarkDirectiveStamp(registry: ComponentRegistry): (tree: Root) => void;
4
+ //# sourceMappingURL=remark-directives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remark-directives.d.ts","sourceRoot":"","sources":["../../src/lib/render/remark-directives.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA8B,IAAI,EAAQ,MAAM,OAAO,CAAC;AAGpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAmCpD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,iBAAiB,IAEvD,MAAM,IAAI,UA8BlB"}
@@ -0,0 +1,74 @@
1
+ import { visit } from 'unist-util-visit';
2
+ // Reconstruct a directive's authored attribute block (`{#id .class key="value"}`).
3
+ // Accidental prose directives carry none, so this is almost always empty.
4
+ function serializeAttributes(attributes) {
5
+ if (!attributes)
6
+ return '';
7
+ const tokens = [];
8
+ for (const [key, value] of Object.entries(attributes)) {
9
+ if (value == null)
10
+ tokens.push(key);
11
+ else if (key === 'id')
12
+ tokens.push(`#${value}`);
13
+ else if (key === 'class')
14
+ for (const c of value.split(/\s+/).filter(Boolean))
15
+ tokens.push(`.${c}`);
16
+ else
17
+ tokens.push(`${key}="${value}"`);
18
+ }
19
+ return tokens.length ? `{${tokens.join(' ')}}` : '';
20
+ }
21
+ // The vocabulary is container-only (`:::name`). A text directive (`:name`) or
22
+ // leaf directive (`::name`) is therefore always an accidental colon in prose
23
+ // ("4:00", "9:30", "ratio 16:9") that micromark tokenized as a directive.
24
+ // Restore it to its literal source text so prose renders verbatim.
25
+ function restoreLiteral(node) {
26
+ const marker = node.type === 'leafDirective' ? '::' : ':';
27
+ const attrs = serializeAttributes(node.attributes);
28
+ if (node.children.length === 0) {
29
+ return [{ type: 'text', value: marker + node.name + attrs }];
30
+ }
31
+ const open = { type: 'text', value: `${marker}${node.name}[` };
32
+ const close = { type: 'text', value: `]${attrs}` };
33
+ return [open, ...node.children, close];
34
+ }
35
+ // Stamp each registered container directive with data-* markers carrying its
36
+ // component name, icon, and role. No structure is built here; the rehype
37
+ // dispatcher rewrites the marked elements once their children are hast.
38
+ // Text and leaf directives are restored to literal text (accidental prose colons).
39
+ export function remarkDirectiveStamp(registry) {
40
+ const known = new Set(registry.names);
41
+ return (tree) => {
42
+ visit(tree, 'containerDirective', (node) => {
43
+ if (!known.has(node.name))
44
+ return;
45
+ const attrs = node.attributes ?? {};
46
+ const role = attrs.role || undefined;
47
+ let icon = attrs.icon || undefined;
48
+ if (!icon && role)
49
+ icon = registry.defaultIcon(node.name, role);
50
+ const properties = { dataPrimitive: node.name };
51
+ if (icon)
52
+ properties.dataIcon = icon;
53
+ if (role)
54
+ properties.dataRole = role;
55
+ const data = node.data ?? (node.data = {});
56
+ data.hName = 'div';
57
+ data.hProperties = properties;
58
+ });
59
+ visit(tree, ['textDirective', 'leafDirective'], (node, index, parent) => {
60
+ if (!parent || index == null)
61
+ return;
62
+ const literal = restoreLiteral(node);
63
+ if (node.type === 'leafDirective') {
64
+ // Leaf directives sit at block level; wrap the restored text in a paragraph.
65
+ const paragraph = { type: 'paragraph', children: literal };
66
+ parent.children.splice(index, 1, paragraph);
67
+ }
68
+ else {
69
+ parent.children.splice(index, 1, ...literal);
70
+ }
71
+ return index;
72
+ });
73
+ };
74
+ }
@@ -1,17 +1,8 @@
1
- import { type Cookies } from '@sveltejs/kit';
2
- import type { KVNamespace } from '@cloudflare/workers-types';
3
- import { type Editor } from '../auth';
4
- import { type EmailSender } from '../email';
1
+ import type { CairnUser } from '../auth/guard';
5
2
  import { type RepoFile } from '../github';
6
3
  import { type CairnAdapter, type CairnField } from '../adapter';
7
- /** The `platform.env` bindings the admin routes read. All optional the handlers guard. */
4
+ /** The `platform.env` bindings the content routes read. All optional; the handlers guard. */
8
5
  export interface AdminEnv {
9
- AUTH_KV?: KVNamespace;
10
- MAGIC_LINK_SECRET?: string;
11
- SESSION_SECRET?: string;
12
- EMAIL?: EmailSender;
13
- /** Overrides `url.origin` for the magic-link base (set in dev, unset in prod). */
14
- PUBLIC_ORIGIN?: string;
15
6
  GITHUB_APP_ID?: string;
16
7
  GITHUB_APP_INSTALLATION_ID?: string;
17
8
  GITHUB_APP_PRIVATE_KEY_B64?: string;
@@ -22,20 +13,20 @@ interface PlatformEvent {
22
13
  };
23
14
  }
24
15
  export interface AdminLayoutData {
25
- editor: Editor | null;
16
+ user: CairnUser | null;
26
17
  siteName: string;
27
18
  pathname: string;
28
19
  }
29
20
  /**
30
21
  * Branding + session for every admin page. `siteName` flows from the adapter without pulling
31
- * its plugin graph into client bundles the import stays server-side in the layout load.
22
+ * its plugin graph into client bundles; the import stays server-side in the layout load.
32
23
  * `pathname` lets the shared shell highlight the active nav item without a `$app/*` import
33
24
  * (those kit virtual modules have no types outside a kit app, so they can't live in the
34
25
  * package); reading `event.url` here also opts the layout load into rerunning on navigation.
35
26
  */
36
27
  export declare function adminLayoutLoad(event: {
37
28
  locals: {
38
- editor: Editor | null;
29
+ user: CairnUser | null;
39
30
  };
40
31
  url: URL;
41
32
  }, adapter: CairnAdapter): AdminLayoutData;
@@ -49,13 +40,6 @@ export interface AdminCollectionList {
49
40
  export declare function adminListLoad(event: PlatformEvent, adapter: CairnAdapter): Promise<{
50
41
  collections: AdminCollectionList[];
51
42
  }>;
52
- export interface LoginData {
53
- sent: boolean;
54
- error: string | null;
55
- }
56
- export declare function loginLoad(event: {
57
- url: URL;
58
- }): LoginData;
59
43
  export interface EditData {
60
44
  type: string;
61
45
  id: string;
@@ -75,48 +59,26 @@ export declare function editLoad(event: PlatformEvent & {
75
59
  };
76
60
  url: URL;
77
61
  }, adapter: CairnAdapter): Promise<EditData>;
78
- export declare function authRequest(event: PlatformEvent & {
79
- request: Request;
80
- url: URL;
81
- }, adapter: CairnAdapter): Promise<never>;
82
- export declare function authCallback(event: PlatformEvent & {
83
- url: URL;
84
- cookies: Cookies;
85
- }): Promise<never>;
86
- export declare function logout(event: {
87
- cookies: Cookies;
88
- }): never;
89
62
  export declare function saveCommit(event: PlatformEvent & {
90
63
  request: Request;
91
64
  locals: {
92
- editor: Editor | null;
65
+ user: CairnUser | null;
93
66
  };
94
67
  }, adapter: CairnAdapter): Promise<never>;
95
- export interface AdminsData {
96
- admins: Editor[];
97
- /** Acting owner's email, so the UI can disable self-targeted remove/demote. */
98
- self: string;
99
- saved: boolean;
100
- error: string | null;
101
- }
102
- /** List the allowlist for the manage-admins page. Owner-only. */
103
- export declare function adminsLoad(event: PlatformEvent & {
104
- locals: {
105
- editor: Editor | null;
68
+ export interface HealthData {
69
+ ok: boolean;
70
+ checks: {
71
+ githubAppSigning: {
72
+ ok: boolean;
73
+ detail?: string;
74
+ };
106
75
  };
107
- url: URL;
108
- }): Promise<AdminsData>;
109
- type AdminsActionEvent = PlatformEvent & {
110
- request: Request;
111
- locals: {
112
- editor: Editor | null;
113
- };
114
- };
115
- /** Add (or update) an allowlist entry. Owner-only. */
116
- export declare function addAdmin(event: AdminsActionEvent): Promise<never>;
117
- /** Remove an allowlist entry. Owner-only; owners can't remove themselves (anti-lockout). */
118
- export declare function removeAdmin(event: AdminsActionEvent): Promise<never>;
119
- /** Change an editor's role. Owner-only; owners can't demote themselves (anti-lockout). */
120
- export declare function setAdminRole(event: AdminsActionEvent): Promise<never>;
76
+ }
77
+ /**
78
+ * Deploy-time health check (M2): signs a dummy App JWT to prove the GitHub App key loads and
79
+ * the PKCS#1→PKCS#8 conversion still works, before an editor hits it on save. Behind the
80
+ * `/admin` guard (signed-in editors only); returns ok/fail with no secret in the body.
81
+ */
82
+ export declare function healthLoad(event: PlatformEvent): Promise<HealthData>;
121
83
  export {};
122
84
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/sveltekit/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/sveltekit/index.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAOL,KAAK,QAAQ,EACd,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAuC,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAErG,6FAA6F;AAC7F,MAAM,WAAW,QAAQ;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,UAAU,aAAa;IACrB,QAAQ,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,QAAQ,CAAA;KAAE,CAAC;CAC/B;AA2BD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE;IAAE,MAAM,EAAE;QAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAAA;KAAE,CAAC;IAAC,GAAG,EAAE,GAAG,CAAA;CAAE,EACvD,OAAO,EAAE,YAAY,GACpB,eAAe,CAEjB;AAID,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,4FAA4F;AAC5F,wBAAsB,aAAa,CACjC,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC;IAAE,WAAW,EAAE,mBAAmB,EAAE,CAAA;CAAE,CAAC,CAajD;AAID,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,aAAa,GAAG;IAAE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,GAAG,EAAE,GAAG,CAAA;CAAE,EACzE,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,QAAQ,CAAC,CAyBnB;AAID,wBAAsB,UAAU,CAC9B,KAAK,EAAE,aAAa,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE;QAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAAA;KAAE,CAAA;CAAE,EAC/E,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,KAAK,CAAC,CAoDhB;AAID,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE;QAAE,gBAAgB,EAAE;YAAE,EAAE,EAAE,OAAO,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;CAChE;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAS1E"}