@tiptap/extension-link 2.1.11 → 2.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -114,6 +114,39 @@ function clickHandler(options) {
114
114
  });
115
115
  }
116
116
 
117
+ function pasteHandler(options) {
118
+ return new state.Plugin({
119
+ key: new state.PluginKey('handlePasteLink'),
120
+ props: {
121
+ handlePaste: (view, event, slice) => {
122
+ var _a;
123
+ const { state } = view;
124
+ const { selection } = state;
125
+ const { empty } = selection;
126
+ if (empty) {
127
+ return false;
128
+ }
129
+ let textContent = '';
130
+ slice.content.forEach(node => {
131
+ textContent += node.textContent;
132
+ });
133
+ const link = linkifyjs.find(textContent).find(item => item.isLink && item.value === textContent);
134
+ if (!textContent || !link) {
135
+ return false;
136
+ }
137
+ const html = (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/html');
138
+ const hrefRegex = /href="([^"]*)"/;
139
+ const existingLink = html === null || html === void 0 ? void 0 : html.match(hrefRegex);
140
+ const url = existingLink ? existingLink[1] : link.href;
141
+ options.editor.commands.setMark(options.type, {
142
+ href: url,
143
+ });
144
+ return true;
145
+ },
146
+ },
147
+ });
148
+ }
149
+
117
150
  const Link = core.Mark.create({
118
151
  name: 'link',
119
152
  priority: 1000,
@@ -167,6 +200,13 @@ const Link = core.Mark.create({
167
200
  return [{ tag: 'a[href]:not([href *= "javascript:" i])' }];
168
201
  },
169
202
  renderHTML({ HTMLAttributes }) {
203
+ var _a;
204
+ // False positive; we're explicitly checking for javascript: links to ignore them
205
+ // eslint-disable-next-line no-script-url
206
+ if ((_a = HTMLAttributes.href) === null || _a === void 0 ? void 0 : _a.startsWith('javascript:')) {
207
+ // strip out the href
208
+ return ['a', core.mergeAttributes(this.options.HTMLAttributes, { ...HTMLAttributes, href: '' }), 0];
209
+ }
170
210
  return ['a', core.mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
171
211
  },
172
212
  addCommands() {
@@ -207,7 +247,7 @@ const Link = core.Mark.create({
207
247
  type: this.type,
208
248
  getAttributes: (match, pasteEvent) => {
209
249
  var _a, _b;
210
- const html = (_a = pasteEvent.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/html');
250
+ const html = (_a = pasteEvent === null || pasteEvent === void 0 ? void 0 : pasteEvent.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/html');
211
251
  const hrefRegex = /href="([^"]*)"/;
212
252
  const existingLink = html === null || html === void 0 ? void 0 : html.match(hrefRegex);
213
253
  if (existingLink) {
@@ -235,6 +275,12 @@ const Link = core.Mark.create({
235
275
  type: this.type,
236
276
  }));
237
277
  }
278
+ if (this.options.linkOnPaste) {
279
+ plugins.push(pasteHandler({
280
+ editor: this.editor,
281
+ type: this.type,
282
+ }));
283
+ }
238
284
  return plugins;
239
285
  },
240
286
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/helpers/autolink.ts","../src/helpers/clickHandler.ts","../src/link.ts"],"sourcesContent":["import {\n combineTransactionSteps,\n findChildrenInRange,\n getChangedRanges,\n getMarksBetween,\n NodeWithPos,\n} from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { find } from 'linkifyjs'\n\ntype AutolinkOptions = {\n type: MarkType\n validate?: (url: string) => boolean\n}\n\nexport function autolink(options: AutolinkOptions): Plugin {\n return new Plugin({\n key: new PluginKey('autolink'),\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges = transactions.some(transaction => transaction.docChanged) && !oldState.doc.eq(newState.doc)\n const preventAutolink = transactions.some(transaction => transaction.getMeta('preventAutolink'))\n\n if (!docChanges || preventAutolink) {\n return\n }\n\n const { tr } = newState\n const transform = combineTransactionSteps(oldState.doc, [...transactions])\n const changes = getChangedRanges(transform)\n\n changes.forEach(({ newRange }) => {\n // Now let’s see if we can add new links.\n const nodesInChangedRanges = findChildrenInRange(\n newState.doc,\n newRange,\n node => node.isTextblock,\n )\n\n let textBlock: NodeWithPos | undefined\n let textBeforeWhitespace: string | undefined\n\n if (nodesInChangedRanges.length > 1) {\n // Grab the first node within the changed ranges (ex. the first of two paragraphs when hitting enter).\n textBlock = nodesInChangedRanges[0]\n textBeforeWhitespace = newState.doc.textBetween(\n textBlock.pos,\n textBlock.pos + textBlock.node.nodeSize,\n undefined,\n ' ',\n )\n } else if (\n nodesInChangedRanges.length\n // We want to make sure to include the block seperator argument to treat hard breaks like spaces.\n && newState.doc.textBetween(newRange.from, newRange.to, ' ', ' ').endsWith(' ')\n ) {\n textBlock = nodesInChangedRanges[0]\n textBeforeWhitespace = newState.doc.textBetween(\n textBlock.pos,\n newRange.to,\n undefined,\n ' ',\n )\n }\n\n if (textBlock && textBeforeWhitespace) {\n const wordsBeforeWhitespace = textBeforeWhitespace.split(' ').filter(s => s !== '')\n\n if (wordsBeforeWhitespace.length <= 0) {\n return false\n }\n\n const lastWordBeforeSpace = wordsBeforeWhitespace[wordsBeforeWhitespace.length - 1]\n const lastWordAndBlockOffset = textBlock.pos + textBeforeWhitespace.lastIndexOf(lastWordBeforeSpace)\n\n if (!lastWordBeforeSpace) {\n return false\n }\n\n find(lastWordBeforeSpace)\n .filter(link => link.isLink)\n // Calculate link position.\n .map(link => ({\n ...link,\n from: lastWordAndBlockOffset + link.start + 1,\n to: lastWordAndBlockOffset + link.end + 1,\n }))\n // ignore link inside code mark\n .filter(link => {\n if (!newState.schema.marks.code) {\n return true\n }\n\n return !newState.doc.rangeHasMark(\n link.from,\n link.to,\n newState.schema.marks.code,\n )\n })\n // validate link\n .filter(link => {\n if (options.validate) {\n return options.validate(link.value)\n }\n return true\n })\n // Add link mark.\n .forEach(link => {\n if (getMarksBetween(link.from, link.to, newState.doc).some(item => item.mark.type === options.type)) {\n return\n }\n\n tr.addMark(\n link.from,\n link.to,\n options.type.create({\n href: link.href,\n }),\n )\n })\n }\n })\n\n if (!tr.steps.length) {\n return\n }\n\n return tr\n },\n })\n}\n","import { getAttributes } from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\ntype ClickHandlerOptions = {\n type: MarkType\n}\n\nexport function clickHandler(options: ClickHandlerOptions): Plugin {\n return new Plugin({\n key: new PluginKey('handleClickLink'),\n props: {\n handleClick: (view, pos, event) => {\n if (event.button !== 0) {\n return false\n }\n\n const eventTarget = event.target as HTMLElement\n\n if (eventTarget.nodeName !== 'A') {\n return false\n }\n\n const attrs = getAttributes(view.state, options.type.name)\n const link = (event.target as HTMLLinkElement)\n\n const href = link?.href ?? attrs.href\n const target = link?.target ?? attrs.target\n\n if (link && href) {\n if (view.editable) {\n window.open(href, target)\n }\n\n return true\n }\n\n return false\n },\n },\n })\n}\n","import { Mark, markPasteRule, mergeAttributes } from '@tiptap/core'\nimport { Plugin } from '@tiptap/pm/state'\nimport { find, registerCustomProtocol, reset } from 'linkifyjs'\n\nimport { autolink } from './helpers/autolink.js'\nimport { clickHandler } from './helpers/clickHandler.js'\n\nexport interface LinkProtocolOptions {\n scheme: string;\n optionalSlashes?: boolean;\n}\n\nexport interface LinkOptions {\n /**\n * If enabled, it adds links as you type.\n */\n autolink: boolean\n /**\n * An array of custom protocols to be registered with linkifyjs.\n */\n protocols: Array<LinkProtocolOptions | string>\n /**\n * If enabled, links will be opened on click.\n */\n openOnClick: boolean\n /**\n * Adds a link to the current selection if the pasted content only contains an url.\n */\n linkOnPaste: boolean\n /**\n * A list of HTML attributes to be rendered.\n */\n HTMLAttributes: Record<string, any>\n /**\n * A validation function that modifies link verification for the auto linker.\n * @param url - The url to be validated.\n * @returns - True if the url is valid, false otherwise.\n */\n validate?: (url: string) => boolean\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n link: {\n /**\n * Set a link mark\n */\n setLink: (attributes: { href: string; target?: string | null; rel?: string | null; class?: string | null }) => ReturnType\n /**\n * Toggle a link mark\n */\n toggleLink: (attributes: { href: string; target?: string | null; rel?: string | null; class?: string | null }) => ReturnType\n /**\n * Unset a link mark\n */\n unsetLink: () => ReturnType\n }\n }\n}\n\nexport const Link = Mark.create<LinkOptions>({\n name: 'link',\n\n priority: 1000,\n\n keepOnSplit: false,\n\n onCreate() {\n this.options.protocols.forEach(protocol => {\n if (typeof protocol === 'string') {\n registerCustomProtocol(protocol)\n return\n }\n registerCustomProtocol(protocol.scheme, protocol.optionalSlashes)\n })\n },\n\n onDestroy() {\n reset()\n },\n\n inclusive() {\n return this.options.autolink\n },\n\n addOptions() {\n return {\n openOnClick: true,\n linkOnPaste: true,\n autolink: true,\n protocols: [],\n HTMLAttributes: {\n target: '_blank',\n rel: 'noopener noreferrer nofollow',\n class: null,\n },\n validate: undefined,\n }\n },\n\n addAttributes() {\n return {\n href: {\n default: null,\n },\n target: {\n default: this.options.HTMLAttributes.target,\n },\n rel: {\n default: this.options.HTMLAttributes.rel,\n },\n class: {\n default: this.options.HTMLAttributes.class,\n },\n }\n },\n\n parseHTML() {\n return [{ tag: 'a[href]:not([href *= \"javascript:\" i])' }]\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['a', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]\n },\n\n addCommands() {\n return {\n setLink:\n attributes => ({ chain }) => {\n return chain().setMark(this.name, attributes).setMeta('preventAutolink', true).run()\n },\n\n toggleLink:\n attributes => ({ chain }) => {\n return chain()\n .toggleMark(this.name, attributes, { extendEmptyMarkRange: true })\n .setMeta('preventAutolink', true)\n .run()\n },\n\n unsetLink:\n () => ({ chain }) => {\n return chain()\n .unsetMark(this.name, { extendEmptyMarkRange: true })\n .setMeta('preventAutolink', true)\n .run()\n },\n }\n },\n\n addPasteRules() {\n return [\n markPasteRule({\n find: text => find(text)\n .filter(link => {\n if (this.options.validate) {\n return this.options.validate(link.value)\n }\n\n return true\n })\n .filter(link => link.isLink)\n .map(link => ({\n text: link.value,\n index: link.start,\n data: link,\n })),\n type: this.type,\n getAttributes: (match, pasteEvent) => {\n const html = pasteEvent.clipboardData?.getData('text/html')\n const hrefRegex = /href=\"([^\"]*)\"/\n\n const existingLink = html?.match(hrefRegex)\n\n if (existingLink) {\n return {\n href: existingLink[1],\n }\n }\n\n return {\n href: match.data?.href,\n }\n },\n }),\n ]\n },\n\n addProseMirrorPlugins() {\n const plugins: Plugin[] = []\n\n if (this.options.autolink) {\n plugins.push(\n autolink({\n type: this.type,\n validate: this.options.validate,\n }),\n )\n }\n\n if (this.options.openOnClick) {\n plugins.push(\n clickHandler({\n type: this.type,\n }),\n )\n }\n\n return plugins\n },\n})\n"],"names":["Plugin","PluginKey","combineTransactionSteps","getChangedRanges","findChildrenInRange","find","getMarksBetween","getAttributes","Mark","registerCustomProtocol","reset","mergeAttributes","markPasteRule"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/helpers/autolink.ts","../src/helpers/clickHandler.ts","../src/helpers/pasteHandler.ts","../src/link.ts"],"sourcesContent":["import {\n combineTransactionSteps,\n findChildrenInRange,\n getChangedRanges,\n getMarksBetween,\n NodeWithPos,\n} from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { find } from 'linkifyjs'\n\ntype AutolinkOptions = {\n type: MarkType\n validate?: (url: string) => boolean\n}\n\nexport function autolink(options: AutolinkOptions): Plugin {\n return new Plugin({\n key: new PluginKey('autolink'),\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges = transactions.some(transaction => transaction.docChanged) && !oldState.doc.eq(newState.doc)\n const preventAutolink = transactions.some(transaction => transaction.getMeta('preventAutolink'))\n\n if (!docChanges || preventAutolink) {\n return\n }\n\n const { tr } = newState\n const transform = combineTransactionSteps(oldState.doc, [...transactions])\n const changes = getChangedRanges(transform)\n\n changes.forEach(({ newRange }) => {\n // Now let’s see if we can add new links.\n const nodesInChangedRanges = findChildrenInRange(\n newState.doc,\n newRange,\n node => node.isTextblock,\n )\n\n let textBlock: NodeWithPos | undefined\n let textBeforeWhitespace: string | undefined\n\n if (nodesInChangedRanges.length > 1) {\n // Grab the first node within the changed ranges (ex. the first of two paragraphs when hitting enter).\n textBlock = nodesInChangedRanges[0]\n textBeforeWhitespace = newState.doc.textBetween(\n textBlock.pos,\n textBlock.pos + textBlock.node.nodeSize,\n undefined,\n ' ',\n )\n } else if (\n nodesInChangedRanges.length\n // We want to make sure to include the block seperator argument to treat hard breaks like spaces.\n && newState.doc.textBetween(newRange.from, newRange.to, ' ', ' ').endsWith(' ')\n ) {\n textBlock = nodesInChangedRanges[0]\n textBeforeWhitespace = newState.doc.textBetween(\n textBlock.pos,\n newRange.to,\n undefined,\n ' ',\n )\n }\n\n if (textBlock && textBeforeWhitespace) {\n const wordsBeforeWhitespace = textBeforeWhitespace.split(' ').filter(s => s !== '')\n\n if (wordsBeforeWhitespace.length <= 0) {\n return false\n }\n\n const lastWordBeforeSpace = wordsBeforeWhitespace[wordsBeforeWhitespace.length - 1]\n const lastWordAndBlockOffset = textBlock.pos + textBeforeWhitespace.lastIndexOf(lastWordBeforeSpace)\n\n if (!lastWordBeforeSpace) {\n return false\n }\n\n find(lastWordBeforeSpace)\n .filter(link => link.isLink)\n // Calculate link position.\n .map(link => ({\n ...link,\n from: lastWordAndBlockOffset + link.start + 1,\n to: lastWordAndBlockOffset + link.end + 1,\n }))\n // ignore link inside code mark\n .filter(link => {\n if (!newState.schema.marks.code) {\n return true\n }\n\n return !newState.doc.rangeHasMark(\n link.from,\n link.to,\n newState.schema.marks.code,\n )\n })\n // validate link\n .filter(link => {\n if (options.validate) {\n return options.validate(link.value)\n }\n return true\n })\n // Add link mark.\n .forEach(link => {\n if (getMarksBetween(link.from, link.to, newState.doc).some(item => item.mark.type === options.type)) {\n return\n }\n\n tr.addMark(\n link.from,\n link.to,\n options.type.create({\n href: link.href,\n }),\n )\n })\n }\n })\n\n if (!tr.steps.length) {\n return\n }\n\n return tr\n },\n })\n}\n","import { getAttributes } from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\ntype ClickHandlerOptions = {\n type: MarkType\n}\n\nexport function clickHandler(options: ClickHandlerOptions): Plugin {\n return new Plugin({\n key: new PluginKey('handleClickLink'),\n props: {\n handleClick: (view, pos, event) => {\n if (event.button !== 0) {\n return false\n }\n\n const eventTarget = event.target as HTMLElement\n\n if (eventTarget.nodeName !== 'A') {\n return false\n }\n\n const attrs = getAttributes(view.state, options.type.name)\n const link = (event.target as HTMLLinkElement)\n\n const href = link?.href ?? attrs.href\n const target = link?.target ?? attrs.target\n\n if (link && href) {\n if (view.editable) {\n window.open(href, target)\n }\n\n return true\n }\n\n return false\n },\n },\n })\n}\n","import { Editor } from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { find } from 'linkifyjs'\n\ntype PasteHandlerOptions = {\n editor: Editor\n type: MarkType\n}\n\nexport function pasteHandler(options: PasteHandlerOptions): Plugin {\n return new Plugin({\n key: new PluginKey('handlePasteLink'),\n props: {\n handlePaste: (view, event, slice) => {\n const { state } = view\n const { selection } = state\n const { empty } = selection\n\n if (empty) {\n return false\n }\n\n let textContent = ''\n\n slice.content.forEach(node => {\n textContent += node.textContent\n })\n\n const link = find(textContent).find(item => item.isLink && item.value === textContent)\n\n if (!textContent || !link) {\n return false\n }\n\n const html = event.clipboardData?.getData('text/html')\n\n const hrefRegex = /href=\"([^\"]*)\"/\n\n const existingLink = html?.match(hrefRegex)\n\n const url = existingLink ? existingLink[1] : link.href\n\n options.editor.commands.setMark(options.type, {\n href: url,\n })\n\n return true\n },\n },\n })\n}\n","import { Mark, markPasteRule, mergeAttributes } from '@tiptap/core'\nimport { Plugin } from '@tiptap/pm/state'\nimport { find, registerCustomProtocol, reset } from 'linkifyjs'\n\nimport { autolink } from './helpers/autolink.js'\nimport { clickHandler } from './helpers/clickHandler.js'\nimport { pasteHandler } from './helpers/pasteHandler.js'\n\nexport interface LinkProtocolOptions {\n scheme: string;\n optionalSlashes?: boolean;\n}\n\nexport interface LinkOptions {\n /**\n * If enabled, it adds links as you type.\n */\n autolink: boolean\n /**\n * An array of custom protocols to be registered with linkifyjs.\n */\n protocols: Array<LinkProtocolOptions | string>\n /**\n * If enabled, links will be opened on click.\n */\n openOnClick: boolean\n /**\n * Adds a link to the current selection if the pasted content only contains an url.\n */\n linkOnPaste: boolean\n /**\n * A list of HTML attributes to be rendered.\n */\n HTMLAttributes: Record<string, any>\n /**\n * A validation function that modifies link verification for the auto linker.\n * @param url - The url to be validated.\n * @returns - True if the url is valid, false otherwise.\n */\n validate?: (url: string) => boolean\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n link: {\n /**\n * Set a link mark\n */\n setLink: (attributes: { href: string; target?: string | null; rel?: string | null; class?: string | null }) => ReturnType\n /**\n * Toggle a link mark\n */\n toggleLink: (attributes: { href: string; target?: string | null; rel?: string | null; class?: string | null }) => ReturnType\n /**\n * Unset a link mark\n */\n unsetLink: () => ReturnType\n }\n }\n}\n\nexport const Link = Mark.create<LinkOptions>({\n name: 'link',\n\n priority: 1000,\n\n keepOnSplit: false,\n\n onCreate() {\n this.options.protocols.forEach(protocol => {\n if (typeof protocol === 'string') {\n registerCustomProtocol(protocol)\n return\n }\n registerCustomProtocol(protocol.scheme, protocol.optionalSlashes)\n })\n },\n\n onDestroy() {\n reset()\n },\n\n inclusive() {\n return this.options.autolink\n },\n\n addOptions() {\n return {\n openOnClick: true,\n linkOnPaste: true,\n autolink: true,\n protocols: [],\n HTMLAttributes: {\n target: '_blank',\n rel: 'noopener noreferrer nofollow',\n class: null,\n },\n validate: undefined,\n }\n },\n\n addAttributes() {\n return {\n href: {\n default: null,\n },\n target: {\n default: this.options.HTMLAttributes.target,\n },\n rel: {\n default: this.options.HTMLAttributes.rel,\n },\n class: {\n default: this.options.HTMLAttributes.class,\n },\n }\n },\n\n parseHTML() {\n return [{ tag: 'a[href]:not([href *= \"javascript:\" i])' }]\n },\n\n renderHTML({ HTMLAttributes }) {\n // False positive; we're explicitly checking for javascript: links to ignore them\n // eslint-disable-next-line no-script-url\n if (HTMLAttributes.href?.startsWith('javascript:')) {\n // strip out the href\n return ['a', mergeAttributes(this.options.HTMLAttributes, { ...HTMLAttributes, href: '' }), 0]\n }\n return ['a', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]\n },\n\n addCommands() {\n return {\n setLink:\n attributes => ({ chain }) => {\n return chain().setMark(this.name, attributes).setMeta('preventAutolink', true).run()\n },\n\n toggleLink:\n attributes => ({ chain }) => {\n return chain()\n .toggleMark(this.name, attributes, { extendEmptyMarkRange: true })\n .setMeta('preventAutolink', true)\n .run()\n },\n\n unsetLink:\n () => ({ chain }) => {\n return chain()\n .unsetMark(this.name, { extendEmptyMarkRange: true })\n .setMeta('preventAutolink', true)\n .run()\n },\n }\n },\n\n addPasteRules() {\n return [\n markPasteRule({\n find: text => find(text)\n .filter(link => {\n if (this.options.validate) {\n return this.options.validate(link.value)\n }\n\n return true\n })\n .filter(link => link.isLink)\n .map(link => ({\n text: link.value,\n index: link.start,\n data: link,\n })),\n type: this.type,\n getAttributes: (match, pasteEvent) => {\n const html = pasteEvent?.clipboardData?.getData('text/html')\n const hrefRegex = /href=\"([^\"]*)\"/\n\n const existingLink = html?.match(hrefRegex)\n\n if (existingLink) {\n return {\n href: existingLink[1],\n }\n }\n\n return {\n href: match.data?.href,\n }\n },\n }),\n ]\n },\n\n addProseMirrorPlugins() {\n const plugins: Plugin[] = []\n\n if (this.options.autolink) {\n plugins.push(\n autolink({\n type: this.type,\n validate: this.options.validate,\n }),\n )\n }\n\n if (this.options.openOnClick) {\n plugins.push(\n clickHandler({\n type: this.type,\n }),\n )\n }\n\n if (this.options.linkOnPaste) {\n plugins.push(\n pasteHandler({\n editor: this.editor,\n type: this.type,\n }),\n )\n }\n\n return plugins\n },\n})\n"],"names":["Plugin","PluginKey","combineTransactionSteps","getChangedRanges","findChildrenInRange","find","getMarksBetween","getAttributes","Mark","registerCustomProtocol","reset","mergeAttributes","markPasteRule"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -110,6 +110,39 @@ function clickHandler(options) {
110
110
  });
111
111
  }
112
112
 
113
+ function pasteHandler(options) {
114
+ return new Plugin({
115
+ key: new PluginKey('handlePasteLink'),
116
+ props: {
117
+ handlePaste: (view, event, slice) => {
118
+ var _a;
119
+ const { state } = view;
120
+ const { selection } = state;
121
+ const { empty } = selection;
122
+ if (empty) {
123
+ return false;
124
+ }
125
+ let textContent = '';
126
+ slice.content.forEach(node => {
127
+ textContent += node.textContent;
128
+ });
129
+ const link = find(textContent).find(item => item.isLink && item.value === textContent);
130
+ if (!textContent || !link) {
131
+ return false;
132
+ }
133
+ const html = (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/html');
134
+ const hrefRegex = /href="([^"]*)"/;
135
+ const existingLink = html === null || html === void 0 ? void 0 : html.match(hrefRegex);
136
+ const url = existingLink ? existingLink[1] : link.href;
137
+ options.editor.commands.setMark(options.type, {
138
+ href: url,
139
+ });
140
+ return true;
141
+ },
142
+ },
143
+ });
144
+ }
145
+
113
146
  const Link = Mark.create({
114
147
  name: 'link',
115
148
  priority: 1000,
@@ -163,6 +196,13 @@ const Link = Mark.create({
163
196
  return [{ tag: 'a[href]:not([href *= "javascript:" i])' }];
164
197
  },
165
198
  renderHTML({ HTMLAttributes }) {
199
+ var _a;
200
+ // False positive; we're explicitly checking for javascript: links to ignore them
201
+ // eslint-disable-next-line no-script-url
202
+ if ((_a = HTMLAttributes.href) === null || _a === void 0 ? void 0 : _a.startsWith('javascript:')) {
203
+ // strip out the href
204
+ return ['a', mergeAttributes(this.options.HTMLAttributes, { ...HTMLAttributes, href: '' }), 0];
205
+ }
166
206
  return ['a', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
167
207
  },
168
208
  addCommands() {
@@ -203,7 +243,7 @@ const Link = Mark.create({
203
243
  type: this.type,
204
244
  getAttributes: (match, pasteEvent) => {
205
245
  var _a, _b;
206
- const html = (_a = pasteEvent.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/html');
246
+ const html = (_a = pasteEvent === null || pasteEvent === void 0 ? void 0 : pasteEvent.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/html');
207
247
  const hrefRegex = /href="([^"]*)"/;
208
248
  const existingLink = html === null || html === void 0 ? void 0 : html.match(hrefRegex);
209
249
  if (existingLink) {
@@ -231,6 +271,12 @@ const Link = Mark.create({
231
271
  type: this.type,
232
272
  }));
233
273
  }
274
+ if (this.options.linkOnPaste) {
275
+ plugins.push(pasteHandler({
276
+ editor: this.editor,
277
+ type: this.type,
278
+ }));
279
+ }
234
280
  return plugins;
235
281
  },
236
282
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/helpers/autolink.ts","../src/helpers/clickHandler.ts","../src/link.ts"],"sourcesContent":["import {\n combineTransactionSteps,\n findChildrenInRange,\n getChangedRanges,\n getMarksBetween,\n NodeWithPos,\n} from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { find } from 'linkifyjs'\n\ntype AutolinkOptions = {\n type: MarkType\n validate?: (url: string) => boolean\n}\n\nexport function autolink(options: AutolinkOptions): Plugin {\n return new Plugin({\n key: new PluginKey('autolink'),\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges = transactions.some(transaction => transaction.docChanged) && !oldState.doc.eq(newState.doc)\n const preventAutolink = transactions.some(transaction => transaction.getMeta('preventAutolink'))\n\n if (!docChanges || preventAutolink) {\n return\n }\n\n const { tr } = newState\n const transform = combineTransactionSteps(oldState.doc, [...transactions])\n const changes = getChangedRanges(transform)\n\n changes.forEach(({ newRange }) => {\n // Now let’s see if we can add new links.\n const nodesInChangedRanges = findChildrenInRange(\n newState.doc,\n newRange,\n node => node.isTextblock,\n )\n\n let textBlock: NodeWithPos | undefined\n let textBeforeWhitespace: string | undefined\n\n if (nodesInChangedRanges.length > 1) {\n // Grab the first node within the changed ranges (ex. the first of two paragraphs when hitting enter).\n textBlock = nodesInChangedRanges[0]\n textBeforeWhitespace = newState.doc.textBetween(\n textBlock.pos,\n textBlock.pos + textBlock.node.nodeSize,\n undefined,\n ' ',\n )\n } else if (\n nodesInChangedRanges.length\n // We want to make sure to include the block seperator argument to treat hard breaks like spaces.\n && newState.doc.textBetween(newRange.from, newRange.to, ' ', ' ').endsWith(' ')\n ) {\n textBlock = nodesInChangedRanges[0]\n textBeforeWhitespace = newState.doc.textBetween(\n textBlock.pos,\n newRange.to,\n undefined,\n ' ',\n )\n }\n\n if (textBlock && textBeforeWhitespace) {\n const wordsBeforeWhitespace = textBeforeWhitespace.split(' ').filter(s => s !== '')\n\n if (wordsBeforeWhitespace.length <= 0) {\n return false\n }\n\n const lastWordBeforeSpace = wordsBeforeWhitespace[wordsBeforeWhitespace.length - 1]\n const lastWordAndBlockOffset = textBlock.pos + textBeforeWhitespace.lastIndexOf(lastWordBeforeSpace)\n\n if (!lastWordBeforeSpace) {\n return false\n }\n\n find(lastWordBeforeSpace)\n .filter(link => link.isLink)\n // Calculate link position.\n .map(link => ({\n ...link,\n from: lastWordAndBlockOffset + link.start + 1,\n to: lastWordAndBlockOffset + link.end + 1,\n }))\n // ignore link inside code mark\n .filter(link => {\n if (!newState.schema.marks.code) {\n return true\n }\n\n return !newState.doc.rangeHasMark(\n link.from,\n link.to,\n newState.schema.marks.code,\n )\n })\n // validate link\n .filter(link => {\n if (options.validate) {\n return options.validate(link.value)\n }\n return true\n })\n // Add link mark.\n .forEach(link => {\n if (getMarksBetween(link.from, link.to, newState.doc).some(item => item.mark.type === options.type)) {\n return\n }\n\n tr.addMark(\n link.from,\n link.to,\n options.type.create({\n href: link.href,\n }),\n )\n })\n }\n })\n\n if (!tr.steps.length) {\n return\n }\n\n return tr\n },\n })\n}\n","import { getAttributes } from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\ntype ClickHandlerOptions = {\n type: MarkType\n}\n\nexport function clickHandler(options: ClickHandlerOptions): Plugin {\n return new Plugin({\n key: new PluginKey('handleClickLink'),\n props: {\n handleClick: (view, pos, event) => {\n if (event.button !== 0) {\n return false\n }\n\n const eventTarget = event.target as HTMLElement\n\n if (eventTarget.nodeName !== 'A') {\n return false\n }\n\n const attrs = getAttributes(view.state, options.type.name)\n const link = (event.target as HTMLLinkElement)\n\n const href = link?.href ?? attrs.href\n const target = link?.target ?? attrs.target\n\n if (link && href) {\n if (view.editable) {\n window.open(href, target)\n }\n\n return true\n }\n\n return false\n },\n },\n })\n}\n","import { Mark, markPasteRule, mergeAttributes } from '@tiptap/core'\nimport { Plugin } from '@tiptap/pm/state'\nimport { find, registerCustomProtocol, reset } from 'linkifyjs'\n\nimport { autolink } from './helpers/autolink.js'\nimport { clickHandler } from './helpers/clickHandler.js'\n\nexport interface LinkProtocolOptions {\n scheme: string;\n optionalSlashes?: boolean;\n}\n\nexport interface LinkOptions {\n /**\n * If enabled, it adds links as you type.\n */\n autolink: boolean\n /**\n * An array of custom protocols to be registered with linkifyjs.\n */\n protocols: Array<LinkProtocolOptions | string>\n /**\n * If enabled, links will be opened on click.\n */\n openOnClick: boolean\n /**\n * Adds a link to the current selection if the pasted content only contains an url.\n */\n linkOnPaste: boolean\n /**\n * A list of HTML attributes to be rendered.\n */\n HTMLAttributes: Record<string, any>\n /**\n * A validation function that modifies link verification for the auto linker.\n * @param url - The url to be validated.\n * @returns - True if the url is valid, false otherwise.\n */\n validate?: (url: string) => boolean\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n link: {\n /**\n * Set a link mark\n */\n setLink: (attributes: { href: string; target?: string | null; rel?: string | null; class?: string | null }) => ReturnType\n /**\n * Toggle a link mark\n */\n toggleLink: (attributes: { href: string; target?: string | null; rel?: string | null; class?: string | null }) => ReturnType\n /**\n * Unset a link mark\n */\n unsetLink: () => ReturnType\n }\n }\n}\n\nexport const Link = Mark.create<LinkOptions>({\n name: 'link',\n\n priority: 1000,\n\n keepOnSplit: false,\n\n onCreate() {\n this.options.protocols.forEach(protocol => {\n if (typeof protocol === 'string') {\n registerCustomProtocol(protocol)\n return\n }\n registerCustomProtocol(protocol.scheme, protocol.optionalSlashes)\n })\n },\n\n onDestroy() {\n reset()\n },\n\n inclusive() {\n return this.options.autolink\n },\n\n addOptions() {\n return {\n openOnClick: true,\n linkOnPaste: true,\n autolink: true,\n protocols: [],\n HTMLAttributes: {\n target: '_blank',\n rel: 'noopener noreferrer nofollow',\n class: null,\n },\n validate: undefined,\n }\n },\n\n addAttributes() {\n return {\n href: {\n default: null,\n },\n target: {\n default: this.options.HTMLAttributes.target,\n },\n rel: {\n default: this.options.HTMLAttributes.rel,\n },\n class: {\n default: this.options.HTMLAttributes.class,\n },\n }\n },\n\n parseHTML() {\n return [{ tag: 'a[href]:not([href *= \"javascript:\" i])' }]\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['a', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]\n },\n\n addCommands() {\n return {\n setLink:\n attributes => ({ chain }) => {\n return chain().setMark(this.name, attributes).setMeta('preventAutolink', true).run()\n },\n\n toggleLink:\n attributes => ({ chain }) => {\n return chain()\n .toggleMark(this.name, attributes, { extendEmptyMarkRange: true })\n .setMeta('preventAutolink', true)\n .run()\n },\n\n unsetLink:\n () => ({ chain }) => {\n return chain()\n .unsetMark(this.name, { extendEmptyMarkRange: true })\n .setMeta('preventAutolink', true)\n .run()\n },\n }\n },\n\n addPasteRules() {\n return [\n markPasteRule({\n find: text => find(text)\n .filter(link => {\n if (this.options.validate) {\n return this.options.validate(link.value)\n }\n\n return true\n })\n .filter(link => link.isLink)\n .map(link => ({\n text: link.value,\n index: link.start,\n data: link,\n })),\n type: this.type,\n getAttributes: (match, pasteEvent) => {\n const html = pasteEvent.clipboardData?.getData('text/html')\n const hrefRegex = /href=\"([^\"]*)\"/\n\n const existingLink = html?.match(hrefRegex)\n\n if (existingLink) {\n return {\n href: existingLink[1],\n }\n }\n\n return {\n href: match.data?.href,\n }\n },\n }),\n ]\n },\n\n addProseMirrorPlugins() {\n const plugins: Plugin[] = []\n\n if (this.options.autolink) {\n plugins.push(\n autolink({\n type: this.type,\n validate: this.options.validate,\n }),\n )\n }\n\n if (this.options.openOnClick) {\n plugins.push(\n clickHandler({\n type: this.type,\n }),\n )\n }\n\n return plugins\n },\n})\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/helpers/autolink.ts","../src/helpers/clickHandler.ts","../src/helpers/pasteHandler.ts","../src/link.ts"],"sourcesContent":["import {\n combineTransactionSteps,\n findChildrenInRange,\n getChangedRanges,\n getMarksBetween,\n NodeWithPos,\n} from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { find } from 'linkifyjs'\n\ntype AutolinkOptions = {\n type: MarkType\n validate?: (url: string) => boolean\n}\n\nexport function autolink(options: AutolinkOptions): Plugin {\n return new Plugin({\n key: new PluginKey('autolink'),\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges = transactions.some(transaction => transaction.docChanged) && !oldState.doc.eq(newState.doc)\n const preventAutolink = transactions.some(transaction => transaction.getMeta('preventAutolink'))\n\n if (!docChanges || preventAutolink) {\n return\n }\n\n const { tr } = newState\n const transform = combineTransactionSteps(oldState.doc, [...transactions])\n const changes = getChangedRanges(transform)\n\n changes.forEach(({ newRange }) => {\n // Now let’s see if we can add new links.\n const nodesInChangedRanges = findChildrenInRange(\n newState.doc,\n newRange,\n node => node.isTextblock,\n )\n\n let textBlock: NodeWithPos | undefined\n let textBeforeWhitespace: string | undefined\n\n if (nodesInChangedRanges.length > 1) {\n // Grab the first node within the changed ranges (ex. the first of two paragraphs when hitting enter).\n textBlock = nodesInChangedRanges[0]\n textBeforeWhitespace = newState.doc.textBetween(\n textBlock.pos,\n textBlock.pos + textBlock.node.nodeSize,\n undefined,\n ' ',\n )\n } else if (\n nodesInChangedRanges.length\n // We want to make sure to include the block seperator argument to treat hard breaks like spaces.\n && newState.doc.textBetween(newRange.from, newRange.to, ' ', ' ').endsWith(' ')\n ) {\n textBlock = nodesInChangedRanges[0]\n textBeforeWhitespace = newState.doc.textBetween(\n textBlock.pos,\n newRange.to,\n undefined,\n ' ',\n )\n }\n\n if (textBlock && textBeforeWhitespace) {\n const wordsBeforeWhitespace = textBeforeWhitespace.split(' ').filter(s => s !== '')\n\n if (wordsBeforeWhitespace.length <= 0) {\n return false\n }\n\n const lastWordBeforeSpace = wordsBeforeWhitespace[wordsBeforeWhitespace.length - 1]\n const lastWordAndBlockOffset = textBlock.pos + textBeforeWhitespace.lastIndexOf(lastWordBeforeSpace)\n\n if (!lastWordBeforeSpace) {\n return false\n }\n\n find(lastWordBeforeSpace)\n .filter(link => link.isLink)\n // Calculate link position.\n .map(link => ({\n ...link,\n from: lastWordAndBlockOffset + link.start + 1,\n to: lastWordAndBlockOffset + link.end + 1,\n }))\n // ignore link inside code mark\n .filter(link => {\n if (!newState.schema.marks.code) {\n return true\n }\n\n return !newState.doc.rangeHasMark(\n link.from,\n link.to,\n newState.schema.marks.code,\n )\n })\n // validate link\n .filter(link => {\n if (options.validate) {\n return options.validate(link.value)\n }\n return true\n })\n // Add link mark.\n .forEach(link => {\n if (getMarksBetween(link.from, link.to, newState.doc).some(item => item.mark.type === options.type)) {\n return\n }\n\n tr.addMark(\n link.from,\n link.to,\n options.type.create({\n href: link.href,\n }),\n )\n })\n }\n })\n\n if (!tr.steps.length) {\n return\n }\n\n return tr\n },\n })\n}\n","import { getAttributes } from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\ntype ClickHandlerOptions = {\n type: MarkType\n}\n\nexport function clickHandler(options: ClickHandlerOptions): Plugin {\n return new Plugin({\n key: new PluginKey('handleClickLink'),\n props: {\n handleClick: (view, pos, event) => {\n if (event.button !== 0) {\n return false\n }\n\n const eventTarget = event.target as HTMLElement\n\n if (eventTarget.nodeName !== 'A') {\n return false\n }\n\n const attrs = getAttributes(view.state, options.type.name)\n const link = (event.target as HTMLLinkElement)\n\n const href = link?.href ?? attrs.href\n const target = link?.target ?? attrs.target\n\n if (link && href) {\n if (view.editable) {\n window.open(href, target)\n }\n\n return true\n }\n\n return false\n },\n },\n })\n}\n","import { Editor } from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { find } from 'linkifyjs'\n\ntype PasteHandlerOptions = {\n editor: Editor\n type: MarkType\n}\n\nexport function pasteHandler(options: PasteHandlerOptions): Plugin {\n return new Plugin({\n key: new PluginKey('handlePasteLink'),\n props: {\n handlePaste: (view, event, slice) => {\n const { state } = view\n const { selection } = state\n const { empty } = selection\n\n if (empty) {\n return false\n }\n\n let textContent = ''\n\n slice.content.forEach(node => {\n textContent += node.textContent\n })\n\n const link = find(textContent).find(item => item.isLink && item.value === textContent)\n\n if (!textContent || !link) {\n return false\n }\n\n const html = event.clipboardData?.getData('text/html')\n\n const hrefRegex = /href=\"([^\"]*)\"/\n\n const existingLink = html?.match(hrefRegex)\n\n const url = existingLink ? existingLink[1] : link.href\n\n options.editor.commands.setMark(options.type, {\n href: url,\n })\n\n return true\n },\n },\n })\n}\n","import { Mark, markPasteRule, mergeAttributes } from '@tiptap/core'\nimport { Plugin } from '@tiptap/pm/state'\nimport { find, registerCustomProtocol, reset } from 'linkifyjs'\n\nimport { autolink } from './helpers/autolink.js'\nimport { clickHandler } from './helpers/clickHandler.js'\nimport { pasteHandler } from './helpers/pasteHandler.js'\n\nexport interface LinkProtocolOptions {\n scheme: string;\n optionalSlashes?: boolean;\n}\n\nexport interface LinkOptions {\n /**\n * If enabled, it adds links as you type.\n */\n autolink: boolean\n /**\n * An array of custom protocols to be registered with linkifyjs.\n */\n protocols: Array<LinkProtocolOptions | string>\n /**\n * If enabled, links will be opened on click.\n */\n openOnClick: boolean\n /**\n * Adds a link to the current selection if the pasted content only contains an url.\n */\n linkOnPaste: boolean\n /**\n * A list of HTML attributes to be rendered.\n */\n HTMLAttributes: Record<string, any>\n /**\n * A validation function that modifies link verification for the auto linker.\n * @param url - The url to be validated.\n * @returns - True if the url is valid, false otherwise.\n */\n validate?: (url: string) => boolean\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n link: {\n /**\n * Set a link mark\n */\n setLink: (attributes: { href: string; target?: string | null; rel?: string | null; class?: string | null }) => ReturnType\n /**\n * Toggle a link mark\n */\n toggleLink: (attributes: { href: string; target?: string | null; rel?: string | null; class?: string | null }) => ReturnType\n /**\n * Unset a link mark\n */\n unsetLink: () => ReturnType\n }\n }\n}\n\nexport const Link = Mark.create<LinkOptions>({\n name: 'link',\n\n priority: 1000,\n\n keepOnSplit: false,\n\n onCreate() {\n this.options.protocols.forEach(protocol => {\n if (typeof protocol === 'string') {\n registerCustomProtocol(protocol)\n return\n }\n registerCustomProtocol(protocol.scheme, protocol.optionalSlashes)\n })\n },\n\n onDestroy() {\n reset()\n },\n\n inclusive() {\n return this.options.autolink\n },\n\n addOptions() {\n return {\n openOnClick: true,\n linkOnPaste: true,\n autolink: true,\n protocols: [],\n HTMLAttributes: {\n target: '_blank',\n rel: 'noopener noreferrer nofollow',\n class: null,\n },\n validate: undefined,\n }\n },\n\n addAttributes() {\n return {\n href: {\n default: null,\n },\n target: {\n default: this.options.HTMLAttributes.target,\n },\n rel: {\n default: this.options.HTMLAttributes.rel,\n },\n class: {\n default: this.options.HTMLAttributes.class,\n },\n }\n },\n\n parseHTML() {\n return [{ tag: 'a[href]:not([href *= \"javascript:\" i])' }]\n },\n\n renderHTML({ HTMLAttributes }) {\n // False positive; we're explicitly checking for javascript: links to ignore them\n // eslint-disable-next-line no-script-url\n if (HTMLAttributes.href?.startsWith('javascript:')) {\n // strip out the href\n return ['a', mergeAttributes(this.options.HTMLAttributes, { ...HTMLAttributes, href: '' }), 0]\n }\n return ['a', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]\n },\n\n addCommands() {\n return {\n setLink:\n attributes => ({ chain }) => {\n return chain().setMark(this.name, attributes).setMeta('preventAutolink', true).run()\n },\n\n toggleLink:\n attributes => ({ chain }) => {\n return chain()\n .toggleMark(this.name, attributes, { extendEmptyMarkRange: true })\n .setMeta('preventAutolink', true)\n .run()\n },\n\n unsetLink:\n () => ({ chain }) => {\n return chain()\n .unsetMark(this.name, { extendEmptyMarkRange: true })\n .setMeta('preventAutolink', true)\n .run()\n },\n }\n },\n\n addPasteRules() {\n return [\n markPasteRule({\n find: text => find(text)\n .filter(link => {\n if (this.options.validate) {\n return this.options.validate(link.value)\n }\n\n return true\n })\n .filter(link => link.isLink)\n .map(link => ({\n text: link.value,\n index: link.start,\n data: link,\n })),\n type: this.type,\n getAttributes: (match, pasteEvent) => {\n const html = pasteEvent?.clipboardData?.getData('text/html')\n const hrefRegex = /href=\"([^\"]*)\"/\n\n const existingLink = html?.match(hrefRegex)\n\n if (existingLink) {\n return {\n href: existingLink[1],\n }\n }\n\n return {\n href: match.data?.href,\n }\n },\n }),\n ]\n },\n\n addProseMirrorPlugins() {\n const plugins: Plugin[] = []\n\n if (this.options.autolink) {\n plugins.push(\n autolink({\n type: this.type,\n validate: this.options.validate,\n }),\n )\n }\n\n if (this.options.openOnClick) {\n plugins.push(\n clickHandler({\n type: this.type,\n }),\n )\n }\n\n if (this.options.linkOnPaste) {\n plugins.push(\n pasteHandler({\n editor: this.editor,\n type: this.type,\n }),\n )\n }\n\n return plugins\n },\n})\n"],"names":[],"mappings":"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"}
package/dist/index.umd.js CHANGED
@@ -112,6 +112,39 @@
112
112
  });
113
113
  }
114
114
 
115
+ function pasteHandler(options) {
116
+ return new state.Plugin({
117
+ key: new state.PluginKey('handlePasteLink'),
118
+ props: {
119
+ handlePaste: (view, event, slice) => {
120
+ var _a;
121
+ const { state } = view;
122
+ const { selection } = state;
123
+ const { empty } = selection;
124
+ if (empty) {
125
+ return false;
126
+ }
127
+ let textContent = '';
128
+ slice.content.forEach(node => {
129
+ textContent += node.textContent;
130
+ });
131
+ const link = linkifyjs.find(textContent).find(item => item.isLink && item.value === textContent);
132
+ if (!textContent || !link) {
133
+ return false;
134
+ }
135
+ const html = (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/html');
136
+ const hrefRegex = /href="([^"]*)"/;
137
+ const existingLink = html === null || html === void 0 ? void 0 : html.match(hrefRegex);
138
+ const url = existingLink ? existingLink[1] : link.href;
139
+ options.editor.commands.setMark(options.type, {
140
+ href: url,
141
+ });
142
+ return true;
143
+ },
144
+ },
145
+ });
146
+ }
147
+
115
148
  const Link = core.Mark.create({
116
149
  name: 'link',
117
150
  priority: 1000,
@@ -165,6 +198,13 @@
165
198
  return [{ tag: 'a[href]:not([href *= "javascript:" i])' }];
166
199
  },
167
200
  renderHTML({ HTMLAttributes }) {
201
+ var _a;
202
+ // False positive; we're explicitly checking for javascript: links to ignore them
203
+ // eslint-disable-next-line no-script-url
204
+ if ((_a = HTMLAttributes.href) === null || _a === void 0 ? void 0 : _a.startsWith('javascript:')) {
205
+ // strip out the href
206
+ return ['a', core.mergeAttributes(this.options.HTMLAttributes, { ...HTMLAttributes, href: '' }), 0];
207
+ }
168
208
  return ['a', core.mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
169
209
  },
170
210
  addCommands() {
@@ -205,7 +245,7 @@
205
245
  type: this.type,
206
246
  getAttributes: (match, pasteEvent) => {
207
247
  var _a, _b;
208
- const html = (_a = pasteEvent.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/html');
248
+ const html = (_a = pasteEvent === null || pasteEvent === void 0 ? void 0 : pasteEvent.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/html');
209
249
  const hrefRegex = /href="([^"]*)"/;
210
250
  const existingLink = html === null || html === void 0 ? void 0 : html.match(hrefRegex);
211
251
  if (existingLink) {
@@ -233,6 +273,12 @@
233
273
  type: this.type,
234
274
  }));
235
275
  }
276
+ if (this.options.linkOnPaste) {
277
+ plugins.push(pasteHandler({
278
+ editor: this.editor,
279
+ type: this.type,
280
+ }));
281
+ }
236
282
  return plugins;
237
283
  },
238
284
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.js","sources":["../src/helpers/autolink.ts","../src/helpers/clickHandler.ts","../src/link.ts"],"sourcesContent":["import {\n combineTransactionSteps,\n findChildrenInRange,\n getChangedRanges,\n getMarksBetween,\n NodeWithPos,\n} from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { find } from 'linkifyjs'\n\ntype AutolinkOptions = {\n type: MarkType\n validate?: (url: string) => boolean\n}\n\nexport function autolink(options: AutolinkOptions): Plugin {\n return new Plugin({\n key: new PluginKey('autolink'),\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges = transactions.some(transaction => transaction.docChanged) && !oldState.doc.eq(newState.doc)\n const preventAutolink = transactions.some(transaction => transaction.getMeta('preventAutolink'))\n\n if (!docChanges || preventAutolink) {\n return\n }\n\n const { tr } = newState\n const transform = combineTransactionSteps(oldState.doc, [...transactions])\n const changes = getChangedRanges(transform)\n\n changes.forEach(({ newRange }) => {\n // Now let’s see if we can add new links.\n const nodesInChangedRanges = findChildrenInRange(\n newState.doc,\n newRange,\n node => node.isTextblock,\n )\n\n let textBlock: NodeWithPos | undefined\n let textBeforeWhitespace: string | undefined\n\n if (nodesInChangedRanges.length > 1) {\n // Grab the first node within the changed ranges (ex. the first of two paragraphs when hitting enter).\n textBlock = nodesInChangedRanges[0]\n textBeforeWhitespace = newState.doc.textBetween(\n textBlock.pos,\n textBlock.pos + textBlock.node.nodeSize,\n undefined,\n ' ',\n )\n } else if (\n nodesInChangedRanges.length\n // We want to make sure to include the block seperator argument to treat hard breaks like spaces.\n && newState.doc.textBetween(newRange.from, newRange.to, ' ', ' ').endsWith(' ')\n ) {\n textBlock = nodesInChangedRanges[0]\n textBeforeWhitespace = newState.doc.textBetween(\n textBlock.pos,\n newRange.to,\n undefined,\n ' ',\n )\n }\n\n if (textBlock && textBeforeWhitespace) {\n const wordsBeforeWhitespace = textBeforeWhitespace.split(' ').filter(s => s !== '')\n\n if (wordsBeforeWhitespace.length <= 0) {\n return false\n }\n\n const lastWordBeforeSpace = wordsBeforeWhitespace[wordsBeforeWhitespace.length - 1]\n const lastWordAndBlockOffset = textBlock.pos + textBeforeWhitespace.lastIndexOf(lastWordBeforeSpace)\n\n if (!lastWordBeforeSpace) {\n return false\n }\n\n find(lastWordBeforeSpace)\n .filter(link => link.isLink)\n // Calculate link position.\n .map(link => ({\n ...link,\n from: lastWordAndBlockOffset + link.start + 1,\n to: lastWordAndBlockOffset + link.end + 1,\n }))\n // ignore link inside code mark\n .filter(link => {\n if (!newState.schema.marks.code) {\n return true\n }\n\n return !newState.doc.rangeHasMark(\n link.from,\n link.to,\n newState.schema.marks.code,\n )\n })\n // validate link\n .filter(link => {\n if (options.validate) {\n return options.validate(link.value)\n }\n return true\n })\n // Add link mark.\n .forEach(link => {\n if (getMarksBetween(link.from, link.to, newState.doc).some(item => item.mark.type === options.type)) {\n return\n }\n\n tr.addMark(\n link.from,\n link.to,\n options.type.create({\n href: link.href,\n }),\n )\n })\n }\n })\n\n if (!tr.steps.length) {\n return\n }\n\n return tr\n },\n })\n}\n","import { getAttributes } from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\ntype ClickHandlerOptions = {\n type: MarkType\n}\n\nexport function clickHandler(options: ClickHandlerOptions): Plugin {\n return new Plugin({\n key: new PluginKey('handleClickLink'),\n props: {\n handleClick: (view, pos, event) => {\n if (event.button !== 0) {\n return false\n }\n\n const eventTarget = event.target as HTMLElement\n\n if (eventTarget.nodeName !== 'A') {\n return false\n }\n\n const attrs = getAttributes(view.state, options.type.name)\n const link = (event.target as HTMLLinkElement)\n\n const href = link?.href ?? attrs.href\n const target = link?.target ?? attrs.target\n\n if (link && href) {\n if (view.editable) {\n window.open(href, target)\n }\n\n return true\n }\n\n return false\n },\n },\n })\n}\n","import { Mark, markPasteRule, mergeAttributes } from '@tiptap/core'\nimport { Plugin } from '@tiptap/pm/state'\nimport { find, registerCustomProtocol, reset } from 'linkifyjs'\n\nimport { autolink } from './helpers/autolink.js'\nimport { clickHandler } from './helpers/clickHandler.js'\n\nexport interface LinkProtocolOptions {\n scheme: string;\n optionalSlashes?: boolean;\n}\n\nexport interface LinkOptions {\n /**\n * If enabled, it adds links as you type.\n */\n autolink: boolean\n /**\n * An array of custom protocols to be registered with linkifyjs.\n */\n protocols: Array<LinkProtocolOptions | string>\n /**\n * If enabled, links will be opened on click.\n */\n openOnClick: boolean\n /**\n * Adds a link to the current selection if the pasted content only contains an url.\n */\n linkOnPaste: boolean\n /**\n * A list of HTML attributes to be rendered.\n */\n HTMLAttributes: Record<string, any>\n /**\n * A validation function that modifies link verification for the auto linker.\n * @param url - The url to be validated.\n * @returns - True if the url is valid, false otherwise.\n */\n validate?: (url: string) => boolean\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n link: {\n /**\n * Set a link mark\n */\n setLink: (attributes: { href: string; target?: string | null; rel?: string | null; class?: string | null }) => ReturnType\n /**\n * Toggle a link mark\n */\n toggleLink: (attributes: { href: string; target?: string | null; rel?: string | null; class?: string | null }) => ReturnType\n /**\n * Unset a link mark\n */\n unsetLink: () => ReturnType\n }\n }\n}\n\nexport const Link = Mark.create<LinkOptions>({\n name: 'link',\n\n priority: 1000,\n\n keepOnSplit: false,\n\n onCreate() {\n this.options.protocols.forEach(protocol => {\n if (typeof protocol === 'string') {\n registerCustomProtocol(protocol)\n return\n }\n registerCustomProtocol(protocol.scheme, protocol.optionalSlashes)\n })\n },\n\n onDestroy() {\n reset()\n },\n\n inclusive() {\n return this.options.autolink\n },\n\n addOptions() {\n return {\n openOnClick: true,\n linkOnPaste: true,\n autolink: true,\n protocols: [],\n HTMLAttributes: {\n target: '_blank',\n rel: 'noopener noreferrer nofollow',\n class: null,\n },\n validate: undefined,\n }\n },\n\n addAttributes() {\n return {\n href: {\n default: null,\n },\n target: {\n default: this.options.HTMLAttributes.target,\n },\n rel: {\n default: this.options.HTMLAttributes.rel,\n },\n class: {\n default: this.options.HTMLAttributes.class,\n },\n }\n },\n\n parseHTML() {\n return [{ tag: 'a[href]:not([href *= \"javascript:\" i])' }]\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['a', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]\n },\n\n addCommands() {\n return {\n setLink:\n attributes => ({ chain }) => {\n return chain().setMark(this.name, attributes).setMeta('preventAutolink', true).run()\n },\n\n toggleLink:\n attributes => ({ chain }) => {\n return chain()\n .toggleMark(this.name, attributes, { extendEmptyMarkRange: true })\n .setMeta('preventAutolink', true)\n .run()\n },\n\n unsetLink:\n () => ({ chain }) => {\n return chain()\n .unsetMark(this.name, { extendEmptyMarkRange: true })\n .setMeta('preventAutolink', true)\n .run()\n },\n }\n },\n\n addPasteRules() {\n return [\n markPasteRule({\n find: text => find(text)\n .filter(link => {\n if (this.options.validate) {\n return this.options.validate(link.value)\n }\n\n return true\n })\n .filter(link => link.isLink)\n .map(link => ({\n text: link.value,\n index: link.start,\n data: link,\n })),\n type: this.type,\n getAttributes: (match, pasteEvent) => {\n const html = pasteEvent.clipboardData?.getData('text/html')\n const hrefRegex = /href=\"([^\"]*)\"/\n\n const existingLink = html?.match(hrefRegex)\n\n if (existingLink) {\n return {\n href: existingLink[1],\n }\n }\n\n return {\n href: match.data?.href,\n }\n },\n }),\n ]\n },\n\n addProseMirrorPlugins() {\n const plugins: Plugin[] = []\n\n if (this.options.autolink) {\n plugins.push(\n autolink({\n type: this.type,\n validate: this.options.validate,\n }),\n )\n }\n\n if (this.options.openOnClick) {\n plugins.push(\n clickHandler({\n type: this.type,\n }),\n )\n }\n\n return plugins\n },\n})\n"],"names":["Plugin","PluginKey","combineTransactionSteps","getChangedRanges","findChildrenInRange","find","getMarksBetween","getAttributes","Mark","registerCustomProtocol","reset","mergeAttributes","markPasteRule"],"mappings":"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"}
1
+ {"version":3,"file":"index.umd.js","sources":["../src/helpers/autolink.ts","../src/helpers/clickHandler.ts","../src/helpers/pasteHandler.ts","../src/link.ts"],"sourcesContent":["import {\n combineTransactionSteps,\n findChildrenInRange,\n getChangedRanges,\n getMarksBetween,\n NodeWithPos,\n} from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { find } from 'linkifyjs'\n\ntype AutolinkOptions = {\n type: MarkType\n validate?: (url: string) => boolean\n}\n\nexport function autolink(options: AutolinkOptions): Plugin {\n return new Plugin({\n key: new PluginKey('autolink'),\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges = transactions.some(transaction => transaction.docChanged) && !oldState.doc.eq(newState.doc)\n const preventAutolink = transactions.some(transaction => transaction.getMeta('preventAutolink'))\n\n if (!docChanges || preventAutolink) {\n return\n }\n\n const { tr } = newState\n const transform = combineTransactionSteps(oldState.doc, [...transactions])\n const changes = getChangedRanges(transform)\n\n changes.forEach(({ newRange }) => {\n // Now let’s see if we can add new links.\n const nodesInChangedRanges = findChildrenInRange(\n newState.doc,\n newRange,\n node => node.isTextblock,\n )\n\n let textBlock: NodeWithPos | undefined\n let textBeforeWhitespace: string | undefined\n\n if (nodesInChangedRanges.length > 1) {\n // Grab the first node within the changed ranges (ex. the first of two paragraphs when hitting enter).\n textBlock = nodesInChangedRanges[0]\n textBeforeWhitespace = newState.doc.textBetween(\n textBlock.pos,\n textBlock.pos + textBlock.node.nodeSize,\n undefined,\n ' ',\n )\n } else if (\n nodesInChangedRanges.length\n // We want to make sure to include the block seperator argument to treat hard breaks like spaces.\n && newState.doc.textBetween(newRange.from, newRange.to, ' ', ' ').endsWith(' ')\n ) {\n textBlock = nodesInChangedRanges[0]\n textBeforeWhitespace = newState.doc.textBetween(\n textBlock.pos,\n newRange.to,\n undefined,\n ' ',\n )\n }\n\n if (textBlock && textBeforeWhitespace) {\n const wordsBeforeWhitespace = textBeforeWhitespace.split(' ').filter(s => s !== '')\n\n if (wordsBeforeWhitespace.length <= 0) {\n return false\n }\n\n const lastWordBeforeSpace = wordsBeforeWhitespace[wordsBeforeWhitespace.length - 1]\n const lastWordAndBlockOffset = textBlock.pos + textBeforeWhitespace.lastIndexOf(lastWordBeforeSpace)\n\n if (!lastWordBeforeSpace) {\n return false\n }\n\n find(lastWordBeforeSpace)\n .filter(link => link.isLink)\n // Calculate link position.\n .map(link => ({\n ...link,\n from: lastWordAndBlockOffset + link.start + 1,\n to: lastWordAndBlockOffset + link.end + 1,\n }))\n // ignore link inside code mark\n .filter(link => {\n if (!newState.schema.marks.code) {\n return true\n }\n\n return !newState.doc.rangeHasMark(\n link.from,\n link.to,\n newState.schema.marks.code,\n )\n })\n // validate link\n .filter(link => {\n if (options.validate) {\n return options.validate(link.value)\n }\n return true\n })\n // Add link mark.\n .forEach(link => {\n if (getMarksBetween(link.from, link.to, newState.doc).some(item => item.mark.type === options.type)) {\n return\n }\n\n tr.addMark(\n link.from,\n link.to,\n options.type.create({\n href: link.href,\n }),\n )\n })\n }\n })\n\n if (!tr.steps.length) {\n return\n }\n\n return tr\n },\n })\n}\n","import { getAttributes } from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\n\ntype ClickHandlerOptions = {\n type: MarkType\n}\n\nexport function clickHandler(options: ClickHandlerOptions): Plugin {\n return new Plugin({\n key: new PluginKey('handleClickLink'),\n props: {\n handleClick: (view, pos, event) => {\n if (event.button !== 0) {\n return false\n }\n\n const eventTarget = event.target as HTMLElement\n\n if (eventTarget.nodeName !== 'A') {\n return false\n }\n\n const attrs = getAttributes(view.state, options.type.name)\n const link = (event.target as HTMLLinkElement)\n\n const href = link?.href ?? attrs.href\n const target = link?.target ?? attrs.target\n\n if (link && href) {\n if (view.editable) {\n window.open(href, target)\n }\n\n return true\n }\n\n return false\n },\n },\n })\n}\n","import { Editor } from '@tiptap/core'\nimport { MarkType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { find } from 'linkifyjs'\n\ntype PasteHandlerOptions = {\n editor: Editor\n type: MarkType\n}\n\nexport function pasteHandler(options: PasteHandlerOptions): Plugin {\n return new Plugin({\n key: new PluginKey('handlePasteLink'),\n props: {\n handlePaste: (view, event, slice) => {\n const { state } = view\n const { selection } = state\n const { empty } = selection\n\n if (empty) {\n return false\n }\n\n let textContent = ''\n\n slice.content.forEach(node => {\n textContent += node.textContent\n })\n\n const link = find(textContent).find(item => item.isLink && item.value === textContent)\n\n if (!textContent || !link) {\n return false\n }\n\n const html = event.clipboardData?.getData('text/html')\n\n const hrefRegex = /href=\"([^\"]*)\"/\n\n const existingLink = html?.match(hrefRegex)\n\n const url = existingLink ? existingLink[1] : link.href\n\n options.editor.commands.setMark(options.type, {\n href: url,\n })\n\n return true\n },\n },\n })\n}\n","import { Mark, markPasteRule, mergeAttributes } from '@tiptap/core'\nimport { Plugin } from '@tiptap/pm/state'\nimport { find, registerCustomProtocol, reset } from 'linkifyjs'\n\nimport { autolink } from './helpers/autolink.js'\nimport { clickHandler } from './helpers/clickHandler.js'\nimport { pasteHandler } from './helpers/pasteHandler.js'\n\nexport interface LinkProtocolOptions {\n scheme: string;\n optionalSlashes?: boolean;\n}\n\nexport interface LinkOptions {\n /**\n * If enabled, it adds links as you type.\n */\n autolink: boolean\n /**\n * An array of custom protocols to be registered with linkifyjs.\n */\n protocols: Array<LinkProtocolOptions | string>\n /**\n * If enabled, links will be opened on click.\n */\n openOnClick: boolean\n /**\n * Adds a link to the current selection if the pasted content only contains an url.\n */\n linkOnPaste: boolean\n /**\n * A list of HTML attributes to be rendered.\n */\n HTMLAttributes: Record<string, any>\n /**\n * A validation function that modifies link verification for the auto linker.\n * @param url - The url to be validated.\n * @returns - True if the url is valid, false otherwise.\n */\n validate?: (url: string) => boolean\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n link: {\n /**\n * Set a link mark\n */\n setLink: (attributes: { href: string; target?: string | null; rel?: string | null; class?: string | null }) => ReturnType\n /**\n * Toggle a link mark\n */\n toggleLink: (attributes: { href: string; target?: string | null; rel?: string | null; class?: string | null }) => ReturnType\n /**\n * Unset a link mark\n */\n unsetLink: () => ReturnType\n }\n }\n}\n\nexport const Link = Mark.create<LinkOptions>({\n name: 'link',\n\n priority: 1000,\n\n keepOnSplit: false,\n\n onCreate() {\n this.options.protocols.forEach(protocol => {\n if (typeof protocol === 'string') {\n registerCustomProtocol(protocol)\n return\n }\n registerCustomProtocol(protocol.scheme, protocol.optionalSlashes)\n })\n },\n\n onDestroy() {\n reset()\n },\n\n inclusive() {\n return this.options.autolink\n },\n\n addOptions() {\n return {\n openOnClick: true,\n linkOnPaste: true,\n autolink: true,\n protocols: [],\n HTMLAttributes: {\n target: '_blank',\n rel: 'noopener noreferrer nofollow',\n class: null,\n },\n validate: undefined,\n }\n },\n\n addAttributes() {\n return {\n href: {\n default: null,\n },\n target: {\n default: this.options.HTMLAttributes.target,\n },\n rel: {\n default: this.options.HTMLAttributes.rel,\n },\n class: {\n default: this.options.HTMLAttributes.class,\n },\n }\n },\n\n parseHTML() {\n return [{ tag: 'a[href]:not([href *= \"javascript:\" i])' }]\n },\n\n renderHTML({ HTMLAttributes }) {\n // False positive; we're explicitly checking for javascript: links to ignore them\n // eslint-disable-next-line no-script-url\n if (HTMLAttributes.href?.startsWith('javascript:')) {\n // strip out the href\n return ['a', mergeAttributes(this.options.HTMLAttributes, { ...HTMLAttributes, href: '' }), 0]\n }\n return ['a', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]\n },\n\n addCommands() {\n return {\n setLink:\n attributes => ({ chain }) => {\n return chain().setMark(this.name, attributes).setMeta('preventAutolink', true).run()\n },\n\n toggleLink:\n attributes => ({ chain }) => {\n return chain()\n .toggleMark(this.name, attributes, { extendEmptyMarkRange: true })\n .setMeta('preventAutolink', true)\n .run()\n },\n\n unsetLink:\n () => ({ chain }) => {\n return chain()\n .unsetMark(this.name, { extendEmptyMarkRange: true })\n .setMeta('preventAutolink', true)\n .run()\n },\n }\n },\n\n addPasteRules() {\n return [\n markPasteRule({\n find: text => find(text)\n .filter(link => {\n if (this.options.validate) {\n return this.options.validate(link.value)\n }\n\n return true\n })\n .filter(link => link.isLink)\n .map(link => ({\n text: link.value,\n index: link.start,\n data: link,\n })),\n type: this.type,\n getAttributes: (match, pasteEvent) => {\n const html = pasteEvent?.clipboardData?.getData('text/html')\n const hrefRegex = /href=\"([^\"]*)\"/\n\n const existingLink = html?.match(hrefRegex)\n\n if (existingLink) {\n return {\n href: existingLink[1],\n }\n }\n\n return {\n href: match.data?.href,\n }\n },\n }),\n ]\n },\n\n addProseMirrorPlugins() {\n const plugins: Plugin[] = []\n\n if (this.options.autolink) {\n plugins.push(\n autolink({\n type: this.type,\n validate: this.options.validate,\n }),\n )\n }\n\n if (this.options.openOnClick) {\n plugins.push(\n clickHandler({\n type: this.type,\n }),\n )\n }\n\n if (this.options.linkOnPaste) {\n plugins.push(\n pasteHandler({\n editor: this.editor,\n type: this.type,\n }),\n )\n }\n\n return plugins\n },\n})\n"],"names":["Plugin","PluginKey","combineTransactionSteps","getChangedRanges","findChildrenInRange","find","getMarksBetween","getAttributes","Mark","registerCustomProtocol","reset","mergeAttributes","markPasteRule"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { Editor } from '@tiptap/core';
2
+ import { MarkType } from '@tiptap/pm/model';
3
+ import { Plugin } from '@tiptap/pm/state';
4
+ declare type PasteHandlerOptions = {
5
+ editor: Editor;
6
+ type: MarkType;
7
+ };
8
+ export declare function pasteHandler(options: PasteHandlerOptions): Plugin;
9
+ export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tiptap/extension-link",
3
3
  "description": "link extension for tiptap",
4
- "version": "2.1.11",
4
+ "version": "2.1.13",
5
5
  "homepage": "https://tiptap.dev",
6
6
  "keywords": [
7
7
  "tiptap",
@@ -32,8 +32,8 @@
32
32
  "linkifyjs": "^4.1.0"
33
33
  },
34
34
  "devDependencies": {
35
- "@tiptap/core": "^2.1.11",
36
- "@tiptap/pm": "^2.1.11"
35
+ "@tiptap/core": "^2.1.13",
36
+ "@tiptap/pm": "^2.1.13"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@tiptap/core": "^2.0.0",
@@ -0,0 +1,52 @@
1
+ import { Editor } from '@tiptap/core'
2
+ import { MarkType } from '@tiptap/pm/model'
3
+ import { Plugin, PluginKey } from '@tiptap/pm/state'
4
+ import { find } from 'linkifyjs'
5
+
6
+ type PasteHandlerOptions = {
7
+ editor: Editor
8
+ type: MarkType
9
+ }
10
+
11
+ export function pasteHandler(options: PasteHandlerOptions): Plugin {
12
+ return new Plugin({
13
+ key: new PluginKey('handlePasteLink'),
14
+ props: {
15
+ handlePaste: (view, event, slice) => {
16
+ const { state } = view
17
+ const { selection } = state
18
+ const { empty } = selection
19
+
20
+ if (empty) {
21
+ return false
22
+ }
23
+
24
+ let textContent = ''
25
+
26
+ slice.content.forEach(node => {
27
+ textContent += node.textContent
28
+ })
29
+
30
+ const link = find(textContent).find(item => item.isLink && item.value === textContent)
31
+
32
+ if (!textContent || !link) {
33
+ return false
34
+ }
35
+
36
+ const html = event.clipboardData?.getData('text/html')
37
+
38
+ const hrefRegex = /href="([^"]*)"/
39
+
40
+ const existingLink = html?.match(hrefRegex)
41
+
42
+ const url = existingLink ? existingLink[1] : link.href
43
+
44
+ options.editor.commands.setMark(options.type, {
45
+ href: url,
46
+ })
47
+
48
+ return true
49
+ },
50
+ },
51
+ })
52
+ }
package/src/link.ts CHANGED
@@ -4,6 +4,7 @@ import { find, registerCustomProtocol, reset } from 'linkifyjs'
4
4
 
5
5
  import { autolink } from './helpers/autolink.js'
6
6
  import { clickHandler } from './helpers/clickHandler.js'
7
+ import { pasteHandler } from './helpers/pasteHandler.js'
7
8
 
8
9
  export interface LinkProtocolOptions {
9
10
  scheme: string;
@@ -120,6 +121,12 @@ export const Link = Mark.create<LinkOptions>({
120
121
  },
121
122
 
122
123
  renderHTML({ HTMLAttributes }) {
124
+ // False positive; we're explicitly checking for javascript: links to ignore them
125
+ // eslint-disable-next-line no-script-url
126
+ if (HTMLAttributes.href?.startsWith('javascript:')) {
127
+ // strip out the href
128
+ return ['a', mergeAttributes(this.options.HTMLAttributes, { ...HTMLAttributes, href: '' }), 0]
129
+ }
123
130
  return ['a', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]
124
131
  },
125
132
 
@@ -167,7 +174,7 @@ export const Link = Mark.create<LinkOptions>({
167
174
  })),
168
175
  type: this.type,
169
176
  getAttributes: (match, pasteEvent) => {
170
- const html = pasteEvent.clipboardData?.getData('text/html')
177
+ const html = pasteEvent?.clipboardData?.getData('text/html')
171
178
  const hrefRegex = /href="([^"]*)"/
172
179
 
173
180
  const existingLink = html?.match(hrefRegex)
@@ -206,6 +213,15 @@ export const Link = Mark.create<LinkOptions>({
206
213
  )
207
214
  }
208
215
 
216
+ if (this.options.linkOnPaste) {
217
+ plugins.push(
218
+ pasteHandler({
219
+ editor: this.editor,
220
+ type: this.type,
221
+ }),
222
+ )
223
+ }
224
+
209
225
  return plugins
210
226
  },
211
227
  })