@abraca/nuxt 2.0.10 → 2.3.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 (126) hide show
  1. package/dist/module.d.mts +68 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +99 -4
  4. package/dist/runtime/components/ACodeEditor.d.vue.ts +26 -0
  5. package/dist/runtime/components/ACodeEditor.vue +268 -0
  6. package/dist/runtime/components/ACodeEditor.vue.d.ts +26 -0
  7. package/dist/runtime/components/ADocumentTree.vue +52 -20
  8. package/dist/runtime/components/AEditor.d.vue.ts +20 -13
  9. package/dist/runtime/components/AEditor.vue +55 -2
  10. package/dist/runtime/components/AEditor.vue.d.ts +20 -13
  11. package/dist/runtime/components/ANodePanel.vue +64 -60
  12. package/dist/runtime/components/ANotificationBell.d.vue.ts +1 -1
  13. package/dist/runtime/components/ANotificationBell.vue.d.ts +1 -1
  14. package/dist/runtime/components/ASpaceFormModal.d.vue.ts +2 -2
  15. package/dist/runtime/components/ASpaceFormModal.vue.d.ts +2 -2
  16. package/dist/runtime/components/aware/APresenceBlobs.d.vue.ts +29 -1
  17. package/dist/runtime/components/aware/APresenceBlobs.vue +54 -8
  18. package/dist/runtime/components/aware/APresenceBlobs.vue.d.ts +29 -1
  19. package/dist/runtime/components/aware/APresenceCursors.d.vue.ts +11 -0
  20. package/dist/runtime/components/aware/APresenceCursors.vue +74 -9
  21. package/dist/runtime/components/aware/APresenceCursors.vue.d.ts +11 -0
  22. package/dist/runtime/components/aware/AToggleGroup.d.vue.ts +28 -13
  23. package/dist/runtime/components/aware/AToggleGroup.vue +56 -20
  24. package/dist/runtime/components/aware/AToggleGroup.vue.d.ts +28 -13
  25. package/dist/runtime/components/docs/ADocsNavigation.d.vue.ts +1 -1
  26. package/dist/runtime/components/docs/ADocsNavigation.vue.d.ts +1 -1
  27. package/dist/runtime/components/docs/ADocsSearchButton.d.vue.ts +1 -1
  28. package/dist/runtime/components/docs/ADocsSearchButton.vue.d.ts +1 -1
  29. package/dist/runtime/components/docs/ADocsToc.d.vue.ts +2 -2
  30. package/dist/runtime/components/docs/ADocsToc.vue.d.ts +2 -2
  31. package/dist/runtime/components/editor/AEditorRedoButton.d.vue.ts +1 -1
  32. package/dist/runtime/components/editor/AEditorRedoButton.vue.d.ts +1 -1
  33. package/dist/runtime/components/editor/AEditorUndoButton.d.vue.ts +1 -1
  34. package/dist/runtime/components/editor/AEditorUndoButton.vue.d.ts +1 -1
  35. package/dist/runtime/components/editor/ANodeInlineLabel.d.vue.ts +1 -1
  36. package/dist/runtime/components/editor/ANodeInlineLabel.vue.d.ts +1 -1
  37. package/dist/runtime/components/registry/APluginBrowser.d.vue.ts +23 -0
  38. package/dist/runtime/components/registry/APluginBrowser.vue +155 -0
  39. package/dist/runtime/components/registry/APluginBrowser.vue.d.ts +23 -0
  40. package/dist/runtime/components/registry/APluginCapabilityDialog.d.vue.ts +17 -0
  41. package/dist/runtime/components/registry/APluginCapabilityDialog.vue +159 -0
  42. package/dist/runtime/components/registry/APluginCapabilityDialog.vue.d.ts +17 -0
  43. package/dist/runtime/components/registry/APluginCard.d.vue.ts +20 -0
  44. package/dist/runtime/components/registry/APluginCard.vue +91 -0
  45. package/dist/runtime/components/registry/APluginCard.vue.d.ts +20 -0
  46. package/dist/runtime/components/registry/APluginDetail.d.vue.ts +18 -0
  47. package/dist/runtime/components/registry/APluginDetail.vue +252 -0
  48. package/dist/runtime/components/registry/APluginDetail.vue.d.ts +18 -0
  49. package/dist/runtime/components/renderers/ACodeRenderer.d.vue.ts +15 -0
  50. package/dist/runtime/components/renderers/ACodeRenderer.vue +68 -0
  51. package/dist/runtime/components/renderers/ACodeRenderer.vue.d.ts +15 -0
  52. package/dist/runtime/components/renderers/AGraphRenderer.vue +416 -120
  53. package/dist/runtime/components/renderers/AProseRenderer.d.vue.ts +2 -2
  54. package/dist/runtime/components/renderers/AProseRenderer.vue.d.ts +2 -2
  55. package/dist/runtime/components/shell/ABreadcrumbForDoc.d.vue.ts +11 -0
  56. package/dist/runtime/components/shell/ABreadcrumbForDoc.vue +16 -0
  57. package/dist/runtime/components/shell/ABreadcrumbForDoc.vue.d.ts +11 -0
  58. package/dist/runtime/components/shell/ASettingsSection.d.vue.ts +35 -0
  59. package/dist/runtime/components/shell/ASettingsSection.vue +26 -0
  60. package/dist/runtime/components/shell/ASettingsSection.vue.d.ts +35 -0
  61. package/dist/runtime/components/shell/ASidebar.d.vue.ts +1 -1
  62. package/dist/runtime/components/shell/ASidebar.vue.d.ts +1 -1
  63. package/dist/runtime/components/shell/AUserMenu.d.vue.ts +3 -0
  64. package/dist/runtime/components/shell/AUserMenu.vue +4 -0
  65. package/dist/runtime/components/shell/AUserMenu.vue.d.ts +3 -0
  66. package/dist/runtime/composables/useAbracadabraSchema.d.ts +83 -0
  67. package/dist/runtime/composables/useAbracadabraSchema.js +52 -0
  68. package/dist/runtime/composables/useAggregatedPresence.d.ts +1 -6
  69. package/dist/runtime/composables/useCalendarView.d.ts +1 -1
  70. package/dist/runtime/composables/useChat.js +1 -0
  71. package/dist/runtime/composables/useDocBreadcrumb.d.ts +21 -0
  72. package/dist/runtime/composables/useDocBreadcrumb.js +33 -0
  73. package/dist/runtime/composables/useDocEntryTyped.d.ts +60 -0
  74. package/dist/runtime/composables/useDocEntryTyped.js +70 -0
  75. package/dist/runtime/composables/useEditorDragHandle.js +18 -0
  76. package/dist/runtime/composables/useEditorSuggestions.js +2 -1
  77. package/dist/runtime/composables/useInstalledPlugins.d.ts +3 -21
  78. package/dist/runtime/composables/useInstalledPlugins.js +2 -12
  79. package/dist/runtime/composables/useMetaMenuItems.d.ts +21 -0
  80. package/dist/runtime/composables/useMetaMenuItems.js +115 -0
  81. package/dist/runtime/composables/useMetaValidator.d.ts +27 -0
  82. package/dist/runtime/composables/useMetaValidator.js +10 -0
  83. package/dist/runtime/composables/usePluginCatalog.d.ts +161 -0
  84. package/dist/runtime/composables/usePluginCatalog.js +234 -0
  85. package/dist/runtime/composables/useQuery.d.ts +79 -0
  86. package/dist/runtime/composables/useQuery.js +97 -0
  87. package/dist/runtime/composables/useSpaces.js +4 -5
  88. package/dist/runtime/composables/useTableView.d.ts +3 -3
  89. package/dist/runtime/composables/useTypedDoc.d.ts +97 -0
  90. package/dist/runtime/composables/useTypedDoc.js +114 -0
  91. package/dist/runtime/composables/useWebRTC.js +44 -5
  92. package/dist/runtime/extensions/document-meta.js +5 -0
  93. package/dist/runtime/extensions/timeline.d.ts +11 -0
  94. package/dist/runtime/extensions/timeline.js +52 -0
  95. package/dist/runtime/extensions/views/DocumentMetaView.d.vue.ts +4 -0
  96. package/dist/runtime/extensions/views/DocumentMetaView.vue +63 -0
  97. package/dist/runtime/extensions/views/DocumentMetaView.vue.d.ts +4 -0
  98. package/dist/runtime/extensions/views/TimelineItemView.d.vue.ts +4 -0
  99. package/dist/runtime/extensions/views/TimelineItemView.vue +131 -0
  100. package/dist/runtime/extensions/views/TimelineItemView.vue.d.ts +4 -0
  101. package/dist/runtime/extensions/views/TimelineView.d.vue.ts +9 -0
  102. package/dist/runtime/extensions/views/TimelineView.vue +29 -0
  103. package/dist/runtime/extensions/views/TimelineView.vue.d.ts +9 -0
  104. package/dist/runtime/locale.d.ts +2 -0
  105. package/dist/runtime/locale.js +2 -0
  106. package/dist/runtime/plugin-abracadabra.client.js +107 -6
  107. package/dist/runtime/plugin-registry.d.ts +11 -30
  108. package/dist/runtime/plugin-registry.js +2 -82
  109. package/dist/runtime/plugins/core.plugin.js +10 -4
  110. package/dist/runtime/server/api/_abracadabra/spaces.get.d.ts +1 -1
  111. package/dist/runtime/server/plugins/abracadabra-service.js +28 -0
  112. package/dist/runtime/server/utils/docCache.js +24 -3
  113. package/dist/runtime/server/utils/schemaServerSupport.d.ts +52 -0
  114. package/dist/runtime/server/utils/schemaServerSupport.js +51 -0
  115. package/dist/runtime/types.d.ts +63 -46
  116. package/dist/runtime/utils/docTypes.d.ts +15 -0
  117. package/dist/runtime/utils/docTypes.js +20 -0
  118. package/dist/runtime/utils/loadCodeMirror.d.ts +32 -0
  119. package/dist/runtime/utils/loadCodeMirror.js +65 -0
  120. package/dist/runtime/utils/markdownToYjs.d.ts +1 -23
  121. package/dist/runtime/utils/markdownToYjs.js +5 -440
  122. package/dist/runtime/utils/schemaSupport.d.ts +60 -0
  123. package/dist/runtime/utils/schemaSupport.js +40 -0
  124. package/dist/runtime/utils/yjsConvert.d.ts +1 -14
  125. package/dist/runtime/utils/yjsConvert.js +5 -331
  126. package/package.json +84 -23
@@ -7,15 +7,36 @@ export function initDocCache(storage, extraExtensions = []) {
7
7
  _storage = storage;
8
8
  _extensions = extraExtensions;
9
9
  }
10
+ let _serverDoc = null;
11
+ async function getServerDoc() {
12
+ if (_serverDoc) return _serverDoc;
13
+ const happyDom = await import("happy-dom");
14
+ const Window = happyDom.Window ?? happyDom.default?.Window;
15
+ if (!Window) {
16
+ throw new Error("happy-dom did not export Window \u2014 install happy-dom or use the legacy DOM-global path.");
17
+ }
18
+ _serverDoc = new Window().document;
19
+ return _serverDoc;
20
+ }
10
21
  async function renderDocToHTML(ydoc) {
11
22
  try {
12
- const [{ generateHTML }, { yDocToProsemirrorJSON }, { default: StarterKit }] = await Promise.all([
23
+ const [{ getSchema }, { yDocToProsemirrorJSON }, { default: StarterKit }, { Node, DOMSerializer }] = await Promise.all([
13
24
  import("@tiptap/core"),
14
25
  import("@tiptap/y-tiptap"),
15
- import("@tiptap/starter-kit")
26
+ import("@tiptap/starter-kit"),
27
+ import("prosemirror-model")
16
28
  ]);
29
+ const schema = getSchema([StarterKit, ..._extensions]);
17
30
  const json = yDocToProsemirrorJSON(ydoc, "default");
18
- return generateHTML(json, [StarterKit, ..._extensions]);
31
+ const node = Node.fromJSON(schema, json);
32
+ const serverDoc = await getServerDoc();
33
+ const container = serverDoc.createElement("div");
34
+ DOMSerializer.fromSchema(schema).serializeFragment(
35
+ node.content,
36
+ { document: serverDoc },
37
+ container
38
+ );
39
+ return container.innerHTML;
19
40
  } catch (e) {
20
41
  console.warn("[abracadabra:doc-cache] HTML render failed:", e);
21
42
  return null;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Server-side mirror of `runtime/utils/schemaSupport.ts`.
3
+ *
4
+ * Reuses the same dynamic-import pattern so a Nitro service plugin can
5
+ * advertise + delegate to `@abraca/schema` registries without forcing
6
+ * the package onto consumers that never opt in (Rule 2). Importing
7
+ * from `runtime/utils/schemaSupport.ts` directly would pull in browser-
8
+ * leaning client-side state (`shallowRef`, the Vue cache); this file
9
+ * is a thin Nitro-only re-implementation with no Vue dependency.
10
+ */
11
+ /** Structural shape of a `@abraca/schema` SchemaRegistry. */
12
+ export interface SchemaRegistryLike<TMap = Record<string, unknown>> {
13
+ readonly types: ReadonlyMap<string, unknown>;
14
+ get: (name: string) => unknown;
15
+ validateMeta: (name: string, value: unknown) => ValidationResultLike;
16
+ validateChildType: (parent: string | null, child: string) => ValidationResultLike;
17
+ readonly __metaMap?: TMap;
18
+ }
19
+ export type ValidationResultLike = {
20
+ ok: true;
21
+ value: unknown;
22
+ } | {
23
+ ok: false;
24
+ errors: ReadonlyArray<{
25
+ path: ReadonlyArray<PropertyKey>;
26
+ message: string;
27
+ code?: string;
28
+ }>;
29
+ };
30
+ /** Subset of the `@abraca/schema` public surface the server needs at runtime. */
31
+ export interface ServerSchemaModule {
32
+ defineSchema: (spec: {
33
+ types: ReadonlyArray<unknown>;
34
+ }) => SchemaRegistryLike;
35
+ defineDocType: (spec: unknown) => unknown;
36
+ runMigrations: (registry: SchemaRegistryLike, typeName: string, meta: unknown) => unknown;
37
+ }
38
+ /**
39
+ * Resolve `@abraca/schema` if it is installed alongside the Nuxt app.
40
+ *
41
+ * Returns `null` (and warns once) when the package is missing or fails
42
+ * to import. Caches the result; subsequent calls reuse it.
43
+ */
44
+ export declare function tryLoadServerSchemaModule(): Promise<ServerSchemaModule | null>;
45
+ /**
46
+ * Build a merged "first-registry-wins" validator from a list of attached
47
+ * registries. Returns null when no registries provide a matching type
48
+ * (Rule 4: pass-through for unknown doc-types).
49
+ */
50
+ export declare function buildServerSchemaValidator(registries: ReadonlyArray<SchemaRegistryLike>): ((typeName: string, meta: unknown) => ValidationResultLike) | null;
51
+ /** Test-only — reset the cached resolution. */
52
+ export declare function __resetServerSchemaSupportCacheForTests(): void;
@@ -0,0 +1,51 @@
1
+ let cached;
2
+ let loading = null;
3
+ let warned = false;
4
+ export async function tryLoadServerSchemaModule() {
5
+ if (cached !== void 0) return cached;
6
+ if (loading) return loading;
7
+ loading = (async () => {
8
+ try {
9
+ const mod = await import("@abraca/schema");
10
+ const candidate = {
11
+ defineSchema: mod.defineSchema,
12
+ defineDocType: mod.defineDocType,
13
+ runMigrations: mod.runMigrations
14
+ };
15
+ if (typeof candidate.defineSchema !== "function" || typeof candidate.defineDocType !== "function" || typeof candidate.runMigrations !== "function") {
16
+ throw new TypeError("unexpected @abraca/schema shape \u2014 missing one of defineSchema / defineDocType / runMigrations");
17
+ }
18
+ cached = candidate;
19
+ return cached;
20
+ } catch (err) {
21
+ if (!warned) {
22
+ warned = true;
23
+ const reason = err instanceof Error ? err.message : String(err);
24
+ console.warn(
25
+ `[abracadabra-service] schema integration requested but @abraca/schema could not be loaded \u2014 install it as a peer dependency to enable server-side typed surfaces (${reason})`
26
+ );
27
+ }
28
+ cached = null;
29
+ return null;
30
+ } finally {
31
+ loading = null;
32
+ }
33
+ })();
34
+ return loading;
35
+ }
36
+ export function buildServerSchemaValidator(registries) {
37
+ if (registries.length === 0) return null;
38
+ return (typeName, meta) => {
39
+ for (const r of registries) {
40
+ if (r.types.has(typeName)) {
41
+ return r.validateMeta(typeName, meta);
42
+ }
43
+ }
44
+ return { ok: true, value: meta };
45
+ };
46
+ }
47
+ export function __resetServerSchemaSupportCacheForTests() {
48
+ cached = void 0;
49
+ loading = null;
50
+ warned = false;
51
+ }
@@ -1,49 +1,39 @@
1
1
  import type { ShallowRef, Ref, Component } from 'vue';
2
- import type { Extension } from '@tiptap/core';
3
2
  import type { Editor } from '@tiptap/vue-3';
4
3
  import type { Node as ProsemirrorNode } from '@tiptap/pm/model';
5
4
  import type * as Y from 'yjs';
6
5
  import type { AbracadabraClient, AbracadabraProvider, AbracadabraWS, CryptoIdentityKeystore } from '@abraca/dabra';
7
6
  import type { Router } from 'vue-router';
7
+ import type { AbraPlugin, AbraAwarenessContribution as BaseAbraAwarenessContribution, AbraNodePanelSlot as BaseAbraNodePanelSlot, AbraSettingsPanel as BaseAbraSettingsPanel, AbraKeyboardShortcut as BaseAbraKeyboardShortcut, AbraMentionItem } from '@abraca/plugin';
8
8
  /**
9
9
  * An Abracadabra plugin contributes editor extensions, page types, toolbar items,
10
10
  * slash commands, mentions, awareness fields, command palette items, and more.
11
11
  *
12
12
  * Plugins are registered before the registry is frozen at boot.
13
13
  * After freezing all contributions are stable for the lifetime of the app.
14
+ *
15
+ * `AbracadabraPlugin` is a tightened alias of `@abraca/plugin`'s universal
16
+ * `AbraPlugin` — same shape, but contribution fields are narrowed to the
17
+ * module's concrete types (`AbracadabraToolbarItem`, `AbracadabraPageType`,
18
+ * `AbracadabraState`-aware setup context, etc.).
14
19
  */
15
- export interface AbracadabraPlugin {
16
- /** Unique slug — must be stable across versions, e.g. 'core', 'kanban', 'my-plugin' */
17
- name: string;
18
- label?: string;
19
- version?: string;
20
- description?: string;
21
- /** TipTap extensions (nodes, marks, extensions) contributed by this plugin */
22
- extensions?: () => Extension[];
23
- /**
24
- * Optional promise that resolves when this plugin's extensions are fully
25
- * loaded. Used by PluginRegistry.waitForExtensions() to ensure the editor
26
- * doesn't initialize before async extension bundles are ready.
27
- */
28
- extensionsReady?: Promise<void>;
20
+ export interface AbracadabraPlugin extends AbraPlugin {
29
21
  /** Document/page type renderers keyed by type slug */
30
22
  pageTypes?: Record<string, AbracadabraPageType>;
31
23
  /** Extra toolbar item groups appended after the built-in toolbar groups */
32
- toolbarItems?: (ctx: EditorPluginCtx) => AbracadabraToolbarItem[][];
24
+ toolbarItems?(ctx: EditorPluginCtx): AbracadabraToolbarItem[][];
33
25
  /** Extra bubble menu item groups (appear on text selection) */
34
- bubbleMenuItems?: (ctx: EditorPluginCtx) => AbracadabraToolbarItem[][];
26
+ bubbleMenuItems?(ctx: EditorPluginCtx): AbracadabraToolbarItem[][];
35
27
  /** Slash command (/) suggestion menu item groups */
36
- suggestionItems?: (ctx: EditorPluginCtx) => AbracadabraSuggestionItem[][];
28
+ suggestionItems?(ctx: EditorPluginCtx): AbracadabraSuggestionItem[][];
37
29
  /** Extra drag-handle menu items (per-block context menu) */
38
- dragHandleItems?: (ctx: DragHandlePluginCtx) => AbracadabraDragHandleItem[][];
39
- /** Custom editor handlers merged into UEditorCustomHandlers */
40
- customHandlers?: () => Record<string, (...args: unknown[]) => unknown>;
30
+ dragHandleItems?(ctx: DragHandlePluginCtx): AbracadabraDragHandleItem[][];
41
31
  /** Mention (@) providers contributing items to the mention popup */
42
32
  mentionProviders?: AbracadabraMentionProvider[];
43
33
  /** Awareness field declarations — keys this plugin reads/writes on awareness */
44
34
  awarenessContributions?: AbracadabraAwarenessContribution[];
45
35
  /** Global command palette (⌘K) items */
46
- commandPaletteItems?: (ctx: CommandPaletteCtx) => AbracadabraCommandItem[] | Promise<AbracadabraCommandItem[]>;
36
+ commandPaletteItems?(ctx: CommandPaletteCtx): AbracadabraCommandItem[] | Promise<AbracadabraCommandItem[]>;
47
37
  /** Extra tabs rendered in the child document slideover panel */
48
38
  nodePanelSlots?: AbracadabraNodePanelSlot[];
49
39
  /** Settings panel contributed to the global settings view */
@@ -54,14 +44,7 @@ export interface AbracadabraPlugin {
54
44
  * Client-side setup hook — called once after client + provider are ready.
55
45
  * May return a teardown function called on app unmount.
56
46
  */
57
- clientSetup?: (ctx: ClientPluginCtx) => undefined | Promise<undefined | (() => void)>;
58
- /** TipTap extensions safe for server-side Y.Doc → HTML rendering (no Vue NodeViews) */
59
- serverExtensions?: () => Extension[];
60
- /**
61
- * Custom cache renderer for non-doc page types.
62
- * Receives the Y.Doc and returns serializable data for the cache.
63
- */
64
- serverCacheRenderer?: (docId: string, ydoc: Y.Doc) => unknown;
47
+ clientSetup?(ctx: ClientPluginCtx): undefined | Promise<undefined | (() => void)>;
65
48
  /**
66
49
  * Server-side background runners (Nitro context).
67
50
  * Each runner receives a ServerRunnerContext and returns a cleanup function.
@@ -165,37 +148,32 @@ export interface AbracadabraCommandItem {
165
148
  icon?: string;
166
149
  group?: string;
167
150
  shortcut?: string;
168
- when?: (ctx: CommandPaletteCtx) => boolean;
169
- handler: (ctx: CommandPaletteCtx) => void | Promise<void>;
151
+ when?(ctx: CommandPaletteCtx): boolean;
152
+ handler(ctx: CommandPaletteCtx): void | Promise<void>;
170
153
  }
171
154
  export interface AbracadabraMentionProvider {
172
155
  /** Group label shown in the suggestion popup */
173
156
  label: string;
174
- getItems: (query: string, ctx: MentionPluginCtx) => AbracadabraMentionItem[] | Promise<AbracadabraMentionItem[]>;
157
+ getItems(query: string, ctx: MentionPluginCtx): AbracadabraMentionItem[] | Promise<AbracadabraMentionItem[]>;
175
158
  }
176
159
  export interface MentionPluginCtx {
177
160
  docId: string;
178
161
  connectedUsers: CollaborationUser[];
179
162
  rootDoc: Y.Doc;
180
163
  }
181
- export interface AbracadabraMentionItem {
182
- id: string;
183
- label: string;
184
- avatar?: string;
185
- color?: string;
186
- attrs?: Record<string, unknown>;
187
- }
188
- export interface AbracadabraAwarenessContribution {
164
+ /** Module-level alias of `AbraMentionItem` for callers that import from `@abraca/nuxt`. */
165
+ export type AbracadabraMentionItem = AbraMentionItem;
166
+ export interface AbracadabraAwarenessContribution extends BaseAbraAwarenessContribution {
189
167
  /** Namespaced keys this plugin writes, e.g. ['cursor', 'presence:kanban'] */
190
168
  keys: string[];
191
169
  /** Optional per-canvas cursor overlay component */
192
170
  cursorComponent?: Component;
193
171
  }
194
- export interface AbracadabraNodePanelSlot {
172
+ export interface AbracadabraNodePanelSlot extends Omit<BaseAbraNodePanelSlot, 'when' | 'component'> {
195
173
  id: string;
196
174
  label: string;
197
175
  icon: string;
198
- when: (ctx: NodePanelCtx) => boolean;
176
+ when(ctx: NodePanelCtx): boolean;
199
177
  component: Component;
200
178
  }
201
179
  export interface NodePanelCtx {
@@ -206,12 +184,12 @@ export interface NodePanelCtx {
206
184
  meta: Record<string, unknown>;
207
185
  tree: DocTreeHelper;
208
186
  }
209
- export interface AbracadabraSettingsPanel {
187
+ export interface AbracadabraSettingsPanel extends Omit<BaseAbraSettingsPanel, 'component'> {
210
188
  label: string;
211
189
  icon: string;
212
190
  component: Component;
213
191
  }
214
- export interface AbracadabraKeyboardShortcut {
192
+ export interface AbracadabraKeyboardShortcut extends BaseAbraKeyboardShortcut {
215
193
  /** e.g. 'Meta+Shift+K', 'Control+Alt+P' */
216
194
  key: string;
217
195
  description: string;
@@ -577,6 +555,45 @@ export interface ServerRunnerContext {
577
555
  storage: NitroStorage;
578
556
  /** Document cache API: read/write HTML+JSON renders, build tree snapshots */
579
557
  docCache: DocCacheAPI;
558
+ /**
559
+ * Pre-write meta validator built from any `@abraca/schema` registries
560
+ * Nitro plugins attached via `BeforeRunnersCtx.attachSchema(...)` during
561
+ * the `abracadabra:before-runners` hook. `undefined` when no plugin
562
+ * attached a registry — runners must short-circuit on `undefined`
563
+ * rather than treating absence as "all writes are invalid" (Rule 4).
564
+ *
565
+ * Returns `{ ok: true, value }` for unknown doc-types — the validator
566
+ * mirrors the server's bundle_path / bundle_dir skip-on-collision rule.
567
+ */
568
+ validateMeta?: (typeName: string, meta: unknown) => {
569
+ ok: true;
570
+ value?: unknown;
571
+ } | {
572
+ ok: false;
573
+ errors: ReadonlyArray<{
574
+ path: ReadonlyArray<PropertyKey>;
575
+ message: string;
576
+ code?: string;
577
+ }>;
578
+ };
579
+ }
580
+ /**
581
+ * Payload of the `abracadabra:before-runners` Nitro hook. Plugins can
582
+ * register runners (`registerServerPlugin(plugin)`) and/or attach
583
+ * `@abraca/schema` registries (`attachSchema(registry)`) before the
584
+ * runner boot fires.
585
+ */
586
+ export interface BeforeRunnersCtx extends ServerRunnerContext {
587
+ /**
588
+ * Attach a SchemaRegistry. Multiple calls accumulate. Validators are
589
+ * built in attach order — the first registry that recognises a type
590
+ * wins. Mirrors the server's bundle_path / bundle_dir behaviour.
591
+ *
592
+ * Available even when `@abraca/schema` is not installed — just collects
593
+ * the references for downstream `validateMeta` wiring; if no module
594
+ * is present the cumulative validator is still safe to call.
595
+ */
596
+ attachSchema?: (registry: import('./server/utils/schemaServerSupport').SchemaRegistryLike) => void;
580
597
  }
581
598
  /**
582
599
  * A named background task that runs inside the Nitro server process.
@@ -584,7 +601,7 @@ export interface ServerRunnerContext {
584
601
  */
585
602
  export interface ServerRunnerDefinition {
586
603
  name: string;
587
- start: (ctx: ServerRunnerContext) => Promise<RunnerCleanup>;
604
+ start(ctx: ServerRunnerContext): Promise<RunnerCleanup>;
588
605
  }
589
606
  /**
590
607
  * API surface for reading/writing cached document renders.
@@ -148,6 +148,21 @@ export interface DocTypeDefinition {
148
148
  grandchildLabel?: string;
149
149
  /** Metadata fields shown/edited in the document properties panel. */
150
150
  metaSchema?: MetaField[];
151
+ /**
152
+ * Optional `@abraca/schema` registry that governs the data shape of
153
+ * this doc-type's `meta` field. Orthogonal to `metaSchema` (UI-form
154
+ * declarations) — `dataSchema` is the wire-level validator surface.
155
+ *
156
+ * When set, renderers can read with `useDocEntryTyped(id, dataSchema, key)`
157
+ * and write through `useTypedDoc(dataSchema)` to get type-narrowed
158
+ * meta and pre-write validation. Built-in `DOC_TYPES` records leave
159
+ * this undefined — apps wire it themselves so the canonical schemas
160
+ * stay opt-in (Rule 2).
161
+ *
162
+ * Typed as `SchemaRegistryLike` (structural, no static peer-dep
163
+ * import) so this file stays buildable without `@abraca/schema`.
164
+ */
165
+ dataSchema?: import('./schemaSupport').SchemaRegistryLike;
151
166
  }
152
167
  /**
153
168
  * Per-geoType meta schemas. Used by AEditor to show the right fields
@@ -81,6 +81,26 @@ export const DOC_TYPES = {
81
81
  () => import("../components/renderers/AProseRenderer.vue")
82
82
  )
83
83
  },
84
+ code: {
85
+ key: "code",
86
+ label: "Code",
87
+ icon: "i-lucide-code-2",
88
+ description: "Collaborative plain-text code editor with syntax highlighting",
89
+ available: true,
90
+ hasEditor: false,
91
+ supportsChildren: false,
92
+ component: defineDocComponent(
93
+ () => import("../components/renderers/ACodeRenderer.vue")
94
+ ),
95
+ metaSchema: [
96
+ {
97
+ type: "select",
98
+ key: "language",
99
+ options: ["javascript", "typescript", "tsx", "jsx", "css", "vue", "json", "markdown", "plain"],
100
+ label: "Language"
101
+ }
102
+ ]
103
+ },
84
104
  kanban: {
85
105
  key: "kanban",
86
106
  label: "Kanban",
@@ -0,0 +1,32 @@
1
+ /**
2
+ * loadCodeMirror — try-import the CodeMirror peer dependencies.
3
+ *
4
+ * Returns a bundle of the modules needed by <ACodeEditor> if the consumer
5
+ * installed them, or `null` if any required package is missing. Cached after
6
+ * the first call; the first failed lookup logs once in dev.
7
+ *
8
+ * Required peers: codemirror, @codemirror/state, @codemirror/view,
9
+ * @codemirror/language, @codemirror/commands, @codemirror/autocomplete,
10
+ * @codemirror/search, @codemirror/lang-javascript, @codemirror/lang-css,
11
+ * @codemirror/lang-vue, @codemirror/lang-json, y-codemirror.next.
12
+ *
13
+ * Apps that want code editing install:
14
+ * pnpm add codemirror @codemirror/state @codemirror/view @codemirror/language \
15
+ * @codemirror/commands @codemirror/autocomplete @codemirror/search \
16
+ * @codemirror/lang-javascript @codemirror/lang-css @codemirror/lang-vue \
17
+ * @codemirror/lang-json y-codemirror.next
18
+ */
19
+ export interface CodeMirrorBundle {
20
+ view: typeof import('@codemirror/view');
21
+ state: typeof import('@codemirror/state');
22
+ language: typeof import('@codemirror/language');
23
+ commands: typeof import('@codemirror/commands');
24
+ autocomplete: typeof import('@codemirror/autocomplete');
25
+ search: typeof import('@codemirror/search');
26
+ langJavascript: typeof import('@codemirror/lang-javascript');
27
+ langCss: typeof import('@codemirror/lang-css');
28
+ langVue: typeof import('@codemirror/lang-vue');
29
+ langJson: typeof import('@codemirror/lang-json');
30
+ yCollab: typeof import('y-codemirror.next');
31
+ }
32
+ export declare function loadCodeMirror(): Promise<CodeMirrorBundle | null>;
@@ -0,0 +1,65 @@
1
+ let cache = null;
2
+ let loading = null;
3
+ let warnedMissing = false;
4
+ export async function loadCodeMirror() {
5
+ if (cache) return cache;
6
+ if (loading) return loading;
7
+ loading = (async () => {
8
+ try {
9
+ const names = [
10
+ "@codemirror/view",
11
+ "@codemirror/state",
12
+ "@codemirror/language",
13
+ "@codemirror/commands",
14
+ "@codemirror/autocomplete",
15
+ "@codemirror/search",
16
+ "@codemirror/lang-javascript",
17
+ "@codemirror/lang-css",
18
+ "@codemirror/lang-vue",
19
+ "@codemirror/lang-json",
20
+ "y-codemirror.next"
21
+ ];
22
+ const [
23
+ view,
24
+ state,
25
+ language,
26
+ commands,
27
+ autocomplete,
28
+ search,
29
+ langJavascript,
30
+ langCss,
31
+ langVue,
32
+ langJson,
33
+ yCollab
34
+ ] = await Promise.all(names.map((n) => import(
35
+ /* @vite-ignore */
36
+ n
37
+ )));
38
+ cache = {
39
+ view,
40
+ state,
41
+ language,
42
+ commands,
43
+ autocomplete,
44
+ search,
45
+ langJavascript,
46
+ langCss,
47
+ langVue,
48
+ langJson,
49
+ yCollab
50
+ };
51
+ return cache;
52
+ } catch {
53
+ if (import.meta.dev && !warnedMissing) {
54
+ warnedMissing = true;
55
+ console.warn(
56
+ "[abracadabra] CodeMirror peer dependencies not installed. Code page type will fall back to a read-only <textarea>. Install: pnpm add codemirror @codemirror/state @codemirror/view @codemirror/language @codemirror/commands @codemirror/autocomplete @codemirror/search @codemirror/lang-javascript @codemirror/lang-css @codemirror/lang-vue @codemirror/lang-json y-codemirror.next"
57
+ );
58
+ }
59
+ return null;
60
+ } finally {
61
+ loading = null;
62
+ }
63
+ })();
64
+ return loading;
65
+ }
@@ -1,23 +1 @@
1
- /**
2
- * markdownToYjs.ts
3
- *
4
- * Parses markdown and populates a Y.XmlFragment with TipTap-compatible nodes.
5
- * Also provides YAML frontmatter parsing and filename → label conversion.
6
- *
7
- * Ported from cou-sh/app/utils/markdownToYjs.ts
8
- */
9
- import * as Y from 'yjs';
10
- import type { DocPageMeta } from '../types.js';
11
- export declare function filenameToLabel(raw: string): string;
12
- export interface FrontmatterResult {
13
- title?: string;
14
- type?: string;
15
- meta: Partial<DocPageMeta>;
16
- body: string;
17
- }
18
- export declare function parseFrontmatter(markdown: string): FrontmatterResult;
19
- /**
20
- * Parses markdown and writes content into a Y.XmlFragment.
21
- * The fragment must already be attached to a live Y.Doc.
22
- */
23
- export declare function populateYDocFromMarkdown(fragment: Y.XmlFragment, markdown: string, fallbackTitle?: string): void;
1
+ export { filenameToLabel, parseFrontmatter, populateYDocFromMarkdown, type FrontmatterResult, } from '@abraca/convert';