From 9ff7e2400e12ce70779d4e090af21f829be40375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 13:00:30 +0200 Subject: [PATCH 01/18] add insertContentAt command --- packages/core/src/commands/insertContent.ts | 25 +----------- packages/core/src/commands/insertContentAt.ts | 39 +++++++++++++++++++ packages/core/src/extensions/commands.ts | 3 ++ 3 files changed, 44 insertions(+), 23 deletions(-) create mode 100644 packages/core/src/commands/insertContentAt.ts diff --git a/packages/core/src/commands/insertContent.ts b/packages/core/src/commands/insertContent.ts index 47ad19be..ac28af3c 100644 --- a/packages/core/src/commands/insertContent.ts +++ b/packages/core/src/commands/insertContent.ts @@ -1,5 +1,3 @@ -import createNodeFromContent from '../helpers/createNodeFromContent' -import selectionToInsertionEnd from '../helpers/selectionToInsertionEnd' import { Command, RawCommands, Content } from '../types' declare module '@tiptap/core' { @@ -13,25 +11,6 @@ declare module '@tiptap/core' { } } -export const insertContent: RawCommands['insertContent'] = value => ({ tr, dispatch, editor }) => { - if (dispatch) { - const content = createNodeFromContent(value, editor.schema) - - if (typeof content === 'string') { - tr.insertText(content) - tr.scrollIntoView() - - return true - } - - if (!tr.selection.empty) { - tr.deleteSelection() - } - - tr.insert(tr.selection.anchor, content) - selectionToInsertionEnd(tr, tr.steps.length - 1, -1) - tr.scrollIntoView() - } - - return true +export const insertContent: RawCommands['insertContent'] = value => ({ tr, commands }) => { + return commands.insertContentAt({ from: tr.selection.from, to: tr.selection.to }, value) } diff --git a/packages/core/src/commands/insertContentAt.ts b/packages/core/src/commands/insertContentAt.ts new file mode 100644 index 00000000..14b2ab26 --- /dev/null +++ b/packages/core/src/commands/insertContentAt.ts @@ -0,0 +1,39 @@ +import createNodeFromContent from '../helpers/createNodeFromContent' +import selectionToInsertionEnd from '../helpers/selectionToInsertionEnd' +import { + Command, RawCommands, Content, Range, +} from '../types' + +declare module '@tiptap/core' { + interface Commands { + insertContentAt: { + /** + * Insert a node or string of HTML at the current position. + */ + insertContentAt: (range: Range, value: Content) => Command, + } + } +} + +export const insertContentAt: RawCommands['insertContentAt'] = (range, value) => ({ tr, dispatch, editor }) => { + if (dispatch) { + const content = createNodeFromContent(value, editor.schema) + + if (typeof content === 'string') { + tr.insertText(content) + tr.scrollIntoView() + + return true + } + + if (!tr.selection.empty) { + tr.deleteRange(range.from, range.to) + } + + tr.insert(range.from, content) + selectionToInsertionEnd(tr, tr.steps.length - 1, -1) + tr.scrollIntoView() + } + + return true +} diff --git a/packages/core/src/extensions/commands.ts b/packages/core/src/extensions/commands.ts index be1c57db..ea8dfb29 100644 --- a/packages/core/src/extensions/commands.ts +++ b/packages/core/src/extensions/commands.ts @@ -12,6 +12,7 @@ import * as extendMarkRange from '../commands/extendMarkRange' import * as first from '../commands/first' import * as focus from '../commands/focus' import * as insertContent from '../commands/insertContent' +import * as insertContentAt from '../commands/insertContentAt' import * as insertHTML from '../commands/insertHTML' import * as insertNode from '../commands/insertNode' import * as insertText from '../commands/insertText' @@ -64,6 +65,7 @@ export { extendMarkRange } export { first } export { focus } export { insertContent } +export { insertContentAt } export { insertHTML } export { insertNode } export { insertText } @@ -121,6 +123,7 @@ export const Commands = Extension.create({ ...first, ...focus, ...insertContent, + ...insertContentAt, ...insertHTML, ...insertNode, ...insertText, From ec838a11f25d912eac9ada96cfa2c8c1b1b2f499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 13:08:19 +0200 Subject: [PATCH 02/18] improve Content type --- packages/core/src/types.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index b0773729..5aa19959 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -60,7 +60,16 @@ export interface EditorOptions { onDestroy: () => void, } -export type Content = string | Record | null +export type HTMLContent = string + +export type JSONContent = { + type: string, + attrs?: Record, + content?: JSONContent[], + [key: string]: any, +} + +export type Content = HTMLContent | JSONContent | JSONContent[] | null export type CommandProps = { editor: Editor, From 63902d4bdbecc68aacfb0842fb5d5bc0043d92b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 13:49:32 +0200 Subject: [PATCH 03/18] remove replaceRange from mention node --- packages/core/src/commands/insertContentAt.ts | 4 ++-- packages/extension-mention/src/mention.ts | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/core/src/commands/insertContentAt.ts b/packages/core/src/commands/insertContentAt.ts index 14b2ab26..659761e6 100644 --- a/packages/core/src/commands/insertContentAt.ts +++ b/packages/core/src/commands/insertContentAt.ts @@ -26,8 +26,8 @@ export const insertContentAt: RawCommands['insertContentAt'] = (range, value) => return true } - if (!tr.selection.empty) { - tr.deleteRange(range.from, range.to) + if (range.from !== range.to) { + tr.delete(range.from, range.to) } tr.insert(range.from, content) diff --git a/packages/extension-mention/src/mention.ts b/packages/extension-mention/src/mention.ts index 3c2c013b..8e4ed9ca 100644 --- a/packages/extension-mention/src/mention.ts +++ b/packages/extension-mention/src/mention.ts @@ -17,12 +17,15 @@ export const Mention = Node.create({ editor .chain() .focus() - .replaceRange(range, 'mention', props) + .insertContentAt(range, { + type: 'mention', + attrs: props, + }) .insertContent(' ') .run() }, allow: ({ editor, range }) => { - return editor.can().replaceRange(range, 'mention') + return editor.can().insertContentAt(range, { type: 'mention' }) }, }, }, From b5c51723ea26a6d355ada878b9749a49a790852d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 14:13:58 +0200 Subject: [PATCH 04/18] remove insertText from insertContent --- packages/core/src/commands/insertContentAt.ts | 18 ++++++--------- .../core/src/helpers/createNodeFromContent.ts | 22 +++++++++---------- packages/core/src/types.ts | 1 + 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/packages/core/src/commands/insertContentAt.ts b/packages/core/src/commands/insertContentAt.ts index 659761e6..4f655c52 100644 --- a/packages/core/src/commands/insertContentAt.ts +++ b/packages/core/src/commands/insertContentAt.ts @@ -1,7 +1,10 @@ import createNodeFromContent from '../helpers/createNodeFromContent' import selectionToInsertionEnd from '../helpers/selectionToInsertionEnd' import { - Command, RawCommands, Content, Range, + Command, + RawCommands, + Content, + Range, } from '../types' declare module '@tiptap/core' { @@ -17,19 +20,12 @@ declare module '@tiptap/core' { export const insertContentAt: RawCommands['insertContentAt'] = (range, value) => ({ tr, dispatch, editor }) => { if (dispatch) { - const content = createNodeFromContent(value, editor.schema) - - if (typeof content === 'string') { - tr.insertText(content) - tr.scrollIntoView() - - return true - } - if (range.from !== range.to) { - tr.delete(range.from, range.to) + tr.deleteRange(range.from, range.to) } + const content = createNodeFromContent(value, editor.schema) + tr.insert(range.from, content) selectionToInsertionEnd(tr, tr.steps.length - 1, -1) tr.scrollIntoView() diff --git a/packages/core/src/helpers/createNodeFromContent.ts b/packages/core/src/helpers/createNodeFromContent.ts index 25be7ae6..a1f1d1e9 100644 --- a/packages/core/src/helpers/createNodeFromContent.ts +++ b/packages/core/src/helpers/createNodeFromContent.ts @@ -17,15 +17,19 @@ export default function createNodeFromContent( content: Content, schema: Schema, options?: CreateNodeFromContentOptions, -): string | ProseMirrorNode | Fragment { +): ProseMirrorNode | Fragment { options = { slice: true, parseOptions: {}, ...options, } - if (content && typeof content === 'object') { + if (typeof content === 'object' && content !== null) { try { + if (Array.isArray(content)) { + return Fragment.fromArray(content.map(item => schema.nodeFromJSON(item))) + } + return schema.nodeFromJSON(content) } catch (error) { console.warn( @@ -41,17 +45,11 @@ export default function createNodeFromContent( } if (typeof content === 'string') { - const isHTML = content.trim().startsWith('<') && content.trim().endsWith('>') + const parser = DOMParser.fromSchema(schema) - if (isHTML || !options.slice) { - const parser = DOMParser.fromSchema(schema) - - return options.slice - ? parser.parseSlice(elementFromString(content), options.parseOptions).content - : parser.parse(elementFromString(content), options.parseOptions) - } - - return content + return options.slice + ? parser.parseSlice(elementFromString(content), options.parseOptions).content + : parser.parse(elementFromString(content), options.parseOptions) } return createNodeFromContent('', schema, options) diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 5aa19959..e00b09b7 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -66,6 +66,7 @@ export type JSONContent = { type: string, attrs?: Record, content?: JSONContent[], + text?: string, [key: string]: any, } From 63b4e15b0cf203c05719df7ec6e1c77d802fc10c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 14:14:09 +0200 Subject: [PATCH 05/18] refactoring --- packages/extension-mention/src/mention.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/extension-mention/src/mention.ts b/packages/extension-mention/src/mention.ts index 8e4ed9ca..513fd835 100644 --- a/packages/extension-mention/src/mention.ts +++ b/packages/extension-mention/src/mention.ts @@ -17,11 +17,16 @@ export const Mention = Node.create({ editor .chain() .focus() - .insertContentAt(range, { - type: 'mention', - attrs: props, - }) - .insertContent(' ') + .insertContentAt(range, [ + { + type: 'mention', + attrs: props, + }, + { + type: 'text', + text: ' ', + }, + ]) .run() }, allow: ({ editor, range }) => { From e2756aab5f10df42cf953a765ac80a9bd6c3c7af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 14:19:24 +0200 Subject: [PATCH 06/18] docs: update content --- .../docPages/api/commands/insert-content.md | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/src/docPages/api/commands/insert-content.md b/docs/src/docPages/api/commands/insert-content.md index 73516d9b..cb1253af 100644 --- a/docs/src/docPages/api/commands/insert-content.md +++ b/docs/src/docPages/api/commands/insert-content.md @@ -29,5 +29,27 @@ editor.commands.insertContent({ }, ], }) + +// Multiple nodes at once +editor.commands.insertContent([ + { + type: 'paragraph', + content: [ + { + type: 'text', + text: 'First paragraph', + }, + ], + }, + { + type: 'paragraph', + content: [ + { + type: 'text', + text: 'Second paragraph', + }, + ], + }, +]) ``` From 12b6f0e4f7cb66cef7d7ac66fc5098f3ee42ae6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 14:50:27 +0200 Subject: [PATCH 07/18] use tr.replaceRangeWith instead of tr.insert for insertContent command --- packages/core/src/commands/insertContentAt.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/core/src/commands/insertContentAt.ts b/packages/core/src/commands/insertContentAt.ts index 4f655c52..ef8002fb 100644 --- a/packages/core/src/commands/insertContentAt.ts +++ b/packages/core/src/commands/insertContentAt.ts @@ -20,15 +20,11 @@ declare module '@tiptap/core' { export const insertContentAt: RawCommands['insertContentAt'] = (range, value) => ({ tr, dispatch, editor }) => { if (dispatch) { - if (range.from !== range.to) { - tr.deleteRange(range.from, range.to) - } - const content = createNodeFromContent(value, editor.schema) - tr.insert(range.from, content) - selectionToInsertionEnd(tr, tr.steps.length - 1, -1) - tr.scrollIntoView() + // @ts-ignore + tr.replaceRangeWith(range.from, range.to, content) + selectionToInsertionEnd(tr, tr.steps.length - 1, 1) } return true From fda4c780d3785a6771f64160cfc1889d477696bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 14:50:43 +0200 Subject: [PATCH 08/18] use insertContent in some extensions --- .../src/horizontal-rule.ts | 37 ++++++++++--------- packages/extension-image/src/image.ts | 14 +++---- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/packages/extension-horizontal-rule/src/horizontal-rule.ts b/packages/extension-horizontal-rule/src/horizontal-rule.ts index 680bc275..0e8b0e50 100644 --- a/packages/extension-horizontal-rule/src/horizontal-rule.ts +++ b/packages/extension-horizontal-rule/src/horizontal-rule.ts @@ -42,28 +42,31 @@ export const HorizontalRule = Node.create({ addCommands() { return { - setHorizontalRule: () => ({ tr, dispatch }) => { - if (dispatch) { - tr.replaceSelectionWith(this.type.create()) + setHorizontalRule: () => ({ chain }) => { + return chain() + .insertContent({ type: this.name }) + .command(({ tr, dispatch }) => { + if (dispatch) { + const { parent, pos } = tr.selection.$from + const posAfter = pos + 1 + const nodeAfter = tr.doc.nodeAt(posAfter) - const { parent, pos } = tr.selection.$from - const posAfter = pos + 1 - const nodeAfter = tr.doc.nodeAt(posAfter) + // end of document + if (!nodeAfter) { + const node = parent.type.contentMatch.defaultType?.create() - // end of document - if (!nodeAfter) { - const node = parent.type.contentMatch.defaultType?.create() + if (node) { + tr.insert(posAfter, node) + tr.setSelection(TextSelection.create(tr.doc, posAfter)) + } + } - if (node) { - tr.insert(posAfter, node) - tr.setSelection(TextSelection.create(tr.doc, posAfter)) + tr.scrollIntoView() } - } - tr.scrollIntoView() - } - - return true + return true + }) + .run() }, } }, diff --git a/packages/extension-image/src/image.ts b/packages/extension-image/src/image.ts index 7e45a6f5..987d893c 100644 --- a/packages/extension-image/src/image.ts +++ b/packages/extension-image/src/image.ts @@ -69,15 +69,11 @@ export const Image = Node.create({ addCommands() { return { - setImage: options => ({ tr, dispatch }) => { - const { selection } = tr - const node = this.type.create(options) - - if (dispatch) { - tr.replaceRangeWith(selection.from, selection.to, node) - } - - return true + setImage: options => ({ commands }) => { + return commands.insertContent({ + type: this.name, + attrs: options, + }) }, } }, From 5c5680d00e931f53f7e5218b43fc1b2e3b15f60b Mon Sep 17 00:00:00 2001 From: Chris O'Sullivan Date: Wed, 5 May 2021 09:44:07 -0500 Subject: [PATCH 09/18] Change how ref is handled in VueRenderer --- packages/vue-3/src/VueRenderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vue-3/src/VueRenderer.ts b/packages/vue-3/src/VueRenderer.ts index 738ae67e..3ad0b7cd 100644 --- a/packages/vue-3/src/VueRenderer.ts +++ b/packages/vue-3/src/VueRenderer.ts @@ -41,7 +41,7 @@ export class VueRenderer { } get ref(): any { - return this.editor.contentComponent?.ctx.$refs[this.id] + return this.editor.contentComponent?.refs[this.id] } updateProps(props: Record = {}): void { From d5dd568d862fee60c975ec7314615032f0558872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 18:21:36 +0200 Subject: [PATCH 10/18] fix: fix lint error --- packages/extension-horizontal-rule/src/horizontal-rule.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/extension-horizontal-rule/src/horizontal-rule.ts b/packages/extension-horizontal-rule/src/horizontal-rule.ts index 680bc275..d2a4b8e9 100644 --- a/packages/extension-horizontal-rule/src/horizontal-rule.ts +++ b/packages/extension-horizontal-rule/src/horizontal-rule.ts @@ -70,7 +70,7 @@ export const HorizontalRule = Node.create({ addInputRules() { return [ - nodeInputRule(/^(?:---|\—-|___\s|\*\*\*\s)$/, this.type), + nodeInputRule(/^(?:---|—-|___\s|\*\*\*\s)$/, this.type), ] }, }) From 9b32e15a8f1d0d33998f431b792e7f364de15083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 18:32:25 +0200 Subject: [PATCH 11/18] Publish - @tiptap/extension-horizontal-rule@2.0.0-beta.9 - @tiptap/starter-kit@2.0.0-beta.40 - @tiptap/vue-3@2.0.0-beta.28 --- packages/extension-horizontal-rule/CHANGELOG.md | 11 +++++++++++ packages/extension-horizontal-rule/package.json | 2 +- packages/starter-kit/CHANGELOG.md | 8 ++++++++ packages/starter-kit/package.json | 4 ++-- packages/vue-3/CHANGELOG.md | 8 ++++++++ packages/vue-3/package.json | 2 +- 6 files changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/extension-horizontal-rule/CHANGELOG.md b/packages/extension-horizontal-rule/CHANGELOG.md index 094eb2c4..94af9d4a 100644 --- a/packages/extension-horizontal-rule/CHANGELOG.md +++ b/packages/extension-horizontal-rule/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.0.0-beta.9](https://github.com/ueberdosis/tiptap/compare/@tiptap/extension-horizontal-rule@2.0.0-beta.8...@tiptap/extension-horizontal-rule@2.0.0-beta.9) (2021-05-05) + + +### Bug Fixes + +* fix lint error ([d5dd568](https://github.com/ueberdosis/tiptap/commit/d5dd568d862fee60c975ec7314615032f0558872)) + + + + + # [2.0.0-beta.8](https://github.com/ueberdosis/tiptap/compare/@tiptap/extension-horizontal-rule@2.0.0-beta.7...@tiptap/extension-horizontal-rule@2.0.0-beta.8) (2021-05-04) **Note:** Version bump only for package @tiptap/extension-horizontal-rule diff --git a/packages/extension-horizontal-rule/package.json b/packages/extension-horizontal-rule/package.json index 4956d0f1..4a99853f 100644 --- a/packages/extension-horizontal-rule/package.json +++ b/packages/extension-horizontal-rule/package.json @@ -1,7 +1,7 @@ { "name": "@tiptap/extension-horizontal-rule", "description": "horizontal rule extension for tiptap", - "version": "2.0.0-beta.8", + "version": "2.0.0-beta.9", "homepage": "https://tiptap.dev", "keywords": [ "tiptap", diff --git a/packages/starter-kit/CHANGELOG.md b/packages/starter-kit/CHANGELOG.md index 75a6fa3e..b887bc62 100644 --- a/packages/starter-kit/CHANGELOG.md +++ b/packages/starter-kit/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.0.0-beta.40](https://github.com/ueberdosis/tiptap/compare/@tiptap/starter-kit@2.0.0-beta.39...@tiptap/starter-kit@2.0.0-beta.40) (2021-05-05) + +**Note:** Version bump only for package @tiptap/starter-kit + + + + + # [2.0.0-beta.39](https://github.com/ueberdosis/tiptap/compare/@tiptap/starter-kit@2.0.0-beta.38...@tiptap/starter-kit@2.0.0-beta.39) (2021-05-05) **Note:** Version bump only for package @tiptap/starter-kit diff --git a/packages/starter-kit/package.json b/packages/starter-kit/package.json index b06fc492..ae9fabef 100644 --- a/packages/starter-kit/package.json +++ b/packages/starter-kit/package.json @@ -1,7 +1,7 @@ { "name": "@tiptap/starter-kit", "description": "starter kit for tiptap", - "version": "2.0.0-beta.39", + "version": "2.0.0-beta.40", "homepage": "https://tiptap.dev", "keywords": [ "tiptap", @@ -34,7 +34,7 @@ "@tiptap/extension-hard-break": "^2.0.0-beta.6", "@tiptap/extension-heading": "^2.0.0-beta.6", "@tiptap/extension-history": "^2.0.0-beta.5", - "@tiptap/extension-horizontal-rule": "^2.0.0-beta.8", + "@tiptap/extension-horizontal-rule": "^2.0.0-beta.9", "@tiptap/extension-italic": "^2.0.0-beta.6", "@tiptap/extension-list-item": "^2.0.0-beta.6", "@tiptap/extension-ordered-list": "^2.0.0-beta.6", diff --git a/packages/vue-3/CHANGELOG.md b/packages/vue-3/CHANGELOG.md index 7ad79297..64e525e4 100644 --- a/packages/vue-3/CHANGELOG.md +++ b/packages/vue-3/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.0.0-beta.28](https://github.com/ueberdosis/tiptap/compare/@tiptap/vue-3@2.0.0-beta.27...@tiptap/vue-3@2.0.0-beta.28) (2021-05-05) + +**Note:** Version bump only for package @tiptap/vue-3 + + + + + # [2.0.0-beta.27](https://github.com/ueberdosis/tiptap/compare/@tiptap/vue-3@2.0.0-beta.26...@tiptap/vue-3@2.0.0-beta.27) (2021-05-04) **Note:** Version bump only for package @tiptap/vue-3 diff --git a/packages/vue-3/package.json b/packages/vue-3/package.json index e1635238..67cb5fc0 100644 --- a/packages/vue-3/package.json +++ b/packages/vue-3/package.json @@ -1,7 +1,7 @@ { "name": "@tiptap/vue-3", "description": "Vue components for tiptap", - "version": "2.0.0-beta.27", + "version": "2.0.0-beta.28", "homepage": "https://tiptap.dev", "keywords": [ "tiptap", From 71740687f47ff17359b6bd35139a81b4fc548db3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 18:48:22 +0200 Subject: [PATCH 12/18] use replaceWith instead of replaceRangeWith in insertContentAt --- packages/core/src/commands/insertContentAt.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/core/src/commands/insertContentAt.ts b/packages/core/src/commands/insertContentAt.ts index ef8002fb..dde7eb6d 100644 --- a/packages/core/src/commands/insertContentAt.ts +++ b/packages/core/src/commands/insertContentAt.ts @@ -22,8 +22,9 @@ export const insertContentAt: RawCommands['insertContentAt'] = (range, value) => if (dispatch) { const content = createNodeFromContent(value, editor.schema) - // @ts-ignore - tr.replaceRangeWith(range.from, range.to, content) + tr.replaceWith(range.from, range.to, content) + + // set cursor at end of inserted content selectionToInsertionEnd(tr, tr.steps.length - 1, 1) } From 55d430ef8f58713299c622c1ec0bc5565e8387f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 18:51:42 +0200 Subject: [PATCH 13/18] refactoring --- packages/extension-hard-break/package.json | 3 +-- packages/extension-hard-break/src/hard-break.ts | 13 +++---------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/extension-hard-break/package.json b/packages/extension-hard-break/package.json index 13fc6259..51800cf9 100644 --- a/packages/extension-hard-break/package.json +++ b/packages/extension-hard-break/package.json @@ -22,7 +22,6 @@ "dist" ], "peerDependencies": { - "@tiptap/core": "^2.0.0-beta.1", - "prosemirror-commands": "^1.1.3" + "@tiptap/core": "^2.0.0-beta.1" } } diff --git a/packages/extension-hard-break/src/hard-break.ts b/packages/extension-hard-break/src/hard-break.ts index 37281c2a..c0f515c4 100644 --- a/packages/extension-hard-break/src/hard-break.ts +++ b/packages/extension-hard-break/src/hard-break.ts @@ -1,5 +1,4 @@ import { Command, Node, mergeAttributes } from '@tiptap/core' -import { exitCode } from 'prosemirror-commands' export interface HardBreakOptions { HTMLAttributes: Record, @@ -41,16 +40,10 @@ export const HardBreak = Node.create({ addCommands() { return { - setHardBreak: () => ({ commands, state, dispatch }) => { + setHardBreak: () => ({ commands }) => { return commands.first([ - () => exitCode(state, dispatch), - () => { - if (dispatch) { - state.tr.replaceSelectionWith(this.type.create()).scrollIntoView() - } - - return true - }, + () => commands.exitCode(), + () => commands.insertContent({ type: this.name }), ]) }, } From 0030f083b09811dd0acb24cd298f9ee17ab04794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 19:42:47 +0200 Subject: [PATCH 14/18] docs: update content --- docs/src/docPages/api/commands.md | 13 ++++++------- .../{replace-range.md => insert-content-at.md} | 2 +- docs/src/docPages/api/commands/replace.md | 3 --- docs/src/links.yaml | 9 +++------ packages/core/src/commands/insertContentAt.ts | 2 +- packages/core/src/commands/replace.ts | 2 ++ packages/core/src/commands/replaceRange.ts | 2 ++ 7 files changed, 15 insertions(+), 18 deletions(-) rename docs/src/docPages/api/commands/{replace-range.md => insert-content-at.md} (52%) delete mode 100644 docs/src/docPages/api/commands/replace.md diff --git a/docs/src/docPages/api/commands.md b/docs/src/docPages/api/commands.md index 66c210c8..fcbb5fab 100644 --- a/docs/src/docPages/api/commands.md +++ b/docs/src/docPages/api/commands.md @@ -154,11 +154,12 @@ export default () => ({ commands }) => { Have a look at all of the core commands listed below. They should give you a good first impression of what’s possible. ### Content -| Command | Description | Links | -| ---------------- | -------------------------------------------------------- | ------------------------------------ | -| .clearContent() | Clear the whole document. | [More](/api/commands/clear-content) | -| .insertContent() | Insert a node or string of HTML at the current position. | [More](/api/commands/insert-content) | -| .setContent() | Replace the whole document with new content. | [More](/api/commands/set-content) | +| Command | Description | Links | +| ------------------ | -------------------------------------------------------- | --------------------------------------- | +| .clearContent() | Clear the whole document. | [More](/api/commands/clear-content) | +| .insertContent() | Insert a node or string of HTML at the current position. | [More](/api/commands/insert-content) | +| .insertContentAt() | Insert a node or string of HTML at a specific position. | [More](/api/commands/insert-content-at) | +| .setContent() | Replace the whole document with new content. | [More](/api/commands/set-content) | ### Nodes & Marks | Command | Description | Links | @@ -172,8 +173,6 @@ Have a look at all of the core commands listed below. They should give you a goo | .lift() | Removes an existing wrap. | [More](/api/commands/lift) | | .liftEmptyBlock() | Lift block if empty. | [More](/api/commands/lift-empty-block) | | .newlineInCode() | Add a newline character in code. | [More](/api/commands/newline-in-code) | -| .replace() | Replaces text with a node. | [More](/api/commands/replace) | -| .replaceRange() | Replaces text with a node within a range. | [More](/api/commands/replace-range) | | .resetAttributes() | Resets some node or mark attributes to the default value. | [More](/api/commands/reset-attributes) | | .setMark() | Add a mark with new attributes. | [More](/api/commands/set-mark) | | .setNode() | Replace a given range with a node. | [More](/api/commands/set-node) | diff --git a/docs/src/docPages/api/commands/replace-range.md b/docs/src/docPages/api/commands/insert-content-at.md similarity index 52% rename from docs/src/docPages/api/commands/replace-range.md rename to docs/src/docPages/api/commands/insert-content-at.md index 85c068ec..2335641a 100644 --- a/docs/src/docPages/api/commands/replace-range.md +++ b/docs/src/docPages/api/commands/insert-content-at.md @@ -1,3 +1,3 @@ -# replaceRange +# insertContentAt diff --git a/docs/src/docPages/api/commands/replace.md b/docs/src/docPages/api/commands/replace.md deleted file mode 100644 index 3c6da44c..00000000 --- a/docs/src/docPages/api/commands/replace.md +++ /dev/null @@ -1,3 +0,0 @@ -# replace - - diff --git a/docs/src/links.yaml b/docs/src/links.yaml index bc5e2b5b..a1afe6c0 100644 --- a/docs/src/links.yaml +++ b/docs/src/links.yaml @@ -157,6 +157,9 @@ type: draft - title: insertContent link: /api/commands/insert-content + - title: insertContentAt + link: /api/commands/insert-content-at + type: draft - title: joinBackward link: /api/commands/join-backward type: draft @@ -178,12 +181,6 @@ - title: newlineInCode link: /api/commands/newline-in-code type: draft - - title: replaceRange - link: /api/commands/replace-range - type: draft - - title: replace - link: /api/commands/replace - type: draft - title: resetAttributes link: /api/commands/reset-attributes type: draft diff --git a/packages/core/src/commands/insertContentAt.ts b/packages/core/src/commands/insertContentAt.ts index dde7eb6d..10af8e38 100644 --- a/packages/core/src/commands/insertContentAt.ts +++ b/packages/core/src/commands/insertContentAt.ts @@ -11,7 +11,7 @@ declare module '@tiptap/core' { interface Commands { insertContentAt: { /** - * Insert a node or string of HTML at the current position. + * Insert a node or string of HTML at a specific position. */ insertContentAt: (range: Range, value: Content) => Command, } diff --git a/packages/core/src/commands/replace.ts b/packages/core/src/commands/replace.ts index 52aff4b1..f3a12d54 100644 --- a/packages/core/src/commands/replace.ts +++ b/packages/core/src/commands/replace.ts @@ -13,6 +13,8 @@ declare module '@tiptap/core' { } export const replace: RawCommands['replace'] = (typeOrName, attributes = {}) => ({ state, commands }) => { + console.warn('[tiptap warn]: replace() is deprecated. please use insertContent() instead.') + const { from, to } = state.selection const range = { from, to } diff --git a/packages/core/src/commands/replaceRange.ts b/packages/core/src/commands/replaceRange.ts index dbb9be77..66867d26 100644 --- a/packages/core/src/commands/replaceRange.ts +++ b/packages/core/src/commands/replaceRange.ts @@ -14,6 +14,8 @@ declare module '@tiptap/core' { } export const replaceRange: RawCommands['replaceRange'] = (range, typeOrName, attributes = {}) => ({ tr, state, dispatch }) => { + console.warn('[tiptap warn]: replaceRange() is deprecated. please use insertContent() instead.') + const type = getNodeType(typeOrName, state.schema) const { from, to } = range // const $from = tr.doc.resolve(from) From db1b957974edb3a32280409bd1a4dfe84071e589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 20:34:41 +0200 Subject: [PATCH 15/18] test: fix link tests --- docs/src/demos/Marks/Link/index.spec.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/src/demos/Marks/Link/index.spec.js b/docs/src/demos/Marks/Link/index.spec.js index 7255d5e4..403cb8c0 100644 --- a/docs/src/demos/Marks/Link/index.spec.js +++ b/docs/src/demos/Marks/Link/index.spec.js @@ -47,10 +47,17 @@ context('/demos/Marks/Link', () => { }) }) + it('detects a pasted URL within a text', () => { + cy.get('.ProseMirror').paste({ pastePayload: 'some text https://example.com around an url', pasteType: 'text/plain' }) + .find('a') + .should('contain', 'https://example.com') + .should('have.attr', 'href', 'https://example.com') + }) + it('detects a pasted URL', () => { cy.get('.ProseMirror').paste({ pastePayload: 'https://example.com', pasteType: 'text/plain' }) .find('a') - .should('contain', 'https://example.com') + .should('contain', 'Example Text') .should('have.attr', 'href', 'https://example.com') }) From dd568dedeafbd1672b3c553afadb59423346fe01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 20:40:41 +0200 Subject: [PATCH 16/18] test: fix readonly test --- docs/src/demos/Guide/Content/ReadOnly/index.spec.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/src/demos/Guide/Content/ReadOnly/index.spec.js b/docs/src/demos/Guide/Content/ReadOnly/index.spec.js index 17cc73cf..60522041 100644 --- a/docs/src/demos/Guide/Content/ReadOnly/index.spec.js +++ b/docs/src/demos/Guide/Content/ReadOnly/index.spec.js @@ -1,12 +1,18 @@ context('/demos/Guide/Content/ReadOnly', () => { - beforeEach(() => { + before(() => { cy.visit('/demos/Guide/Content/ReadOnly') }) + beforeEach(() => { + cy.get('.ProseMirror').then(([{ editor }]) => { + editor.commands.clearContent() + }) + }) + it('should be read-only', () => { cy.get('.ProseMirror').then(([{ editor }]) => { editor.setEditable(false) - editor.commands.insertContent('Edited: ') + cy.get('.ProseMirror').type('Edited: ') cy.get('.ProseMirror p:first').should('not.contain', 'Edited: ') }) @@ -15,7 +21,7 @@ context('/demos/Guide/Content/ReadOnly', () => { it('should be editable', () => { cy.get('.ProseMirror').then(([{ editor }]) => { editor.setEditable(true) - editor.commands.insertContent('Edited: ') + cy.get('.ProseMirror').type('Edited: ') cy.get('.ProseMirror p:first').should('contain', 'Edited: ') }) From 86d570fb79b89a061cf1a5374a377ed6d9bca49e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 20:50:01 +0200 Subject: [PATCH 17/18] feat: remove deprecated commands insertHTML, insertNode and insertText --- packages/core/src/commands/insertHTML.ts | 30 --------------------- packages/core/src/commands/insertNode.ts | 33 ------------------------ packages/core/src/commands/insertText.ts | 22 ---------------- packages/core/src/extensions/commands.ts | 9 ------- 4 files changed, 94 deletions(-) delete mode 100644 packages/core/src/commands/insertHTML.ts delete mode 100644 packages/core/src/commands/insertNode.ts delete mode 100644 packages/core/src/commands/insertText.ts diff --git a/packages/core/src/commands/insertHTML.ts b/packages/core/src/commands/insertHTML.ts deleted file mode 100644 index ceba9bb7..00000000 --- a/packages/core/src/commands/insertHTML.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { DOMParser } from 'prosemirror-model' -import elementFromString from '../utilities/elementFromString' -import selectionToInsertionEnd from '../helpers/selectionToInsertionEnd' -import { Command, RawCommands } from '../types' - -declare module '@tiptap/core' { - interface Commands { - insertHTML: { - /** - * Insert a string of HTML at the current position. - */ - insertHTML: (value: string) => Command, - } - } -} - -export const insertHTML: RawCommands['insertHTML'] = value => ({ tr, state, dispatch }) => { - console.warn('[tiptap warn]: insertHTML() is deprecated. please use insertContent() instead.') - - const { selection } = tr - const element = elementFromString(value) - const slice = DOMParser.fromSchema(state.schema).parseSlice(element) - - if (dispatch) { - tr.insert(selection.anchor, slice.content) - selectionToInsertionEnd(tr, tr.steps.length - 1, -1) - } - - return true -} diff --git a/packages/core/src/commands/insertNode.ts b/packages/core/src/commands/insertNode.ts deleted file mode 100644 index a49e20ad..00000000 --- a/packages/core/src/commands/insertNode.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { NodeType } from 'prosemirror-model' -import getNodeType from '../helpers/getNodeType' -import { Command, RawCommands } from '../types' - -declare module '@tiptap/core' { - interface Commands { - insertNode: { - /** - * Insert a node at the current position. - */ - insertNode: (typeOrName: string | NodeType, attributes?: Record) => Command, - } - } -} - -export const insertNode: RawCommands['insertNode'] = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => { - console.warn('[tiptap warn]: insertNode() is deprecated. please use insertContent() instead.') - - const { selection } = tr - const type = getNodeType(typeOrName, state.schema) - - if (!type) { - return false - } - - const node = type.create(attributes) - - if (dispatch) { - tr.insert(selection.anchor, node) - } - - return true -} diff --git a/packages/core/src/commands/insertText.ts b/packages/core/src/commands/insertText.ts deleted file mode 100644 index 56453aeb..00000000 --- a/packages/core/src/commands/insertText.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Command, RawCommands } from '../types' - -declare module '@tiptap/core' { - interface Commands { - insertText: { - /** - * Insert a string of text at the current position. - */ - insertText: (value: string) => Command, - } - } -} - -export const insertText: RawCommands['insertText'] = value => ({ tr, dispatch }) => { - console.warn('[tiptap warn]: insertText() is deprecated. please use insertContent() instead.') - - if (dispatch) { - tr.insertText(value) - } - - return true -} diff --git a/packages/core/src/extensions/commands.ts b/packages/core/src/extensions/commands.ts index ea8dfb29..e1c1d129 100644 --- a/packages/core/src/extensions/commands.ts +++ b/packages/core/src/extensions/commands.ts @@ -13,9 +13,6 @@ import * as first from '../commands/first' import * as focus from '../commands/focus' import * as insertContent from '../commands/insertContent' import * as insertContentAt from '../commands/insertContentAt' -import * as insertHTML from '../commands/insertHTML' -import * as insertNode from '../commands/insertNode' -import * as insertText from '../commands/insertText' import * as joinBackward from '../commands/joinBackward' import * as joinForward from '../commands/joinForward' import * as keyboardShortcut from '../commands/keyboardShortcut' @@ -66,9 +63,6 @@ export { first } export { focus } export { insertContent } export { insertContentAt } -export { insertHTML } -export { insertNode } -export { insertText } export { joinBackward } export { joinForward } export { keyboardShortcut } @@ -124,9 +118,6 @@ export const Commands = Extension.create({ ...focus, ...insertContent, ...insertContentAt, - ...insertHTML, - ...insertNode, - ...insertText, ...joinBackward, ...joinForward, ...keyboardShortcut, From e9c9176032468145e2531c87618f49c5462e2991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Wed, 5 May 2021 20:50:08 +0200 Subject: [PATCH 18/18] refactoring --- packages/extension-mention/src/mention.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/extension-mention/src/mention.ts b/packages/extension-mention/src/mention.ts index 513fd835..c6165f49 100644 --- a/packages/extension-mention/src/mention.ts +++ b/packages/extension-mention/src/mention.ts @@ -74,11 +74,15 @@ export const Mention = Node.create({ }, renderHTML({ node, HTMLAttributes }) { - return ['span', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), `@${node.attrs.id}`] + return [ + 'span', + mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), + `${this.options.suggestion.char}${node.attrs.id}`, + ] }, renderText({ node }) { - return `@${node.attrs.id}` + return `${this.options.suggestion.char}${node.attrs.id}` }, addKeyboardShortcuts() { @@ -93,7 +97,7 @@ export const Mention = Node.create({ } state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => { - if (node.type.name === 'mention') { + if (node.type.name === this.name) { isMention = true tr.insertText(this.options.suggestion.char || '', pos, pos + node.nodeSize)