Browse Source

修复了一些关于脚注的问题 (#1525)

* :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
justice2001 1 year ago
parent
commit
6bc8fa1910
4 changed files with 57 additions and 36 deletions
  1. 25 36
      src/ts/sv/inputEvent.ts
  2. 3 0
      src/ts/sv/process.ts
  3. 2 0
      src/ts/toolbar/EditMode.ts
  4. 27 0
      src/ts/util/combineFootnote.ts

+ 25 - 36
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);
 

+ 3 - 0
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);

+ 2 - 0
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,

+ 27 - 0
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)
+    })
+}