From 6424db9cce0a42131a6cec44d219ef1bf1813f3d Mon Sep 17 00:00:00 2001 From: Felix Feng Date: Tue, 4 Mar 2025 14:12:53 +0800 Subject: [PATCH 1/4] fix --- .../editor/plugins/skip-mark-plugin.ts | 4 +- .../basic-marks/src/lib/BaseSkipMarkPlugin.ts | 54 +++++++++++-------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/apps/www/src/registry/default/components/editor/plugins/skip-mark-plugin.ts b/apps/www/src/registry/default/components/editor/plugins/skip-mark-plugin.ts index 8502768afa..249a7d4fb0 100644 --- a/apps/www/src/registry/default/components/editor/plugins/skip-mark-plugin.ts +++ b/apps/www/src/registry/default/components/editor/plugins/skip-mark-plugin.ts @@ -5,8 +5,6 @@ import { SuggestionPlugin } from '@udecode/plate-suggestion/react'; export const skipMarkPlugin = SkipMarkPlugin.configure({ options: { - query: { - allow: [SuggestionPlugin.key, CodePlugin.key, CommentsPlugin.key], - }, + allow: [SuggestionPlugin.key, CodePlugin.key, CommentsPlugin.key], }, }); diff --git a/packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts b/packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts index 3fff8c91d8..77212a910c 100644 --- a/packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts +++ b/packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts @@ -1,53 +1,65 @@ import { type PluginConfig, - type QueryNodeOptions, type Text, createTSlatePlugin, - queryNode, RangeApi, + TextApi, } from '@udecode/plate'; export type SkipMarkConfig = PluginConfig< 'skip-mark', { - query?: QueryNodeOptions; + allow: string[]; } >; export const BaseSkipMarkPlugin = createTSlatePlugin({ key: 'skip-mark', - options: {}, + options: { + allow: [], + }, }).overrideEditor(({ editor, getOption, tf: { insertText } }) => ({ transforms: { insertText(text, options) { if (RangeApi.isExpanded(editor.selection)) return insertText(text, options); + const allow = getOption('allow'); + const textNode = editor.api.node({ mode: 'lowest', + match: (node) => { + if (TextApi.isText(node)) { + return allow.some((key) => !!node[key]); + } + }, }); - const query = getOption('query'); + if (!textNode) return insertText(text, options); - if ( - textNode && - !queryNode(textNode, query) && - editor.api.isEnd(editor.selection?.focus, textNode[1]) - ) { - editor.tf.insertNode({ text }); - const _nextPoint = editor.api.start(textNode[1], { next: true }); + const nextPoint = editor.api.start(textNode[1], { next: true }); - if (!_nextPoint) return; + const nextNode = editor.api.node({ + at: nextPoint, + mode: 'lowest', + match: (node) => { + if (TextApi.isText(node)) { + return allow.some((key) => !!node[key]); + } + }, + }); - const nextPoint = { - offset: _nextPoint.offset + 1, - path: _nextPoint.path, - }; + const isBetweenSameMarks = + nextNode && + allow.findIndex((key) => !!textNode[0][key]) === + allow.findIndex((key) => !!nextNode[0][key]); - editor.tf.setSelection({ - anchor: nextPoint, - focus: nextPoint, - }); + if ( + !isBetweenSameMarks && + editor.api.isEnd(editor.selection?.focus, textNode[1]) + ) { + editor.tf.removeMarks(allow); + insertText(text, options); return; } From 4b876da8be012fdd815eb982ac0d71b1eac7abf5 Mon Sep 17 00:00:00 2001 From: Felix Feng Date: Tue, 4 Mar 2025 15:24:14 +0800 Subject: [PATCH 2/4] test --- .../src/lib/BaseSkipMarkPlugin.spec.tsx | 166 ++++++++++++++++++ .../basic-marks/src/lib/BaseSkipMarkPlugin.ts | 20 ++- 2 files changed, 177 insertions(+), 9 deletions(-) create mode 100644 packages/basic-marks/src/lib/BaseSkipMarkPlugin.spec.tsx diff --git a/packages/basic-marks/src/lib/BaseSkipMarkPlugin.spec.tsx b/packages/basic-marks/src/lib/BaseSkipMarkPlugin.spec.tsx new file mode 100644 index 0000000000..bf3bd5709f --- /dev/null +++ b/packages/basic-marks/src/lib/BaseSkipMarkPlugin.spec.tsx @@ -0,0 +1,166 @@ +/** @jsx jsxt */ + +import type { SlateEditor } from '@udecode/plate'; + +import { BaseParagraphPlugin, createSlateEditor } from '@udecode/plate'; +import { jsxt } from '@udecode/plate-test-utils'; + +import { BaseBoldPlugin } from './BaseBoldPlugin'; +import { BaseCodePlugin } from './BaseCodePlugin'; +import { BaseItalicPlugin } from './BaseItalicPlugin'; +import { BaseSkipMarkPlugin } from './BaseSkipMarkPlugin'; + +jsxt; + +const skipMarkPlugin = BaseSkipMarkPlugin.configure({ + options: { + allow: [BaseCodePlugin.key], + }, +}); +const plugins = [ + BaseParagraphPlugin, + BaseBoldPlugin, + BaseCodePlugin, + BaseItalicPlugin, + skipMarkPlugin, +]; + +describe('BaseSkipMarkPlugin', () => { + describe('insertText', () => { + describe('when cursor is not in a mark', () => { + it('should insert text normally', () => { + const input = ( + + + test + + + + ) as any as SlateEditor; + + const output = ( + + + testinserted + + + + ) as any as SlateEditor; + + const editor = createSlateEditor({ + plugins, + selection: input.selection, + value: input.children, + }); + + editor.tf.insertText('inserted'); + + expect(editor.children).toEqual(output.children); + }); + }); + + describe('when cursor is at the end of a mark', () => { + it('should remove marks when inserting text', () => { + const input = ( + + + test + + + + ) as any as SlateEditor; + + const output = ( + + + test + inserted + + + + ) as any as SlateEditor; + + const editor = createSlateEditor({ + plugins, + selection: input.selection, + value: input.children, + }); + + editor.tf.insertText('inserted'); + + expect(editor.children).toEqual(output.children); + }); + + it('should not remove marks when between same marks', () => { + const input = ( + + + test + + + more + + + + ) as any as SlateEditor; + + const output = ( + + + testinserted + + + more + + + + ) as any as SlateEditor; + + const editor = createSlateEditor({ + plugins, + selection: input.selection, + value: input.children, + }); + + editor.tf.insertText('inserted'); + + expect(editor.children).toEqual(output.children); + }); + }); + + describe('when different mark types are adjacent', () => { + it('should remove marks when inserting text', () => { + const input = ( + + + test + + more + + + ) as any as SlateEditor; + + const output = ( + + + test + inserted + + more + + + ) as any as SlateEditor; + + const editor = createSlateEditor({ + plugins, + selection: input.selection, + value: input.children, + }); + + editor.tf.insertText('inserted'); + + expect(editor.children).toEqual(output.children); + }); + }); + }); +}); diff --git a/packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts b/packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts index 77212a910c..4b4e024f9b 100644 --- a/packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts +++ b/packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts @@ -39,15 +39,17 @@ export const BaseSkipMarkPlugin = createTSlatePlugin({ const nextPoint = editor.api.start(textNode[1], { next: true }); - const nextNode = editor.api.node({ - at: nextPoint, - mode: 'lowest', - match: (node) => { - if (TextApi.isText(node)) { - return allow.some((key) => !!node[key]); - } - }, - }); + const nextNode = + nextPoint && + editor.api.node({ + at: nextPoint, + mode: 'lowest', + match: (node) => { + if (TextApi.isText(node)) { + return allow.some((key) => !!node[key]); + } + }, + }); const isBetweenSameMarks = nextNode && From 46e618853d92f00472b3364202b0582e12b7f005 Mon Sep 17 00:00:00 2001 From: Felix Feng Date: Tue, 4 Mar 2025 15:27:13 +0800 Subject: [PATCH 3/4] fix --- .../default/components/editor/plugins/skip-mark-plugin.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/www/src/registry/default/components/editor/plugins/skip-mark-plugin.ts b/apps/www/src/registry/default/components/editor/plugins/skip-mark-plugin.ts index 249a7d4fb0..8502768afa 100644 --- a/apps/www/src/registry/default/components/editor/plugins/skip-mark-plugin.ts +++ b/apps/www/src/registry/default/components/editor/plugins/skip-mark-plugin.ts @@ -5,6 +5,8 @@ import { SuggestionPlugin } from '@udecode/plate-suggestion/react'; export const skipMarkPlugin = SkipMarkPlugin.configure({ options: { - allow: [SuggestionPlugin.key, CodePlugin.key, CommentsPlugin.key], + query: { + allow: [SuggestionPlugin.key, CodePlugin.key, CommentsPlugin.key], + }, }, }); From 575d9496887a97ae698aa695a43dfbead979d0ea Mon Sep 17 00:00:00 2001 From: Felix Feng Date: Tue, 4 Mar 2025 15:27:44 +0800 Subject: [PATCH 4/4] docs --- .changeset/gold-gorillas-report.md | 5 +++++ .../basic-marks/src/lib/BaseSkipMarkPlugin.spec.tsx | 4 +++- packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts | 10 +++++++--- 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 .changeset/gold-gorillas-report.md diff --git a/.changeset/gold-gorillas-report.md b/.changeset/gold-gorillas-report.md new file mode 100644 index 0000000000..c360acb8fc --- /dev/null +++ b/.changeset/gold-gorillas-report.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-basic-marks': patch +--- + +Fix mention plugin conflict with skip mark plugin diff --git a/packages/basic-marks/src/lib/BaseSkipMarkPlugin.spec.tsx b/packages/basic-marks/src/lib/BaseSkipMarkPlugin.spec.tsx index bf3bd5709f..4851438b31 100644 --- a/packages/basic-marks/src/lib/BaseSkipMarkPlugin.spec.tsx +++ b/packages/basic-marks/src/lib/BaseSkipMarkPlugin.spec.tsx @@ -14,7 +14,9 @@ jsxt; const skipMarkPlugin = BaseSkipMarkPlugin.configure({ options: { - allow: [BaseCodePlugin.key], + query: { + allow: [BaseCodePlugin.key], + }, }, }); const plugins = [ diff --git a/packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts b/packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts index 4b4e024f9b..f08075eaa9 100644 --- a/packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts +++ b/packages/basic-marks/src/lib/BaseSkipMarkPlugin.ts @@ -9,14 +9,18 @@ import { export type SkipMarkConfig = PluginConfig< 'skip-mark', { - allow: string[]; + query: { + allow: string[]; + }; } >; export const BaseSkipMarkPlugin = createTSlatePlugin({ key: 'skip-mark', options: { - allow: [], + query: { + allow: [], + }, }, }).overrideEditor(({ editor, getOption, tf: { insertText } }) => ({ transforms: { @@ -24,7 +28,7 @@ export const BaseSkipMarkPlugin = createTSlatePlugin({ if (RangeApi.isExpanded(editor.selection)) return insertText(text, options); - const allow = getOption('allow'); + const allow = getOption('query').allow; const textNode = editor.api.node({ mode: 'lowest',