import {getEventName, updateHotkeyTip} from "../util/compatibility";
import {ToolbarItem} from "./ToolbarItem";
import {setPosition} from "../../util/setPosition";
import {getSelectionPosition} from "../util/selection";
import {Constants} from "../../constants";
import {hasClosestByAttribute} from "../util/hasClosest";
export class Font extends ToolbarItem {
public element: HTMLElement;
constructor(protyle: IProtyle, menuItem: IMenuItem) {
super(protyle, menuItem);
this.element.addEventListener(getEventName(), () => {
if (protyle.toolbar.range.toString() === "") {
return;
}
protyle.toolbar.element.classList.add("fn__none");
protyle.toolbar.subElement.innerHTML = "";
protyle.toolbar.subElement.style.width = "";
protyle.toolbar.subElement.style.padding = "";
protyle.toolbar.subElement.append(fontMenu(protyle));
protyle.toolbar.subElement.classList.remove("fn__none");
protyle.toolbar.subElementCloseCB = undefined;
const position = getSelectionPosition(protyle.wysiwyg.element, protyle.toolbar.range);
setPosition(protyle.toolbar.subElement, position.left, position.top + 18, 26);
});
}
}
export const fontMenu = (protyle: IProtyle) => {
let colorHTML = "";
["var(--b3-font-color1)", "var(--b3-font-color2)", "var(--b3-font-color3)", "var(--b3-font-color4)",
"var(--b3-font-color5)", "var(--b3-font-color6)", "var(--b3-font-color7)", "var(--b3-font-color8)",
"var(--b3-font-color9)", "var(--b3-font-color10)", "var(--b3-font-color11)", "var(--b3-font-color12)",
"var(--b3-font-color13)"].forEach((item) => {
colorHTML += ``;
});
let bgHTML = "";
["var(--b3-font-background1)", "var(--b3-font-background2)", "var(--b3-font-background3)", "var(--b3-font-background4)",
"var(--b3-font-background5)", "var(--b3-font-background6)", "var(--b3-font-background7)", "var(--b3-font-background8)",
"var(--b3-font-background9)", "var(--b3-font-background10)", "var(--b3-font-background11)", "var(--b3-font-background12)",
"var(--b3-font-background13)"].forEach((item) => {
bgHTML += ``;
});
const element = document.createElement("div");
element.classList.add("protyle-font");
let lastColorHTML = "";
const lastFonts = JSON.parse(localStorage.getItem(Constants.LOCAL_FONTSTYLES) || "[]");
if (lastFonts.length > 0) {
lastColorHTML = `
${window.siyuan.languages.lastUsed}
${updateHotkeyTip(window.siyuan.config.keymap.editor.insert.lastUsed.custom)}
`;
lastFonts.forEach((item: string) => {
const lastFontStatus = item.split(Constants.ZWSP);
switch (lastFontStatus[0]) {
case "color":
lastColorHTML += ``;
break;
case "backgroundColor":
lastColorHTML += ``;
break;
case "style2":
lastColorHTML += ``;
break;
case "style4":
lastColorHTML += ``;
break;
case "fontSize":
lastColorHTML += ``;
break;
}
});
lastColorHTML += "
";
}
let textElement = protyle.toolbar.range.cloneContents().querySelector('[data-type~="text"]') as HTMLElement;
let fontSize = "16px";
if (!textElement) {
textElement = hasClosestByAttribute(protyle.toolbar.range.startContainer, "data-type", "text") as HTMLElement;
}
if (textElement) {
fontSize = textElement.style.fontSize || "16px";
}
element.innerHTML = `${lastColorHTML}${window.siyuan.languages.colorFont}
${colorHTML}
${window.siyuan.languages["--b3-theme-background"]}
${bgHTML}
${window.siyuan.languages.fontStyle}
${window.siyuan.languages.fontSize}
`;
element.addEventListener(getEventName(), function (event: Event) {
let target = event.target as HTMLElement;
while (target && !target.isEqualNode(element)) {
if (target.tagName === "BUTTON") {
fontEvent(protyle, target.getAttribute("data-type"), target.style.backgroundColor || target.textContent);
break;
}
target = target.parentElement;
}
});
element.querySelector("select").addEventListener("change", function (event: Event) {
fontEvent(protyle, "fontSize", (event.target as HTMLSelectElement).value);
});
return element;
};
export const fontEvent = (protyle: IProtyle, type?: string, color?: string) => {
let localFontStyles = JSON.parse(localStorage.getItem(Constants.LOCAL_FONTSTYLES) || "[]");
if (type) {
localFontStyles.splice(0, 0, `${type}${Constants.ZWSP}${color}`);
localFontStyles = [...new Set(localFontStyles)];
if (localFontStyles.length > 8) {
localFontStyles.splice(7, 1);
}
localStorage.setItem(Constants.LOCAL_FONTSTYLES, JSON.stringify(localFontStyles));
} else {
if (localFontStyles.length === 0) {
type = "color";
color = "var(--b3-font-color1)";
} else {
const fontStyles = localFontStyles[0].split(Constants.ZWSP);
type = fontStyles[0];
color = fontStyles[1];
}
}
protyle.toolbar.setInlineMark(protyle, "text", "range", {type, color});
};
export const setFontStyle = (textElement: HTMLElement, textOption: ITextOption) => {
const setBlockRef = (blockRefOption: string) => {
const blockRefData = blockRefOption.split(Constants.ZWSP);
// 标签等元素中包含 ZWSP,需移除后拼接 https://github.com/siyuan-note/siyuan/issues/6466
textElement.setAttribute("data-id", blockRefData.splice(0, 1)[0]);
textElement.setAttribute("data-subtype", blockRefData.splice(0, 1)[0]);
textElement.innerText = blockRefData.join("");
};
const setLink = (textOption: string) => {
const options = textOption.split(Constants.ZWSP);
textElement.setAttribute("data-href", options[0]);
textElement.removeAttribute("data-subtype");
textElement.removeAttribute("data-id");
if (options[1]) {
textElement.textContent = options[1];
}
};
if (textOption) {
switch (textOption.type) {
case "color":
textElement.style.color = textOption.color;
break;
case "fontSize":
textElement.style.fontSize = textOption.color;
break;
case "backgroundColor":
textElement.style.backgroundColor = textOption.color;
break;
case "style2":
textElement.style.webkitTextStroke = "0.2px var(--b3-theme-on-background)";
textElement.style.webkitTextFillColor = "transparent";
break;
case "style4":
textElement.style.textShadow = "1px 1px var(--b3-theme-surface-lighter), 2px 2px var(--b3-theme-surface-lighter), 3px 3px var(--b3-theme-surface-lighter), 4px 4px var(--b3-theme-surface-lighter)";
break;
case "id":
setBlockRef(textOption.color);
break;
case "inline-math":
textElement.className = "render-node";
textElement.setAttribute("contenteditable", "false");
textElement.setAttribute("data-subtype", "math");
textElement.setAttribute("data-content", textElement.textContent.replace(Constants.ZWSP, ""));
textElement.removeAttribute("data-render");
textElement.textContent = "";
break;
case "a":
setLink(textOption.color);
break;
case "inline-memo":
textElement.removeAttribute("contenteditable");
textElement.removeAttribute("data-subtype");
textElement.removeAttribute("data-content");
break;
}
}
};
export const hasSameTextStyle = (currentElement: HTMLElement, sideElement: HTMLElement, textObj: ITextOption) => {
if (!textObj) {
return true;
}
if (textObj.type === "inline-math" || textObj.type === "inline-memo" || textObj.type === "a") {
return false;
}
if (textObj.type === "id") {
if (currentElement.nodeType !== 3) {
return currentElement.getAttribute("data-id") === sideElement.getAttribute("data-id") &&
currentElement.getAttribute("data-subtype") === sideElement.getAttribute("data-subtype") &&
currentElement.textContent === sideElement.textContent;
}
const blockRefData = textObj.color.split(Constants.ZWSP);
return blockRefData[0] === sideElement.getAttribute("data-id") &&
blockRefData[1] === sideElement.getAttribute("data-subtype") &&
blockRefData[2] === sideElement.textContent;
}
let color = "";
let webkitTextFillColor = "";
let webkitTextStroke = "";
let textShadow = "";
let backgroundColor = "";
let fontSize = "";
if (currentElement.nodeType !== 3) {
color = currentElement.style.color;
webkitTextFillColor = currentElement.style.webkitTextFillColor;
webkitTextStroke = currentElement.style.webkitTextStroke;
textShadow = currentElement.style.textShadow;
backgroundColor = currentElement.style.backgroundColor;
fontSize = currentElement.style.fontSize;
}
if (textObj.type === "color") {
return textObj.color === sideElement.style.color &&
webkitTextFillColor === sideElement.style.webkitTextFillColor &&
webkitTextStroke === sideElement.style.webkitTextStroke &&
textShadow === sideElement.style.textShadow &&
fontSize === sideElement.style.fontSize &&
backgroundColor === sideElement.style.backgroundColor;
}
if (textObj.type === "backgroundColor") {
return color === sideElement.style.color &&
webkitTextFillColor === sideElement.style.webkitTextFillColor &&
webkitTextStroke === sideElement.style.webkitTextStroke &&
textShadow === sideElement.style.textShadow &&
fontSize === sideElement.style.fontSize &&
textObj.color === sideElement.style.backgroundColor;
}
if (textObj.type === "style2") {
return color === sideElement.style.color &&
"transparent" === sideElement.style.webkitTextFillColor &&
"0.2px var(--b3-theme-on-background)" === sideElement.style.webkitTextStroke &&
textShadow === sideElement.style.textShadow &&
fontSize === sideElement.style.fontSize &&
backgroundColor === sideElement.style.backgroundColor;
}
if (textObj.type === "style4") {
return color === sideElement.style.color &&
webkitTextFillColor === sideElement.style.webkitTextFillColor &&
webkitTextStroke === sideElement.style.webkitTextStroke &&
fontSize === sideElement.style.fontSize &&
"1px 1px var(--b3-theme-surface-lighter), 2px 2px var(--b3-theme-surface-lighter), 3px 3px var(--b3-theme-surface-lighter), 4px 4px var(--b3-theme-surface-lighter)" === sideElement.style.textShadow &&
backgroundColor === sideElement.style.backgroundColor;
}
if (textObj.type === "fontSize") {
return color === sideElement.style.color &&
webkitTextFillColor === sideElement.style.webkitTextFillColor &&
webkitTextStroke === sideElement.style.webkitTextStroke &&
textShadow === sideElement.style.textShadow &&
textObj.color === sideElement.style.fontSize &&
backgroundColor === sideElement.style.backgroundColor;
}
};