diff --git a/app/src/layout/status.ts b/app/src/layout/status.ts index 8f163014b..abc0b0544 100644 --- a/app/src/layout/status.ts +++ b/app/src/layout/status.ts @@ -135,3 +135,14 @@ export const countSelectWord = (range: Range) => { document.querySelector("#status .status__counter").innerHTML = ""; } } + +export const countBlockWord = (ids: string[]) => { + if (ids.length > 0) { + fetchPost("/api/block/getBlocksWordCount", {ids}, (response) => { + document.querySelector("#status .status__counter").innerHTML = `${window.siyuan.languages.blockRuneCount} ${response.data.runeCount}${window.siyuan.languages.blockWordCount} ${response.data.wordCount}`; + }) + } else { + document.querySelector("#status .status__counter").innerHTML = ""; + } +} + diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts index 36a6aa5b0..0f4c7ebd2 100644 --- a/app/src/protyle/gutter/index.ts +++ b/app/src/protyle/gutter/index.ts @@ -21,6 +21,7 @@ import {scrollCenter} from "../../util/highlightById"; import {isMobile} from "../../util/functions"; import {confirmDialog} from "../../dialog/confirmDialog"; import {enableProtyle} from "../util/onGet"; +import {countBlockWord} from "../../layout/status"; export class Gutter { public element: HTMLElement; @@ -566,6 +567,7 @@ export class Gutter { const turnIntoSubmenu: IMenu[] = []; hideElements(["select"], protyle); nodeElement.classList.add("protyle-wysiwyg--select"); + countBlockWord([nodeElement.getAttribute("data-node-id")]); // "heading1-6", "list", "ordered-list", "check", "quote", "code", "table", "line", "math", "paragraph" if (type === "NodeParagraph" && !window.siyuan.config.readonly) { turnIntoSubmenu.push(this.turnsIntoOne({ diff --git a/app/src/protyle/util/selection.ts b/app/src/protyle/util/selection.ts index 7365b03af..c45b035d3 100644 --- a/app/src/protyle/util/selection.ts +++ b/app/src/protyle/util/selection.ts @@ -1,6 +1,6 @@ import {getContenteditableElement, getNextBlock, getPreviousBlock, hasPreviousSibling} from "../wysiwyg/getBlock"; import {hasClosestByMatchTag} from "./hasClosest"; -import {countSelectWord} from "../../layout/status"; +import {countBlockWord, countSelectWord} from "../../layout/status"; const selectIsEditor = (editor: Element, range?: Range) => { if (!range) { @@ -83,9 +83,12 @@ export const selectAll = (protyle: IProtyle, nodeElement: Element, range: Range) selectElements.forEach(item => { item.classList.remove("protyle-wysiwyg--select"); }); + const ids: string [] = []; Array.from(protyle.wysiwyg.element.children).forEach(item => { item.classList.add("protyle-wysiwyg--select"); + ids.push(item.getAttribute("data-node-id")) }); + countBlockWord(ids) }; export const getEditorRange = (element: Element) => { diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 6376189ed..f4af84b12 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -54,7 +54,7 @@ import {MenuItem} from "../../menus/Menu"; import {fetchPost} from "../../util/fetch"; import {onGet} from "../util/onGet"; import {setTableAlign} from "../util/table"; -import {countSelectWord} from "../../layout/status"; +import {countBlockWord, countSelectWord} from "../../layout/status"; export class WYSIWYG { public lastHTMLs: { [key: string]: string } = {}; @@ -204,6 +204,7 @@ export class WYSIWYG { if (selectElements.length === 0 && range.toString() === "" && !range.cloneContents().querySelector("img") && !selectImgElement) { nodeElement.classList.add("protyle-wysiwyg--select"); + countBlockWord([nodeElement.getAttribute("data-node-id")]) selectElements = [nodeElement]; } let html = ""; @@ -884,11 +885,14 @@ export class WYSIWYG { // 只有一个 p 时不选中 protyle.selectElement.style.backgroundColor = "transparent"; } else { + const ids: string[] = [] selectElements.forEach(item => { if (!hasClosestByClassName(item, "protyle-wysiwyg__embed")) { item.classList.add("protyle-wysiwyg--select"); + ids.push(item.getAttribute("data-node-id")) } }); + countBlockWord(ids) protyle.selectElement.style.backgroundColor = ""; } }; @@ -1276,10 +1280,12 @@ export class WYSIWYG { if (nodeElement) { if (isNotEditBlock(nodeElement) && !this.element.querySelector(".protyle-wysiwyg--select")) { nodeElement.classList.add("protyle-wysiwyg--select"); + countBlockWord([nodeElement.getAttribute("data-node-id")]) + } else if (!nodeElement.classList.contains("protyle-wysiwyg--select")) { + countSelectWord(range); } this.setEmptyOutline(protyle, nodeElement); } - countSelectWord(range); event.stopPropagation(); } }); @@ -1785,9 +1791,12 @@ export class WYSIWYG { // 单个 p 不选中 shiftStartElement = undefined; } else { + const ids: string[] = [] selectElements.forEach(item => { item.classList.add("protyle-wysiwyg--select"); + ids.push(item.getAttribute("data-node-id")) }); + countBlockWord(ids); if (toDown) { focusBlock(selectElements[selectElements.length - 1], protyle.wysiwyg.element, false); } else { @@ -1819,6 +1828,11 @@ export class WYSIWYG { if (ctrlParentElement && !ctrlElement.isSameNode(ctrlParentElement)) { ctrlParentElement.classList.remove("protyle-wysiwyg--select"); } + const ids: string[] = [] + protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { + ids.push(item.getAttribute("data-node-id")) + }); + countBlockWord(ids); } } diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts index a0281d20a..354dc22bd 100644 --- a/app/src/protyle/wysiwyg/keydown.ts +++ b/app/src/protyle/wysiwyg/keydown.ts @@ -53,6 +53,7 @@ import {BlockPanel} from "../../block/Panel"; import * as dayjs from "dayjs"; import {highlightRender} from "../markdown/highlightRender"; import {commonHotkey} from "./commonHotkey"; +import {countBlockWord} from "../../layout/status"; export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { editorElement.addEventListener("keydown", (event: KeyboardEvent & { target: HTMLElement }) => { @@ -152,6 +153,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { } nextElement.classList.add("protyle-wysiwyg--select"); + countBlockWord([nextElement.getAttribute("data-node-id")]) const bottom = nextElement.getBoundingClientRect().bottom - protyle.contentElement.getBoundingClientRect().bottom; if (bottom > 0) { protyle.contentElement.scrollTop = protyle.contentElement.scrollTop + bottom; @@ -188,6 +190,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { } if (previousElement) { previousElement.classList.add("protyle-wysiwyg--select"); + countBlockWord([previousElement.getAttribute("data-node-id")]) const top = previousElement.getBoundingClientRect().top - protyle.contentElement.getBoundingClientRect().top; if (top < 0) { protyle.contentElement.scrollTop = protyle.contentElement.scrollTop + top; @@ -312,6 +315,11 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { selectElements[0].parentElement.classList.add("protyle-wysiwyg--select"); } } + const ids: string[] = [] + protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { + ids.push(item.getAttribute("data-node-id")) + }) + countBlockWord(ids); event.stopPropagation(); event.preventDefault(); return; @@ -354,6 +362,11 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { selectLastElement.parentElement.classList.add("protyle-wysiwyg--select"); } } + const ids: string[] = [] + protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { + ids.push(item.getAttribute("data-node-id")) + }) + countBlockWord(ids); event.stopPropagation(); event.preventDefault(); return; @@ -953,6 +966,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { protyle.hint.enableEmoji = false; } else if (nodeElement.classList.contains("protyle-wysiwyg--select")) { hideElements(["select"], protyle); + countBlockWord([]) } else if (!window.siyuan.menus.menu.element.classList.contains("fn__none")) { // 防止 ESC 时选中当前块 window.siyuan.menus.menu.remove(); @@ -961,6 +975,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { item.classList.remove("protyle-wysiwyg--select"); }); nodeElement.classList.add("protyle-wysiwyg--select"); + countBlockWord([nodeElement.getAttribute("data-node-id")]) } event.preventDefault(); return; diff --git a/app/src/protyle/wysiwyg/remove.ts b/app/src/protyle/wysiwyg/remove.ts index a64e55faa..5326b28d9 100644 --- a/app/src/protyle/wysiwyg/remove.ts +++ b/app/src/protyle/wysiwyg/remove.ts @@ -14,6 +14,7 @@ import {setFold, zoomOut} from "../../menus/protyle"; import {preventScroll} from "../scroll/preventScroll"; import {hideElements} from "../ui/hideElements"; import {Constants} from "../../constants"; +import {countBlockWord} from "../../layout/status"; const removeLi = (protyle: IProtyle, blockElement: Element, range: Range) => { if (!blockElement.parentElement.previousElementSibling && blockElement.parentElement.nextElementSibling && blockElement.parentElement.nextElementSibling.classList.contains("protyle-attr")) { @@ -381,10 +382,10 @@ export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Ran const editableElement = getContenteditableElement(blockElement); const previousLastElement = getLastBlock(previousElement) as HTMLElement; const isSelectNode = previousLastElement && (previousLastElement.classList.contains("table") || previousLastElement.classList.contains("render-node") || previousLastElement.classList.contains("iframe") || previousLastElement.classList.contains("hr") || previousLastElement.classList.contains("code-block")); + const previousId = previousLastElement.getAttribute("data-node-id"); if (isSelectNode) { if (previousLastElement.classList.contains("code-block")) { if (editableElement.textContent.trim() === "") { - const previousId = previousLastElement.getAttribute("data-node-id"); const id = blockElement.getAttribute("data-node-id"); const doOperations: IOperation[] = [{ action: "delete", @@ -412,20 +413,20 @@ export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Ran return; } previousLastElement.classList.add("protyle-wysiwyg--select"); + countBlockWord([previousId]) if (previousLastElement.getAttribute("data-type") === "NodeBlockQueryEmbed" || editableElement.textContent !== "") { focusByRange(range); return; } } - const newId = previousLastElement.getAttribute("data-node-id"); const removeElement = getTopEmptyElement(blockElement); const removeId = removeElement.getAttribute("data-node-id"); range.insertNode(document.createElement("wbr")); const undoOperations: IOperation[] = [{ action: "update", data: previousLastElement.outerHTML, - id: newId, + id: previousId, }, { action: "insert", data: removeElement.outerHTML, @@ -468,7 +469,7 @@ export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Ran doOperations.push({ action: "update", data: previousLastElement.outerHTML, - id: newId, + id: previousId, }); } if (parentElement.getAttribute("data-type") === "NodeSuperBlock" && parentElement.childElementCount === 2) {