@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.
- package/dist/module.d.mts +68 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +99 -4
- package/dist/runtime/components/ACodeEditor.d.vue.ts +26 -0
- package/dist/runtime/components/ACodeEditor.vue +268 -0
- package/dist/runtime/components/ACodeEditor.vue.d.ts +26 -0
- package/dist/runtime/components/ADocumentTree.vue +52 -20
- package/dist/runtime/components/AEditor.d.vue.ts +20 -13
- package/dist/runtime/components/AEditor.vue +55 -2
- package/dist/runtime/components/AEditor.vue.d.ts +20 -13
- package/dist/runtime/components/ANodePanel.vue +64 -60
- package/dist/runtime/components/ANotificationBell.d.vue.ts +1 -1
- package/dist/runtime/components/ANotificationBell.vue.d.ts +1 -1
- package/dist/runtime/components/ASpaceFormModal.d.vue.ts +2 -2
- package/dist/runtime/components/ASpaceFormModal.vue.d.ts +2 -2
- package/dist/runtime/components/aware/APresenceBlobs.d.vue.ts +29 -1
- package/dist/runtime/components/aware/APresenceBlobs.vue +54 -8
- package/dist/runtime/components/aware/APresenceBlobs.vue.d.ts +29 -1
- package/dist/runtime/components/aware/APresenceCursors.d.vue.ts +11 -0
- package/dist/runtime/components/aware/APresenceCursors.vue +74 -9
- package/dist/runtime/components/aware/APresenceCursors.vue.d.ts +11 -0
- package/dist/runtime/components/aware/AToggleGroup.d.vue.ts +28 -13
- package/dist/runtime/components/aware/AToggleGroup.vue +56 -20
- package/dist/runtime/components/aware/AToggleGroup.vue.d.ts +28 -13
- package/dist/runtime/components/docs/ADocsNavigation.d.vue.ts +1 -1
- package/dist/runtime/components/docs/ADocsNavigation.vue.d.ts +1 -1
- package/dist/runtime/components/docs/ADocsSearchButton.d.vue.ts +1 -1
- package/dist/runtime/components/docs/ADocsSearchButton.vue.d.ts +1 -1
- package/dist/runtime/components/docs/ADocsToc.d.vue.ts +2 -2
- package/dist/runtime/components/docs/ADocsToc.vue.d.ts +2 -2
- package/dist/runtime/components/editor/AEditorRedoButton.d.vue.ts +1 -1
- package/dist/runtime/components/editor/AEditorRedoButton.vue.d.ts +1 -1
- package/dist/runtime/components/editor/AEditorUndoButton.d.vue.ts +1 -1
- package/dist/runtime/components/editor/AEditorUndoButton.vue.d.ts +1 -1
- package/dist/runtime/components/editor/ANodeInlineLabel.d.vue.ts +1 -1
- package/dist/runtime/components/editor/ANodeInlineLabel.vue.d.ts +1 -1
- package/dist/runtime/components/registry/APluginBrowser.d.vue.ts +23 -0
- package/dist/runtime/components/registry/APluginBrowser.vue +155 -0
- package/dist/runtime/components/registry/APluginBrowser.vue.d.ts +23 -0
- package/dist/runtime/components/registry/APluginCapabilityDialog.d.vue.ts +17 -0
- package/dist/runtime/components/registry/APluginCapabilityDialog.vue +159 -0
- package/dist/runtime/components/registry/APluginCapabilityDialog.vue.d.ts +17 -0
- package/dist/runtime/components/registry/APluginCard.d.vue.ts +20 -0
- package/dist/runtime/components/registry/APluginCard.vue +91 -0
- package/dist/runtime/components/registry/APluginCard.vue.d.ts +20 -0
- package/dist/runtime/components/registry/APluginDetail.d.vue.ts +18 -0
- package/dist/runtime/components/registry/APluginDetail.vue +252 -0
- package/dist/runtime/components/registry/APluginDetail.vue.d.ts +18 -0
- package/dist/runtime/components/renderers/ACodeRenderer.d.vue.ts +15 -0
- package/dist/runtime/components/renderers/ACodeRenderer.vue +68 -0
- package/dist/runtime/components/renderers/ACodeRenderer.vue.d.ts +15 -0
- package/dist/runtime/components/renderers/AGraphRenderer.vue +416 -120
- package/dist/runtime/components/renderers/AProseRenderer.d.vue.ts +2 -2
- package/dist/runtime/components/renderers/AProseRenderer.vue.d.ts +2 -2
- package/dist/runtime/components/shell/ABreadcrumbForDoc.d.vue.ts +11 -0
- package/dist/runtime/components/shell/ABreadcrumbForDoc.vue +16 -0
- package/dist/runtime/components/shell/ABreadcrumbForDoc.vue.d.ts +11 -0
- package/dist/runtime/components/shell/ASettingsSection.d.vue.ts +35 -0
- package/dist/runtime/components/shell/ASettingsSection.vue +26 -0
- package/dist/runtime/components/shell/ASettingsSection.vue.d.ts +35 -0
- package/dist/runtime/components/shell/ASidebar.d.vue.ts +1 -1
- package/dist/runtime/components/shell/ASidebar.vue.d.ts +1 -1
- package/dist/runtime/components/shell/AUserMenu.d.vue.ts +3 -0
- package/dist/runtime/components/shell/AUserMenu.vue +4 -0
- package/dist/runtime/components/shell/AUserMenu.vue.d.ts +3 -0
- package/dist/runtime/composables/useAbracadabraSchema.d.ts +83 -0
- package/dist/runtime/composables/useAbracadabraSchema.js +52 -0
- package/dist/runtime/composables/useAggregatedPresence.d.ts +1 -6
- package/dist/runtime/composables/useCalendarView.d.ts +1 -1
- package/dist/runtime/composables/useChat.js +1 -0
- package/dist/runtime/composables/useDocBreadcrumb.d.ts +21 -0
- package/dist/runtime/composables/useDocBreadcrumb.js +33 -0
- package/dist/runtime/composables/useDocEntryTyped.d.ts +60 -0
- package/dist/runtime/composables/useDocEntryTyped.js +70 -0
- package/dist/runtime/composables/useEditorDragHandle.js +18 -0
- package/dist/runtime/composables/useEditorSuggestions.js +2 -1
- package/dist/runtime/composables/useInstalledPlugins.d.ts +3 -21
- package/dist/runtime/composables/useInstalledPlugins.js +2 -12
- package/dist/runtime/composables/useMetaMenuItems.d.ts +21 -0
- package/dist/runtime/composables/useMetaMenuItems.js +115 -0
- package/dist/runtime/composables/useMetaValidator.d.ts +27 -0
- package/dist/runtime/composables/useMetaValidator.js +10 -0
- package/dist/runtime/composables/usePluginCatalog.d.ts +161 -0
- package/dist/runtime/composables/usePluginCatalog.js +234 -0
- package/dist/runtime/composables/useQuery.d.ts +79 -0
- package/dist/runtime/composables/useQuery.js +97 -0
- package/dist/runtime/composables/useSpaces.js +4 -5
- package/dist/runtime/composables/useTableView.d.ts +3 -3
- package/dist/runtime/composables/useTypedDoc.d.ts +97 -0
- package/dist/runtime/composables/useTypedDoc.js +114 -0
- package/dist/runtime/composables/useWebRTC.js +44 -5
- package/dist/runtime/extensions/document-meta.js +5 -0
- package/dist/runtime/extensions/timeline.d.ts +11 -0
- package/dist/runtime/extensions/timeline.js +52 -0
- package/dist/runtime/extensions/views/DocumentMetaView.d.vue.ts +4 -0
- package/dist/runtime/extensions/views/DocumentMetaView.vue +63 -0
- package/dist/runtime/extensions/views/DocumentMetaView.vue.d.ts +4 -0
- package/dist/runtime/extensions/views/TimelineItemView.d.vue.ts +4 -0
- package/dist/runtime/extensions/views/TimelineItemView.vue +131 -0
- package/dist/runtime/extensions/views/TimelineItemView.vue.d.ts +4 -0
- package/dist/runtime/extensions/views/TimelineView.d.vue.ts +9 -0
- package/dist/runtime/extensions/views/TimelineView.vue +29 -0
- package/dist/runtime/extensions/views/TimelineView.vue.d.ts +9 -0
- package/dist/runtime/locale.d.ts +2 -0
- package/dist/runtime/locale.js +2 -0
- package/dist/runtime/plugin-abracadabra.client.js +107 -6
- package/dist/runtime/plugin-registry.d.ts +11 -30
- package/dist/runtime/plugin-registry.js +2 -82
- package/dist/runtime/plugins/core.plugin.js +10 -4
- package/dist/runtime/server/api/_abracadabra/spaces.get.d.ts +1 -1
- package/dist/runtime/server/plugins/abracadabra-service.js +28 -0
- package/dist/runtime/server/utils/docCache.js +24 -3
- package/dist/runtime/server/utils/schemaServerSupport.d.ts +52 -0
- package/dist/runtime/server/utils/schemaServerSupport.js +51 -0
- package/dist/runtime/types.d.ts +63 -46
- package/dist/runtime/utils/docTypes.d.ts +15 -0
- package/dist/runtime/utils/docTypes.js +20 -0
- package/dist/runtime/utils/loadCodeMirror.d.ts +32 -0
- package/dist/runtime/utils/loadCodeMirror.js +65 -0
- package/dist/runtime/utils/markdownToYjs.d.ts +1 -23
- package/dist/runtime/utils/markdownToYjs.js +5 -440
- package/dist/runtime/utils/schemaSupport.d.ts +60 -0
- package/dist/runtime/utils/schemaSupport.js +40 -0
- package/dist/runtime/utils/yjsConvert.d.ts +1 -14
- package/dist/runtime/utils/yjsConvert.js +5 -331
- package/package.json +84 -23
package/dist/module.d.mts
CHANGED
|
@@ -42,6 +42,7 @@ declare module '@nuxt/schema' {
|
|
|
42
42
|
chat?: boolean;
|
|
43
43
|
media?: boolean;
|
|
44
44
|
slides?: boolean;
|
|
45
|
+
code?: boolean;
|
|
45
46
|
};
|
|
46
47
|
locale: AbracadabraLocale;
|
|
47
48
|
auth: {
|
|
@@ -72,6 +73,20 @@ declare module '@nuxt/schema' {
|
|
|
72
73
|
resetToken: string | null;
|
|
73
74
|
verifyToken: string | null;
|
|
74
75
|
};
|
|
76
|
+
schema: {
|
|
77
|
+
validate: boolean;
|
|
78
|
+
migrateOnRead: boolean;
|
|
79
|
+
bundleDir: string;
|
|
80
|
+
};
|
|
81
|
+
pluginRegistry: {
|
|
82
|
+
/**
|
|
83
|
+
* Public registry URL — the `abracadabra-registry-rs` instance the
|
|
84
|
+
* `usePluginRegistry()` composable reads from. Default points at the
|
|
85
|
+
* local-dev server (`http://127.0.0.1:8787`); production apps should
|
|
86
|
+
* override to the hosted registry.
|
|
87
|
+
*/
|
|
88
|
+
url: string;
|
|
89
|
+
};
|
|
75
90
|
};
|
|
76
91
|
}
|
|
77
92
|
interface RuntimeConfig {
|
|
@@ -165,6 +180,13 @@ interface ModuleOptions {
|
|
|
165
180
|
* Default: true (lightweight, no extra deps).
|
|
166
181
|
*/
|
|
167
182
|
slides?: boolean;
|
|
183
|
+
/**
|
|
184
|
+
* Register the `code` page type and the `<ACodeEditor>` primitive
|
|
185
|
+
* (CodeMirror 6 + y-codemirror.next). CodeMirror packages are loaded
|
|
186
|
+
* via dynamic import as optional peer deps — consumers that never use
|
|
187
|
+
* code pages don't pay the bundle cost. Default: true.
|
|
188
|
+
*/
|
|
189
|
+
code?: boolean;
|
|
168
190
|
};
|
|
169
191
|
/**
|
|
170
192
|
* Automatically add Vite resolve.dedupe entries for ProseMirror, TipTap, and Yjs.
|
|
@@ -248,6 +270,43 @@ interface ModuleOptions {
|
|
|
248
270
|
/** Query param holding the email-verification token. Default: 'verify_token'. */
|
|
249
271
|
verifyToken?: string | null;
|
|
250
272
|
};
|
|
273
|
+
/**
|
|
274
|
+
* Optional `@abraca/schema` integration.
|
|
275
|
+
*
|
|
276
|
+
* The schema package is an **optional peer dependency**. Apps that
|
|
277
|
+
* never set this block — or never install `@abraca/schema` — are
|
|
278
|
+
* unaffected (Rule 4 of `feedback_schema_free_core.md`).
|
|
279
|
+
*
|
|
280
|
+
* When opted in, consuming code attaches one or more `SchemaRegistry`
|
|
281
|
+
* instances at boot via the `abracadabra:before-boot` Nuxt hook (see
|
|
282
|
+
* `useAbracadabraSchema()` for the runtime side). The block here
|
|
283
|
+
* controls whether the client plugin should auto-call
|
|
284
|
+
* `provider.dm.meta.setSchema(...)`, whether typed-reads should
|
|
285
|
+
* `runMigrations` before returning, and tells operators the path the
|
|
286
|
+
* server's `[extensions.schema] bundle_dir` is loading.
|
|
287
|
+
*/
|
|
288
|
+
schema?: {
|
|
289
|
+
/**
|
|
290
|
+
* When true, the client plugin calls `dm.meta.setSchema(merged)`
|
|
291
|
+
* once after boot using the registries attached via the
|
|
292
|
+
* `abracadabra:before-boot` hook. Invalid meta writes throw
|
|
293
|
+
* `MetaValidationError` from `@abraca/dabra`. Default: false.
|
|
294
|
+
*/
|
|
295
|
+
validate?: boolean;
|
|
296
|
+
/**
|
|
297
|
+
* When true, the typed-doc composables run `runMigrations(...)`
|
|
298
|
+
* before returning meta on read. Migrations are forward-only and
|
|
299
|
+
* declared per doc-type in `@abraca/schema`. Default: false.
|
|
300
|
+
*/
|
|
301
|
+
migrateOnRead?: boolean;
|
|
302
|
+
/**
|
|
303
|
+
* Path to the directory of JSON Schema bundles the Abracadabra
|
|
304
|
+
* server is loading via `[extensions.schema] bundle_dir`. Logged
|
|
305
|
+
* at boot for operator visibility. Not read by the module — the
|
|
306
|
+
* server is authoritative. Default: '' (no advertisement).
|
|
307
|
+
*/
|
|
308
|
+
bundleDir?: string;
|
|
309
|
+
};
|
|
251
310
|
/**
|
|
252
311
|
* WebRTC P2P configuration. Only used when features.webrtc is true.
|
|
253
312
|
*/
|
|
@@ -284,6 +343,15 @@ interface ModuleOptions {
|
|
|
284
343
|
/** Disable the service provider even if keys are present. Default: false. */
|
|
285
344
|
disabled?: boolean;
|
|
286
345
|
};
|
|
346
|
+
/**
|
|
347
|
+
* Public plugin registry — the `abracadabra-registry-rs` instance used by
|
|
348
|
+
* `usePluginRegistry()` + the `<APluginBrowser>` UI. Default points at the
|
|
349
|
+
* local dev server (`http://127.0.0.1:8787`). Set
|
|
350
|
+
* `ABRACADABRA_PLUGIN_REGISTRY_URL` env var or override here for prod.
|
|
351
|
+
*/
|
|
352
|
+
pluginRegistry?: {
|
|
353
|
+
url?: string;
|
|
354
|
+
};
|
|
287
355
|
}
|
|
288
356
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
289
357
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -32,7 +32,8 @@ const module$1 = defineNuxtModule({
|
|
|
32
32
|
webrtc: false,
|
|
33
33
|
chat: false,
|
|
34
34
|
media: false,
|
|
35
|
-
slides: true
|
|
35
|
+
slides: true,
|
|
36
|
+
code: true
|
|
36
37
|
},
|
|
37
38
|
addViteDedupe: true,
|
|
38
39
|
prefix: "",
|
|
@@ -52,14 +53,25 @@ const module$1 = defineNuxtModule({
|
|
|
52
53
|
webrtc: {
|
|
53
54
|
iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
|
|
54
55
|
e2ee: false,
|
|
55
|
-
|
|
56
|
+
// Default ON. Opting into WebRTC almost always implies wanting data
|
|
57
|
+
// channels (file transfer is the marquee use case). Apps that want
|
|
58
|
+
// a strictly voice/video mesh can flip to false.
|
|
59
|
+
fileTransfer: true
|
|
56
60
|
},
|
|
57
61
|
authQueryKeys: {
|
|
58
62
|
resetToken: "reset_token",
|
|
59
63
|
verifyToken: "verify_token"
|
|
60
64
|
},
|
|
65
|
+
schema: {
|
|
66
|
+
validate: false,
|
|
67
|
+
migrateOnRead: false,
|
|
68
|
+
bundleDir: ""
|
|
69
|
+
},
|
|
61
70
|
service: {
|
|
62
71
|
disabled: false
|
|
72
|
+
},
|
|
73
|
+
pluginRegistry: {
|
|
74
|
+
url: process.env.ABRACADABRA_PLUGIN_REGISTRY_URL ?? "http://127.0.0.1:8787"
|
|
63
75
|
}
|
|
64
76
|
},
|
|
65
77
|
setup(options, nuxt) {
|
|
@@ -68,6 +80,9 @@ const module$1 = defineNuxtModule({
|
|
|
68
80
|
nuxt.options.runtimeConfig.public,
|
|
69
81
|
{
|
|
70
82
|
abracadabra: {
|
|
83
|
+
pluginRegistry: {
|
|
84
|
+
url: options.pluginRegistry?.url ?? "http://127.0.0.1:8787"
|
|
85
|
+
},
|
|
71
86
|
url: options.url,
|
|
72
87
|
entryDocId: options.entryDocId ?? "",
|
|
73
88
|
persistAuth: options.persistAuth,
|
|
@@ -87,11 +102,16 @@ const module$1 = defineNuxtModule({
|
|
|
87
102
|
webrtc: {
|
|
88
103
|
iceServers: options.webrtc?.iceServers ?? [{ urls: "stun:stun.l.google.com:19302" }],
|
|
89
104
|
e2ee: options.webrtc?.e2ee ?? false,
|
|
90
|
-
fileTransfer: options.webrtc?.fileTransfer ??
|
|
105
|
+
fileTransfer: options.webrtc?.fileTransfer ?? true
|
|
91
106
|
},
|
|
92
107
|
authQueryKeys: {
|
|
93
108
|
resetToken: options.authQueryKeys?.resetToken ?? "reset_token",
|
|
94
109
|
verifyToken: options.authQueryKeys?.verifyToken ?? "verify_token"
|
|
110
|
+
},
|
|
111
|
+
schema: {
|
|
112
|
+
validate: options.schema?.validate ?? false,
|
|
113
|
+
migrateOnRead: options.schema?.migrateOnRead ?? false,
|
|
114
|
+
bundleDir: options.schema?.bundleDir ?? ""
|
|
95
115
|
}
|
|
96
116
|
}
|
|
97
117
|
}
|
|
@@ -112,6 +132,36 @@ const module$1 = defineNuxtModule({
|
|
|
112
132
|
}
|
|
113
133
|
}
|
|
114
134
|
});
|
|
135
|
+
try {
|
|
136
|
+
let resolveEsmTwin = function(cjsPath) {
|
|
137
|
+
const candidates = [
|
|
138
|
+
cjsPath.replace(/\.cjs$/, ".mjs"),
|
|
139
|
+
cjsPath.replace(/\.cjs$/, ".js"),
|
|
140
|
+
path.join(path.dirname(path.dirname(cjsPath)), path.basename(cjsPath, ".cjs") + ".js")
|
|
141
|
+
];
|
|
142
|
+
for (const c of candidates) {
|
|
143
|
+
if (fs.existsSync(c)) return c;
|
|
144
|
+
}
|
|
145
|
+
if (nuxt.options.dev) {
|
|
146
|
+
console.warn(`[abracadabra] could not find ESM twin for ${cjsPath} \u2014 leaving Nitro alias on .cjs`);
|
|
147
|
+
}
|
|
148
|
+
return cjsPath;
|
|
149
|
+
};
|
|
150
|
+
const nodeRequire = createRequire(`${nuxt.options.rootDir}/`);
|
|
151
|
+
const fs = nodeRequire("node:fs");
|
|
152
|
+
const path = nodeRequire("node:path");
|
|
153
|
+
const yjsCjs = nodeRequire.resolve("yjs");
|
|
154
|
+
const yjsEsm = resolveEsmTwin(yjsCjs);
|
|
155
|
+
const yProtocolsCjs = nodeRequire.resolve("y-protocols/awareness");
|
|
156
|
+
const yProtocolsEsm = resolveEsmTwin(yProtocolsCjs);
|
|
157
|
+
nuxt.options.nitro = defu(nuxt.options.nitro, {
|
|
158
|
+
alias: {
|
|
159
|
+
"yjs": yjsEsm,
|
|
160
|
+
"y-protocols/awareness": yProtocolsEsm
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
} catch {
|
|
164
|
+
}
|
|
115
165
|
if (options.addViteDedupe) {
|
|
116
166
|
const dedupePackages = [
|
|
117
167
|
"prosemirror-view",
|
|
@@ -136,7 +186,13 @@ const module$1 = defineNuxtModule({
|
|
|
136
186
|
"@tiptap/pm",
|
|
137
187
|
"@tiptap/vue-3",
|
|
138
188
|
"@tiptap/extension-collaboration",
|
|
139
|
-
"@tiptap/extension-collaboration-caret"
|
|
189
|
+
"@tiptap/extension-collaboration-caret",
|
|
190
|
+
// CodeMirror — view + state are singletons (similar to ProseMirror).
|
|
191
|
+
// Two copies cause plugin-key collisions and silent decoration drops.
|
|
192
|
+
"@codemirror/state",
|
|
193
|
+
"@codemirror/view",
|
|
194
|
+
"@codemirror/language",
|
|
195
|
+
"y-codemirror.next"
|
|
140
196
|
];
|
|
141
197
|
nuxt.options.vite = defu(nuxt.options.vite, { resolve: { dedupe: [] } });
|
|
142
198
|
const existing = nuxt.options.vite.resolve?.dedupe ?? [];
|
|
@@ -229,6 +285,29 @@ const module$1 = defineNuxtModule({
|
|
|
229
285
|
prebundleDeps.push("jszip");
|
|
230
286
|
} catch {
|
|
231
287
|
}
|
|
288
|
+
if (options.features?.code !== false) {
|
|
289
|
+
const cmPeers = [
|
|
290
|
+
"@codemirror/view",
|
|
291
|
+
"@codemirror/state",
|
|
292
|
+
"@codemirror/language",
|
|
293
|
+
"@codemirror/commands",
|
|
294
|
+
"@codemirror/autocomplete",
|
|
295
|
+
"@codemirror/search",
|
|
296
|
+
"@codemirror/lang-javascript",
|
|
297
|
+
"@codemirror/lang-css",
|
|
298
|
+
"@codemirror/lang-vue",
|
|
299
|
+
"@codemirror/lang-json",
|
|
300
|
+
"y-codemirror.next"
|
|
301
|
+
];
|
|
302
|
+
const nodeRequire = createRequire(`${nuxt.options.rootDir}/`);
|
|
303
|
+
for (const pkg of cmPeers) {
|
|
304
|
+
try {
|
|
305
|
+
nodeRequire.resolve(pkg);
|
|
306
|
+
prebundleDeps.push(pkg);
|
|
307
|
+
} catch {
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
232
311
|
nuxt.options.vite.optimizeDeps.include = [
|
|
233
312
|
.../* @__PURE__ */ new Set([...includeList, ...prebundleDeps])
|
|
234
313
|
];
|
|
@@ -243,6 +322,17 @@ const module$1 = defineNuxtModule({
|
|
|
243
322
|
"@noble/curves/ed25519.js"
|
|
244
323
|
])
|
|
245
324
|
];
|
|
325
|
+
nuxt.options.vite.optimizeDeps.include = [
|
|
326
|
+
.../* @__PURE__ */ new Set([
|
|
327
|
+
...nuxt.options.vite.optimizeDeps.include ?? [],
|
|
328
|
+
"@scure/bip39",
|
|
329
|
+
// Subpath ships with the `.js` extension in the package's exports
|
|
330
|
+
// map (`./wordlists/english.js` → `./wordlists/english.js`).
|
|
331
|
+
// Listing it without the extension throws ERR_PACKAGE_PATH_NOT_EXPORTED.
|
|
332
|
+
"@scure/bip39/wordlists/english.js",
|
|
333
|
+
"@scure/base"
|
|
334
|
+
])
|
|
335
|
+
];
|
|
246
336
|
nuxt.options.css.push(resolver.resolve("./runtime/assets/aware-tokens.css"));
|
|
247
337
|
if (options.features?.editor !== false) {
|
|
248
338
|
nuxt.options.css.push(resolver.resolve("./runtime/assets/editor.css"));
|
|
@@ -341,6 +431,11 @@ const module$1 = defineNuxtModule({
|
|
|
341
431
|
pathPrefix: false
|
|
342
432
|
});
|
|
343
433
|
}
|
|
434
|
+
addComponentsDir({
|
|
435
|
+
path: resolver.resolve("./runtime/components/registry"),
|
|
436
|
+
prefix: options.prefix ?? "",
|
|
437
|
+
pathPrefix: false
|
|
438
|
+
});
|
|
344
439
|
addComponentsDir({
|
|
345
440
|
path: resolver.resolve("./runtime/components"),
|
|
346
441
|
prefix: options.prefix ?? "",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
type Lang = 'javascript' | 'typescript' | 'tsx' | 'jsx' | 'css' | 'vue' | 'json' | 'markdown' | 'plain';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
/** Child Y.Doc provider — exposes `.document` (Y.Doc) and `.awareness`. */
|
|
4
|
+
provider: any | null;
|
|
5
|
+
/** Y type field name. Default `'code'` for Y.Text; in source-view mode this is the XmlFragment name. */
|
|
6
|
+
fieldName?: string;
|
|
7
|
+
/** Syntax-highlight language. */
|
|
8
|
+
language?: Lang;
|
|
9
|
+
/** Read-only editor. Forced true when `asXmlFragment` is set. */
|
|
10
|
+
readOnly?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Source-view mode: bind to `provider.document.getXmlFragment(fieldName)` and
|
|
13
|
+
* render its `.toString()` as plain text. One-way — no write-back.
|
|
14
|
+
*/
|
|
15
|
+
asXmlFragment?: boolean;
|
|
16
|
+
};
|
|
17
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
18
|
+
editorView: import("vue").ShallowRef<any, any>;
|
|
19
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
20
|
+
readOnly: boolean;
|
|
21
|
+
language: Lang;
|
|
22
|
+
fieldName: string;
|
|
23
|
+
asXmlFragment: boolean;
|
|
24
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
25
|
+
declare const _default: typeof __VLS_export;
|
|
26
|
+
export default _default;
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref, shallowRef, watch, computed, onMounted, onBeforeUnmount } from "vue";
|
|
3
|
+
import { loadCodeMirror } from "../utils/loadCodeMirror";
|
|
4
|
+
import { useNuxtApp } from "#imports";
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
provider: { type: null, required: true },
|
|
7
|
+
fieldName: { type: String, required: false, default: "code" },
|
|
8
|
+
language: { type: String, required: false, default: "javascript" },
|
|
9
|
+
readOnly: { type: Boolean, required: false, default: false },
|
|
10
|
+
asXmlFragment: { type: Boolean, required: false, default: false }
|
|
11
|
+
});
|
|
12
|
+
const containerRef = ref(null);
|
|
13
|
+
const editorView = shallowRef(null);
|
|
14
|
+
const fallbackText = ref("");
|
|
15
|
+
const cmBundle = shallowRef(null);
|
|
16
|
+
const peersMissing = ref(false);
|
|
17
|
+
const effectiveReadOnly = computed(() => props.readOnly || props.asXmlFragment);
|
|
18
|
+
const { userName, userColor, publicKeyB64 } = useNuxtApp().$abracadabra ?? {
|
|
19
|
+
userName: { value: "" },
|
|
20
|
+
userColor: { value: "#888" },
|
|
21
|
+
publicKeyB64: { value: "" }
|
|
22
|
+
};
|
|
23
|
+
function getLanguageExtension(bundle, lang) {
|
|
24
|
+
switch (lang) {
|
|
25
|
+
case "vue":
|
|
26
|
+
return bundle.langVue.vue();
|
|
27
|
+
case "typescript":
|
|
28
|
+
case "tsx":
|
|
29
|
+
return bundle.langJavascript.javascript({ typescript: true, jsx: lang === "tsx" });
|
|
30
|
+
case "javascript":
|
|
31
|
+
case "jsx":
|
|
32
|
+
return bundle.langJavascript.javascript({ jsx: lang === "jsx" });
|
|
33
|
+
case "css":
|
|
34
|
+
return bundle.langCss.css();
|
|
35
|
+
case "json":
|
|
36
|
+
return bundle.langJson.json();
|
|
37
|
+
case "markdown":
|
|
38
|
+
case "plain":
|
|
39
|
+
return [];
|
|
40
|
+
default:
|
|
41
|
+
return bundle.langJavascript.javascript();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function buildTheme(bundle) {
|
|
45
|
+
return bundle.view.EditorView.theme({
|
|
46
|
+
"&": {
|
|
47
|
+
backgroundColor: "var(--ui-bg)",
|
|
48
|
+
color: "var(--ui-text-highlighted)",
|
|
49
|
+
height: "100%",
|
|
50
|
+
fontSize: "13px",
|
|
51
|
+
fontFamily: 'ui-monospace, "SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", Menlo, Monaco, Consolas, monospace'
|
|
52
|
+
},
|
|
53
|
+
".cm-content": {
|
|
54
|
+
fontFamily: "inherit",
|
|
55
|
+
caretColor: "var(--ui-text-highlighted)",
|
|
56
|
+
padding: "8px 0"
|
|
57
|
+
},
|
|
58
|
+
".cm-cursor": {
|
|
59
|
+
borderLeftColor: "var(--ui-text-highlighted)"
|
|
60
|
+
},
|
|
61
|
+
".cm-activeLine": {
|
|
62
|
+
backgroundColor: "color-mix(in srgb, var(--ui-bg-elevated) 50%, transparent)"
|
|
63
|
+
},
|
|
64
|
+
".cm-activeLineGutter": {
|
|
65
|
+
backgroundColor: "color-mix(in srgb, var(--ui-bg-elevated) 50%, transparent)"
|
|
66
|
+
},
|
|
67
|
+
".cm-gutters": {
|
|
68
|
+
fontFamily: "inherit",
|
|
69
|
+
backgroundColor: "var(--ui-bg)",
|
|
70
|
+
color: "var(--ui-text-dimmed)",
|
|
71
|
+
border: "none",
|
|
72
|
+
borderRight: "1px solid var(--ui-border)"
|
|
73
|
+
},
|
|
74
|
+
".cm-selectionBackground": {
|
|
75
|
+
backgroundColor: "color-mix(in srgb, var(--ui-primary) 25%, transparent) !important"
|
|
76
|
+
},
|
|
77
|
+
"&.cm-focused .cm-selectionBackground": {
|
|
78
|
+
backgroundColor: "color-mix(in srgb, var(--ui-primary) 30%, transparent) !important"
|
|
79
|
+
},
|
|
80
|
+
".cm-matchingBracket": {
|
|
81
|
+
backgroundColor: "color-mix(in srgb, var(--ui-primary) 20%, transparent)",
|
|
82
|
+
outline: "1px solid color-mix(in srgb, var(--ui-primary) 40%, transparent)"
|
|
83
|
+
},
|
|
84
|
+
".cm-ySelectionInfo": {
|
|
85
|
+
fontSize: "10px",
|
|
86
|
+
fontFamily: "system-ui, sans-serif",
|
|
87
|
+
padding: "1px 4px",
|
|
88
|
+
borderRadius: "3px",
|
|
89
|
+
opacity: "0.9",
|
|
90
|
+
position: "absolute",
|
|
91
|
+
top: "-1.3em",
|
|
92
|
+
left: "-1px",
|
|
93
|
+
whiteSpace: "nowrap",
|
|
94
|
+
color: "#fff"
|
|
95
|
+
}
|
|
96
|
+
}, { dark: true });
|
|
97
|
+
}
|
|
98
|
+
let xmlObserverCleanup = null;
|
|
99
|
+
function destroyEditor() {
|
|
100
|
+
if (xmlObserverCleanup) {
|
|
101
|
+
xmlObserverCleanup();
|
|
102
|
+
xmlObserverCleanup = null;
|
|
103
|
+
}
|
|
104
|
+
if (editorView.value) {
|
|
105
|
+
editorView.value.destroy();
|
|
106
|
+
editorView.value = null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function createEditor(bundle, container) {
|
|
110
|
+
const { EditorView, lineNumbers, highlightActiveLine, highlightActiveLineGutter, drawSelection, rectangularSelection, crosshairCursor, highlightSpecialChars, dropCursor, keymap } = bundle.view;
|
|
111
|
+
const { EditorState } = bundle.state;
|
|
112
|
+
const { defaultKeymap, history, historyKeymap, indentWithTab } = bundle.commands;
|
|
113
|
+
const { syntaxHighlighting, defaultHighlightStyle, indentOnInput, bracketMatching, foldGutter, foldKeymap } = bundle.language;
|
|
114
|
+
const { closeBrackets, closeBracketsKeymap, autocompletion, completionKeymap } = bundle.autocomplete;
|
|
115
|
+
const { searchKeymap, highlightSelectionMatches } = bundle.search;
|
|
116
|
+
const baseExtensions = [
|
|
117
|
+
lineNumbers(),
|
|
118
|
+
highlightActiveLineGutter(),
|
|
119
|
+
highlightSpecialChars(),
|
|
120
|
+
foldGutter(),
|
|
121
|
+
drawSelection(),
|
|
122
|
+
dropCursor(),
|
|
123
|
+
EditorState.allowMultipleSelections.of(true),
|
|
124
|
+
indentOnInput(),
|
|
125
|
+
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
|
126
|
+
bracketMatching(),
|
|
127
|
+
closeBrackets(),
|
|
128
|
+
autocompletion(),
|
|
129
|
+
rectangularSelection(),
|
|
130
|
+
crosshairCursor(),
|
|
131
|
+
highlightActiveLine(),
|
|
132
|
+
highlightSelectionMatches(),
|
|
133
|
+
keymap.of([
|
|
134
|
+
...closeBracketsKeymap,
|
|
135
|
+
...defaultKeymap,
|
|
136
|
+
...searchKeymap,
|
|
137
|
+
...historyKeymap,
|
|
138
|
+
...foldKeymap,
|
|
139
|
+
...completionKeymap,
|
|
140
|
+
indentWithTab
|
|
141
|
+
]),
|
|
142
|
+
getLanguageExtension(bundle, props.language),
|
|
143
|
+
buildTheme(bundle),
|
|
144
|
+
EditorView.lineWrapping,
|
|
145
|
+
EditorState.readOnly.of(effectiveReadOnly.value)
|
|
146
|
+
];
|
|
147
|
+
const prov = props.provider;
|
|
148
|
+
const ydoc = prov?.document;
|
|
149
|
+
if (props.asXmlFragment && ydoc) {
|
|
150
|
+
const fragment = ydoc.getXmlFragment(props.fieldName);
|
|
151
|
+
const initial = fragment?.toString?.() ?? "";
|
|
152
|
+
const state = EditorState.create({
|
|
153
|
+
doc: initial,
|
|
154
|
+
extensions: [...baseExtensions, history()]
|
|
155
|
+
});
|
|
156
|
+
const view = new EditorView({ state, parent: container });
|
|
157
|
+
const onFragmentChange = () => {
|
|
158
|
+
const next = fragment?.toString?.() ?? "";
|
|
159
|
+
const current = view.state.doc.toString();
|
|
160
|
+
if (next === current) return;
|
|
161
|
+
view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: next } });
|
|
162
|
+
};
|
|
163
|
+
fragment?.observeDeep?.(onFragmentChange);
|
|
164
|
+
xmlObserverCleanup = () => fragment?.unobserveDeep?.(onFragmentChange);
|
|
165
|
+
return view;
|
|
166
|
+
}
|
|
167
|
+
if (prov && ydoc) {
|
|
168
|
+
const ytext = ydoc.getText(props.fieldName);
|
|
169
|
+
const awareness = prov.awareness;
|
|
170
|
+
if (awareness && userName?.value && publicKeyB64?.value) {
|
|
171
|
+
awareness.setLocalStateField("user", {
|
|
172
|
+
name: userName.value,
|
|
173
|
+
color: userColor?.value ?? "#888",
|
|
174
|
+
publicKey: publicKeyB64.value
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
const extensions = [...baseExtensions];
|
|
178
|
+
if (awareness && !effectiveReadOnly.value) {
|
|
179
|
+
extensions.push(bundle.yCollab.yCollab(ytext, awareness));
|
|
180
|
+
} else {
|
|
181
|
+
extensions.push(history());
|
|
182
|
+
}
|
|
183
|
+
return new EditorView({
|
|
184
|
+
state: EditorState.create({ doc: ytext.toString(), extensions }),
|
|
185
|
+
parent: container
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
return new EditorView({
|
|
189
|
+
state: EditorState.create({ doc: "", extensions: [...baseExtensions, history()] }),
|
|
190
|
+
parent: container
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
async function mount() {
|
|
194
|
+
destroyEditor();
|
|
195
|
+
if (!containerRef.value) return;
|
|
196
|
+
const bundle = cmBundle.value ?? await loadCodeMirror();
|
|
197
|
+
cmBundle.value = bundle;
|
|
198
|
+
if (!bundle) {
|
|
199
|
+
peersMissing.value = true;
|
|
200
|
+
const prov = props.provider;
|
|
201
|
+
if (props.asXmlFragment && prov?.document) {
|
|
202
|
+
fallbackText.value = prov.document.getXmlFragment(props.fieldName)?.toString?.() ?? "";
|
|
203
|
+
} else if (prov?.document) {
|
|
204
|
+
fallbackText.value = prov.document.getText(props.fieldName)?.toString?.() ?? "";
|
|
205
|
+
}
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
editorView.value = createEditor(bundle, containerRef.value);
|
|
209
|
+
}
|
|
210
|
+
onMounted(() => {
|
|
211
|
+
void mount();
|
|
212
|
+
});
|
|
213
|
+
watch(containerRef, (el) => {
|
|
214
|
+
if (el) void mount();
|
|
215
|
+
});
|
|
216
|
+
watch(
|
|
217
|
+
() => [props.provider, props.fieldName, props.language, props.readOnly, props.asXmlFragment],
|
|
218
|
+
() => {
|
|
219
|
+
void mount();
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
watch(
|
|
223
|
+
() => [userName?.value, userColor?.value, publicKeyB64?.value],
|
|
224
|
+
([n, c, k]) => {
|
|
225
|
+
const awareness = props.provider?.awareness;
|
|
226
|
+
if (!awareness || !n || !k) return;
|
|
227
|
+
awareness.setLocalStateField("user", { name: n, color: c ?? "#888", publicKey: k });
|
|
228
|
+
}
|
|
229
|
+
);
|
|
230
|
+
onBeforeUnmount(destroyEditor);
|
|
231
|
+
defineExpose({ editorView });
|
|
232
|
+
</script>
|
|
233
|
+
|
|
234
|
+
<template>
|
|
235
|
+
<div class="acode-root">
|
|
236
|
+
<ClientOnly>
|
|
237
|
+
<div v-if="peersMissing" class="acode-fallback">
|
|
238
|
+
<p class="acode-fallback__note">
|
|
239
|
+
CodeMirror peer dependencies not installed. Showing a read-only fallback.
|
|
240
|
+
<a
|
|
241
|
+
href="https://codemirror.net/"
|
|
242
|
+
target="_blank"
|
|
243
|
+
rel="noopener"
|
|
244
|
+
class="acode-fallback__link"
|
|
245
|
+
>Install instructions</a>.
|
|
246
|
+
</p>
|
|
247
|
+
<textarea
|
|
248
|
+
:value="fallbackText"
|
|
249
|
+
readonly
|
|
250
|
+
class="acode-fallback__textarea"
|
|
251
|
+
spellcheck="false"
|
|
252
|
+
/>
|
|
253
|
+
</div>
|
|
254
|
+
<div
|
|
255
|
+
v-else
|
|
256
|
+
ref="containerRef"
|
|
257
|
+
class="acode-container"
|
|
258
|
+
/>
|
|
259
|
+
<template #fallback>
|
|
260
|
+
<div class="acode-container acode-container--ssr" />
|
|
261
|
+
</template>
|
|
262
|
+
</ClientOnly>
|
|
263
|
+
</div>
|
|
264
|
+
</template>
|
|
265
|
+
|
|
266
|
+
<style scoped>
|
|
267
|
+
.acode-root{display:flex;flex-direction:column}.acode-container,.acode-root{flex:1 1 0;min-height:0;overflow:hidden}.acode-container--ssr{background:var(--ui-bg)}.acode-fallback{display:flex;flex:1 1 0;flex-direction:column;gap:.5rem;min-height:0;padding:.5rem}.acode-fallback__note{color:var(--ui-text-muted);font-size:.75rem}.acode-fallback__link{color:var(--ui-primary);text-decoration:underline}.acode-fallback__textarea{background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius);color:var(--ui-text-highlighted);flex:1 1 0;font-family:ui-monospace,SF Mono,Fira Code,Fira Mono,Roboto Mono,Menlo,Monaco,Consolas,monospace;font-size:13px;min-height:0;padding:.5rem;resize:none;width:100%}
|
|
268
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
type Lang = 'javascript' | 'typescript' | 'tsx' | 'jsx' | 'css' | 'vue' | 'json' | 'markdown' | 'plain';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
/** Child Y.Doc provider — exposes `.document` (Y.Doc) and `.awareness`. */
|
|
4
|
+
provider: any | null;
|
|
5
|
+
/** Y type field name. Default `'code'` for Y.Text; in source-view mode this is the XmlFragment name. */
|
|
6
|
+
fieldName?: string;
|
|
7
|
+
/** Syntax-highlight language. */
|
|
8
|
+
language?: Lang;
|
|
9
|
+
/** Read-only editor. Forced true when `asXmlFragment` is set. */
|
|
10
|
+
readOnly?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Source-view mode: bind to `provider.document.getXmlFragment(fieldName)` and
|
|
13
|
+
* render its `.toString()` as plain text. One-way — no write-back.
|
|
14
|
+
*/
|
|
15
|
+
asXmlFragment?: boolean;
|
|
16
|
+
};
|
|
17
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
18
|
+
editorView: import("vue").ShallowRef<any, any>;
|
|
19
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
20
|
+
readOnly: boolean;
|
|
21
|
+
language: Lang;
|
|
22
|
+
fieldName: string;
|
|
23
|
+
asXmlFragment: boolean;
|
|
24
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
25
|
+
declare const _default: typeof __VLS_export;
|
|
26
|
+
export default _default;
|