From 6bc8fa191090a190e3a16474dd8fefa30e527090 Mon Sep 17 00:00:00 2001 From: justice2001 Date: Sun, 17 Dec 2023 16:05:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E5=85=B3=E4=BA=8E=E8=84=9A=E6=B3=A8=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20(#1525)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :bug: Fix https://github.com/Vanessa219/vditor/issues/1518 * :bug: Fix https://github.com/Vanessa219/vditor/issues/1269 * :wastebasket: Clean code for 1269 * :bug: Fix link-ref-defs-block parsing error * :recycle: Refactor the combine footnote function * :bug: Fix similar problem with #1518 on link-ref-defs-block --- src/ts/sv/inputEvent.ts | 61 ++++++++++++++-------------------- src/ts/sv/process.ts | 3 ++ src/ts/toolbar/EditMode.ts | 2 ++ src/ts/util/combineFootnote.ts | 27 +++++++++++++++ 4 files changed, 57 insertions(+), 36 deletions(-) create mode 100644 src/ts/util/combineFootnote.ts diff --git a/src/ts/sv/inputEvent.ts b/src/ts/sv/inputEvent.ts index 787ff1518..3392fca7c 100644 --- a/src/ts/sv/inputEvent.ts +++ b/src/ts/sv/inputEvent.ts @@ -2,6 +2,7 @@ import {scrollCenter} from "../util/editorCommonEvent"; import {hasClosestByAttribute} from "../util/hasClosest"; import {getSelectPosition, setRangeByWbr} from "../util/selection"; import {getSideByType, processAfterRender, processSpinVditorSVDOM} from "./process"; +import { combineFootnote } from "../util/combineFootnote" export const inputEvent = (vditor: IVditor, event?: InputEvent) => { const range = getSelection().getRangeAt(0).cloneRange(); @@ -140,24 +141,24 @@ export const inputEvent = (vditor: IVditor, event?: InputEvent) => { html = blockElement.previousElementSibling.textContent + html; blockElement.previousElementSibling.remove(); } - if (!blockElement.innerText.startsWith("```")) { - // 添加链接引用 - vditor.sv.element.querySelectorAll("[data-type='link-ref-defs-block']").forEach((item, index) => { - if (index === 0 && item && !(blockElement as HTMLElement).isEqualNode(item.parentElement)) { - html += "\n" + item.parentElement.textContent; - item.parentElement.remove(); - } - }); + // 添加链接引用 + let footnotes = "" - // 添加脚注 - vditor.sv.element.querySelectorAll("[data-type='footnotes-link']").forEach((item, index) => { - // 加入所有脚注便于渲染引用 - if (item && !(blockElement as HTMLElement).isEqualNode(item.parentElement)) { - html += "\n" + item.parentElement.textContent; - item.parentElement.remove(); - } - }); - } + vditor.sv.element.querySelectorAll("[data-type='link-ref-defs-block']").forEach((item, index) => { + if (item && !(blockElement as HTMLElement).isEqualNode(item.parentElement)) { + footnotes += item.parentElement.textContent + "\n"; + item.parentElement.remove(); + } + }); + + // 添加脚注到文章头,便于lute处理 + vditor.sv.element.querySelectorAll("[data-type='footnotes-link']").forEach((item, index) => { + if (item && !(blockElement as HTMLElement).isEqualNode(item.parentElement)) { + footnotes += item.parentElement.textContent + "\n"; + item.parentElement.remove(); + } + }); + html = footnotes + html; } html = processSpinVditorSVDOM(html, vditor); if (isSVElement) { @@ -166,26 +167,14 @@ export const inputEvent = (vditor: IVditor, event?: InputEvent) => { blockElement.outerHTML = html; } - let firstLinkRefDefElement: Element; - const allLinkRefDefsElement = vditor.sv.element.querySelectorAll("[data-type='link-ref-defs-block']"); - allLinkRefDefsElement.forEach((item, index) => { - if (index === 0) { - firstLinkRefDefElement = item.parentElement; - } else { - firstLinkRefDefElement.lastElementChild.remove(); - firstLinkRefDefElement.insertAdjacentHTML("beforeend", `${item.parentElement.innerHTML}`); - item.parentElement.remove(); - } - }); - if (allLinkRefDefsElement.length > 0) { - vditor.sv.element.insertAdjacentElement("beforeend", firstLinkRefDefElement); - } + vditor.sv.element.querySelectorAll("[data-type='link-ref-defs-block']").forEach((item) => { + vditor.sv.element.insertAdjacentElement("beforeend", item.parentElement) + }) - // 脚注合并后添加的末尾 - vditor.sv.element.querySelectorAll("[data-type='footnotes-link']") - .forEach((item, index) => { - vditor.sv.element.insertAdjacentElement("beforeend", item.parentElement) - }); + // 合并脚注 + combineFootnote(vditor.sv.element, (root: HTMLElement) => { + vditor.sv.element.insertAdjacentElement("beforeend", root) + }) setRangeByWbr(vditor.sv.element, range); diff --git a/src/ts/sv/process.ts b/src/ts/sv/process.ts index 46b1a33d8..497df3353 100644 --- a/src/ts/sv/process.ts +++ b/src/ts/sv/process.ts @@ -6,6 +6,8 @@ import {hasClosestByTag} from "../util/hasClosestByHeadings"; import {log} from "../util/log"; import {getEditorRange, setRangeByWbr} from "../util/selection"; import {inputEvent} from "./inputEvent"; +import { combineFootnote } from "../util/combineFootnote" + export const processPaste = (vditor: IVditor, text: string) => { const range = getEditorRange(vditor); @@ -25,6 +27,7 @@ export const processPaste = (vditor: IVditor, text: string) => { } else { blockElement.outerHTML = spinHTML; } + combineFootnote(vditor.sv.element) setRangeByWbr(vditor.sv.element, range); scrollCenter(vditor); diff --git a/src/ts/toolbar/EditMode.ts b/src/ts/toolbar/EditMode.ts index e85e46ac8..37e0fcdb9 100644 --- a/src/ts/toolbar/EditMode.ts +++ b/src/ts/toolbar/EditMode.ts @@ -18,6 +18,7 @@ import { removeCurrentToolbar, showToolbar, toggleSubMenu, } from "./setToolbar"; +import { combineFootnote } from "../util/combineFootnote" export const setEditMode = (vditor: IVditor, type: string, event: Event | string) => { let markdownText; @@ -122,6 +123,7 @@ export const setEditMode = (vditor: IVditor, type: string, event: Event | string svHTML = ""; } vditor.sv.element.innerHTML = svHTML; + combineFootnote(vditor.sv.element) processSVAfterRender(vditor, { enableAddUndoStack: true, enableHint: false, diff --git a/src/ts/util/combineFootnote.ts b/src/ts/util/combineFootnote.ts new file mode 100644 index 000000000..3e56e4440 --- /dev/null +++ b/src/ts/util/combineFootnote.ts @@ -0,0 +1,27 @@ +/** + * 合并脚注 + * @param elements vditor.sv.element + * @param afterCombine 每个脚注块合并完成后的回调, param: root为合并后的脚注块 + */ +export const combineFootnote = (elements: HTMLElement, afterCombine?: (root: HTMLElement) => void ) => { + elements.querySelectorAll("[data-type=footnotes-link]").forEach((el: Element) => { + const root = el.parentElement + let footnote = root.nextSibling + // 寻找所有该脚注的块 + while (footnote) { + if (footnote.textContent.startsWith(" ")) { + // 解析到四个空格,加入到root并继续解析 + const thisNode = footnote + thisNode.childNodes.forEach(node => { + root.append(node.cloneNode(true)) + }) + footnote = footnote.nextSibling + thisNode.remove() + } else { + // 非空格停止解析 + break + } + } + afterCombine && afterCombine(root) + }) +}