189 lines
5.2 KiB

10 months ago
8 months ago
10 months ago
9 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
9 months ago
  1. <template>
  2. <div>
  3. <div
  4. v-for="anchor in titles"
  5. :style="{ padding: `10px 0 10px ${anchor.indent}px` }"
  6. @click="handleAnchorClick(anchor)"
  7. :key="anchor.lineIndex"
  8. >
  9. <a style="cursor: pointer">{{ anchor.title }}</a>
  10. </div>
  11. <v-md-preview :text="text" ref="preview" />
  12. </div>
  13. </template>
  14. <script setup lang="ts">
  15. import { ref, onMounted } from 'vue';
  16. const text = `
  17. # heading 1
  18. contentcontentcontent
  19. contentcontentcontent
  20. contentcontentcontent
  21. contentcontentcontentcontentcontentcontent
  22. contentcontentcontent
  23. contentcontentcontentcontentcontentcontent
  24. contentcontentcontent
  25. contentcontentcontentcontentcontentcontent
  26. contentcontentcontent
  27. contentcontentcontentcontentcontentcontent
  28. contentcontentcontent
  29. contentcontentcontentcontentcontentcontent
  30. contentcontentcontent
  31. contentcontentcontentcontentcontentcontent
  32. contentcontentcontent
  33. contentcontentcontentcontentcontentcontent
  34. contentcontentcontent
  35. contentcontentcontentcontentcontentcontent
  36. contentcontentcontent
  37. contentcontentcontentcontentcontentcontent
  38. contentcontentcontent
  39. contentcontentcontentcontentcontentcontent
  40. contentcontentcontent
  41. contentcontentcontentcontentcontentcontent
  42. contentcontentcontent
  43. contentcontentcontentcontentcontentcontent
  44. contentcontentcontent
  45. contentcontentcontentcontentcontentcontent
  46. contentcontentcontent
  47. contentcontentcontentcontentcontentcontent
  48. contentcontentcontent
  49. contentcontentcontentcontentcontentcontent
  50. contentcontentcontent
  51. contentcontentcontentcontentcontentcontent
  52. contentcontentcontent
  53. contentcontentcontentcontentcontentcontent
  54. contentcontentcontent
  55. contentcontentcontentcontentcontentcontent
  56. contentcontentcontent
  57. contentcontentcontent
  58. contentcontentcontent
  59. ## heading 2
  60. contentcontentcontent
  61. contentcontentcontent
  62. contentcontentcontent
  63. contentcontentcontent
  64. contentcontentcontentcontentcontentcontent
  65. contentcontentcontent
  66. contentcontentcontent
  67. contentcontentcontentcontentcontentcontent
  68. contentcontentcontent
  69. contentcontentcontent
  70. contentcontentcontentcontentcontentcontent
  71. contentcontentcontent
  72. contentcontentcontent
  73. contentcontentcontentcontentcontentcontent
  74. contentcontentcontent
  75. contentcontentcontent
  76. contentcontentcontentcontentcontentcontent
  77. contentcontentcontent
  78. contentcontentcontent
  79. contentcontentcontentcontentcontentcontent
  80. contentcontentcontent
  81. contentcontentcontent
  82. contentcontentcontentcontentcontentcontent
  83. contentcontentcontent
  84. contentcontentcontent
  85. contentcontentcontentcontentcontentcontent
  86. contentcontentcontent
  87. contentcontentcontent
  88. contentcontentcontentcontentcontentcontent
  89. contentcontentcontent
  90. contentcontentcontent
  91. contentcontentcontentcontentcontentcontent
  92. contentcontentcontent
  93. contentcontentcontent
  94. contentcontentcontentcontentcontentcontent
  95. contentcontentcontent
  96. contentcontentcontent
  97. contentcontentcontent
  98. ### heading 3
  99. contentcontentcontent
  100. contentcontentcontent
  101. contentcontentcontent
  102. contentcontentcontent
  103. contentcontentcontentcontentcontentcontent
  104. contentcontentcontent
  105. contentcontentcontent
  106. contentcontentcontentcontentcontentcontent
  107. contentcontentcontent
  108. contentcontentcontent
  109. contentcontentcontentcontentcontentcontent
  110. contentcontentcontent
  111. contentcontentcontent
  112. contentcontentcontentcontentcontentcontent
  113. contentcontentcontent
  114. contentcontentcontent
  115. contentcontentcontentcontentcontentcontent
  116. contentcontentcontent
  117. contentcontentcontent
  118. contentcontentcontentcontentcontentcontent
  119. contentcontentcontent
  120. contentcontentcontent
  121. contentcontentcontentcontentcontentcontent
  122. contentcontentcontent
  123. contentcontentcontent
  124. contentcontentcontentcontentcontentcontent
  125. contentcontentcontent
  126. contentcontentcontent
  127. contentcontentcontentcontentcontentcontent
  128. contentcontentcontent
  129. contentcontentcontent
  130. contentcontentcontentcontentcontentcontent
  131. contentcontentcontent
  132. contentcontentcontent
  133. contentcontentcontentcontentcontentcontent
  134. contentcontentcontent
  135. contentcontentcontent
  136. contentcontentcontentcontentcontentcontent
  137. contentcontentcontent
  138. contentcontentcontent
  139. contentcontentcontentcontentcontentcontent
  140. contentcontentcontent
  141. contentcontentcontent
  142. contentcontentcontent
  143. `;
  144. const preview = ref<any>(null);
  145. const titles = ref<{ title: string; lineIndex: string; indent: number }[]>([]);
  146. onMounted(() => {
  147. const anchors = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
  148. const titlesArray = Array.from(anchors).filter((title) => !!title.innerText.trim());
  149. if (!titlesArray.length) {
  150. titles.value = [];
  151. return;
  152. }
  153. const hTags = Array.from(new Set(titlesArray.map((title) => title.tagName))).sort();
  154. titles.value = titlesArray.map((el) => ({
  155. title: el.innerText,
  156. lineIndex: el.getAttribute('data-v-md-line') || '', // 确认属性名是否正确
  157. indent: 20 * (parseInt(el.tagName.substring(1)) - 1) // 确认缩进计算是否正确
  158. }));
  159. });
  160. function handleAnchorClick(anchor: { title: string; lineIndex: string }) {
  161. if (preview.value) {
  162. const heading = preview.value.$el.querySelector(`[data-v-md-line="${anchor.lineIndex}"]`);
  163. if (heading) {
  164. preview.value.scrollToTarget({
  165. target: heading,
  166. scrollContainer: window,
  167. top: 60,
  168. });
  169. } else {
  170. console.error(`Heading element not found for lineIndex: ${anchor.lineIndex}`);
  171. }
  172. } else {
  173. console.error('Preview component not initialized.');
  174. }
  175. }
  176. </script>