You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

189 lines
5.2 KiB

<template>
<div>
<div
v-for="anchor in titles"
:style="{ padding: `10px 0 10px ${anchor.indent}px` }"
@click="handleAnchorClick(anchor)"
:key="anchor.lineIndex"
>
<a style="cursor: pointer">{{ anchor.title }}</a>
</div>
<v-md-preview :text="text" ref="preview" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
const text = `
# heading 1
contentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontent
## heading 2
contentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontent
### heading 3
contentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontentcontentcontentcontent
contentcontentcontent
contentcontentcontent
contentcontentcontent
`;
const preview = ref<any>(null);
const titles = ref<{ title: string; lineIndex: string; indent: number }[]>([]);
onMounted(() => {
const anchors = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
const titlesArray = Array.from(anchors).filter((title) => !!title.innerText.trim());
if (!titlesArray.length) {
titles.value = [];
return;
}
const hTags = Array.from(new Set(titlesArray.map((title) => title.tagName))).sort();
titles.value = titlesArray.map((el) => ({
title: el.innerText,
lineIndex: el.getAttribute('data-v-md-line') || '', // 确认属性名是否正确
indent: 20 * (parseInt(el.tagName.substring(1)) - 1) // 确认缩进计算是否正确
}));
});
function handleAnchorClick(anchor: { title: string; lineIndex: string }) {
if (preview.value) {
const heading = preview.value.$el.querySelector(`[data-v-md-line="${anchor.lineIndex}"]`);
if (heading) {
preview.value.scrollToTarget({
target: heading,
scrollContainer: window,
top: 60,
});
} else {
console.error(`Heading element not found for lineIndex: ${anchor.lineIndex}`);
}
} else {
console.error('Preview component not initialized.');
}
}
</script>