@glw907/cairn-cms 0.52.1 → 0.54.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 (45) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/components/AdminLayout.svelte +58 -23
  3. package/dist/components/EditPage.svelte +456 -124
  4. package/dist/components/EditPage.svelte.d.ts +4 -2
  5. package/dist/components/EditorToolbar.svelte +29 -53
  6. package/dist/components/EditorToolbar.svelte.d.ts +3 -11
  7. package/dist/components/MarkdownEditor.svelte +163 -24
  8. package/dist/components/MarkdownEditor.svelte.d.ts +3 -0
  9. package/dist/components/MarkdownHelpDialog.svelte +5 -0
  10. package/dist/components/ShortcutsDialog.svelte +37 -0
  11. package/dist/components/ShortcutsDialog.svelte.d.ts +13 -0
  12. package/dist/components/ShortcutsGrid.svelte +18 -0
  13. package/dist/components/ShortcutsGrid.svelte.d.ts +23 -0
  14. package/dist/components/cairn-admin.css +199 -99
  15. package/dist/components/editor-folding.d.ts +7 -0
  16. package/dist/components/editor-folding.js +331 -0
  17. package/dist/components/editor-highlight.js +55 -6
  18. package/dist/components/editor-shortcuts.d.ts +16 -0
  19. package/dist/components/editor-shortcuts.js +36 -0
  20. package/dist/components/fonts/{Figtree-OFL.txt → IBMPlexSans-OFL.txt} +2 -2
  21. package/dist/components/fonts/ibm-plex-sans.woff2 +0 -0
  22. package/dist/components/markdown-directives.d.ts +17 -0
  23. package/dist/components/markdown-directives.js +41 -0
  24. package/dist/components/topbar-context.d.ts +13 -0
  25. package/dist/components/topbar-context.js +17 -0
  26. package/dist/sveltekit/static-admin-page.js +2 -2
  27. package/package.json +1 -1
  28. package/src/lib/components/AdminLayout.svelte +58 -23
  29. package/src/lib/components/EditPage.svelte +456 -124
  30. package/src/lib/components/EditorToolbar.svelte +29 -53
  31. package/src/lib/components/MarkdownEditor.svelte +163 -24
  32. package/src/lib/components/MarkdownHelpDialog.svelte +5 -0
  33. package/src/lib/components/ShortcutsDialog.svelte +37 -0
  34. package/src/lib/components/ShortcutsGrid.svelte +18 -0
  35. package/src/lib/components/cairn-admin.css +51 -14
  36. package/src/lib/components/editor-folding.ts +356 -0
  37. package/src/lib/components/editor-highlight.ts +54 -4
  38. package/src/lib/components/editor-shortcuts.ts +42 -0
  39. package/src/lib/components/fonts/{Figtree-OFL.txt → IBMPlexSans-OFL.txt} +2 -2
  40. package/src/lib/components/fonts/ibm-plex-sans.woff2 +0 -0
  41. package/src/lib/components/markdown-directives.ts +42 -0
  42. package/src/lib/components/topbar-context.ts +30 -0
  43. package/src/lib/sveltekit/static-admin-page.ts +2 -2
  44. package/dist/components/fonts/figtree.woff2 +0 -0
  45. package/src/lib/components/fonts/figtree.woff2 +0 -0
@@ -124,6 +124,32 @@ export function caretContainerRange(scan: FenceScan, caretLine: number): Contain
124
124
  return { fromLine, toLine, depth };
125
125
  }
126
126
 
127
+ /**
128
+ * Every paired directive container in the document, as inclusive line ranges. Walks the scan's
129
+ * roles with a stack: an opener pushes its line, a closer pops the nearest open one and emits the
130
+ * pair at the opener's depth. The ranges come back in close order, so an inner container precedes
131
+ * the outer that holds it, which is exactly the order a fold consumer wants (folding the innermost
132
+ * first). An unbalanced opener is left on the stack and never emitted (a half-typed fence earns no
133
+ * fold range, the safety invariant), and a stray closer with nothing open is dropped. The scan
134
+ * already disowns a fence-shaped line inside a code block (its role is null), so a documented
135
+ * example can neither open nor close a range. This is the sole source of fold ranges.
136
+ */
137
+ export function containerRanges(scan: FenceScan): ContainerRange[] {
138
+ const { depths, roles } = scan;
139
+ const out: ContainerRange[] = [];
140
+ const stack: number[] = [];
141
+ for (let i = 0; i < roles.length; i++) {
142
+ if (roles[i] === 'opener') {
143
+ stack.push(i);
144
+ } else if (roles[i] === 'closer') {
145
+ const fromLine = stack.pop();
146
+ if (fromLine === undefined) continue;
147
+ out.push({ fromLine, toLine: i, depth: depths[fromLine] ?? 1 });
148
+ }
149
+ }
150
+ return out;
151
+ }
152
+
127
153
  /** One span of a fence line, in line-local offsets: machinery (`mark`) or meaning (`label`). */
128
154
  export interface FenceToken {
129
155
  from: number;
@@ -163,6 +189,22 @@ export function fenceTokens(line: string): FenceToken[] {
163
189
  return out;
164
190
  }
165
191
 
192
+ // The marker prefix of a quote or list line: leading indentation, the marker itself, and the one
193
+ // space after it. A task checkbox (`[ ]`/`[x]`) extends a bullet's marker. Ordered markers vary in
194
+ // width (a two-digit number is wider than a bullet), so the width is read from the match, never
195
+ // assumed. The anchored alternatives mirror the markers the highlight pass styles.
196
+ const MARKER = /^(\s*)(?:[-*+](?: \[[ xX]\])?|\d+[.)]|>) /;
197
+
198
+ /**
199
+ * The marker prefix of a line (indentation plus marker plus its trailing space), or null when the
200
+ * line carries no quote or list marker. The hanging-indent decoration uses the prefix length, in
201
+ * fixed-pitch chars, to wrap continuation lines under the content rather than under the marker.
202
+ */
203
+ export function markerPrefix(line: string): string | null {
204
+ const m = MARKER.exec(line);
205
+ return m ? m[0] : null;
206
+ }
207
+
166
208
  /** Inline directive ranges (`:name[...]{...}`) within a line of text. */
167
209
  export function findInlineDirectives(text: string): { from: number; to: number }[] {
168
210
  const out: { from: number; to: number }[] = [];
@@ -0,0 +1,30 @@
1
+ import { getContext, setContext, type Snippet } from 'svelte';
2
+
3
+ // The topbar context portal. On an edit route the document owns the band's live state (status,
4
+ // save-state, the lifecycle actions), so the desk's controls have to render up in AdminLayout's
5
+ // one topbar rather than in a second header of their own. AdminLayout owns a holder and provides
6
+ // it; EditPage, a descendant through the children snippet, registers its desk snippet into the
7
+ // holder and clears it on teardown. CairnAdmin's view switch unmounts EditPage, which nulls the
8
+ // holder, so the band reverts to the office layout with no route plumbing.
9
+
10
+ const TOPBAR_CONTEXT_KEY = Symbol('cairn-topbar');
11
+
12
+ /** The shared holder: the desk snippet a document registers, or null on the office routes. */
13
+ export interface TopbarHolder {
14
+ desk: Snippet | null;
15
+ /** True while the document is in zen: AdminLayout drops the whole topbar element so the band
16
+ * slides away (the desk's three clusters include AdminLayout-owned chrome, the drawer toggle and
17
+ * breadcrumb, that must vanish with it). EditPage sets this; the office routes leave it false. */
18
+ zen: boolean;
19
+ }
20
+
21
+ /** Called by AdminLayout once: creates the holder, provides it on context, returns it to render. */
22
+ export function provideTopbar(holder: TopbarHolder): TopbarHolder {
23
+ setContext(TOPBAR_CONTEXT_KEY, holder);
24
+ return holder;
25
+ }
26
+
27
+ /** Called by a descendant document (EditPage) to reach the holder it registers its desk into. */
28
+ export function useTopbar(): TopbarHolder | undefined {
29
+ return getContext<TopbarHolder | undefined>(TOPBAR_CONTEXT_KEY);
30
+ }
@@ -32,7 +32,7 @@ const SHARED_STYLE = `:root {
32
32
  --shadow: 0 1px 2px oklch(28% 0.02 75 / 0.05), 0 18px 40px -12px oklch(28% 0.02 75 / 0.16);
33
33
  --radius-box: 1rem;
34
34
  --radius-field: 0.625rem;
35
- --font: 'Figtree Variable', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
35
+ --font: 'IBM Plex Sans Variable', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
36
36
  }
37
37
  @media (prefers-color-scheme: dark) {
38
38
  :root {
@@ -107,7 +107,7 @@ main {
107
107
  h1 {
108
108
  margin: 0 0 0.75rem;
109
109
  font-size: 1.6rem;
110
- font-weight: 800;
110
+ font-weight: 700;
111
111
  letter-spacing: -0.02em;
112
112
  line-height: 1.15;
113
113
  }
Binary file