@abraca/nuxt 2.20.0 → 2.22.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.json +1 -1
- package/dist/module.mjs +7 -1
- package/dist/runtime/components/docs/ADocsSearch.d.vue.ts +1 -1
- package/dist/runtime/components/docs/ADocsSearch.vue.d.ts +1 -1
- package/dist/runtime/composables/useDocTree.js +1 -1
- package/dist/runtime/server/api/_abracadabra/resolve/[...slug].get.js +1 -1
- package/dist/runtime/server/utils/docCache.d.ts +1 -0
- package/dist/runtime/server/utils/docCache.js +10 -5
- package/dist/runtime/server/utils/serverSchemaStubs.d.ts +23 -0
- package/dist/runtime/server/utils/serverSchemaStubs.js +50 -0
- package/package.json +1 -1
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -124,7 +124,13 @@ const module$1 = defineNuxtModule({
|
|
|
124
124
|
abracadabra: {
|
|
125
125
|
servicePublicKey: options.service?.publicKey ?? "",
|
|
126
126
|
servicePrivateKey: options.service?.privateKey ?? "",
|
|
127
|
-
|
|
127
|
+
// Default the service root to the app's entry doc. The previous
|
|
128
|
+
// fallback (the backend's /info root_doc_id) is the all-zeros server
|
|
129
|
+
// WORLD root on multi-space servers — the service then synced an
|
|
130
|
+
// empty doc-tree: 0 slugs, empty SSR cache, no server rendering.
|
|
131
|
+
// An explicit service.rootDocId still wins; /info discovery remains
|
|
132
|
+
// the last resort inside the service plugin when both are unset.
|
|
133
|
+
serviceRootDocId: options.service?.rootDocId ?? options.entryDocId ?? "",
|
|
128
134
|
serviceDisabled: options.service?.disabled ?? false
|
|
129
135
|
}
|
|
130
136
|
});
|
|
@@ -239,8 +239,8 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<import
|
|
|
239
239
|
autofocus: boolean;
|
|
240
240
|
loading: boolean;
|
|
241
241
|
dismissible: boolean;
|
|
242
|
-
overlay: boolean;
|
|
243
242
|
colorMode: boolean;
|
|
243
|
+
overlay: boolean;
|
|
244
244
|
fullscreen: boolean;
|
|
245
245
|
modal: boolean;
|
|
246
246
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>, __VLS_Slots>;
|
|
@@ -239,8 +239,8 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<import
|
|
|
239
239
|
autofocus: boolean;
|
|
240
240
|
loading: boolean;
|
|
241
241
|
dismissible: boolean;
|
|
242
|
-
overlay: boolean;
|
|
243
242
|
colorMode: boolean;
|
|
243
|
+
overlay: boolean;
|
|
244
244
|
fullscreen: boolean;
|
|
245
245
|
modal: boolean;
|
|
246
246
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>, __VLS_Slots>;
|
|
@@ -23,7 +23,7 @@ export function useDocTree() {
|
|
|
23
23
|
};
|
|
24
24
|
const slugMap = computed(() => buildSlugMap(entries.value));
|
|
25
25
|
const navigationItems = computed(
|
|
26
|
-
() => topLevelDocs.value.map((e) => {
|
|
26
|
+
() => topLevelDocs.value.filter((e) => e.meta?.hidden !== true).map((e) => {
|
|
27
27
|
const slug = slugMap.value.idToSlug[e.id];
|
|
28
28
|
const path = slug ?? e.id;
|
|
29
29
|
return {
|
|
@@ -15,7 +15,7 @@ function extractFirstImage(html) {
|
|
|
15
15
|
return match?.[1] ?? "";
|
|
16
16
|
}
|
|
17
17
|
export default defineEventHandler(async (event) => {
|
|
18
|
-
const slugParam = getRouterParam(event, "slug");
|
|
18
|
+
const slugParam = getRouterParam(event, "slug") ?? event.context.params?._;
|
|
19
19
|
if (!slugParam) {
|
|
20
20
|
throw createError({ statusCode: 400, message: "slug is required" });
|
|
21
21
|
}
|
|
@@ -14,6 +14,7 @@ import type { DocCacheAPI, NitroStorage } from '../../../runtime/types.js';
|
|
|
14
14
|
* Must be called before observeDoc().
|
|
15
15
|
*/
|
|
16
16
|
export declare function initDocCache(storage: NitroStorage, extraExtensions?: AnyExtension[]): void;
|
|
17
|
+
export declare function renderDocToHTML(ydoc: Y.Doc): Promise<string | null>;
|
|
17
18
|
export declare function getCachedHTML(docId: string): Promise<string | null>;
|
|
18
19
|
export declare function getCachedJSON(docId: string): Promise<Record<string, unknown> | null>;
|
|
19
20
|
export declare function invalidateDoc(docId: string, ydoc?: Y.Doc): Promise<void>;
|
|
@@ -18,16 +18,21 @@ async function getServerDoc() {
|
|
|
18
18
|
_serverDoc = new Window().document;
|
|
19
19
|
return _serverDoc;
|
|
20
20
|
}
|
|
21
|
-
async function renderDocToHTML(ydoc) {
|
|
21
|
+
export async function renderDocToHTML(ydoc) {
|
|
22
22
|
try {
|
|
23
|
-
const [{ getSchema }, { yDocToProsemirrorJSON }, { default: StarterKit }, { Node, DOMSerializer }] = await Promise.all([
|
|
23
|
+
const [{ getSchema }, { yDocToProsemirrorJSON }, { default: StarterKit }, { Node, DOMSerializer }, { coreServerSchemaStubs, pruneUnknownNodes }] = await Promise.all([
|
|
24
24
|
import("@tiptap/core"),
|
|
25
25
|
import("@tiptap/y-tiptap"),
|
|
26
26
|
import("@tiptap/starter-kit"),
|
|
27
|
-
import("prosemirror-model")
|
|
27
|
+
import("prosemirror-model"),
|
|
28
|
+
import("./serverSchemaStubs.js")
|
|
28
29
|
]);
|
|
29
|
-
const schema = getSchema([
|
|
30
|
-
|
|
30
|
+
const schema = getSchema([
|
|
31
|
+
StarterKit,
|
|
32
|
+
...coreServerSchemaStubs(_extensions),
|
|
33
|
+
..._extensions
|
|
34
|
+
]);
|
|
35
|
+
const json = pruneUnknownNodes(yDocToProsemirrorJSON(ydoc, "default"), schema);
|
|
31
36
|
const node = Node.fromJSON(schema, json);
|
|
32
37
|
const serverDoc = await getServerDoc();
|
|
33
38
|
const container = serverDoc.createElement("div");
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AnyExtension } from '@tiptap/core';
|
|
2
|
+
import type { Schema } from 'prosemirror-model';
|
|
3
|
+
/**
|
|
4
|
+
* Stubs for the doc-cache schema. Any stub whose node name is already
|
|
5
|
+
* provided by the app's `serverExtensions()` is skipped — apps with richer
|
|
6
|
+
* server definitions win.
|
|
7
|
+
*/
|
|
8
|
+
export declare function coreServerSchemaStubs(appExtensions?: AnyExtension[]): AnyExtension[];
|
|
9
|
+
interface PmJsonNode {
|
|
10
|
+
type?: string;
|
|
11
|
+
content?: PmJsonNode[];
|
|
12
|
+
marks?: Array<{
|
|
13
|
+
type?: string;
|
|
14
|
+
}>;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Drop nodes whose type the schema doesn't know (and unknown marks), keeping
|
|
19
|
+
* everything else intact. Returns a structurally-cloned JSON tree that is
|
|
20
|
+
* safe to feed into `Node.fromJSON`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function pruneUnknownNodes<T extends PmJsonNode>(json: T, schema: Schema): T;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Node } from "@tiptap/core";
|
|
2
|
+
const DocumentHeaderStub = Node.create({
|
|
3
|
+
name: "documentHeader",
|
|
4
|
+
group: "block",
|
|
5
|
+
content: "inline*",
|
|
6
|
+
renderHTML: () => ["h1", 0]
|
|
7
|
+
});
|
|
8
|
+
const DocumentMetaStub = Node.create({
|
|
9
|
+
name: "documentMeta",
|
|
10
|
+
group: "block",
|
|
11
|
+
atom: true,
|
|
12
|
+
renderHTML: () => ["div", { "data-document-meta": "", "style": "display:none" }]
|
|
13
|
+
});
|
|
14
|
+
const CalloutStub = Node.create({
|
|
15
|
+
name: "callout",
|
|
16
|
+
group: "block",
|
|
17
|
+
content: "block+",
|
|
18
|
+
renderHTML: () => ["div", { class: "callout" }, 0]
|
|
19
|
+
});
|
|
20
|
+
const DividerStub = Node.create({
|
|
21
|
+
name: "divider",
|
|
22
|
+
group: "block",
|
|
23
|
+
atom: true,
|
|
24
|
+
renderHTML: () => ["hr"]
|
|
25
|
+
});
|
|
26
|
+
const QuoteStub = Node.create({
|
|
27
|
+
name: "quote",
|
|
28
|
+
group: "block",
|
|
29
|
+
content: "block+",
|
|
30
|
+
renderHTML: () => ["blockquote", 0]
|
|
31
|
+
});
|
|
32
|
+
export function coreServerSchemaStubs(appExtensions = []) {
|
|
33
|
+
const taken = new Set(appExtensions.map((e) => e.name));
|
|
34
|
+
return [DocumentHeaderStub, DocumentMetaStub, CalloutStub, DividerStub, QuoteStub].filter((s) => !taken.has(s.name));
|
|
35
|
+
}
|
|
36
|
+
export function pruneUnknownNodes(json, schema) {
|
|
37
|
+
const knownNode = (t) => !!t && !!schema.nodes[t];
|
|
38
|
+
const knownMark = (t) => !!t && !!schema.marks[t];
|
|
39
|
+
const walk = (node) => {
|
|
40
|
+
const out = { ...node };
|
|
41
|
+
if (Array.isArray(node.marks)) {
|
|
42
|
+
out.marks = node.marks.filter((m) => knownMark(m?.type));
|
|
43
|
+
}
|
|
44
|
+
if (Array.isArray(node.content)) {
|
|
45
|
+
out.content = node.content.filter((child) => child?.type === "text" || knownNode(child?.type)).map(walk);
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
};
|
|
49
|
+
return walk(json);
|
|
50
|
+
}
|