mirror of
https://github.com/docmost/docmost.git
synced 2026-07-27 18:54:47 +10:00
Merge branch 'main' into tiptap3-migration
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
export { UniqueID } from "./unique-id";
|
||||
export * from "./unique-id.util";
|
||||
@@ -0,0 +1,11 @@
|
||||
import { generateNodeId } from "../utils";
|
||||
import { UniqueID as TiptapUniqueID } from "@tiptap/extension-unique-id";
|
||||
|
||||
export const UniqueID = TiptapUniqueID.extend({
|
||||
addOptions() {
|
||||
return {
|
||||
...this.parent?.(),
|
||||
generateID: () => generateNodeId(),
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
import type { Extensions, JSONContent } from "@tiptap/core";
|
||||
import { findChildren, getSchema } from "@tiptap/core";
|
||||
import { Node } from "@tiptap/pm/model";
|
||||
import { EditorState } from "@tiptap/pm/state";
|
||||
import type { UniqueID } from "./unique-id";
|
||||
|
||||
/**
|
||||
* Creates a new document with unique IDs added to the nodes. Does the same
|
||||
* thing as the UniqueID extension, but without the need to create an `Editor`
|
||||
* instance. This lets you add unique IDs to the document in the server.
|
||||
*
|
||||
* When you call it, include the `UniqueID` extension in the `extensions` array.
|
||||
* The configuration from the `UniqueID` extension will be picked up
|
||||
* automatically, including its configuration options like `types` and
|
||||
* `attributeName`.
|
||||
*
|
||||
* @see `UniqueID` extension for more information.
|
||||
*
|
||||
* @throws {Error} If the `UniqueID` extension is not found in the extensions array.
|
||||
*
|
||||
* @example
|
||||
* const doc = {
|
||||
* type: 'doc',
|
||||
* content: [
|
||||
* { type: 'paragraph', content: [{ type: 'text', text: 'Hello, world!' }] }
|
||||
* ]
|
||||
* }
|
||||
* const newDoc = addUniqueIds(doc, [StarterKit, UniqueID.configure({ types: ['paragraph', 'heading'] })])
|
||||
* console.log(newDoc)
|
||||
* // Result:
|
||||
* // {
|
||||
* // type: 'doc',
|
||||
* // content: [
|
||||
* // { type: 'paragraph', content: [{ type: 'text', text: 'Hello, world!' }], id: '123' }
|
||||
* // ]
|
||||
* // }
|
||||
*
|
||||
* @param doc - A Tiptap JSON document to add unique IDs to.
|
||||
* @param extensions - The extensions to use. Must include the `UniqueID` extension.
|
||||
* @returns The updated Tiptap JSON document, with the unique IDs added to the nodes.
|
||||
*/
|
||||
export function addUniqueIdsToDoc(
|
||||
doc: JSONContent,
|
||||
extensions: Extensions,
|
||||
): JSONContent {
|
||||
// Find the UniqueID extension in the extensions array. If it's not found, throw an error.
|
||||
const uniqueIDExtension = extensions.find(
|
||||
(ext) => ext.name === "uniqueID",
|
||||
) as typeof UniqueID | undefined;
|
||||
if (!uniqueIDExtension) {
|
||||
throw new Error("UniqueID extension not found in the extensions array");
|
||||
}
|
||||
const { types, attributeName, generateID } = uniqueIDExtension.options;
|
||||
|
||||
// Convert the JSON content to a ProseMirror node
|
||||
const schema = getSchema([
|
||||
...extensions.filter((ext) => ext.name !== "uniqueID"),
|
||||
uniqueIDExtension,
|
||||
]);
|
||||
const contentNode = Node.fromJSON(schema, doc);
|
||||
|
||||
// Find nodes that don't have a unique ID
|
||||
const nodesWithoutId = findChildren(contentNode, (node) => {
|
||||
return !node.attrs[attributeName] && types.includes(node.type.name);
|
||||
});
|
||||
|
||||
// Edit the document to add unique IDs to the nodes that don't have a unique ID
|
||||
let tr = EditorState.create({
|
||||
doc: contentNode,
|
||||
}).tr;
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const { node, pos } of nodesWithoutId) {
|
||||
tr = tr.setNodeAttribute(pos, attributeName, generateID({ node, pos }));
|
||||
}
|
||||
|
||||
// Return the updated document
|
||||
return tr.doc.toJSON();
|
||||
}
|
||||
Reference in New Issue
Block a user