From ef10ae53b2a3854fceefc2999e166ed1fe4e9b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kol=C4=8D=C3=A1=C5=99?= Date: Thu, 7 Sep 2023 13:33:06 +0200 Subject: [PATCH] Revert "autolink improvement" This reverts commit 9a9e94b4cbfc01ef565febdcb31ed61f8d6d1955. --- .../extension-link/src/helpers/autolink.ts | 86 +++++++++---------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/packages/extension-link/src/helpers/autolink.ts b/packages/extension-link/src/helpers/autolink.ts index 8932cf67b2..90b2fdd0de 100644 --- a/packages/extension-link/src/helpers/autolink.ts +++ b/packages/extension-link/src/helpers/autolink.ts @@ -3,23 +3,15 @@ import { findChildrenInRange, getChangedRanges, getMarksBetween, + NodeWithPos, } from '@tiptap/core' import { MarkType } from '@tiptap/pm/model' import { Plugin, PluginKey } from '@tiptap/pm/state' import { find } from 'linkifyjs' type AutolinkOptions = { - type: MarkType; - validate?: (url: string) => boolean; -} - -type LinkType = { - type: string; - value: string; - isLink: boolean; - href: string; - start: number; - end: number; + type: MarkType + validate?: (url: string) => boolean } export function autolink(options: AutolinkOptions): Plugin { @@ -45,34 +37,40 @@ export function autolink(options: AutolinkOptions): Plugin { node => node.isTextblock, ) - // Grab the first node within the changed ranges (ex. the first of two paragraphs when hitting enter). - const textBlock = nodesInChangedRanges[0] - - if (!textBlock) { - return + let textBlock: NodeWithPos | undefined + let textBeforeWhitespace: string | undefined + + if (nodesInChangedRanges.length > 1) { + // Grab the first node within the changed ranges (ex. the first of two paragraphs when hitting enter). + textBlock = nodesInChangedRanges[0] + textBeforeWhitespace = newState.doc.textBetween( + textBlock.pos, + textBlock.pos + textBlock.node.nodeSize, + undefined, + ' ', + ) + } else if ( + nodesInChangedRanges.length + // We want to make sure to include the block seperator argument to treat hard breaks like spaces. + && newState.doc.textBetween(newRange.from, newRange.to, ' ', ' ').endsWith(' ') + ) { + textBlock = nodesInChangedRanges[0] + textBeforeWhitespace = newState.doc.textBetween( + textBlock.pos, + newRange.to, + undefined, + ' ', + ) } - const textBeforeWhitespace = newState.doc.textBetween( - textBlock.pos, - newRange.to, - ' ', - ' ', - ) - - if (textBeforeWhitespace) { + if (textBlock && textBeforeWhitespace) { + const wordsBeforeWhitespace = textBeforeWhitespace.split(' ').filter(s => s !== '') - if (!/\s*\S+\s+$/gm.test(textBeforeWhitespace)) { - return - } - - const lastWordBeforeSpaceMatch = textBeforeWhitespace.matchAll(/\s*(\S+)\s+$/gm) - const lastMatch = Array.from(lastWordBeforeSpaceMatch).at(-1) - - if (lastMatch === undefined || lastMatch.length < 2) { - return + if (wordsBeforeWhitespace.length <= 0) { + return false } - const lastWordBeforeSpace = lastMatch[1] + const lastWordBeforeSpace = wordsBeforeWhitespace[wordsBeforeWhitespace.length - 1] const lastWordAndBlockOffset = textBlock.pos + textBeforeWhitespace.lastIndexOf(lastWordBeforeSpace) if (!lastWordBeforeSpace) { @@ -80,22 +78,22 @@ export function autolink(options: AutolinkOptions): Plugin { } find(lastWordBeforeSpace) - .filter((link: LinkType) => link.isLink) + .filter(link => link.isLink) // Calculate link position. - .map((link: LinkType) => ({ + .map(link => ({ ...link, - start: lastWordAndBlockOffset + link.start + 1, - end: lastWordAndBlockOffset + link.end + 1, + from: lastWordAndBlockOffset + link.start + 1, + to: lastWordAndBlockOffset + link.end + 1, })) // ignore link inside code mark - .filter((link: LinkType) => { + .filter(link => { if (!newState.schema.marks.code) { return true } return !newState.doc.rangeHasMark( - link.start, - link.end, + link.from, + link.to, newState.schema.marks.code, ) }) @@ -108,13 +106,13 @@ export function autolink(options: AutolinkOptions): Plugin { }) // Add link mark. .forEach(link => { - if (getMarksBetween(link.start, link.end, newState.doc).some(item => item.mark.type === options.type)) { + if (getMarksBetween(link.from, link.to, newState.doc).some(item => item.mark.type === options.type)) { return } tr.addMark( - link.start, - link.end, + link.from, + link.to, options.type.create({ href: link.href, }),