mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-01-30 12:15:16 +01:00
83 lines
3.2 KiB
TypeScript
83 lines
3.2 KiB
TypeScript
import {ToolbarItem} from "./ToolbarItem";
|
||
import {linkMenu} from "../../menus/protyle";
|
||
import {hasClosestBlock, hasClosestByAttribute} from "../util/hasClosest";
|
||
import {focusByRange, focusByWbr} from "../util/selection";
|
||
import {readText} from "../util/compatibility";
|
||
import {Constants} from "../../constants";
|
||
|
||
export class Link extends ToolbarItem {
|
||
public element: HTMLElement;
|
||
|
||
constructor(protyle: IProtyle, menuItem: IMenuItem) {
|
||
super(protyle, menuItem);
|
||
// 不能用 getEventName,否则会导致光标位置变动到点击的文档中
|
||
this.element.addEventListener("click", async (event: MouseEvent & { changedTouches: MouseEvent[] }) => {
|
||
protyle.toolbar.element.classList.add("fn__none");
|
||
event.stopPropagation();
|
||
|
||
const range = protyle.toolbar.range;
|
||
const nodeElement = hasClosestBlock(range.startContainer);
|
||
if (!nodeElement) {
|
||
return;
|
||
}
|
||
const aElement = hasClosestByAttribute(range.startContainer, "data-type", "a");
|
||
if (aElement) {
|
||
linkMenu(protyle, aElement);
|
||
return;
|
||
}
|
||
|
||
const rangeString = range.toString().trim().replace(Constants.ZWSP, "");
|
||
let dataHref = "";
|
||
let dataText = "";
|
||
try {
|
||
const clipText = await readText();
|
||
// 选中链接时需忽略剪切板内容 https://ld246.com/article/1643035329737
|
||
if (protyle.lute.IsValidLinkDest(rangeString)) {
|
||
dataHref = rangeString;
|
||
} else if (protyle.lute.IsValidLinkDest(clipText)) {
|
||
dataHref = clipText;
|
||
} else {
|
||
// 360
|
||
const lastSpace = clipText.lastIndexOf(" ");
|
||
if (lastSpace > -1) {
|
||
if (protyle.lute.IsValidLinkDest(clipText.substring(lastSpace))) {
|
||
dataHref = clipText.substring(lastSpace);
|
||
dataText = clipText.substring(0, lastSpace);
|
||
}
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.log(e);
|
||
}
|
||
protyle.toolbar.setInlineMark(protyle, "a", "range", {
|
||
type: "a",
|
||
color: dataHref + (dataText ? Constants.ZWSP + dataText : "")
|
||
});
|
||
});
|
||
}
|
||
}
|
||
|
||
export const removeLink = (linkElement: HTMLElement, range?: Range) => {
|
||
const types = linkElement.getAttribute("data-type").split(" ");
|
||
if (types.length === 1) {
|
||
const linkParentElement = linkElement.parentElement;
|
||
linkElement.outerHTML = linkElement.innerHTML.replace(Constants.ZWSP, "") + "<wbr>";
|
||
if (range) {
|
||
focusByWbr(linkParentElement, range);
|
||
}
|
||
} else {
|
||
types.find((itemType, index) => {
|
||
if ("a" === itemType) {
|
||
types.splice(index, 1);
|
||
return true;
|
||
}
|
||
});
|
||
linkElement.setAttribute("data-type", types.join(" "));
|
||
linkElement.removeAttribute("data-href");
|
||
if (range) {
|
||
range.selectNodeContents(linkElement);
|
||
range.collapse(false);
|
||
focusByRange(range);
|
||
}
|
||
}
|
||
};
|