diff --git a/app/src/protyle/toolbar/Font.ts b/app/src/protyle/toolbar/Font.ts index 05179f427..97cb00813 100644 --- a/app/src/protyle/toolbar/Font.ts +++ b/app/src/protyle/toolbar/Font.ts @@ -142,3 +142,49 @@ export const setFontStyle = (textElement:HTMLElement, textOption:ITextOption) => } } } + +export const hasSameTextStyle = (currentElement: HTMLElement, sideElement: HTMLElement, textObj: ITextOption) => { + if (!textObj) { + return true; + } + let color = ""; + let webkitTextFillColor = "" + let webkitTextStroke = "" + let textShadow = "" + let backgroundColor = "" + if (currentElement.nodeType !== 3) { + color = currentElement.style.color; + webkitTextFillColor = currentElement.style.webkitTextFillColor; + webkitTextStroke = currentElement.style.webkitTextStroke; + textShadow = currentElement.style.textShadow; + backgroundColor = currentElement.style.backgroundColor; + } + if (textObj.type === "color") { + return textObj.color === sideElement.style.color && + webkitTextFillColor === sideElement.style.webkitTextFillColor && + webkitTextStroke === sideElement.style.webkitTextStroke && + textShadow === sideElement.style.textShadow && + 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 && + 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 && + backgroundColor === sideElement.style.backgroundColor + } + if (textObj.type === "style4") { + return color === sideElement.style.color && + webkitTextFillColor === sideElement.style.webkitTextFillColor && + webkitTextStroke === sideElement.style.webkitTextStroke && + "1px 1px var(--b3-border-color), 2px 2px var(--b3-border-color), 3px 3px var(--b3-border-color), 4px 4px var(--b3-border-color)" === sideElement.style.textShadow && + backgroundColor === sideElement.style.backgroundColor + } +} diff --git a/app/src/protyle/toolbar/index.ts b/app/src/protyle/toolbar/index.ts index 412428c22..6afa1a3e7 100644 --- a/app/src/protyle/toolbar/index.ts +++ b/app/src/protyle/toolbar/index.ts @@ -1,5 +1,5 @@ import {Divider} from "./Divider"; -import {Font, setFontStyle} from "./Font"; +import {Font, hasSameTextStyle, setFontStyle} from "./Font"; import {ToolbarItem} from "./ToolbarItem"; import { focusByRange, @@ -231,49 +231,25 @@ export class Toolbar { }); } - private hasSameStyle(currentElement: HTMLElement, sideElement: HTMLElement, textObj: ITextOption) { - if (!textObj) { - return true; + // 合并多个 text 为一个 text + private mergeNode(nodes: NodeListOf) { + for (let i = 0; i < nodes.length; i++) { + if (nodes[i].nodeType !== 3 && (nodes[i] as HTMLElement).tagName === "WBR") { + nodes[i].remove(); + i--; + } } - let color = ""; - let webkitTextFillColor = "" - let webkitTextStroke = "" - let textShadow = "" - let backgroundColor = "" - if (currentElement.nodeType !== 3) { - color = currentElement.style.color; - webkitTextFillColor = currentElement.style.webkitTextFillColor; - webkitTextStroke = currentElement.style.webkitTextStroke; - textShadow = currentElement.style.textShadow; - backgroundColor = currentElement.style.backgroundColor; - } - if (textObj.type === "color") { - return textObj.color === sideElement.style.color && - webkitTextFillColor === sideElement.style.webkitTextFillColor && - webkitTextStroke === sideElement.style.webkitTextStroke && - textShadow === sideElement.style.textShadow && - 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 && - 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 && - backgroundColor === sideElement.style.backgroundColor - } - if (textObj.type === "style4") { - return color === sideElement.style.color && - webkitTextFillColor === sideElement.style.webkitTextFillColor && - webkitTextStroke === sideElement.style.webkitTextStroke && - "1px 1px var(--b3-border-color), 2px 2px var(--b3-border-color), 3px 3px var(--b3-border-color), 4px 4px var(--b3-border-color)" === sideElement.style.textShadow && - backgroundColor === sideElement.style.backgroundColor + for (let i = 0; i < nodes.length; i++) { + if (nodes[i].nodeType === 3) { + if (nodes[i].textContent === "") { + nodes[i].remove(); + i--; + } else if (nodes[i + 1] && nodes[i + 1].nodeType === 3) { + nodes[i].textContent = nodes[i].textContent + nodes[i + 1].textContent; + nodes[i + 1].remove(); + i--; + } + } } } @@ -315,22 +291,7 @@ export class Toolbar { this.range.insertNode(wbrElement); const html = nodeElement.outerHTML; const contents = this.range.extractContents(); - // 合并多个 text 为一个 text - for (let i = 0; i < contents.childNodes.length; i++) { - if (contents.childNodes[i].nodeType === 3) { - if (contents.childNodes[i].textContent === "") { - contents.childNodes[i].remove(); - i--; - } else if (contents.childNodes[i + 1] && contents.childNodes[i + 1].nodeType === 3) { - contents.childNodes[i].textContent = contents.childNodes[i].textContent + contents.childNodes[i + 1].textContent; - contents.childNodes[i + 1].remove(); - i--; - } - } else if (contents.childNodes[i].nodeType !== 3 && (contents.childNodes[i] as HTMLElement).tagName === "WBR") { - contents.childNodes[i].remove(); - i--; - } - } + this.mergeNode(contents.childNodes); const actionBtn = action === "toolbar" ? this.element.querySelector(`[data-type="${type}"]`) : undefined; const newNodes: Node[] = []; if (action === "remove" || actionBtn?.classList.contains("protyle-toolbar__item--current") || @@ -360,12 +321,12 @@ export class Toolbar { } if (index === 0 && previousElement && previousElement.nodeType !== 3 && isArrayEqual(types, previousElement.getAttribute("data-type").split(" ")) && - this.hasSameStyle(item, previousElement, textObj)) { + hasSameTextStyle(item, previousElement, textObj)) { previousIndex = previousElement.textContent.length; previousElement.innerHTML = previousElement.innerHTML + item.innerHTML; } else if (index === contents.childNodes.length - 1 && nextElement && nextElement.nodeType !== 3 && isArrayEqual(types, nextElement.getAttribute("data-type").split(" ")) && - this.hasSameStyle(item, nextElement, textObj)) { + hasSameTextStyle(item, nextElement, textObj)) { nextIndex = item.textContent.length; nextElement.innerHTML = item.innerHTML + nextElement.innerHTML; } else { @@ -386,12 +347,12 @@ export class Toolbar { if (item.nodeType === 3) { if (index === 0 && previousElement && previousElement.nodeType !== 3 && type === previousElement.getAttribute("data-type") && - this.hasSameStyle(item, previousElement, textObj)) { + hasSameTextStyle(item, previousElement, textObj)) { previousIndex = previousElement.textContent.length; previousElement.innerHTML = previousElement.innerHTML + item.textContent; } else if (index === contents.childNodes.length - 1 && nextElement && nextElement.nodeType !== 3 && type === nextElement.getAttribute("data-type") && - this.hasSameStyle(item, nextElement, textObj)) { + hasSameTextStyle(item, nextElement, textObj)) { nextIndex = item.textContent.length; nextElement.innerHTML = item.textContent + nextElement.innerHTML; } else { @@ -407,12 +368,12 @@ export class Toolbar { types = [...new Set(types)]; if (index === 0 && previousElement && previousElement.nodeType !== 3 && isArrayEqual(types, previousElement.getAttribute("data-type").split(" ")) && - this.hasSameStyle(item, previousElement, textObj)) { + hasSameTextStyle(item, previousElement, textObj)) { previousIndex = previousElement.textContent.length; previousElement.innerHTML = previousElement.innerHTML + item.innerHTML; } else if (index === contents.childNodes.length - 1 && nextElement && nextElement.nodeType !== 3 && isArrayEqual(types, nextElement.getAttribute("data-type").split(" ")) && - this.hasSameStyle(item, nextElement, textObj)) { + hasSameTextStyle(item, nextElement, textObj)) { nextIndex = item.textContent.length; nextElement.innerHTML = item.innerHTML + nextElement.innerHTML; } else { @@ -427,6 +388,12 @@ export class Toolbar { this.range.insertNode(item); this.range.collapse(false); }); + if (previousElement) { + this.mergeNode(previousElement.childNodes); + } + if (nextElement) { + this.mergeNode(nextElement.childNodes); + } if (previousIndex) { this.range.setStart(previousElement.firstChild, previousIndex); } else if (newNodes.length > 0) { @@ -450,6 +417,7 @@ export class Toolbar { } } else { // **aaa**bbb 选中 bbb 加粗 + // 需进行 mergeNode ,否用 alt+x 为相同颜色 aaabbb 中的 bbb 再次赋值后无法选中 this.range.setEnd(previousElement.firstChild, previousElement.firstChild.textContent.length); } nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss")); diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts index 06234f039..a8ba6549d 100644 --- a/app/src/protyle/wysiwyg/keydown.ts +++ b/app/src/protyle/wysiwyg/keydown.ts @@ -1185,8 +1185,8 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { } if (matchHotKey(menuItem.hotkey, event)) { protyle.toolbar.range = getEditorRange(protyle.wysiwyg.element); - if (menuItem.name === "font") { - protyle.toolbar.element.querySelector('[data-type="font"]').dispatchEvent(new CustomEvent(getEventName())); + if (menuItem.name === "text") { + protyle.toolbar.element.querySelector('[data-type="text"]').dispatchEvent(new CustomEvent(getEventName())); } else { protyle.toolbar.setInlineMark(protyle, menuItem.name, "range"); }