@glw907/cairn-cms 0.38.0 → 0.41.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 (97) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +7 -6
  3. package/dist/components/AdminLayout.svelte +53 -0
  4. package/dist/components/ComponentInsertDialog.svelte +27 -13
  5. package/dist/components/ComponentInsertDialog.svelte.d.ts +13 -2
  6. package/dist/components/ConceptList.svelte +22 -3
  7. package/dist/components/DeleteDialog.svelte +18 -7
  8. package/dist/components/DeleteDialog.svelte.d.ts +11 -1
  9. package/dist/components/EditPage.svelte +604 -75
  10. package/dist/components/EditPage.svelte.d.ts +8 -1
  11. package/dist/components/EditorToolbar.svelte +206 -29
  12. package/dist/components/EditorToolbar.svelte.d.ts +12 -4
  13. package/dist/components/LinkPicker.svelte +14 -6
  14. package/dist/components/LinkPicker.svelte.d.ts +9 -2
  15. package/dist/components/MarkdownEditor.svelte +80 -34
  16. package/dist/components/MarkdownEditor.svelte.d.ts +9 -3
  17. package/dist/components/MarkdownHelpDialog.svelte +58 -0
  18. package/dist/components/MarkdownHelpDialog.svelte.d.ts +11 -0
  19. package/dist/components/RenameDialog.svelte +13 -4
  20. package/dist/components/RenameDialog.svelte.d.ts +9 -1
  21. package/dist/components/WebLinkDialog.svelte +89 -0
  22. package/dist/components/WebLinkDialog.svelte.d.ts +23 -0
  23. package/dist/components/cairn-admin.css +353 -4
  24. package/dist/components/editor-highlight.d.ts +9 -0
  25. package/dist/components/editor-highlight.js +62 -0
  26. package/dist/components/link-completion.js +10 -3
  27. package/dist/components/markdown-directives.d.ts +7 -0
  28. package/dist/components/markdown-directives.js +22 -0
  29. package/dist/components/markdown-format.d.ts +1 -1
  30. package/dist/components/markdown-format.js +91 -12
  31. package/dist/content/pending.d.ts +9 -0
  32. package/dist/content/pending.js +24 -0
  33. package/dist/diagnostics/conditions.d.ts +8 -1
  34. package/dist/diagnostics/conditions.js +68 -1
  35. package/dist/doctor/bin.d.ts +2 -0
  36. package/dist/doctor/bin.js +44 -0
  37. package/dist/doctor/check-send.d.ts +3 -0
  38. package/dist/doctor/check-send.js +43 -0
  39. package/dist/doctor/checks-cloudflare.d.ts +5 -0
  40. package/dist/doctor/checks-cloudflare.js +200 -0
  41. package/dist/doctor/checks-github.d.ts +2 -0
  42. package/dist/doctor/checks-github.js +57 -0
  43. package/dist/doctor/checks-local.d.ts +5 -0
  44. package/dist/doctor/checks-local.js +112 -0
  45. package/dist/doctor/cloudflare-api.d.ts +7 -0
  46. package/dist/doctor/cloudflare-api.js +24 -0
  47. package/dist/doctor/index.d.ts +23 -0
  48. package/dist/doctor/index.js +68 -0
  49. package/dist/doctor/report.d.ts +5 -0
  50. package/dist/doctor/report.js +21 -0
  51. package/dist/doctor/run.d.ts +8 -0
  52. package/dist/doctor/run.js +20 -0
  53. package/dist/doctor/types.d.ts +41 -0
  54. package/dist/doctor/types.js +10 -0
  55. package/dist/doctor/wrangler-config.d.ts +12 -0
  56. package/dist/doctor/wrangler-config.js +125 -0
  57. package/dist/github/branches.d.ts +11 -0
  58. package/dist/github/branches.js +75 -0
  59. package/dist/github/signing.d.ts +3 -1
  60. package/dist/github/signing.js +13 -5
  61. package/dist/log/events.d.ts +1 -1
  62. package/dist/sveltekit/content-routes.d.ts +22 -1
  63. package/dist/sveltekit/content-routes.js +320 -72
  64. package/package.json +8 -5
  65. package/src/lib/components/AdminLayout.svelte +53 -0
  66. package/src/lib/components/ComponentInsertDialog.svelte +27 -13
  67. package/src/lib/components/ConceptList.svelte +22 -3
  68. package/src/lib/components/DeleteDialog.svelte +18 -7
  69. package/src/lib/components/EditPage.svelte +604 -75
  70. package/src/lib/components/EditorToolbar.svelte +206 -29
  71. package/src/lib/components/LinkPicker.svelte +14 -6
  72. package/src/lib/components/MarkdownEditor.svelte +80 -34
  73. package/src/lib/components/MarkdownHelpDialog.svelte +58 -0
  74. package/src/lib/components/RenameDialog.svelte +13 -4
  75. package/src/lib/components/WebLinkDialog.svelte +89 -0
  76. package/src/lib/components/cairn-admin.css +26 -4
  77. package/src/lib/components/editor-highlight.ts +67 -0
  78. package/src/lib/components/link-completion.ts +10 -3
  79. package/src/lib/components/markdown-directives.ts +23 -0
  80. package/src/lib/components/markdown-format.ts +118 -13
  81. package/src/lib/content/pending.ts +24 -0
  82. package/src/lib/diagnostics/conditions.ts +75 -2
  83. package/src/lib/doctor/bin.ts +45 -0
  84. package/src/lib/doctor/check-send.ts +43 -0
  85. package/src/lib/doctor/checks-cloudflare.ts +222 -0
  86. package/src/lib/doctor/checks-github.ts +63 -0
  87. package/src/lib/doctor/checks-local.ts +119 -0
  88. package/src/lib/doctor/cloudflare-api.ts +33 -0
  89. package/src/lib/doctor/index.ts +93 -0
  90. package/src/lib/doctor/report.ts +30 -0
  91. package/src/lib/doctor/run.ts +23 -0
  92. package/src/lib/doctor/types.ts +52 -0
  93. package/src/lib/doctor/wrangler-config.ts +142 -0
  94. package/src/lib/github/branches.ts +83 -0
  95. package/src/lib/github/signing.ts +13 -6
  96. package/src/lib/log/events.ts +4 -0
  97. package/src/lib/sveltekit/content-routes.ts +400 -73
@@ -0,0 +1,58 @@
1
+ <!--
2
+ @component
3
+ The Markdown cheat sheet, opened from the edit page's editor footer. A one-screen table pairs
4
+ each piece of syntax with what it makes, and a closing note explains the ::: layout blocks.
5
+ Built on a native <dialog>, the DeleteDialog recipe; the host drives it through the exported
6
+ open(), so the component renders no trigger of its own.
7
+ -->
8
+ <script lang="ts">
9
+ let dialog = $state<HTMLDialogElement | null>(null);
10
+
11
+ /** Open the cheat sheet. The trigger lives in the host (the edit page's editor footer). */
12
+ export function open() {
13
+ dialog?.showModal();
14
+ }
15
+ function close() {
16
+ dialog?.close();
17
+ }
18
+ </script>
19
+
20
+ <dialog class="modal" aria-labelledby="cairn-markdown-help-title" bind:this={dialog}>
21
+ <div class="modal-box">
22
+ <div class="mb-3 flex items-center justify-between">
23
+ <h2 id="cairn-markdown-help-title" class="text-base font-semibold">Markdown help</h2>
24
+ <button type="button" class="btn btn-ghost btn-sm" aria-label="Close" onclick={close}>✕</button>
25
+ </div>
26
+ <table class="table table-sm">
27
+ <thead>
28
+ <tr>
29
+ <th class="text-[0.6875rem] font-semibold uppercase tracking-[0.08em] text-[var(--color-muted)]">Type this</th>
30
+ <th class="text-[0.6875rem] font-semibold uppercase tracking-[0.08em] text-[var(--color-muted)]">What it makes</th>
31
+ </tr>
32
+ </thead>
33
+ <tbody>
34
+ <tr><td><code>## Heading</code></td><td>A heading</td></tr>
35
+ <tr><td><code>### Heading</code></td><td>A smaller heading</td></tr>
36
+ <tr><td><code>**bold**</code></td><td>Bold text</td></tr>
37
+ <tr><td><code>*italic*</code></td><td>Italic text</td></tr>
38
+ <tr><td><code>~~text~~</code></td><td>Crossed-out text</td></tr>
39
+ <tr><td><code>[text](url)</code></td><td>A link</td></tr>
40
+ <tr><td><code>[[page-name]]</code></td><td>A link to one of your pages</td></tr>
41
+ <tr><td><code>- item</code></td><td>A bulleted list</td></tr>
42
+ <tr><td><code>1. item</code></td><td>A numbered list</td></tr>
43
+ <tr><td><code>- [ ] item</code></td><td>A checklist</td></tr>
44
+ <tr><td><code>&gt; quote</code></td><td>A quote</td></tr>
45
+ <tr><td><code>`code`</code></td><td>Code</td></tr>
46
+ <tr><td>Table</td><td>The Table button in the toolbar inserts one</td></tr>
47
+ <tr><td><code>---</code></td><td>A horizontal rule</td></tr>
48
+ </tbody>
49
+ </table>
50
+ <p class="mt-3 text-sm">
51
+ Lines starting with <code>:::</code> are layout blocks. Edit the text inside them and leave
52
+ the <code>:::</code> lines alone.
53
+ </p>
54
+ </div>
55
+ <form method="dialog" class="modal-backdrop">
56
+ <button tabindex="-1" aria-label="Close">close</button>
57
+ </form>
58
+ </dialog>
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The Markdown cheat sheet, opened from the edit page's editor footer. A one-screen table pairs
3
+ * each piece of syntax with what it makes, and a closing note explains the ::: layout blocks.
4
+ * Built on a native <dialog>, the DeleteDialog recipe; the host drives it through the exported
5
+ * open(), so the component renders no trigger of its own.
6
+ */
7
+ declare const MarkdownHelpDialog: import("svelte").Component<Record<string, never>, {
8
+ open: () => void;
9
+ }, "">;
10
+ type MarkdownHelpDialog = ReturnType<typeof MarkdownHelpDialog>;
11
+ export default MarkdownHelpDialog;
@@ -17,9 +17,15 @@ DeleteDialog a11y conventions.
17
17
  label: string;
18
18
  /** The current slug, prefilled into the input. */
19
19
  slug: string;
20
+ /** Render the built-in Change URL trigger. False mounts only the dialog, for a host that
21
+ * supplies its own trigger and opens the dialog through the exported open(). */
22
+ trigger?: boolean;
23
+ /** Called when the rename form submits, before the document navigates. The edit page uses it
24
+ * to stand down its leave guard while the POST is in flight. */
25
+ onsubmitting?: () => void;
20
26
  }
21
27
 
22
- let { conceptId, id, label, slug }: Props = $props();
28
+ let { conceptId, id, label, slug, trigger = true, onsubmitting }: Props = $props();
23
29
 
24
30
  let dialog = $state<HTMLDialogElement | null>(null);
25
31
  let slugInput = $state<HTMLInputElement | null>(null);
@@ -27,7 +33,8 @@ DeleteDialog a11y conventions.
27
33
  // current slug each time the dialog opens without capturing only the initial prop value.
28
34
  let nextSlug = $state('');
29
35
 
30
- function open() {
36
+ /** Open the dialog with a fresh prefill. Exported so a trigger={false} host can drive it. */
37
+ export function open() {
31
38
  nextSlug = slug;
32
39
  dialog?.showModal();
33
40
  // showModal() lands focus on the first focusable element (the header Close button), so move
@@ -43,7 +50,9 @@ DeleteDialog a11y conventions.
43
50
  }
44
51
  </script>
45
52
 
46
- <button type="button" class="btn btn-sm btn-ghost" aria-haspopup="dialog" onclick={open}>Change URL</button>
53
+ {#if trigger}
54
+ <button type="button" class="btn btn-sm btn-ghost" aria-haspopup="dialog" onclick={open}>Change URL</button>
55
+ {/if}
47
56
 
48
57
  <dialog class="modal" aria-labelledby="cairn-rename-dialog-title" bind:this={dialog}>
49
58
  <div class="modal-box">
@@ -51,7 +60,7 @@ DeleteDialog a11y conventions.
51
60
  <h2 id="cairn-rename-dialog-title" class="text-base font-semibold">Change this {label.toLowerCase()} URL</h2>
52
61
  <button type="button" class="btn btn-ghost btn-sm" aria-label="Close" onclick={close}>✕</button>
53
62
  </div>
54
- <form method="POST" action="?/rename" class="flex flex-col gap-3">
63
+ <form method="POST" action="?/rename" class="flex flex-col gap-3" onsubmit={() => onsubmitting?.()}>
55
64
  <CsrfField />
56
65
  <input type="hidden" name="concept" value={conceptId} />
57
66
  <input type="hidden" name="id" value={id} />
@@ -7,6 +7,12 @@ interface Props {
7
7
  label: string;
8
8
  /** The current slug, prefilled into the input. */
9
9
  slug: string;
10
+ /** Render the built-in Change URL trigger. False mounts only the dialog, for a host that
11
+ * supplies its own trigger and opens the dialog through the exported open(). */
12
+ trigger?: boolean;
13
+ /** Called when the rename form submits, before the document navigates. The edit page uses it
14
+ * to stand down its leave guard while the POST is in flight. */
15
+ onsubmitting?: () => void;
10
16
  }
11
17
  /**
12
18
  * The Change URL control and its modal. The author edits the URL slug; on submit the ?/rename action
@@ -14,6 +20,8 @@ interface Props {
14
20
  * dated post keeps its date; only the slug changes. Built on a native <dialog>, following the
15
21
  * DeleteDialog a11y conventions.
16
22
  */
17
- declare const RenameDialog: import("svelte").Component<Props, {}, "">;
23
+ declare const RenameDialog: import("svelte").Component<Props, {
24
+ open: () => void;
25
+ }, "">;
18
26
  type RenameDialog = ReturnType<typeof RenameDialog>;
19
27
  export default RenameDialog;
@@ -0,0 +1,89 @@
1
+ <!--
2
+ @component
3
+ The Web link control and its modal: the way to link out to an ordinary web address, beside the
4
+ Link to page picker that handles internal targets. Two fields, the address and an optional display
5
+ text; when the editor holds a selection it arrives as the default text, and the insert seam wraps
6
+ that selection either way. Built on a native <dialog>, following the LinkPicker a11y conventions,
7
+ and opened by the host's Ctrl/Cmd+K shortcut through the exported open().
8
+ -->
9
+ <script lang="ts">
10
+ interface Props {
11
+ /** Insert an inline link at the editor cursor; the editor's registerInsertLink seam. */
12
+ insert: (href: string, title: string) => void;
13
+ /** Read the editor's current selection, for the Text field's default. */
14
+ selection?: () => string;
15
+ /** Disable the trigger; the host sets it while Preview shows. */
16
+ disabled?: boolean;
17
+ /** Render the built-in Web link trigger. False mounts only the dialog, for a host that
18
+ * supplies its own trigger and opens the dialog through the exported open(). */
19
+ trigger?: boolean;
20
+ }
21
+
22
+ let { insert, selection, disabled = false, trigger = true }: Props = $props();
23
+
24
+ let dialog = $state<HTMLDialogElement | null>(null);
25
+ let hrefInput = $state<HTMLInputElement | null>(null);
26
+ let href = $state('');
27
+ let text = $state('');
28
+
29
+ /** Open the dialog with fresh fields; the edit page's Ctrl/Cmd+K shortcut calls it too. */
30
+ export function open() {
31
+ href = '';
32
+ text = selection?.() ?? '';
33
+ dialog?.showModal();
34
+ // showModal() lands focus on the first focusable element (the header Close button), so move
35
+ // it to the address input the dialog exists for (WCAG 2.4.3). A microtask defers past the
36
+ // dialog's own focus handling, the RenameDialog recipe.
37
+ queueMicrotask(() => hrefInput?.focus());
38
+ }
39
+ function close() {
40
+ dialog?.close();
41
+ }
42
+ function submit(e: SubmitEvent) {
43
+ e.preventDefault();
44
+ // With no text and no selection the address itself becomes the display text, so the link
45
+ // never renders as an invisible pair of brackets.
46
+ insert(href, text.trim() || href);
47
+ close();
48
+ }
49
+ </script>
50
+
51
+ {#if trigger}
52
+ <button
53
+ type="button"
54
+ class="btn btn-sm btn-ghost"
55
+ aria-haspopup="dialog"
56
+ aria-label="Web link (Ctrl+K)"
57
+ title="Web link (Ctrl+K)"
58
+ {disabled}
59
+ onclick={open}
60
+ >
61
+ Web link
62
+ </button>
63
+ {/if}
64
+
65
+ <dialog class="modal" aria-labelledby="cairn-web-link-dialog-title" bind:this={dialog}>
66
+ <div class="modal-box">
67
+ <div class="mb-3 flex items-center justify-between">
68
+ <h2 id="cairn-web-link-dialog-title" class="text-base font-semibold">Add a web link</h2>
69
+ <button type="button" class="btn btn-ghost btn-sm" aria-label="Close" onclick={close}>✕</button>
70
+ </div>
71
+ <form onsubmit={submit} class="flex flex-col gap-3">
72
+ <label class="flex flex-col gap-1">
73
+ <span class="text-sm font-medium">Web address</span>
74
+ <input class="input w-full" type="url" required placeholder="https://…" bind:value={href} bind:this={hrefInput} />
75
+ </label>
76
+ <label class="flex flex-col gap-1">
77
+ <span class="text-sm font-medium">Text</span>
78
+ <input class="input w-full" placeholder="What the link says" bind:value={text} />
79
+ </label>
80
+ <div class="flex justify-end gap-2">
81
+ <button type="button" class="btn btn-sm" onclick={close}>Cancel</button>
82
+ <button type="submit" class="btn btn-sm btn-primary">Add link</button>
83
+ </div>
84
+ </form>
85
+ </div>
86
+ <form method="dialog" class="modal-backdrop">
87
+ <button tabindex="-1" aria-label="Close">close</button>
88
+ </form>
89
+ </dialog>
@@ -0,0 +1,23 @@
1
+ interface Props {
2
+ /** Insert an inline link at the editor cursor; the editor's registerInsertLink seam. */
3
+ insert: (href: string, title: string) => void;
4
+ /** Read the editor's current selection, for the Text field's default. */
5
+ selection?: () => string;
6
+ /** Disable the trigger; the host sets it while Preview shows. */
7
+ disabled?: boolean;
8
+ /** Render the built-in Web link trigger. False mounts only the dialog, for a host that
9
+ * supplies its own trigger and opens the dialog through the exported open(). */
10
+ trigger?: boolean;
11
+ }
12
+ /**
13
+ * The Web link control and its modal: the way to link out to an ordinary web address, beside the
14
+ * Link to page picker that handles internal targets. Two fields, the address and an optional display
15
+ * text; when the editor holds a selection it arrives as the default text, and the insert seam wraps
16
+ * that selection either way. Built on a native <dialog>, following the LinkPicker a11y conventions,
17
+ * and opened by the host's Ctrl/Cmd+K shortcut through the exported open().
18
+ */
19
+ declare const WebLinkDialog: import("svelte").Component<Props, {
20
+ open: () => void;
21
+ }, "">;
22
+ type WebLinkDialog = ReturnType<typeof WebLinkDialog>;
23
+ export default WebLinkDialog;