mirror of
https://github.com/colanode/colanode.git
synced 2025-12-29 00:25:03 +01:00
Prevent duplicate ids in editor
This commit is contained in:
@@ -81,7 +81,7 @@ const createWindow = async () => {
|
||||
if (MAIN_WINDOW_VITE_DEV_SERVER_URL) {
|
||||
mainWindow.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL);
|
||||
// Open the DevTools.
|
||||
mainWindow.webContents.openDevTools();
|
||||
// mainWindow.webContents.openDevTools();
|
||||
} else {
|
||||
mainWindow.loadFile(
|
||||
path.join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { EditorNodeTypes,generateId, getIdTypeFromNode } from '@colanode/core';
|
||||
import { EditorNodeTypes, generateId, IdType } from '@colanode/core';
|
||||
import { Extension } from '@tiptap/react';
|
||||
import { Plugin, PluginKey } from 'prosemirror-state';
|
||||
|
||||
@@ -50,16 +50,31 @@ export const IdExtension = Extension.create({
|
||||
key: new PluginKey('id'),
|
||||
appendTransaction(_, __, state) {
|
||||
const { tr } = state;
|
||||
const ids = new Set<string>();
|
||||
state.doc.descendants((node, pos) => {
|
||||
if (node.isText) {
|
||||
return; // Text nodes don't need IDs
|
||||
}
|
||||
|
||||
if (!node.attrs.id || typeof node.attrs.id !== 'string') {
|
||||
const id = generateId(IdType.Block);
|
||||
ids.add(id);
|
||||
tr.setNodeMarkup(pos, null, {
|
||||
...node.attrs,
|
||||
id: generateId(getIdTypeFromNode(node.type.name)),
|
||||
id,
|
||||
});
|
||||
} else {
|
||||
let id = node.attrs.id;
|
||||
if (ids.has(id)) {
|
||||
id = generateId(IdType.Block);
|
||||
ids.add(id);
|
||||
tr.setNodeMarkup(pos, null, {
|
||||
...node.attrs,
|
||||
id,
|
||||
});
|
||||
} else {
|
||||
ids.add(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
return tr;
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
EditorNodeTypes,
|
||||
generateId,
|
||||
generateNodeIndex,
|
||||
getIdTypeFromNode,
|
||||
IdType,
|
||||
} from '@colanode/core';
|
||||
import { JSONContent } from '@tiptap/core';
|
||||
|
||||
@@ -208,7 +208,7 @@ const getIdFromContent = (content: JSONContent): string => {
|
||||
throw new Error('Invalid content type');
|
||||
}
|
||||
|
||||
return content.attrs?.id ?? generateId(getIdTypeFromNode(content.type));
|
||||
return content.attrs?.id ?? generateId(IdType.Block);
|
||||
};
|
||||
|
||||
export const editorHasContent = (block?: JSONContent) => {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { monotonicFactory } from 'ulid';
|
||||
|
||||
import { NodeTypes } from './constants';
|
||||
|
||||
const ulid = monotonicFactory();
|
||||
|
||||
export enum IdType {
|
||||
@@ -17,18 +15,6 @@ export enum IdType {
|
||||
Node = 'nd',
|
||||
Message = 'ms',
|
||||
Subscriber = 'sb',
|
||||
Paragraph = 'pa',
|
||||
Heading1 = 'h1',
|
||||
Heading2 = 'h2',
|
||||
Heading3 = 'h3',
|
||||
Blockquote = 'bq',
|
||||
CodeBlock = 'cb',
|
||||
ListItem = 'li',
|
||||
OrderedList = 'ol',
|
||||
BulletList = 'bl',
|
||||
TaskList = 'tl',
|
||||
TaskItem = 'ti',
|
||||
HorizontalRule = 'hr',
|
||||
Database = 'db',
|
||||
DatabaseReplica = 'dr',
|
||||
Record = 'rc',
|
||||
@@ -49,6 +35,7 @@ export enum IdType {
|
||||
Transaction = 'tx',
|
||||
Event = 'ev',
|
||||
Host = 'ht',
|
||||
Block = 'bl',
|
||||
}
|
||||
|
||||
export const generateId = (type: IdType): string => {
|
||||
@@ -62,28 +49,3 @@ export const isIdOfType = (id: string, type: IdType): boolean => {
|
||||
export const getIdType = (id: string): IdType => {
|
||||
return id.substring(id.length - 2) as IdType;
|
||||
};
|
||||
|
||||
export const getIdTypeFromNode = (nodeType: string): IdType => {
|
||||
switch (nodeType) {
|
||||
case NodeTypes.User:
|
||||
return IdType.User;
|
||||
case NodeTypes.Space:
|
||||
return IdType.Space;
|
||||
case NodeTypes.Page:
|
||||
return IdType.Page;
|
||||
case NodeTypes.Channel:
|
||||
return IdType.Channel;
|
||||
case NodeTypes.Message:
|
||||
return IdType.Message;
|
||||
case NodeTypes.Database:
|
||||
return IdType.Database;
|
||||
case NodeTypes.DatabaseReplica:
|
||||
return IdType.DatabaseReplica;
|
||||
case NodeTypes.Record:
|
||||
return IdType.Record;
|
||||
case NodeTypes.Folder:
|
||||
return IdType.Folder;
|
||||
default:
|
||||
return IdType.Node;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user