AcadeDoc/packages/editor-ext/src/lib/database-view.ts
Corentin b802f1d647 feat(editor-ext): share wikilink and database-view node schemas
Add WikilinkNode and DatabaseView schema-only nodes to @docmost/editor-ext
and register them in the Hocuspocus server tiptapExtensions list.

Without the shared schema, jsonToNode on the server hit a RangeError for
those node types and stripUnknownNodes dropped them on every collab save,
so wikilinks disappeared on page reload and database-view embeds lost
their config and rendered as empty placeholders.
2026-05-11 12:28:12 +00:00

88 lines
2.2 KiB
TypeScript

import { Node, mergeAttributes } from "@tiptap/core";
export interface DatabaseViewAttrs {
tableId: string;
viewId: string;
viewType: string;
bridgeUrl?: string | null;
}
declare module "@tiptap/core" {
interface Commands<ReturnType> {
databaseView: {
insertDatabaseView: (attrs: DatabaseViewAttrs) => ReturnType;
};
}
}
/**
* Shared DatabaseView node (schema only, no NodeView).
*
* Registered on the Hocuspocus server so embedded Baserow views survive
* collab saves. The client extends this node to attach the React renderer.
*/
export const DatabaseView = Node.create({
name: "database-view",
group: "block",
atom: true,
selectable: true,
draggable: true,
addAttributes() {
return {
tableId: {
default: "",
parseHTML: (el: HTMLElement) => el.getAttribute("data-table-id") ?? "",
renderHTML: (attrs) => ({ "data-table-id": attrs.tableId }),
},
viewId: {
default: "",
parseHTML: (el: HTMLElement) => el.getAttribute("data-view-id") ?? "",
renderHTML: (attrs) => ({ "data-view-id": attrs.viewId }),
},
viewType: {
default: "grid",
parseHTML: (el: HTMLElement) =>
el.getAttribute("data-view-type") ?? "grid",
renderHTML: (attrs) => ({ "data-view-type": attrs.viewType }),
},
bridgeUrl: {
default: null,
parseHTML: (el: HTMLElement) =>
el.getAttribute("data-bridge-url") ?? null,
renderHTML: (attrs) =>
attrs.bridgeUrl ? { "data-bridge-url": attrs.bridgeUrl } : {},
},
};
},
parseHTML() {
return [{ tag: "div[data-node-type=database-view]" }];
},
renderHTML({ HTMLAttributes }) {
return [
"div",
mergeAttributes(HTMLAttributes, { "data-node-type": "database-view" }),
];
},
addCommands() {
return {
insertDatabaseView:
(attrs: DatabaseViewAttrs) =>
({ commands }) =>
commands.insertContent({
type: this.name,
attrs: {
tableId: attrs.tableId,
viewId: attrs.viewId,
viewType: attrs.viewType,
bridgeUrl: attrs.bridgeUrl ?? null,
},
}),
};
},
});
export default DatabaseView;