Skip to content

Commit 989fb85

Browse files
nperez0111claude
andcommitted
refactor: simplify inlined Link extension by removing unused tiptap options
Strip out carried-over options (openOnClick, enableClickSelection, linkOnPaste, protocols, validate), deprecated types (LinkProtocolOptions, LinkOptions), and verbose JSDoc comments. Inline configuration defaults directly, pre-compile the URI validation regex, and simplify the extension registration in ExtensionManager. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2cc8acd commit 989fb85

File tree

7 files changed

+97
-464
lines changed

7 files changed

+97
-464
lines changed

packages/core/src/editor/managers/ExtensionManager/extensions.ts

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ import {
2626
TableHandlesExtension,
2727
TrailingNodeExtension,
2828
} from "../../../extensions/index.js";
29-
import {
30-
DEFAULT_LINK_PROTOCOL,
31-
VALID_LINK_PROTOCOLS,
32-
} from "../../../extensions/LinkToolbar/protocols.js";
3329
import {
3430
BackgroundColorExtension,
3531
HardBreak,
@@ -49,8 +45,6 @@ import {
4945
import { ExtensionFactoryInstance } from "../../BlockNoteExtension.js";
5046
import { CollaborationExtension } from "../../../extensions/Collaboration/Collaboration.js";
5147

52-
let LINKIFY_INITIALIZED = false;
53-
5448
/**
5549
* Get all the Tiptap extensions BlockNote is configured with by default
5650
*/
@@ -78,22 +72,7 @@ export function getDefaultTiptapExtensions(
7872
SuggestionAddMark,
7973
SuggestionDeleteMark,
8074
SuggestionModificationMark,
81-
Link.extend({
82-
inclusive: false,
83-
})
84-
.extend({
85-
// Remove the title attribute to avoid unnecessary null attributes in serialized output
86-
addAttributes() {
87-
const attrs = this.parent?.() || {};
88-
delete (attrs as Record<string, unknown>).title;
89-
return attrs;
90-
},
91-
})
92-
.configure({
93-
defaultProtocol: DEFAULT_LINK_PROTOCOL,
94-
// only call this once if we have multiple editors installed. Or fix https://github.com/ueberdosis/tiptap/issues/5450
95-
protocols: LINKIFY_INITIALIZED ? [] : VALID_LINK_PROTOCOLS,
96-
}),
75+
Link,
9776
...(Object.values(editor.schema.styleSpecs).map((styleSpec) => {
9877
return styleSpec.implementation.mark.configure({
9978
editor: editor,
@@ -170,8 +149,6 @@ export function getDefaultTiptapExtensions(
170149
createDropFileExtension(editor),
171150
];
172151

173-
LINKIFY_INITIALIZED = true;
174-
175152
return tiptapExtensions;
176153
}
177154

packages/core/src/extensions/tiptap-extensions/Link/helpers/autolink.ts

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,6 @@ import {
1818
/**
1919
* Check if the provided tokens form a valid link structure, which can either be a single link token
2020
* or a link token surrounded by parentheses or square brackets.
21-
*
22-
* This ensures that only complete and valid text is hyperlinked, preventing cases where a valid
23-
* top-level domain (TLD) is immediately followed by an invalid character, like a number. For
24-
* example, with the `find` method from Linkify, entering `example.com1` would result in
25-
* `example.com` being linked and the trailing `1` left as plain text. By using the `tokenize`
26-
* method, we can perform more comprehensive validation on the input text.
2721
*/
2822
function isValidLinkStructure(tokens: LinkMatch[]) {
2923
if (tokens.length === 1) {
@@ -42,36 +36,23 @@ type AutolinkOptions = {
4236
defaultProtocol: string;
4337
validate: (url: string) => boolean;
4438
shouldAutoLink: (url: string) => boolean;
45-
protocols: Array<{ scheme: string; optionalSlashes?: boolean } | string>;
4639
};
4740

4841
/**
49-
* This plugin allows you to automatically add links to your editor.
50-
* @param options The plugin options
51-
* @returns The plugin instance
42+
* Plugin that automatically adds link marks when typing URLs.
5243
*/
5344
export function autolink(options: AutolinkOptions): Plugin {
5445
return new Plugin({
5546
key: new PluginKey("autolink"),
5647
appendTransaction: (transactions, oldState, newState) => {
57-
/**
58-
* Does the transaction change the document?
59-
*/
6048
const docChanges =
6149
transactions.some((transaction) => transaction.docChanged) &&
6250
!oldState.doc.eq(newState.doc);
6351

64-
/**
65-
* Prevent autolink if the transaction is not a document change or if the transaction has the meta `preventAutolink`.
66-
*/
6752
const preventAutolink = transactions.some((transaction) =>
6853
transaction.getMeta("preventAutolink")
6954
);
7055

71-
/**
72-
* Prevent autolink if the transaction is not a document change
73-
* or if the transaction has the meta `preventAutolink`.
74-
*/
7556
if (!docChanges || preventAutolink) {
7657
return;
7758
}
@@ -83,7 +64,6 @@ export function autolink(options: AutolinkOptions): Plugin {
8364
const changes = getChangedRanges(transform);
8465

8566
changes.forEach(({ newRange }) => {
86-
// Now let's see if we can add new links.
8767
const nodesInChangedRanges = findChildrenInRange(
8868
newState.doc,
8969
newRange,
@@ -94,7 +74,6 @@ export function autolink(options: AutolinkOptions): Plugin {
9474
let textBeforeWhitespace: string | undefined;
9575

9676
if (nodesInChangedRanges.length > 1) {
97-
// Grab the first node within the changed ranges (ex. the first of two paragraphs when hitting enter).
9877
textBlock = nodesInChangedRanges[0];
9978
textBeforeWhitespace = newState.doc.textBetween(
10079
textBlock.pos,
@@ -151,7 +130,6 @@ export function autolink(options: AutolinkOptions): Plugin {
151130

152131
linksBeforeSpace
153132
.filter((link) => link.isLink)
154-
// Calculate link position.
155133
.map((link) => ({
156134
...link,
157135
from: lastWordAndBlockOffset + link.start + 1,
@@ -169,11 +147,8 @@ export function autolink(options: AutolinkOptions): Plugin {
169147
newState.schema.marks.code
170148
);
171149
})
172-
// validate link
173150
.filter((link) => options.validate(link.value))
174-
// check whether should autolink
175151
.filter((link) => options.shouldAutoLink(link.value))
176-
// Add link mark.
177152
.forEach((link) => {
178153
if (
179154
getMarksBetween(link.from, link.to, newState.doc).some(

packages/core/src/extensions/tiptap-extensions/Link/helpers/clickHandler.ts

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import { Plugin, PluginKey } from "@tiptap/pm/state";
66
type ClickHandlerOptions = {
77
type: MarkType;
88
editor: Editor;
9-
openOnClick?: boolean;
10-
enableClickSelection?: boolean;
119
};
1210

1311
export function clickHandler(options: ClickHandlerOptions): Plugin {
@@ -48,27 +46,16 @@ export function clickHandler(options: ClickHandlerOptions): Plugin {
4846
return false;
4947
}
5048

51-
let handled = false;
49+
const attrs = getAttributes(view.state, options.type.name);
50+
const href = link.href ?? attrs.href;
51+
const target = link.target ?? attrs.target;
5252

53-
if (options.enableClickSelection) {
54-
const commandResult = options.editor.commands.extendMarkRange(
55-
options.type.name
56-
);
57-
handled = commandResult;
53+
if (href) {
54+
window.open(href, target);
55+
return true;
5856
}
5957

60-
if (options.openOnClick) {
61-
const attrs = getAttributes(view.state, options.type.name);
62-
const href = link.href ?? attrs.href;
63-
const target = link.target ?? attrs.target;
64-
65-
if (href) {
66-
window.open(href, target);
67-
handled = true;
68-
}
69-
}
70-
71-
return handled;
58+
return false;
7259
},
7360
},
7461
});

packages/core/src/extensions/tiptap-extensions/Link/helpers/linkDetector.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ const SPECIAL_HOSTS = new Set(["localhost"]);
3737
// Regex building blocks
3838
// ---------------------------------------------------------------------------
3939

40-
// URL-safe characters in path/query/fragment (everything except whitespace)
41-
const URL_BODY = "[^\\s]";
4240
// Characters that are unlikely to be part of a URL when they appear at the end
4341
const TRAILING_PUNCT = /[.,;:!?"']+$/;
4442

packages/core/src/extensions/tiptap-extensions/Link/helpers/pasteHandler.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import type { Editor } from "@tiptap/core";
22
import type { MarkType } from "@tiptap/pm/model";
33
import { Plugin, PluginKey } from "@tiptap/pm/state";
4-
import type { LinkOptions } from "../link.js";
54
import { findLinks } from "./linkDetector.js";
65

76
type PasteHandlerOptions = {
87
editor: Editor;
98
defaultProtocol: string;
109
type: MarkType;
11-
shouldAutoLink?: LinkOptions["shouldAutoLink"];
10+
shouldAutoLink?: (url: string) => boolean;
1211
};
1312

1413
export function pasteHandler(options: PasteHandlerOptions): Plugin {
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
export { Link } from "./link.js";
2-
export type { LinkOptions, LinkProtocolOptions } from "./link.js";
3-
export { isAllowedUri, pasteRegex } from "./link.js";
2+
export { isAllowedUri } from "./link.js";

0 commit comments

Comments
 (0)