@datawhale/prosemirror-render 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. package/dist/AttachmentBlock-ChMNTUOo.mjs +351 -0
  2. package/dist/AttachmentBlock-DsmJP3Kw.js +1 -0
  3. package/dist/AttachmentInline-Dc3dp0g-.js +1 -0
  4. package/dist/AttachmentInline-tbC8BJBy.mjs +52 -0
  5. package/dist/AttachmentMenu-B5x8P9_n.mjs +541 -0
  6. package/dist/AttachmentMenu-ExoCOe4B.js +1 -0
  7. package/dist/Blockquote-BamWUQND.mjs +15 -0
  8. package/dist/Blockquote-CQSBFnsu.js +1 -0
  9. package/dist/BulletList-BQTUD69X.mjs +15 -0
  10. package/dist/BulletList-CFjF3U-l.js +1 -0
  11. package/dist/Callout-Cu6HI-xq.mjs +28 -0
  12. package/dist/Callout-DPdOqTb4.js +1 -0
  13. package/dist/CellOutput-C33VK0df.mjs +981 -0
  14. package/dist/CellOutput-DiKZlIFa.js +6 -0
  15. package/dist/CodeBlock-Cjuxuq7B.mjs +8359 -0
  16. package/dist/CodeBlock-DWniNUQB.js +148 -0
  17. package/dist/Doc-6s4VMDsx.mjs +15 -0
  18. package/dist/Doc-D2yvlSII.js +1 -0
  19. package/dist/FoldBlock-DRdlU-DX.mjs +75 -0
  20. package/dist/FoldBlock-ZPMf0QsR.js +1 -0
  21. package/dist/Grid-GfmJxM93.mjs +31 -0
  22. package/dist/Grid-QToZdaRT.js +1 -0
  23. package/dist/HardBreak-B2tFO31P.mjs +13 -0
  24. package/dist/HardBreak-Dbf5Zg5o.js +1 -0
  25. package/dist/Heading-BElRvhGn.mjs +21 -0
  26. package/dist/Heading-BUnffIAz.js +1 -0
  27. package/dist/HorizontalRule-BRG45oT0.mjs +13 -0
  28. package/dist/HorizontalRule-CE09LZGf.js +1 -0
  29. package/dist/IFrame-CaAOVLGN.mjs +17 -0
  30. package/dist/IFrame-DcCpSoDC.js +1 -0
  31. package/dist/Image-C8v5dCij.mjs +105 -0
  32. package/dist/Image-cHL85CXs.js +1 -0
  33. package/dist/ListItem-BrjxeGxz.js +1 -0
  34. package/dist/ListItem-X0T7a_z8.mjs +15 -0
  35. package/dist/MathDisplay-CESKZV46.js +1 -0
  36. package/dist/MathDisplay-CoGsFzXW.mjs +30 -0
  37. package/dist/MathInline-0xTZoIIq.mjs +30 -0
  38. package/dist/MathInline-C_1SJUVz.js +1 -0
  39. package/dist/McChoices-Aj394G5E.mjs +52 -0
  40. package/dist/McChoices-B4euzY7M.js +1 -0
  41. package/dist/McQuestion-Dq0aM5tC.js +1 -0
  42. package/dist/McQuestion-DvD-J47M.mjs +38 -0
  43. package/dist/McSolution-C5sTXz3y.mjs +24 -0
  44. package/dist/McSolution-N79CllH9.js +1 -0
  45. package/dist/MultipleChoice-DTCF3Q8m.js +1 -0
  46. package/dist/MultipleChoice-Dv-k1zUU.mjs +47 -0
  47. package/dist/OrderedList-B8v1gchv.mjs +17 -0
  48. package/dist/OrderedList-DMl3tvwP.js +1 -0
  49. package/dist/Paragraph-CzRSCJNr.js +1 -0
  50. package/dist/Paragraph-DGcZy8t_.mjs +16 -0
  51. package/dist/SlotNode-6OpoUcOa.mjs +10 -0
  52. package/dist/SlotNode-DMG0R6Vf.js +1 -0
  53. package/dist/TableCell-BY9gdldc.js +1 -0
  54. package/dist/TableCell-Bp52L368.mjs +20 -0
  55. package/dist/TableContainer-C5KXY6f7.js +1 -0
  56. package/dist/TableContainer-C9PhNGlz.mjs +29 -0
  57. package/dist/TableHeader-BTuqvorM.js +1 -0
  58. package/dist/TableHeader-C7KKz3e1.mjs +17 -0
  59. package/dist/TableRow-D4F6AKFt.js +1 -0
  60. package/dist/TableRow-OzpVq1qW.mjs +15 -0
  61. package/dist/Text-Br_pcGz4.mjs +78 -0
  62. package/dist/Text-DlUfrsNI.js +1 -0
  63. package/dist/emoji-Bk6FG72F.js +1 -0
  64. package/dist/emoji-CmOToDEU.mjs +3711 -0
  65. package/dist/index-D2CtpNvR.js +1 -0
  66. package/dist/index-DVmWCrQE.mjs +159 -0
  67. package/dist/index.cjs.js +1 -0
  68. package/dist/index.es.js +4 -0
  69. package/dist/katex-CS0ZfoxP.js +261 -0
  70. package/dist/katex-r9TeExgs.mjs +11690 -0
  71. package/dist/prosemirror-render.css +1 -0
  72. package/dist/types/apis/monitor.d.ts +9 -0
  73. package/dist/types/apis/tingwu.d.ts +14 -0
  74. package/dist/types/apis/types.d.ts +23 -0
  75. package/dist/types/components/TreeRecursive.vue.d.ts +7 -0
  76. package/dist/types/components/TreeRender.vue.d.ts +9 -0
  77. package/dist/types/components/collections/async/AsyncError.vue.d.ts +3 -0
  78. package/dist/types/components/collections/async/AsyncLoading.vue.d.ts +3 -0
  79. package/dist/types/components/collections/attachment/AttachmentBlock.vue.d.ts +7 -0
  80. package/dist/types/components/collections/attachment/AttachmentInline.vue.d.ts +7 -0
  81. package/dist/types/components/collections/attachment/AttachmentMenu.vue.d.ts +16 -0
  82. package/dist/types/components/collections/attachment/VideoDetail.vue.d.ts +7 -0
  83. package/dist/types/components/collections/attachment/index.d.ts +1 -0
  84. package/dist/types/components/collections/basic/Blockquote.vue.d.ts +17 -0
  85. package/dist/types/components/collections/basic/BulletList.vue.d.ts +17 -0
  86. package/dist/types/components/collections/basic/HardBreak.vue.d.ts +7 -0
  87. package/dist/types/components/collections/basic/Heading.vue.d.ts +17 -0
  88. package/dist/types/components/collections/basic/HorizontalRule.vue.d.ts +7 -0
  89. package/dist/types/components/collections/basic/ListItem.vue.d.ts +17 -0
  90. package/dist/types/components/collections/basic/OrderedList.vue.d.ts +17 -0
  91. package/dist/types/components/collections/basic/Paragraph.vue.d.ts +17 -0
  92. package/dist/types/components/collections/basic/Text.vue.d.ts +7 -0
  93. package/dist/types/components/collections/basic/index.d.ts +1 -0
  94. package/dist/types/components/collections/callout/Callout.vue.d.ts +7 -0
  95. package/dist/types/components/collections/callout/index.d.ts +1 -0
  96. package/dist/types/components/collections/code/CellOutput.vue.d.ts +7 -0
  97. package/dist/types/components/collections/code/CodeBlock.vue.d.ts +7 -0
  98. package/dist/types/components/collections/code/index.d.ts +1 -0
  99. package/dist/types/components/collections/fold/FoldBlock.vue.d.ts +7 -0
  100. package/dist/types/components/collections/fold/index.d.ts +1 -0
  101. package/dist/types/components/collections/grid/Grid.vue.d.ts +7 -0
  102. package/dist/types/components/collections/grid/index.d.ts +1 -0
  103. package/dist/types/components/collections/iframe/IFrame.vue.d.ts +7 -0
  104. package/dist/types/components/collections/iframe/index.d.ts +1 -0
  105. package/dist/types/components/collections/img/Image.vue.d.ts +7 -0
  106. package/dist/types/components/collections/img/index.d.ts +1 -0
  107. package/dist/types/components/collections/index.d.ts +1 -0
  108. package/dist/types/components/collections/math/MathDisplay.vue.d.ts +7 -0
  109. package/dist/types/components/collections/math/MathInline.vue.d.ts +7 -0
  110. package/dist/types/components/collections/math/index.d.ts +1 -0
  111. package/dist/types/components/collections/multipleChoice/McChoices.vue.d.ts +16 -0
  112. package/dist/types/components/collections/multipleChoice/McQuestion.vue.d.ts +7 -0
  113. package/dist/types/components/collections/multipleChoice/McSolution.vue.d.ts +8 -0
  114. package/dist/types/components/collections/multipleChoice/MultipleChoice.vue.d.ts +7 -0
  115. package/dist/types/components/collections/multipleChoice/index.d.ts +1 -0
  116. package/dist/types/components/collections/table/TableCell.vue.d.ts +17 -0
  117. package/dist/types/components/collections/table/TableContainer.vue.d.ts +17 -0
  118. package/dist/types/components/collections/table/TableHeader.vue.d.ts +17 -0
  119. package/dist/types/components/collections/table/TableRow.vue.d.ts +17 -0
  120. package/dist/types/components/collections/table/index.d.ts +1 -0
  121. package/dist/types/components/collections/utils.d.ts +2 -0
  122. package/dist/types/components/collections/wrapper/Doc.vue.d.ts +17 -0
  123. package/dist/types/components/collections/wrapper/SlotNode.vue.d.ts +13 -0
  124. package/dist/types/components/collections/wrapper/index.d.ts +1 -0
  125. package/dist/types/components/index.d.ts +1 -0
  126. package/dist/types/icons/Attachment/CardView.vue.d.ts +9 -0
  127. package/dist/types/icons/Attachment/Code/Bat.vue.d.ts +3 -0
  128. package/dist/types/icons/Attachment/Code/C.vue.d.ts +3 -0
  129. package/dist/types/icons/Attachment/Code/Cpp.vue.d.ts +3 -0
  130. package/dist/types/icons/Attachment/Code/Css.vue.d.ts +3 -0
  131. package/dist/types/icons/Attachment/Code/Go.vue.d.ts +3 -0
  132. package/dist/types/icons/Attachment/Code/Html.vue.d.ts +3 -0
  133. package/dist/types/icons/Attachment/Code/Java.vue.d.ts +3 -0
  134. package/dist/types/icons/Attachment/Code/Js.vue.d.ts +3 -0
  135. package/dist/types/icons/Attachment/Code/Json.vue.d.ts +3 -0
  136. package/dist/types/icons/Attachment/Code/Jsx.vue.d.ts +3 -0
  137. package/dist/types/icons/Attachment/Code/Md.vue.d.ts +3 -0
  138. package/dist/types/icons/Attachment/Code/Php.vue.d.ts +3 -0
  139. package/dist/types/icons/Attachment/Code/Python.vue.d.ts +3 -0
  140. package/dist/types/icons/Attachment/Code/Rb.vue.d.ts +3 -0
  141. package/dist/types/icons/Attachment/Code/Sh.vue.d.ts +3 -0
  142. package/dist/types/icons/Attachment/Code/Sql.vue.d.ts +3 -0
  143. package/dist/types/icons/Attachment/Code/Swift.vue.d.ts +3 -0
  144. package/dist/types/icons/Attachment/Code/Ts.vue.d.ts +3 -0
  145. package/dist/types/icons/Attachment/Code/Tsx.vue.d.ts +3 -0
  146. package/dist/types/icons/Attachment/Code/Vue.vue.d.ts +3 -0
  147. package/dist/types/icons/Attachment/Excel.vue.d.ts +3 -0
  148. package/dist/types/icons/Attachment/Eye.vue.d.ts +3 -0
  149. package/dist/types/icons/Attachment/FullScreen.vue.d.ts +3 -0
  150. package/dist/types/icons/Attachment/InlineView.vue.d.ts +9 -0
  151. package/dist/types/icons/Attachment/Pdf.vue.d.ts +3 -0
  152. package/dist/types/icons/Attachment/Ppt.vue.d.ts +3 -0
  153. package/dist/types/icons/Attachment/PreviewView.vue.d.ts +9 -0
  154. package/dist/types/icons/Attachment/UnknownFile.vue.d.ts +3 -0
  155. package/dist/types/icons/Attachment/VideoIcon.vue.d.ts +3 -0
  156. package/dist/types/icons/Attachment/VideoPlay.vue.d.ts +3 -0
  157. package/dist/types/icons/Attachment/Word.vue.d.ts +3 -0
  158. package/dist/types/icons/Code/Confirm.vue.d.ts +3 -0
  159. package/dist/types/icons/Code/Paste.vue.d.ts +3 -0
  160. package/dist/types/icons/Common/Choice.vue.d.ts +3 -0
  161. package/dist/types/icons/Common/Close.vue.d.ts +3 -0
  162. package/dist/types/icons/Common/Comment.vue.d.ts +3 -0
  163. package/dist/types/icons/Common/CopyAnchorLink.vue.d.ts +3 -0
  164. package/dist/types/icons/Common/Delete.vue.d.ts +3 -0
  165. package/dist/types/icons/Common/Download.vue.d.ts +3 -0
  166. package/dist/types/icons/Common/FoldClose.vue.d.ts +3 -0
  167. package/dist/types/icons/Common/FoldOpen.vue.d.ts +3 -0
  168. package/dist/types/icons/Common/Plate.vue.d.ts +3 -0
  169. package/dist/types/icons/Common/Question.vue.d.ts +3 -0
  170. package/dist/types/icons/Common/ShareTextLink.vue.d.ts +3 -0
  171. package/dist/types/index.d.ts +2 -0
  172. package/dist/types/types.d.ts +269 -0
  173. package/dist/types/utils/common.d.ts +1 -0
  174. package/dist/types/utils/emoji.d.ts +10 -0
  175. package/dist/types/utils/globalStatus.d.ts +16 -0
  176. package/dist/types/utils/shiki.d.ts +3 -0
  177. package/dist/types/utils/useAttachment.d.ts +8 -0
  178. package/package.json +29 -0
  179. package/src/apis/monitor.ts +8 -0
  180. package/src/apis/tingwu.ts +22 -0
  181. package/src/apis/types.ts +45 -0
  182. package/src/components/TreeRecursive.vue +47 -0
  183. package/src/components/TreeRender.vue +404 -0
  184. package/src/components/collections/async/AsyncError.vue +17 -0
  185. package/src/components/collections/async/AsyncLoading.vue +1 -0
  186. package/src/components/collections/attachment/AttachmentBlock.vue +561 -0
  187. package/src/components/collections/attachment/AttachmentInline.vue +90 -0
  188. package/src/components/collections/attachment/AttachmentMenu.vue +359 -0
  189. package/src/components/collections/attachment/VideoDetail.vue +375 -0
  190. package/src/components/collections/attachment/index.ts +6 -0
  191. package/src/components/collections/basic/Blockquote.vue +15 -0
  192. package/src/components/collections/basic/BulletList.vue +15 -0
  193. package/src/components/collections/basic/HardBreak.vue +11 -0
  194. package/src/components/collections/basic/Heading.vue +15 -0
  195. package/src/components/collections/basic/HorizontalRule.vue +11 -0
  196. package/src/components/collections/basic/ListItem.vue +15 -0
  197. package/src/components/collections/basic/OrderedList.vue +15 -0
  198. package/src/components/collections/basic/Paragraph.vue +19 -0
  199. package/src/components/collections/basic/Text.vue +73 -0
  200. package/src/components/collections/basic/index.ts +13 -0
  201. package/src/components/collections/callout/Callout.vue +77 -0
  202. package/src/components/collections/callout/index.ts +5 -0
  203. package/src/components/collections/code/CellOutput.vue +72 -0
  204. package/src/components/collections/code/CodeBlock.vue +83 -0
  205. package/src/components/collections/code/index.ts +6 -0
  206. package/src/components/collections/fold/FoldBlock.vue +130 -0
  207. package/src/components/collections/fold/index.ts +5 -0
  208. package/src/components/collections/grid/Grid.vue +70 -0
  209. package/src/components/collections/grid/index.ts +5 -0
  210. package/src/components/collections/iframe/IFrame.vue +19 -0
  211. package/src/components/collections/iframe/index.ts +5 -0
  212. package/src/components/collections/img/Image.vue +318 -0
  213. package/src/components/collections/img/index.ts +5 -0
  214. package/src/components/collections/index.ts +29 -0
  215. package/src/components/collections/math/MathDisplay.vue +42 -0
  216. package/src/components/collections/math/MathInline.vue +42 -0
  217. package/src/components/collections/math/index.ts +6 -0
  218. package/src/components/collections/multipleChoice/McChoices.vue +72 -0
  219. package/src/components/collections/multipleChoice/McQuestion.vue +61 -0
  220. package/src/components/collections/multipleChoice/McSolution.vue +47 -0
  221. package/src/components/collections/multipleChoice/MultipleChoice.vue +62 -0
  222. package/src/components/collections/multipleChoice/index.ts +8 -0
  223. package/src/components/collections/table/TableCell.vue +20 -0
  224. package/src/components/collections/table/TableContainer.vue +32 -0
  225. package/src/components/collections/table/TableHeader.vue +15 -0
  226. package/src/components/collections/table/TableRow.vue +15 -0
  227. package/src/components/collections/table/index.ts +8 -0
  228. package/src/components/collections/utils.ts +17 -0
  229. package/src/components/collections/wrapper/Doc.vue +15 -0
  230. package/src/components/collections/wrapper/SlotNode.vue +5 -0
  231. package/src/components/collections/wrapper/index.ts +6 -0
  232. package/src/components/index.ts +1 -0
  233. package/src/icons/Attachment/CardView.vue +21 -0
  234. package/src/icons/Attachment/Code/Bat.vue +26 -0
  235. package/src/icons/Attachment/Code/C.vue +26 -0
  236. package/src/icons/Attachment/Code/Cpp.vue +26 -0
  237. package/src/icons/Attachment/Code/Css.vue +34 -0
  238. package/src/icons/Attachment/Code/Go.vue +26 -0
  239. package/src/icons/Attachment/Code/Html.vue +34 -0
  240. package/src/icons/Attachment/Code/Java.vue +42 -0
  241. package/src/icons/Attachment/Code/Js.vue +26 -0
  242. package/src/icons/Attachment/Code/Json.vue +26 -0
  243. package/src/icons/Attachment/Code/Jsx.vue +30 -0
  244. package/src/icons/Attachment/Code/Md.vue +26 -0
  245. package/src/icons/Attachment/Code/Php.vue +26 -0
  246. package/src/icons/Attachment/Code/Python.vue +30 -0
  247. package/src/icons/Attachment/Code/Rb.vue +26 -0
  248. package/src/icons/Attachment/Code/Sh.vue +30 -0
  249. package/src/icons/Attachment/Code/Sql.vue +30 -0
  250. package/src/icons/Attachment/Code/Swift.vue +26 -0
  251. package/src/icons/Attachment/Code/Ts.vue +26 -0
  252. package/src/icons/Attachment/Code/Tsx.vue +30 -0
  253. package/src/icons/Attachment/Code/Vue.vue +24 -0
  254. package/src/icons/Attachment/Excel.vue +26 -0
  255. package/src/icons/Attachment/Eye.vue +15 -0
  256. package/src/icons/Attachment/FullScreen.vue +15 -0
  257. package/src/icons/Attachment/InlineView.vue +21 -0
  258. package/src/icons/Attachment/Pdf.vue +25 -0
  259. package/src/icons/Attachment/Ppt.vue +26 -0
  260. package/src/icons/Attachment/PreviewView.vue +21 -0
  261. package/src/icons/Attachment/UnknownFile.vue +26 -0
  262. package/src/icons/Attachment/VideoIcon.vue +25 -0
  263. package/src/icons/Attachment/VideoPlay.vue +15 -0
  264. package/src/icons/Attachment/Word.vue +26 -0
  265. package/src/icons/Code/Confirm.vue +38 -0
  266. package/src/icons/Code/Paste.vue +8 -0
  267. package/src/icons/Common/Choice.vue +28 -0
  268. package/src/icons/Common/Close.vue +15 -0
  269. package/src/icons/Common/Comment.vue +16 -0
  270. package/src/icons/Common/CopyAnchorLink.vue +15 -0
  271. package/src/icons/Common/Delete.vue +15 -0
  272. package/src/icons/Common/Download.vue +15 -0
  273. package/src/icons/Common/FoldClose.vue +9 -0
  274. package/src/icons/Common/FoldOpen.vue +9 -0
  275. package/src/icons/Common/Plate.vue +23 -0
  276. package/src/icons/Common/Question.vue +8 -0
  277. package/src/icons/Common/ShareTextLink.vue +15 -0
  278. package/src/index.ts +3 -0
  279. package/src/types.ts +236 -0
  280. package/src/utils/common.ts +6 -0
  281. package/src/utils/emoji.ts +3715 -0
  282. package/src/utils/globalStatus.ts +19 -0
  283. package/src/utils/shiki.ts +25 -0
  284. package/src/utils/useAttachment.ts +215 -0
  285. package/tsconfig.build.json +10 -0
  286. package/tsconfig.json +23 -0
  287. package/vite.config.ts +24 -0
@@ -0,0 +1,318 @@
1
+ <template>
2
+ <div class="image-container" :style="{ alignItems: node.attrs.align }">
3
+ <div class="image-wrapper" :style="{ width: restrictedWidth }">
4
+ <img :src="node.attrs.src" :alt="node.attrs.caption ? node.attrs.caption : '图片'" @click="enlarge" />
5
+ </div>
6
+ <input type="text" v-if="node.attrs.caption" class="image-caption" :value="node.attrs.caption" disabled />
7
+ <Teleport to="body">
8
+ <Transition name="modal">
9
+ <div v-show="showModal" class="modal-mask" @click="closeModal">
10
+ <div class="modal-close">×</div>
11
+ <img class="modal-body" :src="currentImageNode?.attrs.src" :width="currentImgWidth" :height="currentImgHeight"
12
+ alt="图片" />
13
+ <div class="modal-footer">
14
+ <div class="prev-image" :class="{ disabled: currentIndex === 0 }" @click.stop="prevImage">‹</div>
15
+ <div class="zoom-out" :class="{ disabled: percentage <= 10 }" @click.stop="zoomOut">-</div>
16
+ <div class="percentage">{{ percentage.toFixed(0) }}%</div>
17
+ <div class="zoom-in" :class="{ disabled: percentage >= 500 }" @click.stop="zoomIn">+</div>
18
+ <div class="next-image" :class="{ disabled: currentIndex === imageNodes.length - 1 }"
19
+ @click.stop="nextImage">
20
+
21
+ </div>
22
+ </div>
23
+ </div>
24
+ </Transition>
25
+ </Teleport>
26
+ </div>
27
+ </template>
28
+
29
+ <script setup lang="ts">
30
+ import { type Ref, computed, inject, ref } from 'vue';
31
+ import { imageNodesKey } from '@datawhale/dipwap-render/utils/globalStatus';
32
+ import type { PMImg } from '@datawhale/dipwap-types/index';
33
+
34
+ const { node } = defineProps<{
35
+ node: PMImg;
36
+ }>();
37
+
38
+ const imageNodes = inject<Ref<PMImg[]>>(imageNodesKey, ref([]));
39
+
40
+ const restrictedWidth = computed(() => {
41
+ const attrsWidth = node.attrs.width as string;
42
+ if (attrsWidth && attrsWidth.endsWith('%') && !attrsWidth.startsWith('0')) {
43
+ const curWidth = parseFloat(attrsWidth.slice(0, -1));
44
+ return Math.max(Math.min(curWidth, 100), 10) + '%';
45
+ } else {
46
+ return '80%';
47
+ }
48
+ });
49
+
50
+ // 图片放大相关功能实现
51
+ const imgWidth = ref<number>(0); // 原始图片宽度
52
+ const imgHeight = ref<number>(0); // 原始图片高度
53
+ const showModal = ref<boolean>(false);
54
+ const percentage = ref<number>(100); // 放大百分比
55
+ const currentImageNode = ref<PMImg | null>(null); // 当前浏览的图片节点
56
+ const currentImgWidth = ref<number>(0); // 当前浏览的图片的宽度
57
+ const currentImgHeight = ref<number>(0); // 当前浏览的图片的高度
58
+ const currentIndex = ref<number>(0); // 当前浏览的图片的索引
59
+
60
+ async function updateImageInfo(index: number) {
61
+ currentImageNode.value = imageNodes.value[index]!;
62
+ const img = new Image();
63
+ img.src = imageNodes.value[index]!.attrs.src;
64
+ await img.decode();
65
+ imgWidth.value = img.naturalWidth;
66
+ imgHeight.value = img.height;
67
+ if (!imgWidth.value || !imgHeight.value) return;
68
+ calculateSize();
69
+ }
70
+
71
+ const enlarge = async () => {
72
+ // 初始化放大时,设置 `currentImage`并计算percentage
73
+ currentIndex.value = imageNodes.value.findIndex((imgNode) => imgNode.attrs.src === node.attrs.src);
74
+ await updateImageInfo(currentIndex.value);
75
+ showModal.value = true;
76
+ document.body.style.overflow = 'hidden'; // 打开模态框时禁止页面内容滚动
77
+ };
78
+
79
+ // 图片切换功能实现
80
+ const prevImage = async () => {
81
+ if (currentIndex.value > 0) {
82
+ currentIndex.value -= 1;
83
+ await updateImageInfo(currentIndex.value);
84
+ }
85
+ };
86
+
87
+ const nextImage = async () => {
88
+ if (currentIndex.value < imageNodes.value.length - 1) {
89
+ currentIndex.value += 1;
90
+ await updateImageInfo(currentIndex.value);
91
+ }
92
+ };
93
+
94
+ const calculateSize = () => {
95
+ // 视口宽高
96
+ const windowWidth = window.innerWidth;
97
+ const windowHeight = window.innerHeight;
98
+ // 计算按原比例放大后的图片宽高(适应屏幕大小)
99
+ // 如果宽度为90vw时,高度等比放大后仍在屏幕高度90%的范围内,则使宽度为90vw,并计算等比放大后高度
100
+ // 如果宽度为90vw时,高度等比放大后超出屏幕高度的90%,则使高度为屏幕宽度的90%,并计算等比放大后的宽度
101
+ const tempHeight = ((windowWidth * 0.9) / imgWidth.value) * imgHeight.value;
102
+ if (tempHeight <= windowHeight * 0.9) {
103
+ currentImgWidth.value = windowWidth * 0.9;
104
+ currentImgHeight.value = tempHeight;
105
+ } else {
106
+ currentImgWidth.value = ((windowHeight * 0.9) / imgHeight.value) * imgWidth.value;
107
+ currentImgHeight.value = windowHeight * 0.9;
108
+ }
109
+ percentage.value = (currentImgWidth.value / imgWidth.value) * 100;
110
+ };
111
+
112
+ const zoomOut = () => {
113
+ if (percentage.value <= 10) return;
114
+ // 使百分比为10的倍数
115
+ if (percentage.value % 10 !== 0) {
116
+ percentage.value = Math.floor(percentage.value / 10) * 10;
117
+ } else {
118
+ percentage.value -= 10;
119
+ }
120
+ currentImgWidth.value = (percentage.value / 100) * imgWidth.value;
121
+ currentImgHeight.value = (percentage.value / 100) * imgHeight.value;
122
+ };
123
+
124
+ const zoomIn = () => {
125
+ if (percentage.value >= 500) return;
126
+ if (percentage.value % 10 !== 0) {
127
+ percentage.value = Math.ceil(percentage.value / 10) * 10;
128
+ } else {
129
+ percentage.value += 10;
130
+ }
131
+ currentImgWidth.value = (percentage.value / 100) * imgWidth.value;
132
+ currentImgHeight.value = (percentage.value / 100) * imgHeight.value;
133
+ };
134
+
135
+ const closeModal = () => {
136
+ showModal.value = false;
137
+ document.body.style.overflow = '';
138
+ };
139
+ </script>
140
+
141
+ <style scoped lang="scss">
142
+ .image-container {
143
+ display: flex;
144
+ flex-direction: column;
145
+ margin-bottom: 16px;
146
+
147
+ // ========== 图片及图片的高亮框 ==========
148
+ .image-wrapper {
149
+ position: relative;
150
+ box-sizing: border-box;
151
+ border: 1px solid transparent;
152
+ margin-bottom: 8px;
153
+ max-width: 100%;
154
+
155
+ &::before {
156
+ content: '';
157
+ position: absolute;
158
+ top: 0;
159
+ left: 0;
160
+ right: 0;
161
+ bottom: 0;
162
+ border: 1px solid;
163
+ border-color: inherit;
164
+ pointer-events: none;
165
+ }
166
+
167
+ &:hover {
168
+ cursor: zoom-in;
169
+
170
+ &::before {
171
+ border: 2px solid #c2d4ff;
172
+ }
173
+ }
174
+
175
+ img {
176
+ width: 100%;
177
+ height: 100%;
178
+ -webkit-touch-callout: none;
179
+ }
180
+ }
181
+
182
+ .image-caption {
183
+ all: unset;
184
+ display: inline;
185
+ text-align: center;
186
+ font-size: 16px;
187
+ margin: 0 auto;
188
+ background-color: transparent;
189
+ width: 100%;
190
+ transition: border-color 0.3s ease;
191
+ color: rgb(100, 106, 115);
192
+ }
193
+ }
194
+
195
+ /** 以下为放大效果 **/
196
+ .modal-mask {
197
+ position: fixed;
198
+ z-index: 100000;
199
+ top: 0;
200
+ left: 0;
201
+ width: 100%;
202
+ height: 100%;
203
+ background-color: rgba(0, 0, 0, 0.5);
204
+ display: flex;
205
+ flex-direction: column;
206
+ justify-content: center;
207
+ align-items: center;
208
+ transition: opacity 0.3s ease;
209
+
210
+ .modal-close {
211
+ position: absolute;
212
+ top: 2rem;
213
+ right: 2rem;
214
+ width: 3rem;
215
+ height: 3rem;
216
+ line-height: 2.8rem;
217
+ text-align: center;
218
+ color: #fff;
219
+ font-size: 2rem;
220
+ font-weight: bold;
221
+ border-radius: 50%;
222
+ z-index: 9999;
223
+ background-color: rgba(0, 0, 0, 0.5);
224
+ cursor: pointer;
225
+ user-select: none;
226
+ }
227
+
228
+ .modal-body {
229
+ display: block;
230
+ transition: all 0.3s ease;
231
+ }
232
+
233
+ .modal-footer {
234
+ position: absolute;
235
+ bottom: 20px;
236
+ left: calc(50vw - 80px);
237
+ display: flex;
238
+ justify-content: center;
239
+ align-items: center;
240
+ width: 160px;
241
+ height: 40px;
242
+ background-color: rgba(0, 0, 0, 0.5);
243
+ cursor: default;
244
+ user-select: none;
245
+
246
+ .zoom-in,
247
+ .zoom-out {
248
+ width: 39px;
249
+ height: 100%;
250
+ line-height: 37px;
251
+ text-align: center;
252
+ color: #fff;
253
+ font-size: 30px;
254
+ }
255
+
256
+ .zoom-in {
257
+ border-left: 1px solid #fff;
258
+ }
259
+
260
+ .zoom-out {
261
+ border-right: 1px solid #fff;
262
+ }
263
+
264
+ .disabled {
265
+ color: rgb(100, 100, 100);
266
+ cursor: not-allowed;
267
+ }
268
+
269
+ .percentage {
270
+ width: 80px;
271
+ height: 100%;
272
+ display: flex;
273
+ justify-content: center;
274
+ align-items: center;
275
+ color: #fff;
276
+ }
277
+
278
+ .prev-image,
279
+ .next-image {
280
+ width: 39px;
281
+ height: 100%;
282
+ line-height: 37px;
283
+ text-align: center;
284
+ color: #fff;
285
+ font-size: 30px;
286
+ cursor: pointer;
287
+ user-select: none;
288
+ }
289
+
290
+ .prev-image {
291
+ border-right: 1px solid #fff;
292
+ }
293
+
294
+ .next-image {
295
+ border-left: 1px solid #fff;
296
+ }
297
+
298
+ .disabled {
299
+ color: rgb(100, 100, 100);
300
+ cursor: not-allowed;
301
+ }
302
+ }
303
+ }
304
+
305
+ .modal-enter-from {
306
+ opacity: 0;
307
+ }
308
+
309
+ .modal-leave-to {
310
+ opacity: 0;
311
+ }
312
+
313
+ .modal-enter-from .modal-body,
314
+ .modal-leave-to .modal-body {
315
+ -webkit-transform: scale(1.1);
316
+ transform: scale(1.1);
317
+ }
318
+ </style>
@@ -0,0 +1,5 @@
1
+ import { customDefineAsyncComponent } from '../utils';
2
+
3
+ export const imgMapper: Record<string, any> = {
4
+ image: customDefineAsyncComponent(() => import('./Image.vue')),
5
+ };
@@ -0,0 +1,29 @@
1
+ // 这里各个mapper的import和使用都按照字典序排序
2
+ // 以后有新增时也按照字典序排序,好看一点,也便于查找
3
+ import { attachmentMapper } from './attachment/index.js';
4
+ import { basicMapper } from './basic/index.js';
5
+ import { calloutMapper } from './callout/index.js';
6
+ import { codeMapper } from './code/index.js';
7
+ import { foldBlockMapper } from './fold/index.js';
8
+ import { gridMapper } from './grid/index.js';
9
+ import { iframeMapper } from './iframe/index.js';
10
+ import { imgMapper } from './img/index.js';
11
+ import { mathMapper } from './math/index.js';
12
+ import { multipleChoiceMapper } from './multipleChoice/index.js';
13
+ import { tableMapper } from './table/index.js';
14
+ import { wrapperMapper } from './wrapper/index.js';
15
+
16
+ export const componentMapper: Record<string, any> = {
17
+ ...attachmentMapper, // 附件和视频类型
18
+ ...basicMapper, // 基础类型,包括各种字体样式
19
+ ...calloutMapper, // 高亮块
20
+ ...codeMapper, // 代码块
21
+ ...foldBlockMapper, // 折叠块
22
+ ...gridMapper, // 分栏
23
+ ...imgMapper, // 图片
24
+ ...mathMapper, // 数学公式
25
+ ...multipleChoiceMapper, //选择题
26
+ ...tableMapper, // 表格
27
+ ...wrapperMapper, // 容器
28
+ ...iframeMapper, // iframe
29
+ };
@@ -0,0 +1,42 @@
1
+ <template>
2
+ <div class="math-display">
3
+ <div class="math-render" v-html="content"></div>
4
+ </div>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ import { ref } from 'vue';
9
+ import type { PMMath } from '@datawhale/dipwap-types/index';
10
+
11
+ const { node } = defineProps<{
12
+ node: PMMath;
13
+ }>();
14
+
15
+ const content = ref('');
16
+
17
+ try {
18
+ const { default: katex } = await import('katex');
19
+ content.value = katex.renderToString(node.content[0]!.text, {
20
+ displayMode: true,
21
+ strict: (errorCode: string) => (errorCode === 'unicodeTextInMathMode' ? 'ignore' : 'warn'),
22
+ });
23
+ } catch (error) {
24
+ console.error(error);
25
+ }
26
+ </script>
27
+
28
+ <style scoped lang="scss">
29
+ .math-display {
30
+ min-width: 0.95em;
31
+ min-height: 0.95em;
32
+ font-size: 0.95em;
33
+ font-family:
34
+ Consolas,
35
+ Ubuntu Mono,
36
+ monospace;
37
+
38
+ .math-render :deep(.katex-display) {
39
+ margin: 0;
40
+ }
41
+ }
42
+ </style>
@@ -0,0 +1,42 @@
1
+ <template>
2
+ <span class="math-inline">
3
+ <span class="math-render" v-html="content"></span>
4
+ </span>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ import { ref } from 'vue';
9
+ import type { PMInlineMath } from '@datawhale/dipwap-types/index';
10
+
11
+ const { node } = defineProps<{
12
+ node: PMInlineMath;
13
+ }>();
14
+
15
+ const content = ref('');
16
+
17
+ try {
18
+ const { default: katex } = await import('katex');
19
+ content.value = katex.renderToString(node.content[0]!.text, {
20
+ displayMode: false,
21
+ strict: (errorCode: string) => (errorCode === 'unicodeTextInMathMode' ? 'ignore' : 'warn'),
22
+ });
23
+ } catch (error) {
24
+ console.error(error);
25
+ }
26
+ </script>
27
+
28
+ <style scoped lang="scss">
29
+ .math-inline {
30
+ min-width: 1em;
31
+ min-height: 1em;
32
+ font-size: 0.95em;
33
+ font-family:
34
+ Consolas,
35
+ Ubuntu Mono,
36
+ monospace;
37
+ .math-render {
38
+ display: inline-block;
39
+ font-size: 0.85em;
40
+ }
41
+ }
42
+ </style>
@@ -0,0 +1,6 @@
1
+ import { customDefineAsyncComponent } from '../utils';
2
+
3
+ export const mathMapper: Record<string, any> = {
4
+ math_inline: customDefineAsyncComponent(() => import('./MathInline.vue')),
5
+ math_display: customDefineAsyncComponent(() => import('./MathDisplay.vue')),
6
+ };
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <div class="mc-choices-header">
3
+ <div class="choices-header-bar">
4
+ <Choice class="header-icon" />
5
+ <span class="header-text">选项</span>
6
+ </div>
7
+ <div class="choice-list">
8
+ <label class="choice-item" v-for="(child, index) in node.content" :key="index">
9
+ <input type="radio" :value="index" v-model="selectedModel" :disabled="submitted" />
10
+ <span class="prefix">{{ String.fromCharCode(65 + index) }}.</span>
11
+ <TreeRecursive :node="child" />
12
+ </label>
13
+ </div>
14
+ </div>
15
+ </template>
16
+
17
+ <script setup lang="ts">
18
+ import TreeRecursive from '@datawhale/dipwap-render/components/TreeRecursive.vue';
19
+ import Choice from '@datawhale/dipwap-render/icons/Common/Choice.vue';
20
+ import type { PMMCChoices } from '@datawhale/dipwap-types/index';
21
+
22
+ defineProps<{
23
+ node: PMMCChoices;
24
+ submitted: boolean;
25
+ }>();
26
+
27
+ const selectedModel = defineModel<number | null>('selected');
28
+ </script>
29
+
30
+ <style scoped lang="scss">
31
+ .mc-choices-header {
32
+ .choices-header-bar {
33
+ display: flex;
34
+ align-items: center;
35
+ padding: 10px 15px;
36
+ border-radius: 5px;
37
+ background-color: #e1e1e8;
38
+ .header-icon {
39
+ height: 24px;
40
+ width: 24px;
41
+ margin-right: 8px;
42
+ }
43
+ .header-text {
44
+ font-size: 18px;
45
+ font-weight: 700;
46
+ font-family: Arial, sans-serif;
47
+ }
48
+ }
49
+ .choice-list {
50
+ display: flex;
51
+ flex-direction: column;
52
+ background-color: #fff;
53
+ padding: 8px 0px;
54
+
55
+ .choice-item {
56
+ display: flex;
57
+ flex-direction: row;
58
+ align-items: center;
59
+ justify-content: flex-start;
60
+ padding: 0px 12px;
61
+ input[type='radio'] {
62
+ cursor: pointer;
63
+ }
64
+ .prefix {
65
+ font-weight: bold;
66
+ width: 1.5em;
67
+ margin-left: 12px;
68
+ }
69
+ }
70
+ }
71
+ }
72
+ </style>
@@ -0,0 +1,61 @@
1
+ <template>
2
+ <div class="mc-question-header">
3
+ <div class="question-header">
4
+ <Question class="icon" />
5
+ <span class="header-text">题目</span>
6
+ </div>
7
+ <div class="question-content">
8
+ <TreeRecursive v-for="child in node.content" :node="child" :key="useId()" />
9
+ </div>
10
+ </div>
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ import { useId } from 'vue';
15
+ import TreeRecursive from '@datawhale/dipwap-render/components/TreeRecursive.vue';
16
+ import Question from '@datawhale/dipwap-render/icons/Common/Question.vue';
17
+ import type { PMMCQuestion } from '@datawhale/dipwap-types/index';
18
+
19
+ defineProps<{
20
+ node: PMMCQuestion;
21
+ }>();
22
+ </script>
23
+
24
+ <style scoped lang="scss">
25
+ .mc-question-header {
26
+ display: flex;
27
+ flex-direction: column;
28
+ border-radius: 12px;
29
+ .question-header {
30
+ display: flex;
31
+ align-items: center;
32
+ padding: 10px 15px;
33
+ background-color: #e1e1e8;
34
+ border-radius: 12px;
35
+ .icon {
36
+ height: 24px;
37
+ width: 24px;
38
+ margin-right: 8px;
39
+ }
40
+
41
+ .header-text {
42
+ font-size: 18px;
43
+ font-weight: 700;
44
+ font-family: Arial, sans-serif;
45
+ }
46
+ }
47
+
48
+ .question-content {
49
+ padding: 12px 16px;
50
+ background-color: #fff;
51
+
52
+ :deep(p:first-child) {
53
+ margin-top: 0;
54
+ }
55
+
56
+ :deep(p:last-child) {
57
+ margin-bottom: 0;
58
+ }
59
+ }
60
+ }
61
+ </style>
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <div class="mc-solution">
3
+ <div :class="['solution-content', correct ? 'correct' : 'wrong']">
4
+ <TreeRecursive v-for="child in node.content" :node="child" :key="useId()" />
5
+ </div>
6
+ </div>
7
+ </template>
8
+
9
+ <script setup lang="ts">
10
+ import { useId } from 'vue';
11
+ import TreeRecursive from '@datawhale/dipwap-render/components/TreeRecursive.vue';
12
+ import type { PMMCSolution } from '@datawhale/dipwap-types/index';
13
+
14
+ defineProps<{
15
+ node: PMMCSolution;
16
+ correct: boolean;
17
+ }>();
18
+ </script>
19
+
20
+ <style scoped lang="scss">
21
+ .mc-solution {
22
+ margin: 12px;
23
+ .solution-content {
24
+ border-radius: 4px;
25
+ padding: 12px 16px;
26
+ font-size: 14px;
27
+ color: #333;
28
+
29
+ :deep(p:first-child) {
30
+ margin-top: 0;
31
+ }
32
+
33
+ :deep(p:last-child) {
34
+ margin-bottom: 0;
35
+ }
36
+
37
+ &.correct {
38
+ background-color: #eef8ea;
39
+ border: 1.5px solid #83c17e;
40
+ }
41
+ &.wrong {
42
+ background-color: #fdecea;
43
+ border: 1.5px solid #f08b83;
44
+ }
45
+ }
46
+ }
47
+ </style>
@@ -0,0 +1,62 @@
1
+ <template>
2
+ <div class="multiple-choice">
3
+ <McQuestion :node="node.content[0]" />
4
+
5
+ <McChoices v-model:selected="selected" :node="node.content[1]" :submitted="submitted" />
6
+
7
+ <div class="submit-area" v-if="!submitted">
8
+ <button class="submit-button" :disabled="selected === null" @click="submit">提交答案</button>
9
+ </div>
10
+
11
+ <McSolution v-if="submitted" :node="node.content[2]" :correct="isCorrect" />
12
+ </div>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ import { ref } from 'vue';
17
+ import type { PMMultipleChoice } from '@datawhale/dipwap-types/index';
18
+ import McChoices from './McChoices.vue';
19
+ import McQuestion from './McQuestion.vue';
20
+ import McSolution from './McSolution.vue';
21
+
22
+ const props = defineProps<{
23
+ node: PMMultipleChoice;
24
+ }>();
25
+
26
+ const selected = ref<number | null>(null);
27
+ const submitted = ref(false);
28
+ const isCorrect = ref(false);
29
+
30
+ const submit = () => {
31
+ submitted.value = true;
32
+ const correctIndex = props.node.content[1].attrs.correctIndex;
33
+ isCorrect.value = selected.value === correctIndex;
34
+ };
35
+ </script>
36
+
37
+ <style scoped lang="scss">
38
+ .multiple-choice {
39
+ border: 2px solid rgb(128, 124, 124);
40
+ border-radius: 8px;
41
+ margin: 20px 0;
42
+ background-color: rgb(225, 225, 232);
43
+ .submit-area {
44
+ padding: 12px;
45
+ }
46
+
47
+ .submit-button {
48
+ padding: 6px 12px;
49
+ background-color: #4caf50;
50
+ color: white;
51
+ border: none;
52
+ border-radius: 4px;
53
+ font-weight: bold;
54
+ cursor: pointer;
55
+
56
+ &:disabled {
57
+ background-color: #929292;
58
+ cursor: not-allowed;
59
+ }
60
+ }
61
+ }
62
+ </style>
@@ -0,0 +1,8 @@
1
+ import { customDefineAsyncComponent } from '../utils';
2
+
3
+ export const multipleChoiceMapper: Record<string, any> = {
4
+ multipleChoice: customDefineAsyncComponent(() => import('./MultipleChoice.vue')),
5
+ mcQuestion: customDefineAsyncComponent(() => import('./McQuestion.vue')),
6
+ mcChoices: customDefineAsyncComponent(() => import('./McChoices.vue')),
7
+ mcSolution: customDefineAsyncComponent(() => import('./McSolution.vue')),
8
+ };