From f459881407fe12808dfb24d0e1ba8a03c968967f Mon Sep 17 00:00:00 2001 From: YangFong Date: Sat, 8 Mar 2025 21:51:44 +0800 Subject: [PATCH] feat: support title navigation --- src/stores/index.ts | 29 ++++++++++++++++++++++++++ src/utils/renderer.ts | 3 ++- src/views/CodemirrorEditor.vue | 37 +++++++++++++++++++++------------- 3 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/stores/index.ts b/src/stores/index.ts index 404c4b476..832a17de1 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -184,6 +184,13 @@ export const useStore = defineStore(`store`, () => { const readingTime = ref(null) + // 文章标题 + const titleList = ref<{ + url: string + title: string + level: number + }[]>([]) + // 更新编辑器 const editorRefresh = () => { codeThemeChange() @@ -192,6 +199,26 @@ export const useStore = defineStore(`store`, () => { const { markdownContent, readingTime: readingTimeResult } = renderer.parseFrontMatterAndContent(editor.value!.getValue()) readingTime.value = readingTimeResult let outputTemp = marked.parse(markdownContent) as string + + // 提取标题 + const div = document.createElement('div') + div.innerHTML = outputTemp + const list = div.querySelectorAll(`[data-heading]`) + + titleList.value = [] + let i = 0 + for (const item of list) { + item.setAttribute(`id`, `${i}`) + titleList.value.push({ + url: `#${i}`, + title: `${item.innerText}`, + level: Number(item.tagName.slice(1)) + }) + i++ + } + + outputTemp = div.innerHTML + outputTemp = DOMPurify.sanitize(outputTemp) // 阅读时间及字数统计 @@ -501,6 +528,8 @@ export const useStore = defineStore(`store`, () => { delPost, isOpenPostSlider, isOpenRightSlider, + + titleList, } }) diff --git a/src/utils/renderer.ts b/src/utils/renderer.ts index 0be2d3bbf..cd3a23efa 100644 --- a/src/utils/renderer.ts +++ b/src/utils/renderer.ts @@ -157,7 +157,8 @@ export function initRenderer(opts: IOpts) { function styledContent(styleLabel: string, content: string, tagName?: string): string { const tag = tagName ?? styleLabel - return `<${tag} ${styles(styleLabel)}>${content}` + + return `<${tag} ${/^h\d$/.test(tag) ? `data-heading="true"` : ``} ${styles(styleLabel)}>${content}` } function addFootnote(title: string, link: string): number { diff --git a/src/views/CodemirrorEditor.vue b/src/views/CodemirrorEditor.vue index 69c19f97d..16786fc99 100644 --- a/src/views/CodemirrorEditor.vue +++ b/src/views/CodemirrorEditor.vue @@ -418,24 +418,33 @@ onMounted(() => { -
-
-
-
-
-
-
- 正在生成 +
+
+
+
+
+
+
+
+ 正在生成 +
-
- + +
+