UNPKG

@renpan/v-md-editor

Version:
78 lines (68 loc) 1.89 kB
import { LINE_MARKUP } from '@/utils/constants/markup'; export default { data() { return { tocVisible: false, titles: [], }; }, props: { defaultTocVisible: Boolean, includeLevel: { type: Array, default: () => [2, 3], }, }, mounted() { if (this.defaultTocVisible) { this.toggleToc(); this.$emit('toc-nav-loaded', this.titles); } }, watch: { text: { immediate: true, handler(newval, oldVal) { // render in the first time if (typeof oldVal === 'undefined') { this.$nextTick(this.updateTocNav); return; } if (this.updateTocNavTimmer) clearTimeout(this.updateTocNavTimmer); this.updateTocNavTimmer = setTimeout(this.updateTocNav, 800); }, }, }, computed: { anchorsSelector() { return this.includeLevel.map((level) => `h${level}`).join(','); }, }, methods: { toggleToc(visible = !this.tocVisible) { this.tocVisible = visible; }, updateTocNav() { const previewEl = this.$refs.preview?.$el; if (!previewEl) return; const anchors = previewEl.querySelectorAll(this.anchorsSelector); const titles = Array.from(anchors).filter((title) => !!title.innerText.trim()); if (!titles.length) { this.titles = []; return; } const hTags = Array.from(new Set(titles.map((title) => title.tagName))).sort(); this.titles = titles.map((el) => ({ title: el.innerText, lineIndex: el.getAttribute(LINE_MARKUP), indent: hTags.indexOf(el.tagName), })); if (this.defaultTocVisible) { this.$emit('toc-nav-loaded', titles); } }, handleNavClick({ lineIndex }) { this.scrollToLine(lineIndex); }, }, };