marked.js 渲染markdown文档,并在右上角生成锚点

背景

因为是markdown,所以用户可以随便写,像图一这种规规矩矩的标题 做成锚点很简单。
但是markdown里面 用户可以随便写,就会出现图二这种情况,这种情况下 antdv的anchor的带children嵌套的那种数组就不好实现了
marked.js 渲染markdown文档,并在右上角生成锚点_第1张图片图一
marked.js 渲染markdown文档,并在右上角生成锚点_第2张图片图二

方案

因此我们选择 把所有的项放到同一级,然后给不同的标题加class,通过css来做成这种有间距的效果

<script setup>
import { marked } from 'marked'
import { onMounted, computed, ref } from 'vue'

const anchorLinkList = ref([])
const anchorIndex = ref(0)
const sidebarMainRef = ref(null);

// 文章内容
const content = computed(() => {
    const renderer = {
        heading(text, level) {
        	// level代表几级标题 拼接上anchorIndex.value++ 放置id重复
            const idName = level + '_' + anchorIndex.value++
            const className = 'level' + level
            anchorLinkList.value.push({
                level: level,
                title: text,
                key: className,
                href: '#' + idName
            })

            return `
                ${level} id=${idName} class=${className}>
                    ${text}
                ${level}>
            `
        }
    }
    marked.use({ renderer })

    marked.parse(detail.value.content)

})

const getContainer = () => {
    return this.$refs.sidebarMain;
}

onMounted(() => {
    sidebarMainRef.value = document.querySelector('.sidebar-main');
})
</script>


<template>
    <div class="sidebar-main" ref="sidebarMainRef">
        <div class="content" v-html="content"></div>
    </div>
    <a-anchor :getContainer="getContainer">
        <a-anchor-link
            v-for="link in anchorLinkList"
            :key="link.key"
            :href="link.href"
            :class="link.key"
        />
    </a-anchor>
    <mtd-anchor class="title-wrap" :offset-top="20" container="#marked-content">
      <mtd-anchor-link
        v-for="link in anchorLinkList"
        :href="link.href"
        :title="link.title"
        :key="link.key"
        :class="link.key"
      />
    </mtd-anchor>
</template>

<style scoped>
.level2 {
    text-indent: 10px;
}

.level3 {
    text-indent: 20px;
}

.level4 {
    text-indent: 30px;
}

.level5 {
    text-indent: 40px;
}

.level6 {
    text-indent: 50px;
}

.title-wrap {
    position: sticky;
    top: 80px;
    padding-right: 10px;
    height: 400px;
    overflow-y: auto;
}

#marked-content {
    height: 100vh;
    overflow-y: auto;
}
</style>

效果

规规矩矩的标题
marked.js 渲染markdown文档,并在右上角生成锚点_第3张图片

不规矩的标题
marked.js 渲染markdown文档,并在右上角生成锚点_第4张图片

ps

最开始想复杂了,就像写children那种嵌套的,但是 这种乱序的怎么写都不对
中午吃个饭 缓了缓,然后就想到了 写在同一级,然后拼上不同的class 来实现按照 间距的效果
然后就写出来了

你可能感兴趣的:(javascript,vue.js,开发语言)