mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
[WEB-617] fix: link behaviour fixed on formatting (#3855)
* fix: link behaviour fixed on formatting * chore: added harmful script checks for links
This commit is contained in:
parent
87eadc3c5d
commit
126d01bdc5
@ -15,9 +15,15 @@ export function clickHandler(options: ClickHandlerOptions): Plugin {
|
||||
return false;
|
||||
}
|
||||
|
||||
const eventTarget = event.target as HTMLElement;
|
||||
let a = event.target as HTMLElement;
|
||||
const els = [];
|
||||
|
||||
if (eventTarget.nodeName !== "A") {
|
||||
while (a.nodeName !== "DIV") {
|
||||
els.push(a);
|
||||
a = a.parentNode as HTMLElement;
|
||||
}
|
||||
|
||||
if (!els.find((value) => value.nodeName === "A")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -28,9 +34,7 @@ export function clickHandler(options: ClickHandlerOptions): Plugin {
|
||||
const target = link?.target ?? attrs.target;
|
||||
|
||||
if (link && href) {
|
||||
if (view.editable) {
|
||||
window.open(href, target);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -33,16 +33,8 @@ export function pasteHandler(options: PasteHandlerOptions): Plugin {
|
||||
return false;
|
||||
}
|
||||
|
||||
const html = event.clipboardData?.getData("text/html");
|
||||
|
||||
const hrefRegex = /href="([^"]*)"/;
|
||||
|
||||
const existingLink = html?.match(hrefRegex);
|
||||
|
||||
const url = existingLink ? existingLink[1] : link.href;
|
||||
|
||||
options.editor.commands.setMark(options.type, {
|
||||
href: url,
|
||||
href: link.href,
|
||||
});
|
||||
|
||||
return true;
|
||||
|
@ -1,41 +1,76 @@
|
||||
import { Mark, markPasteRule, mergeAttributes } from "@tiptap/core";
|
||||
import { Mark, markPasteRule, mergeAttributes, PasteRuleMatch } from "@tiptap/core";
|
||||
import { Plugin } from "@tiptap/pm/state";
|
||||
import { find, registerCustomProtocol, reset } from "linkifyjs";
|
||||
|
||||
import { autolink } from "src/ui/extensions/custom-link/helpers/autolink";
|
||||
import { clickHandler } from "src/ui/extensions/custom-link/helpers/clickHandler";
|
||||
import { pasteHandler } from "src/ui/extensions/custom-link/helpers/pasteHandler";
|
||||
import { autolink } from "./helpers/autolink";
|
||||
import { clickHandler } from "./helpers/clickHandler";
|
||||
import { pasteHandler } from "./helpers/pasteHandler";
|
||||
|
||||
export interface LinkProtocolOptions {
|
||||
scheme: string;
|
||||
optionalSlashes?: boolean;
|
||||
}
|
||||
|
||||
export const pasteRegex =
|
||||
/https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z]{2,}\b(?:[-a-zA-Z0-9@:%._+~#=?!&/]*)(?:[-a-zA-Z0-9@:%._+~#=?!&/]*)/gi;
|
||||
|
||||
export interface LinkOptions {
|
||||
/**
|
||||
* If enabled, it adds links as you type.
|
||||
*/
|
||||
autolink: boolean;
|
||||
inclusive: boolean;
|
||||
/**
|
||||
* An array of custom protocols to be registered with linkifyjs.
|
||||
*/
|
||||
protocols: Array<LinkProtocolOptions | string>;
|
||||
/**
|
||||
* If enabled, links will be opened on click.
|
||||
*/
|
||||
openOnClick: boolean;
|
||||
/**
|
||||
* If enabled, links will be inclusive i.e. if you move your cursor to the
|
||||
* link text, and start typing, it'll be a part of the link itself.
|
||||
*/
|
||||
inclusive: boolean;
|
||||
/**
|
||||
* Adds a link to the current selection if the pasted content only contains an url.
|
||||
*/
|
||||
linkOnPaste: boolean;
|
||||
/**
|
||||
* A list of HTML attributes to be rendered.
|
||||
*/
|
||||
HTMLAttributes: Record<string, any>;
|
||||
/**
|
||||
* A validation function that modifies link verification for the auto linker.
|
||||
* @param url - The url to be validated.
|
||||
* @returns - True if the url is valid, false otherwise.
|
||||
*/
|
||||
validate?: (url: string) => boolean;
|
||||
}
|
||||
|
||||
declare module "@tiptap/core" {
|
||||
interface Commands<ReturnType> {
|
||||
link: {
|
||||
/**
|
||||
* Set a link mark
|
||||
*/
|
||||
setLink: (attributes: {
|
||||
href: string;
|
||||
target?: string | null;
|
||||
rel?: string | null;
|
||||
class?: string | null;
|
||||
}) => ReturnType;
|
||||
/**
|
||||
* Toggle a link mark
|
||||
*/
|
||||
toggleLink: (attributes: {
|
||||
href: string;
|
||||
target?: string | null;
|
||||
rel?: string | null;
|
||||
class?: string | null;
|
||||
}) => ReturnType;
|
||||
/**
|
||||
* Unset a link mark
|
||||
*/
|
||||
unsetLink: () => ReturnType;
|
||||
};
|
||||
}
|
||||
@ -150,37 +185,31 @@ export const CustomLinkExtension = Mark.create<LinkOptions>({
|
||||
addPasteRules() {
|
||||
return [
|
||||
markPasteRule({
|
||||
find: (text) =>
|
||||
find(text)
|
||||
.filter((link) => {
|
||||
if (this.options.validate) {
|
||||
return this.options.validate(link.value);
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.filter((link) => link.isLink)
|
||||
.map((link) => ({
|
||||
find: (text) => {
|
||||
const foundLinks: PasteRuleMatch[] = [];
|
||||
|
||||
if (text) {
|
||||
const links = find(text).filter((item) => item.isLink);
|
||||
|
||||
if (links.length) {
|
||||
links.forEach((link) =>
|
||||
foundLinks.push({
|
||||
text: link.value,
|
||||
data: {
|
||||
href: link.href,
|
||||
},
|
||||
index: link.start,
|
||||
data: link,
|
||||
})),
|
||||
type: this.type,
|
||||
getAttributes: (match, pasteEvent) => {
|
||||
const html = pasteEvent?.clipboardData?.getData("text/html");
|
||||
const hrefRegex = /href="([^"]*)"/;
|
||||
|
||||
const existingLink = html?.match(hrefRegex);
|
||||
|
||||
if (existingLink) {
|
||||
return {
|
||||
href: existingLink[1],
|
||||
};
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
href: match.data?.href,
|
||||
};
|
||||
return foundLinks;
|
||||
},
|
||||
type: this.type,
|
||||
getAttributes: (match) => ({
|
||||
href: match.data?.href,
|
||||
}),
|
||||
}),
|
||||
];
|
||||
},
|
Loading…
Reference in New Issue
Block a user