@vue-skuilder/common-ui 0.2.34 → 0.2.36

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 (207) hide show
  1. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/defineProperty.mjs +13 -0
  2. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/toPrimitive.mjs +15 -0
  3. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/toPropertyKey.mjs +10 -0
  4. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/typeof.mjs +12 -0
  5. package/dist/_virtual/_plugin-vue_export-helper.mjs +9 -0
  6. package/dist/_virtual/_rolldown/runtime.mjs +7 -0
  7. package/dist/admin/admin.css +1 -1
  8. package/dist/admin/common-ui-admin.es.js +1074 -473
  9. package/dist/admin/common-ui-admin.es.js.map +1 -1
  10. package/dist/admin/components/EChart.vue.d.ts +14 -0
  11. package/dist/admin/components/EChart.vue.d.ts.map +1 -0
  12. package/dist/admin/components/LearnerDiagnostics.vue.d.ts +3 -3
  13. package/dist/admin/components/LearnerDiagnostics.vue.d.ts.map +1 -1
  14. package/dist/admin/components/LearnerTagElo.vue.d.ts +14 -0
  15. package/dist/admin/components/LearnerTagElo.vue.d.ts.map +1 -0
  16. package/dist/admin/index.d.ts +1 -0
  17. package/dist/admin/index.d.ts.map +1 -1
  18. package/dist/assets/index.css +2 -1
  19. package/dist/components/CardBrowser.mjs +63 -0
  20. package/dist/components/CardBrowser.mjs.map +1 -0
  21. package/dist/components/CardBrowser.vue_vue_type_script_lang.mjs +50 -0
  22. package/dist/components/CardBrowser.vue_vue_type_script_lang.mjs.map +1 -0
  23. package/dist/components/CardHistoryViewer.mjs +70 -0
  24. package/dist/components/CardHistoryViewer.mjs.map +1 -0
  25. package/dist/components/CardHistoryViewer.vue_vue_type_script_lang.mjs +108 -0
  26. package/dist/components/CardHistoryViewer.vue_vue_type_script_lang.mjs.map +1 -0
  27. package/dist/components/CardSearch.mjs +26 -0
  28. package/dist/components/CardSearch.mjs.map +1 -0
  29. package/dist/components/CardSearch.vue_vue_type_script_lang.mjs +17 -0
  30. package/dist/components/CardSearch.vue_vue_type_script_lang.mjs.map +1 -0
  31. package/dist/components/CardSearchResults.mjs +32 -0
  32. package/dist/components/CardSearchResults.mjs.map +1 -0
  33. package/dist/components/CardSearchResults.vue_vue_type_script_lang.mjs +71 -0
  34. package/dist/components/CardSearchResults.vue_vue_type_script_lang.mjs.map +1 -0
  35. package/dist/components/CourseCardBrowser.mjs +175 -0
  36. package/dist/components/CourseCardBrowser.mjs.map +1 -0
  37. package/dist/components/CourseCardBrowser.vue.d.ts +3 -3
  38. package/dist/components/CourseCardBrowser.vue_vue_type_script_lang.mjs +173 -0
  39. package/dist/components/CourseCardBrowser.vue_vue_type_script_lang.mjs.map +1 -0
  40. package/dist/components/CourseInformation.mjs +132 -0
  41. package/dist/components/CourseInformation.mjs.map +1 -0
  42. package/dist/components/CourseInformation.vue.d.ts +3 -3
  43. package/dist/components/CourseInformation.vue_vue_type_script_lang.mjs +56 -0
  44. package/dist/components/CourseInformation.vue_vue_type_script_lang.mjs.map +1 -0
  45. package/dist/components/CourseTagFilterWidget.mjs +114 -0
  46. package/dist/components/CourseTagFilterWidget.mjs.map +1 -0
  47. package/dist/components/CourseTagFilterWidget.vue_vue_type_script_lang.mjs +65 -0
  48. package/dist/components/CourseTagFilterWidget.vue_vue_type_script_lang.mjs.map +1 -0
  49. package/dist/components/HeatMap.mjs +40 -0
  50. package/dist/components/HeatMap.mjs.map +1 -0
  51. package/dist/components/HeatMap.vue_vue_type_script_lang.mjs +211 -0
  52. package/dist/components/HeatMap.vue_vue_type_script_lang.mjs.map +1 -0
  53. package/dist/components/PaginatingToolbar.mjs +94 -0
  54. package/dist/components/PaginatingToolbar.mjs.map +1 -0
  55. package/dist/components/PaginatingToolbar.vue.d.ts +3 -3
  56. package/dist/components/PaginatingToolbar.vue_vue_type_script_lang.mjs +36 -0
  57. package/dist/components/PaginatingToolbar.vue_vue_type_script_lang.mjs.map +1 -0
  58. package/dist/components/SessionControllerDebug.mjs +130 -0
  59. package/dist/components/SessionControllerDebug.mjs.map +1 -0
  60. package/dist/components/SessionControllerDebug.vue_vue_type_script_lang.mjs +45 -0
  61. package/dist/components/SessionControllerDebug.vue_vue_type_script_lang.mjs.map +1 -0
  62. package/dist/components/SkMouseTrap.mjs +66 -0
  63. package/dist/components/SkMouseTrap.mjs.map +1 -0
  64. package/dist/components/SkMouseTrap.vue_vue_type_script_lang.mjs +31 -0
  65. package/dist/components/SkMouseTrap.vue_vue_type_script_lang.mjs.map +1 -0
  66. package/dist/components/SkMouseTrapToolTip.mjs +28 -0
  67. package/dist/components/SkMouseTrapToolTip.mjs.map +1 -0
  68. package/dist/components/SkMouseTrapToolTip.vue.d.ts +1 -1
  69. package/dist/components/SkMouseTrapToolTip.vue_vue_type_script_lang.mjs +91 -0
  70. package/dist/components/SkMouseTrapToolTip.vue_vue_type_script_lang.mjs.map +1 -0
  71. package/dist/components/SnackbarService.mjs +24 -0
  72. package/dist/components/SnackbarService.mjs.map +1 -0
  73. package/dist/components/SnackbarService.vue_vue_type_script_lang.mjs +34 -0
  74. package/dist/components/SnackbarService.vue_vue_type_script_lang.mjs.map +1 -0
  75. package/dist/components/SnackbarService2.mjs +40 -0
  76. package/dist/components/SnackbarService2.mjs.map +1 -0
  77. package/dist/components/StudySession.mjs +123 -0
  78. package/dist/components/StudySession.mjs.map +1 -0
  79. package/dist/components/StudySession.vue_vue_type_script_lang.mjs +280 -0
  80. package/dist/components/StudySession.vue_vue_type_script_lang.mjs.map +1 -0
  81. package/dist/components/StudySessionTimer.mjs +50 -0
  82. package/dist/components/StudySessionTimer.mjs.map +1 -0
  83. package/dist/components/StudySessionTimer.vue_vue_type_script_lang.mjs +43 -0
  84. package/dist/components/StudySessionTimer.vue_vue_type_script_lang.mjs.map +1 -0
  85. package/dist/components/TagsInput.mjs +45 -0
  86. package/dist/components/TagsInput.mjs.map +1 -0
  87. package/dist/components/TagsInput.vue_vue_type_script_lang.mjs +117 -0
  88. package/dist/components/TagsInput.vue_vue_type_script_lang.mjs.map +1 -0
  89. package/dist/components/UserTagPreferences.mjs +205 -0
  90. package/dist/components/UserTagPreferences.mjs.map +1 -0
  91. package/dist/components/UserTagPreferences.vue_vue_type_script_lang.mjs +139 -0
  92. package/dist/components/UserTagPreferences.vue_vue_type_script_lang.mjs.map +1 -0
  93. package/dist/components/auth/RequestPasswordReset.mjs +96 -0
  94. package/dist/components/auth/RequestPasswordReset.mjs.map +1 -0
  95. package/dist/components/auth/RequestPasswordReset.vue_vue_type_script_lang.mjs +47 -0
  96. package/dist/components/auth/RequestPasswordReset.vue_vue_type_script_lang.mjs.map +1 -0
  97. package/dist/components/auth/ResetPassword.mjs +129 -0
  98. package/dist/components/auth/ResetPassword.mjs.map +1 -0
  99. package/dist/components/auth/ResetPassword.vue_vue_type_script_lang.mjs +69 -0
  100. package/dist/components/auth/ResetPassword.vue_vue_type_script_lang.mjs.map +1 -0
  101. package/dist/components/auth/UserChip.mjs +9 -0
  102. package/dist/components/auth/UserChip.mjs.map +1 -0
  103. package/dist/components/auth/UserChip.vue_vue_type_script_setup_true_lang.mjs +213 -0
  104. package/dist/components/auth/UserChip.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  105. package/dist/components/auth/UserLogin.mjs +9 -0
  106. package/dist/components/auth/UserLogin.mjs.map +1 -0
  107. package/dist/components/auth/UserLogin.vue_vue_type_script_setup_true_lang.mjs +155 -0
  108. package/dist/components/auth/UserLogin.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  109. package/dist/components/auth/UserLoginAndRegistrationContainer.mjs +9 -0
  110. package/dist/components/auth/UserLoginAndRegistrationContainer.mjs.map +1 -0
  111. package/dist/components/auth/UserLoginAndRegistrationContainer.vue_vue_type_script_setup_true_lang.mjs +126 -0
  112. package/dist/components/auth/UserLoginAndRegistrationContainer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  113. package/dist/components/auth/UserRegistration.mjs +147 -0
  114. package/dist/components/auth/UserRegistration.mjs.map +1 -0
  115. package/dist/components/auth/UserRegistration.vue_vue_type_script_lang.mjs +130 -0
  116. package/dist/components/auth/UserRegistration.vue_vue_type_script_lang.mjs.map +1 -0
  117. package/dist/components/auth/VerifyEmail.mjs +118 -0
  118. package/dist/components/auth/VerifyEmail.mjs.map +1 -0
  119. package/dist/components/auth/VerifyEmail.vue_vue_type_script_lang.mjs +59 -0
  120. package/dist/components/auth/VerifyEmail.vue_vue_type_script_lang.mjs.map +1 -0
  121. package/dist/components/cardRendering/AudioAutoPlayer.mjs +9 -0
  122. package/dist/components/cardRendering/AudioAutoPlayer.mjs.map +1 -0
  123. package/dist/components/cardRendering/AudioAutoPlayer.vue_vue_type_script_setup_true_lang.mjs +69 -0
  124. package/dist/components/cardRendering/AudioAutoPlayer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  125. package/dist/components/cardRendering/CardLoader.mjs +31 -0
  126. package/dist/components/cardRendering/CardLoader.mjs.map +1 -0
  127. package/dist/components/cardRendering/CardLoader.vue_vue_type_script_lang.mjs +75 -0
  128. package/dist/components/cardRendering/CardLoader.vue_vue_type_script_lang.mjs.map +1 -0
  129. package/dist/components/cardRendering/CardViewer.mjs +39 -0
  130. package/dist/components/cardRendering/CardViewer.mjs.map +1 -0
  131. package/dist/components/cardRendering/CardViewer.vue_vue_type_script_lang.mjs +66 -0
  132. package/dist/components/cardRendering/CardViewer.vue_vue_type_script_lang.mjs.map +1 -0
  133. package/dist/components/cardRendering/CodeBlockRenderer.mjs +8 -0
  134. package/dist/components/cardRendering/CodeBlockRenderer.mjs.map +1 -0
  135. package/dist/components/cardRendering/CodeBlockRenderer.vue_vue_type_script_setup_true_lang.mjs +44 -0
  136. package/dist/components/cardRendering/CodeBlockRenderer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  137. package/dist/components/cardRendering/MarkdownRenderer.mjs +21 -0
  138. package/dist/components/cardRendering/MarkdownRenderer.mjs.map +1 -0
  139. package/dist/components/cardRendering/MarkdownRenderer.vue_vue_type_script_lang.mjs +24 -0
  140. package/dist/components/cardRendering/MarkdownRenderer.vue_vue_type_script_lang.mjs.map +1 -0
  141. package/dist/components/cardRendering/MarkdownRendererHelpers.mjs +79 -0
  142. package/dist/components/cardRendering/MarkdownRendererHelpers.mjs.map +1 -0
  143. package/dist/components/cardRendering/MdTokenRenderer.mjs +9 -0
  144. package/dist/components/cardRendering/MdTokenRenderer.mjs.map +1 -0
  145. package/dist/components/cardRendering/MdTokenRenderer.vue_vue_type_script_setup_true_lang.mjs +176 -0
  146. package/dist/components/cardRendering/MdTokenRenderer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  147. package/dist/components/studentInputs/BaseUserInput.mjs +54 -0
  148. package/dist/components/studentInputs/BaseUserInput.mjs.map +1 -0
  149. package/dist/components/studentInputs/MultipleChoiceOption.mjs +26 -0
  150. package/dist/components/studentInputs/MultipleChoiceOption.mjs.map +1 -0
  151. package/dist/components/studentInputs/MultipleChoiceOption.vue_vue_type_script_lang.mjs +76 -0
  152. package/dist/components/studentInputs/MultipleChoiceOption.vue_vue_type_script_lang.mjs.map +1 -0
  153. package/dist/components/studentInputs/RadioMultipleChoice.mjs +33 -0
  154. package/dist/components/studentInputs/RadioMultipleChoice.mjs.map +1 -0
  155. package/dist/components/studentInputs/RadioMultipleChoice.vue_vue_type_script_lang.mjs +105 -0
  156. package/dist/components/studentInputs/RadioMultipleChoice.vue_vue_type_script_lang.mjs.map +1 -0
  157. package/dist/components/studentInputs/TrueFalse.mjs +19 -0
  158. package/dist/components/studentInputs/TrueFalse.mjs.map +1 -0
  159. package/dist/components/studentInputs/TrueFalse.vue_vue_type_script_lang.mjs +21 -0
  160. package/dist/components/studentInputs/TrueFalse.vue_vue_type_script_lang.mjs.map +1 -0
  161. package/dist/components/studentInputs/UserInputNumber.mjs +33 -0
  162. package/dist/components/studentInputs/UserInputNumber.mjs.map +1 -0
  163. package/dist/components/studentInputs/UserInputNumber.vue_vue_type_script_lang.mjs +25 -0
  164. package/dist/components/studentInputs/UserInputNumber.vue_vue_type_script_lang.mjs.map +1 -0
  165. package/dist/components/studentInputs/UserInputString.mjs +22 -0
  166. package/dist/components/studentInputs/UserInputString.mjs.map +1 -0
  167. package/dist/components/studentInputs/UserInputString.vue_vue_type_script_lang.mjs +23 -0
  168. package/dist/components/studentInputs/UserInputString.vue_vue_type_script_lang.mjs.map +1 -0
  169. package/dist/components/studentInputs/fillInInput.mjs +25 -0
  170. package/dist/components/studentInputs/fillInInput.mjs.map +1 -0
  171. package/dist/components/studentInputs/fillInInput.vue_vue_type_script_lang.mjs +26 -0
  172. package/dist/components/studentInputs/fillInInput.vue_vue_type_script_lang.mjs.map +1 -0
  173. package/dist/composables/CompositionViewable.mjs +65 -0
  174. package/dist/composables/CompositionViewable.mjs.map +1 -0
  175. package/dist/composables/Displayable.mjs +36 -0
  176. package/dist/composables/Displayable.mjs.map +1 -0
  177. package/dist/composables/useAuthUI.mjs +38 -0
  178. package/dist/composables/useAuthUI.mjs.map +1 -0
  179. package/dist/composables/useEntitlements.mjs +58 -0
  180. package/dist/composables/useEntitlements.mjs.map +1 -0
  181. package/dist/index.mjs +49 -0
  182. package/dist/plugins/pinia.mjs +12 -0
  183. package/dist/plugins/pinia.mjs.map +1 -0
  184. package/dist/services/authAPI.mjs +159 -0
  185. package/dist/services/authAPI.mjs.map +1 -0
  186. package/dist/stores/useAuthStore.mjs +68 -0
  187. package/dist/stores/useAuthStore.mjs.map +1 -0
  188. package/dist/stores/useCardPreviewModeStore.mjs +20 -0
  189. package/dist/stores/useCardPreviewModeStore.mjs.map +1 -0
  190. package/dist/stores/useConfigStore.mjs +60 -0
  191. package/dist/stores/useConfigStore.mjs.map +1 -0
  192. package/dist/utils/SkldrMouseTrap.mjs +48 -0
  193. package/dist/utils/SkldrMouseTrap.mjs.map +1 -0
  194. package/dist/utils/passwordValidation.mjs +12 -0
  195. package/dist/utils/passwordValidation.mjs.map +1 -0
  196. package/package.json +8 -8
  197. package/src/admin/components/EChart.vue +59 -0
  198. package/src/admin/components/LearnerDiagnostics.vue +8 -4
  199. package/src/admin/components/LearnerTagElo.vue +563 -0
  200. package/src/admin/index.ts +1 -0
  201. package/dist/MarkdownRenderer-U_iPiA2x.mjs +0 -4966
  202. package/dist/MarkdownRenderer-U_iPiA2x.mjs.map +0 -1
  203. package/dist/assets/MarkdownRenderer.css +0 -1
  204. package/dist/common-ui.es.js +0 -5090
  205. package/dist/common-ui.es.js.map +0 -1
  206. package/dist/common-ui.umd.js +0 -77
  207. package/dist/common-ui.umd.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CardViewer.mjs","names":[],"sources":["../../../src/components/cardRendering/CardViewer.vue"],"sourcesContent":["<template>\n <!-- Frameless mode: direct render -->\n <component\n v-if=\"frameless\"\n :is=\"view\"\n ref=\"activeView\"\n :key=\"course_id + '-' + card_id + '-' + sessionOrder\"\n :data=\"data\"\n :modify-difficulty=\"user_elo.global.score - card_elo\"\n class=\"cardView\"\n @emit-response=\"processResponse($event)\"\n @request-replan=\"$emit('requestReplan', $event)\"\n @ready-to-advance=\"$emit('readyToAdvance')\"\n />\n\n <!-- Traditional mode: v-card wrapper -->\n <v-card v-else elevation=\"12\">\n <component\n :is=\"view\"\n ref=\"activeView\"\n :key=\"course_id + '-' + card_id + '-' + sessionOrder\"\n :data=\"data\"\n :modify-difficulty=\"user_elo.global.score - card_elo\"\n class=\"cardView ma-2 pa-2\"\n @emit-response=\"processResponse($event)\"\n @request-replan=\"$emit('requestReplan', $event)\"\n @ready-to-advance=\"$emit('readyToAdvance')\"\n />\n </v-card>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType } from 'vue';\nimport { CardRecord } from '@vue-skuilder/db';\nimport { CourseElo, ViewData } from '@vue-skuilder/common';\nimport { ViewComponent } from '../../composables';\n\ninterface CardViewerRefs {\n activeView: ViewComponent;\n}\n\nexport default defineComponent({\n name: 'CardViewer',\n\n ref: {} as CardViewerRefs,\n\n props: {\n sessionOrder: {\n type: Number,\n required: false,\n default: 0,\n },\n card_id: {\n type: String as () => PouchDB.Core.DocumentId,\n required: true,\n default: '',\n },\n course_id: {\n type: String,\n required: true,\n default: '',\n },\n view: {\n type: [Function, Object] as PropType<ViewComponent>,\n required: true,\n },\n data: {\n type: Array as () => ViewData[],\n required: true,\n },\n user_elo: {\n type: Object as () => CourseElo,\n default: () => ({\n global: {\n score: 1000,\n count: 0,\n },\n tags: {},\n misc: {},\n }),\n },\n card_elo: {\n type: Number,\n default: 1000,\n },\n frameless: {\n type: Boolean,\n default: false,\n },\n },\n\n emits: ['emitResponse', 'requestReplan', 'readyToAdvance'],\n\n methods: {\n processResponse(r: CardRecord): void {\n console.log(`\n Card was displayed at ${r.timeStamp}\n User spent ${r.timeSpent} milliseconds with the card.\n `);\n this.$emit('emitResponse', r);\n },\n },\n});\n</script>\n\n<style scoped>\n.cardView {\n padding: 15px;\n border-radius: 8px;\n}\n\n</style>\n"],"mappings":";;;;;;;;QAGU,EAAA,aAAA,GAAA,EADR,EAWE,EATK,EAAA,KAAI,EAAA;EACT,KAAI;EACH,KAAK,EAAA,YAAS,MAAS,EAAA,UAAO,MAAS,EAAA;EACvC,MAAM,EAAA;EACN,qBAAmB,EAAA,SAAS,OAAO,QAAQ,EAAA;EAC5C,OAAM;EACL,gBAAa,EAAA,OAAA,EAAA,MAAA,MAAE,EAAA,gBAAgB,EAAM;EACrC,iBAAc,EAAA,OAAA,EAAA,MAAA,MAAE,EAAA,MAAK,iBAAkB,EAAM;EAC7C,kBAAgB,EAAA,OAAA,EAAA,MAAA,MAAE,EAAA,MAAK,iBAAA;sDAI1B,EAYS,GAAA;EA5BX,KAAA;EAgBiB,WAAU;;EAhB3B,SAAA,QA2BM,EAAA,GAAA,EAVF,EAUE,EATK,EAAA,KAAI,EAAA;GACT,KAAI;GACH,KAAK,EAAA,YAAS,MAAS,EAAA,UAAO,MAAS,EAAA;GACvC,MAAM,EAAA;GACN,qBAAmB,EAAA,SAAS,OAAO,QAAQ,EAAA;GAC5C,OAAM;GACL,gBAAa,EAAA,OAAA,EAAA,MAAA,MAAE,EAAA,gBAAgB,EAAM;GACrC,iBAAc,EAAA,OAAA,EAAA,MAAA,MAAE,EAAA,MAAK,iBAAkB,EAAM;GAC7C,kBAAgB,EAAA,OAAA,EAAA,MAAA,MAAE,EAAA,MAAK,iBAAA;;EA1B9B,GAAA"}
@@ -0,0 +1,66 @@
1
+ import "../../_virtual/_rolldown/runtime.mjs";
2
+ import { defineComponent as e } from "vue";
3
+ //#region src/components/cardRendering/CardViewer.vue?vue&type=script&lang.ts
4
+ var t = e({
5
+ name: "CardViewer",
6
+ ref: {},
7
+ props: {
8
+ sessionOrder: {
9
+ type: Number,
10
+ required: !1,
11
+ default: 0
12
+ },
13
+ card_id: {
14
+ type: String,
15
+ required: !0,
16
+ default: ""
17
+ },
18
+ course_id: {
19
+ type: String,
20
+ required: !0,
21
+ default: ""
22
+ },
23
+ view: {
24
+ type: [Function, Object],
25
+ required: !0
26
+ },
27
+ data: {
28
+ type: Array,
29
+ required: !0
30
+ },
31
+ user_elo: {
32
+ type: Object,
33
+ default: () => ({
34
+ global: {
35
+ score: 1e3,
36
+ count: 0
37
+ },
38
+ tags: {},
39
+ misc: {}
40
+ })
41
+ },
42
+ card_elo: {
43
+ type: Number,
44
+ default: 1e3
45
+ },
46
+ frameless: {
47
+ type: Boolean,
48
+ default: !1
49
+ }
50
+ },
51
+ emits: [
52
+ "emitResponse",
53
+ "requestReplan",
54
+ "readyToAdvance"
55
+ ],
56
+ methods: { processResponse(e) {
57
+ console.log(`
58
+ Card was displayed at ${e.timeStamp}
59
+ User spent ${e.timeSpent} milliseconds with the card.
60
+ `), this.$emit("emitResponse", e);
61
+ } }
62
+ });
63
+ //#endregion
64
+ export { t as default };
65
+
66
+ //# sourceMappingURL=CardViewer.vue_vue_type_script_lang.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CardViewer.vue_vue_type_script_lang.mjs","names":[],"sources":["../../../src/components/cardRendering/CardViewer.vue"],"sourcesContent":["<template>\n <!-- Frameless mode: direct render -->\n <component\n v-if=\"frameless\"\n :is=\"view\"\n ref=\"activeView\"\n :key=\"course_id + '-' + card_id + '-' + sessionOrder\"\n :data=\"data\"\n :modify-difficulty=\"user_elo.global.score - card_elo\"\n class=\"cardView\"\n @emit-response=\"processResponse($event)\"\n @request-replan=\"$emit('requestReplan', $event)\"\n @ready-to-advance=\"$emit('readyToAdvance')\"\n />\n\n <!-- Traditional mode: v-card wrapper -->\n <v-card v-else elevation=\"12\">\n <component\n :is=\"view\"\n ref=\"activeView\"\n :key=\"course_id + '-' + card_id + '-' + sessionOrder\"\n :data=\"data\"\n :modify-difficulty=\"user_elo.global.score - card_elo\"\n class=\"cardView ma-2 pa-2\"\n @emit-response=\"processResponse($event)\"\n @request-replan=\"$emit('requestReplan', $event)\"\n @ready-to-advance=\"$emit('readyToAdvance')\"\n />\n </v-card>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType } from 'vue';\nimport { CardRecord } from '@vue-skuilder/db';\nimport { CourseElo, ViewData } from '@vue-skuilder/common';\nimport { ViewComponent } from '../../composables';\n\ninterface CardViewerRefs {\n activeView: ViewComponent;\n}\n\nexport default defineComponent({\n name: 'CardViewer',\n\n ref: {} as CardViewerRefs,\n\n props: {\n sessionOrder: {\n type: Number,\n required: false,\n default: 0,\n },\n card_id: {\n type: String as () => PouchDB.Core.DocumentId,\n required: true,\n default: '',\n },\n course_id: {\n type: String,\n required: true,\n default: '',\n },\n view: {\n type: [Function, Object] as PropType<ViewComponent>,\n required: true,\n },\n data: {\n type: Array as () => ViewData[],\n required: true,\n },\n user_elo: {\n type: Object as () => CourseElo,\n default: () => ({\n global: {\n score: 1000,\n count: 0,\n },\n tags: {},\n misc: {},\n }),\n },\n card_elo: {\n type: Number,\n default: 1000,\n },\n frameless: {\n type: Boolean,\n default: false,\n },\n },\n\n emits: ['emitResponse', 'requestReplan', 'readyToAdvance'],\n\n methods: {\n processResponse(r: CardRecord): void {\n console.log(`\n Card was displayed at ${r.timeStamp}\n User spent ${r.timeSpent} milliseconds with the card.\n `);\n this.$emit('emitResponse', r);\n },\n },\n});\n</script>\n\n<style scoped>\n.cardView {\n padding: 15px;\n border-radius: 8px;\n}\n\n</style>\n"],"mappings":";;;AAyCA,IAAA,IAAe,EAAgB;CAC7B,MAAM;CAEN,KAAK,EAAC;CAEN,OAAO;EACL,cAAc;GACZ,MAAM;GACN,UAAU;GACV,SAAS;GACV;EACD,SAAS;GACP,MAAM;GACN,UAAU;GACV,SAAS;GACV;EACD,WAAW;GACT,MAAM;GACN,UAAU;GACV,SAAS;GACV;EACD,MAAM;GACJ,MAAM,CAAC,UAAU,OAAM;GACvB,UAAU;GACX;EACD,MAAM;GACJ,MAAM;GACN,UAAU;GACX;EACD,UAAU;GACR,MAAM;GACN,gBAAgB;IACd,QAAQ;KACN,OAAO;KACP,OAAO;KACR;IACD,MAAM,EAAE;IACR,MAAM,EAAE;IACT;GACF;EACD,UAAU;GACR,MAAM;GACN,SAAS;GACV;EACD,WAAW;GACT,MAAM;GACN,SAAS;GACV;EACF;CAED,OAAO;EAAC;EAAgB;EAAiB;EAAiB;CAE1D,SAAS,EACP,gBAAgB,GAAqB;AAKnC,EAJA,QAAQ,IAAI;gCACc,EAAE,UAAS;qBACtB,EAAE,UAAS;UACtB,EACJ,KAAK,MAAM,gBAAgB,EAAE;IAEhC;CACF,CAAC"}
@@ -0,0 +1,8 @@
1
+ import e from "./CodeBlockRenderer.vue_vue_type_script_setup_true_lang.mjs";
2
+ /* empty css */
3
+ //#region src/components/cardRendering/CodeBlockRenderer.vue
4
+ var t = e;
5
+ //#endregion
6
+ export { t as default };
7
+
8
+ //# sourceMappingURL=CodeBlockRenderer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeBlockRenderer.mjs","names":[],"sources":["../../../src/components/cardRendering/CodeBlockRenderer.vue"],"sourcesContent":["<template>\n <div class=\"code-block-wrapper pa-2\">\n <div class=\"language-indicator\" v-if=\"language\">{{ language }}</div>\n <highlightjs :language=\"language\" :code=\"code\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport hljs from 'highlight.js/lib/core';\nimport hljsVuePlugin from '@highlightjs/vue-plugin';\nimport { getCurrentInstance } from 'vue';\n\n// Import only the languages you need\nimport javascript from 'highlight.js/lib/languages/javascript';\nimport typescript from 'highlight.js/lib/languages/typescript';\nimport css from 'highlight.js/lib/languages/css';\nimport html from 'highlight.js/lib/languages/xml';\nimport bash from 'highlight.js/lib/languages/bash';\nimport json from 'highlight.js/lib/languages/json';\nimport go from 'highlight.js/lib/languages/go';\nimport python from 'highlight.js/lib/languages/python';\n\n// Register languages\nhljs.registerLanguage('js', javascript);\nhljs.registerLanguage('javascript', javascript);\nhljs.registerLanguage('ts', typescript);\nhljs.registerLanguage('typescript', typescript);\nhljs.registerLanguage('css', css);\nhljs.registerLanguage('html', html);\nhljs.registerLanguage('bash', bash);\nhljs.registerLanguage('sh', bash);\nhljs.registerLanguage('json', json);\nhljs.registerLanguage('go', go);\nhljs.registerLanguage('golang', go);\nhljs.registerLanguage('python', python);\n\n// Get access to the current component instance\nconst instance = getCurrentInstance();\nif (instance) {\n // Register the component locally\n instance.appContext.app.component('highlightjs', hljsVuePlugin.component);\n}\n\ndefineProps({\n code: {\n type: String,\n required: true,\n },\n language: {\n type: String,\n default: '',\n },\n});\n</script>\n\n<style>\n/* Import a highlight.js theme */\n@import 'highlight.js/styles/github.css';\n\n.code-block-wrapper {\n margin: 1rem 0;\n border-radius: 4px;\n background-color: #f6f8fa;\n overflow: auto;\n position: relative;\n}\n\n.language-indicator {\n position: absolute;\n top: 8px;\n right: 10px;\n padding: 2px 8px;\n font-size: 0.75rem;\n color: #666;\n background-color: rgba(255, 255, 255, 0.7);\n border-radius: 4px;\n z-index: 1;\n font-family: monospace;\n text-transform: lowercase;\n}\n</style>\n"],"mappings":""}
@@ -0,0 +1,44 @@
1
+ import "../../_virtual/_rolldown/runtime.mjs";
2
+ import { createCommentVNode as e, createElementBlock as t, createVNode as n, defineComponent as r, getCurrentInstance as i, openBlock as a, resolveComponent as o, toDisplayString as s } from "vue";
3
+ import c from "highlight.js/lib/core";
4
+ import l from "@highlightjs/vue-plugin";
5
+ import u from "highlight.js/lib/languages/javascript";
6
+ import d from "highlight.js/lib/languages/typescript";
7
+ import f from "highlight.js/lib/languages/css";
8
+ import p from "highlight.js/lib/languages/xml";
9
+ import m from "highlight.js/lib/languages/bash";
10
+ import h from "highlight.js/lib/languages/json";
11
+ import g from "highlight.js/lib/languages/go";
12
+ import _ from "highlight.js/lib/languages/python";
13
+ //#region src/components/cardRendering/CodeBlockRenderer.vue?vue&type=script&setup=true&lang.ts
14
+ var v = { class: "code-block-wrapper pa-2" }, y = {
15
+ key: 0,
16
+ class: "language-indicator"
17
+ }, b = /* @__PURE__ */ r({
18
+ __name: "CodeBlockRenderer",
19
+ props: {
20
+ code: {
21
+ type: String,
22
+ required: !0
23
+ },
24
+ language: {
25
+ type: String,
26
+ default: ""
27
+ }
28
+ },
29
+ setup(r) {
30
+ c.registerLanguage("js", u), c.registerLanguage("javascript", u), c.registerLanguage("ts", d), c.registerLanguage("typescript", d), c.registerLanguage("css", f), c.registerLanguage("html", p), c.registerLanguage("bash", m), c.registerLanguage("sh", m), c.registerLanguage("json", h), c.registerLanguage("go", g), c.registerLanguage("golang", g), c.registerLanguage("python", _);
31
+ let b = i();
32
+ return b && b.appContext.app.component("highlightjs", l.component), (i, c) => {
33
+ let l = o("highlightjs");
34
+ return a(), t("div", v, [r.language ? (a(), t("div", y, s(r.language), 1)) : e("", !0), n(l, {
35
+ language: r.language,
36
+ code: r.code
37
+ }, null, 8, ["language", "code"])]);
38
+ };
39
+ }
40
+ });
41
+ //#endregion
42
+ export { b as default };
43
+
44
+ //# sourceMappingURL=CodeBlockRenderer.vue_vue_type_script_setup_true_lang.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeBlockRenderer.vue_vue_type_script_setup_true_lang.mjs","names":[],"sources":["../../../src/components/cardRendering/CodeBlockRenderer.vue"],"sourcesContent":["<template>\n <div class=\"code-block-wrapper pa-2\">\n <div class=\"language-indicator\" v-if=\"language\">{{ language }}</div>\n <highlightjs :language=\"language\" :code=\"code\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport hljs from 'highlight.js/lib/core';\nimport hljsVuePlugin from '@highlightjs/vue-plugin';\nimport { getCurrentInstance } from 'vue';\n\n// Import only the languages you need\nimport javascript from 'highlight.js/lib/languages/javascript';\nimport typescript from 'highlight.js/lib/languages/typescript';\nimport css from 'highlight.js/lib/languages/css';\nimport html from 'highlight.js/lib/languages/xml';\nimport bash from 'highlight.js/lib/languages/bash';\nimport json from 'highlight.js/lib/languages/json';\nimport go from 'highlight.js/lib/languages/go';\nimport python from 'highlight.js/lib/languages/python';\n\n// Register languages\nhljs.registerLanguage('js', javascript);\nhljs.registerLanguage('javascript', javascript);\nhljs.registerLanguage('ts', typescript);\nhljs.registerLanguage('typescript', typescript);\nhljs.registerLanguage('css', css);\nhljs.registerLanguage('html', html);\nhljs.registerLanguage('bash', bash);\nhljs.registerLanguage('sh', bash);\nhljs.registerLanguage('json', json);\nhljs.registerLanguage('go', go);\nhljs.registerLanguage('golang', go);\nhljs.registerLanguage('python', python);\n\n// Get access to the current component instance\nconst instance = getCurrentInstance();\nif (instance) {\n // Register the component locally\n instance.appContext.app.component('highlightjs', hljsVuePlugin.component);\n}\n\ndefineProps({\n code: {\n type: String,\n required: true,\n },\n language: {\n type: String,\n default: '',\n },\n});\n</script>\n\n<style>\n/* Import a highlight.js theme */\n@import 'highlight.js/styles/github.css';\n\n.code-block-wrapper {\n margin: 1rem 0;\n border-radius: 4px;\n background-color: #f6f8fa;\n overflow: auto;\n position: relative;\n}\n\n.language-indicator {\n position: absolute;\n top: 8px;\n right: 10px;\n padding: 2px 8px;\n font-size: 0.75rem;\n color: #666;\n background-color: rgba(255, 255, 255, 0.7);\n border-radius: 4px;\n z-index: 1;\n font-family: monospace;\n text-transform: lowercase;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,EAXA,EAAK,iBAAiB,MAAM,EAAW,EACvC,EAAK,iBAAiB,cAAc,EAAW,EAC/C,EAAK,iBAAiB,MAAM,EAAW,EACvC,EAAK,iBAAiB,cAAc,EAAW,EAC/C,EAAK,iBAAiB,OAAO,EAAI,EACjC,EAAK,iBAAiB,QAAQ,EAAK,EACnC,EAAK,iBAAiB,QAAQ,EAAK,EACnC,EAAK,iBAAiB,MAAM,EAAK,EACjC,EAAK,iBAAiB,QAAQ,EAAK,EACnC,EAAK,iBAAiB,MAAM,EAAG,EAC/B,EAAK,iBAAiB,UAAU,EAAG,EACnC,EAAK,iBAAiB,UAAU,EAAO;EAGvC,IAAM,IAAW,GAAoB;SACjC,KAEF,EAAS,WAAW,IAAI,UAAU,eAAe,EAAc,UAAU"}
@@ -0,0 +1,21 @@
1
+ import "../../_virtual/_rolldown/runtime.mjs";
2
+ import e from "../../_virtual/_plugin-vue_export-helper.mjs";
3
+ import t from "./MarkdownRenderer.vue_vue_type_script_lang.mjs";
4
+ import { Fragment as n, createBlock as r, createCommentVNode as i, createElementBlock as a, openBlock as o, renderList as s, resolveComponent as c } from "vue";
5
+ //#region src/components/cardRendering/MarkdownRenderer.vue
6
+ function _sfc_render(e, t, l, u, d, f) {
7
+ let p = c("md-token-renderer"), m = c("audio-auto-player");
8
+ return o(), a("div", null, [(o(!0), a(n, null, s(e.tokens, (t, n) => (o(), a("span", { key: n }, [t.type ? (o(), r(p, {
9
+ key: 0,
10
+ token: t,
11
+ last: n === e.tokens.length - 1
12
+ }, null, 8, ["token", "last"])) : t.audio ? (o(), r(m, {
13
+ key: 1,
14
+ src: t.audio
15
+ }, null, 8, ["src"])) : i("", !0)]))), 128))]);
16
+ }
17
+ var l = /* @__PURE__ */ e(t, [["render", _sfc_render]]);
18
+ //#endregion
19
+ export { l as default };
20
+
21
+ //# sourceMappingURL=MarkdownRenderer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownRenderer.mjs","names":[],"sources":["../../../src/components/cardRendering/MarkdownRenderer.vue"],"sourcesContent":["<template>\n <div>\n <!-- <v-textarea v-if=\"testRoute\" v-model=\"md\" variant=\"outlined\" label=\"Type Here\" name=\"name\" /> -->\n <span v-for=\"(token, i) in tokens\" :key=\"i\">\n <md-token-renderer v-if=\"token.type\" :token=\"token\" :last=\"i === tokens.length - 1\" />\n <audio-auto-player v-else-if=\"token.audio\" :src=\"token.audio\" />\n <!-- // [ ] insert img display here. \"if token.image ? (also see if the audio aboke is functional)\" -->\n </span>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType } from 'vue';\nimport MdTokenRenderer from './MdTokenRenderer.vue';\nimport AudioAutoPlayer from './AudioAutoPlayer.vue';\nimport * as marked from 'marked';\n\ntype SkldrToken =\n | marked.Token\n | {\n type: false;\n audio: string;\n };\n\n// Using Options API with mixin\nexport default defineComponent({\n name: 'MarkdownRenderer',\n components: {\n MdTokenRenderer,\n AudioAutoPlayer,\n },\n props: {\n md: {\n type: String as PropType<string>,\n required: true,\n },\n },\n computed: {\n tokens(): SkldrToken[] {\n return marked.lexer(this.md);\n },\n },\n});\n</script>\n\n<style lang=\"css\" scoped></style>\n"],"mappings":";;;;;;;aACE,EAOM,OAAA,MAAA,EAAA,EAAA,GAAA,EALJ,EAIO,GAAA,MAPX,EAG+B,EAAA,SAAb,GAAO,YAArB,EAIO,QAAA,EAJ6B,KAAK,GAAC,EAAA,CACf,EAAM,QAAA,GAAA,EAA/B,EAAsF,GAAA;EAJ5F,KAAA;EAImD;EAAQ,MAAM,MAAM,EAAA,OAAO,SAAM;mCAChD,EAAM,SAAA,GAAA,EAApC,EAAgE,GAAA;EALtE,KAAA;EAKkD,KAAK,EAAM;yBAL7D,EAAA,IAAA,GAAA,CAAA,CAAA"}
@@ -0,0 +1,24 @@
1
+ import "../../_virtual/_rolldown/runtime.mjs";
2
+ import e from "./AudioAutoPlayer.mjs";
3
+ import t from "./MdTokenRenderer.mjs";
4
+ import { defineComponent as n } from "vue";
5
+ import * as r from "marked";
6
+ //#region src/components/cardRendering/MarkdownRenderer.vue?vue&type=script&lang.ts
7
+ var i = n({
8
+ name: "MarkdownRenderer",
9
+ components: {
10
+ MdTokenRenderer: t,
11
+ AudioAutoPlayer: e
12
+ },
13
+ props: { md: {
14
+ type: String,
15
+ required: !0
16
+ } },
17
+ computed: { tokens() {
18
+ return r.lexer(this.md);
19
+ } }
20
+ });
21
+ //#endregion
22
+ export { i as default };
23
+
24
+ //# sourceMappingURL=MarkdownRenderer.vue_vue_type_script_lang.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownRenderer.vue_vue_type_script_lang.mjs","names":[],"sources":["../../../src/components/cardRendering/MarkdownRenderer.vue"],"sourcesContent":["<template>\n <div>\n <!-- <v-textarea v-if=\"testRoute\" v-model=\"md\" variant=\"outlined\" label=\"Type Here\" name=\"name\" /> -->\n <span v-for=\"(token, i) in tokens\" :key=\"i\">\n <md-token-renderer v-if=\"token.type\" :token=\"token\" :last=\"i === tokens.length - 1\" />\n <audio-auto-player v-else-if=\"token.audio\" :src=\"token.audio\" />\n <!-- // [ ] insert img display here. \"if token.image ? (also see if the audio aboke is functional)\" -->\n </span>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType } from 'vue';\nimport MdTokenRenderer from './MdTokenRenderer.vue';\nimport AudioAutoPlayer from './AudioAutoPlayer.vue';\nimport * as marked from 'marked';\n\ntype SkldrToken =\n | marked.Token\n | {\n type: false;\n audio: string;\n };\n\n// Using Options API with mixin\nexport default defineComponent({\n name: 'MarkdownRenderer',\n components: {\n MdTokenRenderer,\n AudioAutoPlayer,\n },\n props: {\n md: {\n type: String as PropType<string>,\n required: true,\n },\n },\n computed: {\n tokens(): SkldrToken[] {\n return marked.lexer(this.md);\n },\n },\n});\n</script>\n\n<style lang=\"css\" scoped></style>\n"],"mappings":";;;;;;AAyBA,IAAA,IAAe,EAAgB;CAC7B,MAAM;CACN,YAAY;EACV,iBAAA;EACA,iBAAA;EACD;CACD,OAAO,EACL,IAAI;EACF,MAAM;EACN,UAAU;EACX,EACF;CACD,UAAU,EACR,SAAuB;AACrB,SAAO,EAAO,MAAM,KAAK,GAAG;IAE/B;CACF,CAAC"}
@@ -0,0 +1,79 @@
1
+ import "../../_virtual/_rolldown/runtime.mjs";
2
+ import * as e from "marked";
3
+ //#region src/components/cardRendering/MarkdownRendererHelpers.ts
4
+ function splitByDelimiters(e, t, n) {
5
+ if (e.length === 0) return [];
6
+ let r = [], i = e.indexOf(t), a = e.indexOf(n, i);
7
+ if (i >= 0 && a > i) r.push(e.substring(0, i)), r.push(e.substring(i, a + n.length)), r = r.concat(splitByDelimiters(e.substring(a + n.length), t, n));
8
+ else return [e];
9
+ return r;
10
+ }
11
+ function stripTrailingNewlines(e) {
12
+ return e.replace(/[\r\n]+$/, "");
13
+ }
14
+ function splitTextToken(e) {
15
+ if (containsComponent(e)) {
16
+ let t = splitByDelimiters(stripTrailingNewlines(e.text), "{{", "}}"), n = splitByDelimiters(stripTrailingNewlines(e.raw), "{{", "}}");
17
+ if (t.length === n.length) return t.map((e, r) => ({
18
+ type: "text",
19
+ text: t[r],
20
+ raw: n[r]
21
+ }));
22
+ throw Error("Error parsing markdown");
23
+ } else return [e];
24
+ }
25
+ function splitParagraphToken(t) {
26
+ let n = [];
27
+ if (containsComponent(t)) {
28
+ let r = splitByDelimiters(stripTrailingNewlines(t.text), "{{", "}}"), i = splitByDelimiters(stripTrailingNewlines(t.raw), "{{", "}}");
29
+ if (r.length === i.length) {
30
+ for (let t = 0; t < r.length; t++) {
31
+ let a = {
32
+ type: "text",
33
+ text: r[t],
34
+ raw: i[t]
35
+ };
36
+ isComponent(a) ? n.push(a) : e.lexer(i[t]).forEach((e) => {
37
+ e.type === "paragraph" ? n = n.concat(e.tokens) : n.push(e);
38
+ });
39
+ }
40
+ return n;
41
+ } else throw Error("Error parsing Markdown");
42
+ } else n.push(t);
43
+ return n;
44
+ }
45
+ function containsComponent(e) {
46
+ if (e.type === "text" || e.type === "paragraph") {
47
+ let t = e.raw.indexOf("{{"), n = e.raw.indexOf("}}");
48
+ return t !== -1 && n !== -1 && n > t;
49
+ } else return !1;
50
+ }
51
+ function isComponent(e) {
52
+ return e.type === "text" && e.text.startsWith("{{") && e.text.endsWith("}}");
53
+ }
54
+ function parseComponentSyntax(e) {
55
+ if (e.length > 1e4) return null;
56
+ let t = e.match(/^\{\{\s*<([\w-]+)((?:\s+[\w-]+="[^"]*")*)\s*\/>\s*\}\}$/);
57
+ if (!t) return null;
58
+ let n = t[1], r = t[2], i = {};
59
+ if (r) {
60
+ let e = /\s+([\w-]+)="([^"]*)"/g, t;
61
+ for (; (t = e.exec(r)) !== null;) i[t[1]] = t[2];
62
+ }
63
+ return {
64
+ componentName: n,
65
+ props: i
66
+ };
67
+ }
68
+ function isInlineComponent(e) {
69
+ if (e.length > 1e4) return !1;
70
+ let t = e.trim();
71
+ return /^<[\w-]+(?:\s+[\w-]+="[^"]*")*\s*\/?>$/.test(t);
72
+ }
73
+ function parseComponentToken(e) {
74
+ return parseComponentSyntax("text" in e ? e.text : "raw" in e ? e.raw : "");
75
+ }
76
+ //#endregion
77
+ export { containsComponent, isComponent, isInlineComponent, parseComponentSyntax, parseComponentToken, splitByDelimiters, splitParagraphToken, splitTextToken };
78
+
79
+ //# sourceMappingURL=MarkdownRendererHelpers.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownRendererHelpers.mjs","names":[],"sources":["../../../src/components/cardRendering/MarkdownRendererHelpers.ts"],"sourcesContent":["import { MarkedToken, Tokens } from 'marked';\nimport * as marked from 'marked';\n\n/**\n * recursively splits text according to the passed delimiters.\n *\n * eg: (\"abcde\", \"b\", \"d\") => [\"a\", \"bcd\", \"e\"]\n * (\"a[b][c]\", \"[\", \"]\") => [\"a\", \"[b]\", \"[c]\"]\n *\n * it does not check that the delimiters are well formed in the text\n * @param text the text to be split\n * @param l the left delimiter\n * @param r the right delimiter\n * @returns the split result\n */\nexport function splitByDelimiters(text: string, l: string, r: string): string[] {\n if (text.length === 0) return [];\n\n let ret: string[] = [];\n\n const left = text.indexOf(l);\n const right = text.indexOf(r, left);\n\n if (left >= 0 && right > left) {\n // pre-delimited characters\n ret.push(text.substring(0, left));\n // delimited section\n ret.push(text.substring(left, right + r.length));\n // recurse on remaining text\n ret = ret.concat(splitByDelimiters(text.substring(right + r.length), l, r));\n } else {\n return [text];\n }\n\n return ret;\n}\n\n/** Strip trailing newline characters (but not spaces/tabs) from a string. */\nfunction stripTrailingNewlines(text: string): string {\n return text.replace(/[\\r\\n]+$/, '');\n}\n\nexport function splitTextToken(token: Tokens.Text): Tokens.Text[] {\n if (containsComponent(token)) {\n // See splitParagraphToken: normalize trailing newlines (only) to neutralize\n // marked's text/raw asymmetry without disturbing trailing spaces.\n const textChunks = splitByDelimiters(stripTrailingNewlines(token.text), '{{', '}}');\n const rawChunks = splitByDelimiters(stripTrailingNewlines(token.raw), '{{', '}}');\n\n if (textChunks.length === rawChunks.length) {\n return textChunks.map((_c, i) => {\n return {\n type: 'text',\n text: textChunks[i],\n raw: rawChunks[i],\n };\n });\n } else {\n throw new Error(`Error parsing markdown`);\n }\n } else {\n return [token];\n }\n}\n\nexport type TokenOrComponent = MarkedToken | { type: 'component'; raw: string };\n\nexport function splitParagraphToken(token: Tokens.Paragraph): TokenOrComponent[] {\n let ret: MarkedToken[] = [];\n\n if (containsComponent(token)) {\n // marked strips a trailing newline from token.text but keeps it on token.raw.\n // When a blank/component is the last token, that asymmetry gives raw an extra\n // trailing chunk, tripping the length check below and throwing. Strip trailing\n // newlines (only) from both so the splits stay parallel. We must NOT strip\n // trailing spaces: a trailing-space chunk is the documented workaround that\n // keeps a final component from being treated as `last` (see MdTokenRenderer).\n const textChunks = splitByDelimiters(stripTrailingNewlines(token.text), '{{', '}}');\n const rawChunks = splitByDelimiters(stripTrailingNewlines(token.raw), '{{', '}}');\n if (textChunks.length === rawChunks.length) {\n for (let i = 0; i < textChunks.length; i++) {\n const textToken = {\n type: 'text',\n text: textChunks[i],\n raw: rawChunks[i],\n } as Tokens.Text;\n\n if (isComponent(textToken)) {\n ret.push(textToken);\n } else {\n marked.lexer(rawChunks[i]).forEach((t) => {\n if (t.type === 'paragraph') {\n ret = ret.concat(t.tokens as MarkedToken[]);\n } else {\n ret.push(t as MarkedToken);\n }\n });\n }\n }\n return ret;\n } else {\n throw new Error(`Error parsing Markdown`);\n }\n } else {\n ret.push(token);\n }\n return ret;\n}\n\nexport function containsComponent(token: MarkedToken) {\n if (token.type === 'text' || token.type === 'paragraph') {\n const opening = token.raw.indexOf('{{');\n const closing = token.raw.indexOf('}}');\n\n if (opening !== -1 && closing !== -1 && closing > opening) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n}\n\nexport function isComponent(token: MarkedToken) {\n return token.type === 'text' && token.text.startsWith('{{') && token.text.endsWith('}}');\n}\n\n/**\n * Parses inline component syntax from a string\n * @param text - String containing component syntax, e.g., \"{{ <badge /> }}\" or \" <badge prop=\"value\" /> \"\n * @returns Object with componentName and props, or null if not valid component syntax\n *\n * @example\n * parseComponentSyntax(\"{{ <badge /> }}\") // { componentName: 'badge', props: {} }\n * parseComponentSyntax(\"{{ <chessBoard fen=\\\"...\\\" size=\\\"large\\\" /> }}\") // { componentName: 'chessBoard', props: { fen: '...', size: 'large' } }\n * parseComponentSyntax(\"{{ Paris }}\") // null (not a component)\n */\nexport function parseComponentSyntax(text: string): {\n componentName: string;\n props: Record<string, string>;\n} | null {\n // Guard against excessively long input (prevents ReDoS attacks)\n if (text.length > 10000) {\n return null;\n }\n\n // Simplified regex to avoid catastrophic backtracking\n // Captures component name and all attributes as a single string\n const match = text.match(/^\\{\\{\\s*<([\\w-]+)((?:\\s+[\\w-]+=\"[^\"]*\")*)\\s*\\/>\\s*\\}\\}$/);\n\n if (!match) {\n return null;\n }\n\n const componentName = match[1]; // e.g., \"badge\", \"chessBoard\"\n const attrsString = match[2]; // e.g., ' fen=\"...\" size=\"large\"'\n const props: Record<string, string> = {};\n\n if (attrsString) {\n // Parse attributes: requires space before each attribute\n // More specific pattern reduces backtracking potential\n const attrRegex = /\\s+([\\w-]+)=\"([^\"]*)\"/g;\n let attrMatch;\n\n while ((attrMatch = attrRegex.exec(attrsString)) !== null) {\n props[attrMatch[1]] = attrMatch[2];\n }\n }\n\n return { componentName, props };\n}\n\n/**\n * Checks if delimited content (content between {{ }}) is an inline component vs a fillIn blank\n * @param delimitedContent - Content between {{ and }}, e.g., \" <badge /> \" or \"Paris\" or \" choice1 || choice2 \"\n * @returns true if this is an inline component, false if it's a fillIn blank\n *\n * @example\n * isInlineComponent(\"<badge />\") // true\n * isInlineComponent(\"<chessBoard fen=\\\"...\\\" />\") // true\n * isInlineComponent(\"Paris\") // false (fillIn blank)\n * isInlineComponent(\"choice || alt1 | alt2\") // false (fillIn with options)\n */\nexport function isInlineComponent(delimitedContent: string): boolean {\n // Guard against excessively long input (prevents ReDoS attacks)\n if (delimitedContent.length > 10000) {\n return false;\n }\n\n const trimmed = delimitedContent.trim();\n // Simplified regex to avoid catastrophic backtracking\n // Non-capturing group with possessive-like behavior\n return /^<[\\w-]+(?:\\s+[\\w-]+=\"[^\"]*\")*\\s*\\/?>$/.test(trimmed);\n}\n\n/**\n * Parses component syntax from a MarkedToken\n * Convenience wrapper around parseComponentSyntax for token-based usage\n * @param token - MarkedToken with text or raw property\n * @returns Object with componentName and props, or null if not valid component syntax\n */\nexport function parseComponentToken(token: MarkedToken): {\n componentName: string;\n props: Record<string, string>;\n} | null {\n const text = ('text' in token ? token.text : 'raw' in token ? token.raw : '') as string;\n return parseComponentSyntax(text);\n}\n"],"mappings":";;;AAeA,SAAgB,kBAAkB,GAAc,GAAW,GAAqB;AAC9E,KAAI,EAAK,WAAW,EAAG,QAAO,EAAE;CAEhC,IAAI,IAAgB,EAAE,EAEhB,IAAO,EAAK,QAAQ,EAAE,EACtB,IAAQ,EAAK,QAAQ,GAAG,EAAK;AAEnC,KAAI,KAAQ,KAAK,IAAQ,EAMvB,CAJA,EAAI,KAAK,EAAK,UAAU,GAAG,EAAK,CAAC,EAEjC,EAAI,KAAK,EAAK,UAAU,GAAM,IAAQ,EAAE,OAAO,CAAC,EAEhD,IAAM,EAAI,OAAO,kBAAkB,EAAK,UAAU,IAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;KAE3E,QAAO,CAAC,EAAK;AAGf,QAAO;;AAIT,SAAS,sBAAsB,GAAsB;AACnD,QAAO,EAAK,QAAQ,YAAY,GAAG;;AAGrC,SAAgB,eAAe,GAAmC;AAChE,KAAI,kBAAkB,EAAM,EAAE;EAG5B,IAAM,IAAa,kBAAkB,sBAAsB,EAAM,KAAK,EAAE,MAAM,KAAK,EAC7E,IAAY,kBAAkB,sBAAsB,EAAM,IAAI,EAAE,MAAM,KAAK;AAEjF,MAAI,EAAW,WAAW,EAAU,OAClC,QAAO,EAAW,KAAK,GAAI,OAClB;GACL,MAAM;GACN,MAAM,EAAW;GACjB,KAAK,EAAU;GAChB,EACD;AAEF,QAAU,MAAM,yBAAyB;OAG3C,QAAO,CAAC,EAAM;;AAMlB,SAAgB,oBAAoB,GAA6C;CAC/E,IAAI,IAAqB,EAAE;AAE3B,KAAI,kBAAkB,EAAM,EAAE;EAO5B,IAAM,IAAa,kBAAkB,sBAAsB,EAAM,KAAK,EAAE,MAAM,KAAK,EAC7E,IAAY,kBAAkB,sBAAsB,EAAM,IAAI,EAAE,MAAM,KAAK;AACjF,MAAI,EAAW,WAAW,EAAU,QAAQ;AAC1C,QAAK,IAAI,IAAI,GAAG,IAAI,EAAW,QAAQ,KAAK;IAC1C,IAAM,IAAY;KAChB,MAAM;KACN,MAAM,EAAW;KACjB,KAAK,EAAU;KAChB;AAED,IAAI,YAAY,EAAU,GACxB,EAAI,KAAK,EAAU,GAEnB,EAAO,MAAM,EAAU,GAAG,CAAC,SAAS,MAAM;AACxC,KAAI,EAAE,SAAS,cACb,IAAM,EAAI,OAAO,EAAE,OAAwB,GAE3C,EAAI,KAAK,EAAiB;MAE5B;;AAGN,UAAO;QAEP,OAAU,MAAM,yBAAyB;OAG3C,GAAI,KAAK,EAAM;AAEjB,QAAO;;AAGT,SAAgB,kBAAkB,GAAoB;AACpD,KAAI,EAAM,SAAS,UAAU,EAAM,SAAS,aAAa;EACvD,IAAM,IAAU,EAAM,IAAI,QAAQ,KAAK,EACjC,IAAU,EAAM,IAAI,QAAQ,KAAK;AAKrC,SAHE,MAAY,MAAM,MAAY,MAAM,IAAU;OAMlD,QAAO;;AAIX,SAAgB,YAAY,GAAoB;AAC9C,QAAO,EAAM,SAAS,UAAU,EAAM,KAAK,WAAW,KAAK,IAAI,EAAM,KAAK,SAAS,KAAK;;AAa1F,SAAgB,qBAAqB,GAG5B;AAEP,KAAI,EAAK,SAAS,IAChB,QAAO;CAKT,IAAM,IAAQ,EAAK,MAAM,0DAA0D;AAEnF,KAAI,CAAC,EACH,QAAO;CAGT,IAAM,IAAgB,EAAM,IACtB,IAAc,EAAM,IACpB,IAAgC,EAAE;AAExC,KAAI,GAAa;EAGf,IAAM,IAAY,0BACd;AAEJ,UAAQ,IAAY,EAAU,KAAK,EAAY,MAAM,MACnD,GAAM,EAAU,MAAM,EAAU;;AAIpC,QAAO;EAAE;EAAe;EAAO;;AAcjC,SAAgB,kBAAkB,GAAmC;AAEnE,KAAI,EAAiB,SAAS,IAC5B,QAAO;CAGT,IAAM,IAAU,EAAiB,MAAM;AAGvC,QAAO,yCAAyC,KAAK,EAAQ;;AAS/D,SAAgB,oBAAoB,GAG3B;AAEP,QAAO,qBADO,UAAU,IAAQ,EAAM,OAAO,SAAS,IAAQ,EAAM,MAAM,GACzC"}
@@ -0,0 +1,9 @@
1
+ import e from "../../_virtual/_plugin-vue_export-helper.mjs";
2
+ import t from "./MdTokenRenderer.vue_vue_type_script_setup_true_lang.mjs";
3
+ /* empty css */
4
+ //#region src/components/cardRendering/MdTokenRenderer.vue
5
+ var n = /* @__PURE__ */ e(t, [["__scopeId", "data-v-de3eebd6"]]);
6
+ //#endregion
7
+ export { n as default };
8
+
9
+ //# sourceMappingURL=MdTokenRenderer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MdTokenRenderer.mjs","names":[],"sources":["../../../src/components/cardRendering/MdTokenRenderer.vue"],"sourcesContent":["<template>\n <span v-if=\"isText(token)\">\n <span v-if=\"!token.tokens || token.tokens.length === 0\">\n <span v-if=\"isComponent(token)\">\n <!--\n KNOWN LIMITATION: Components cannot be the final token of the entire markdown document\n The v-if=\"!last\" check prevents rendering when this is the last token overall\n Components CAN be the last token in a paragraph (just not the whole document)\n Reason unclear but necessary historically - Chesterton's Fence applies\n Workaround: Add trailing whitespace, punctuation, or newline after component\n See: \"MarkdownRenderer - Known Limitations\" test group\n -->\n <component\n v-if=\"!last && getComponent(parsedComponent(token).is)\"\n :is=\"getComponent(parsedComponent(token).is)\"\n :text=\"parsedComponent(token).text\"\n v-bind=\"parsedComponent(token).props\"\n />\n <span v-else-if=\"!last && !getComponent(parsedComponent(token).is)\" class=\"error--text\">\n [Unknown component: {{ parsedComponent(token).is }}]\n </span>\n </span>\n <span v-else-if=\"containsComponent(token)\">\n <md-token-renderer v-for=\"(subTok, j) in splitTextToken(token)\" :key=\"j\" :token=\"subTok\" />\n </span>\n <span v-else>{{ decodeBasicEntities(token.text) }}</span>\n </span>\n <span v-else-if=\"token.tokens && token.tokens.length !== 0\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </span>\n </span>\n\n <span v-else-if=\"token.type === 'heading'\">\n <h1 v-if=\"token.depth === 1\" class=\"text-h2\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </h1>\n <h2 v-else-if=\"token.depth === 2\" class=\"text-h3\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </h2>\n <h3 v-else-if=\"token.depth === 3\" class=\"text-h4\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </h3>\n <h4 v-else-if=\"token.depth === 4\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </h4>\n <h5 v-else-if=\"token.depth === 5\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </h5>\n <h6 v-else-if=\"token.depth === 6\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </h6>\n </span>\n\n <strong v-else-if=\"token.type === 'strong'\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </strong>\n\n <p v-else-if=\"token.type === 'paragraph'\" class=\"text-h5\">\n <span v-if=\"containsComponent(token)\">\n <md-token-renderer\n v-for=\"(splitTok, j) in splitParagraphToken(token)\"\n :key=\"j\"\n :token=\"splitTok\"\n :last=\"last && token.tokens.length === 1 && j === splitParagraphToken(token).length - 1\"\n />\n </span>\n <template v-else>\n <md-token-renderer\n v-for=\"(subTok, j) in token.tokens\"\n :key=\"j\"\n :token=\"subTok\"\n :last=\"last && token.tokens.length === 1\"\n />\n </template>\n </p>\n\n <a v-else-if=\"token.type === 'link'\" :href=\"token.href\" :title=\"token.title\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </a>\n\n <ul v-else-if=\"token.type === 'list' && token.ordered === false\">\n <md-token-renderer v-for=\"(item, j) in token.items\" :key=\"j\" :token=\"item\" />\n </ul>\n\n <ol v-else-if=\"token.type === 'list' && token.ordered === true\">\n <md-token-renderer v-for=\"(item, j) in token.items\" :key=\"j\" :token=\"item\" />\n </ol>\n\n <li v-else-if=\"token.type === 'list_item'\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </li>\n\n <img v-else-if=\"token.type === 'image'\" :src=\"token.href\" :alt=\"token.title\" />\n <hr v-else-if=\"token.type === 'hr'\" />\n <br v-else-if=\"token.type === 'br'\" />\n <del v-else-if=\"token.type === 'del'\" />\n\n <table v-else-if=\"token.type === 'table'\" :align=\"token.align\">\n <thead>\n <th v-for=\"(h, j) in token.header\" :key=\"j\">{{ h.text }}</th>\n </thead>\n <tbody>\n <tr v-for=\"(row, r) in token.rows\" :key=\"r\">\n <td v-for=\"(cell, c) in row\" :key=\"c\">{{ cell.text }}</td>\n </tr>\n </tbody>\n </table>\n\n <span v-else-if=\"token.type === 'html'\" v-html=\"token.raw\"></span>\n\n <code-block-renderer v-else-if=\"token.type === 'code'\" :code=\"token.text\" :language=\"token.lang\" />\n <!-- <highlightjs v-else-if=\"token.type === 'code'\" class=\"hljs_render pa-2\" :language=\"token.lang\" :code=\"token.text\" /> -->\n\n <code v-else-if=\"token.type === 'codespan'\" class=\"codespan\" v-html=\"token.text\"></code>\n\n <blockquote v-else-if=\"token.type === 'blockquote'\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </blockquote>\n\n <span v-else-if=\"token.type === 'escape'\">{{ token.text }}</span>\n\n <em v-else-if=\"token.type === 'em'\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </em>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n containsComponent as _containsComponent,\n isComponent as _isComponent,\n splitParagraphToken as _splitParagraphToken,\n splitTextToken as _splitTextToken,\n parseComponentSyntax,\n TokenOrComponent,\n} from './MarkdownRendererHelpers';\nimport CodeBlockRenderer from './CodeBlockRenderer.vue';\nimport FillInInput from '../../components/studentInputs/fillInInput.vue';\nimport { MarkedToken, Tokens } from 'marked';\nimport { markRaw, inject } from 'vue';\nimport { PropType } from 'vue';\n\n// Inject custom components provided at app level (defaults to empty object)\nconst providedComponents = inject<Record<string, any>>('markdownComponents', {});\n\n// Register components to be used in the template\n// In Vue 3 with <script setup>, components used via :is must be explicitly registered\n// Merge built-in components with injected custom components\nconst components = {\n fillIn: markRaw(FillInInput),\n ...providedComponents,\n};\n\n// Define component props\ndefineProps({\n token: {\n type: Object as PropType<TokenOrComponent>,\n required: true,\n },\n last: {\n type: Boolean,\n required: false,\n default: false,\n },\n});\n\n// Methods\nfunction isComponent(token: MarkedToken): boolean {\n return _isComponent(token);\n}\n\nfunction containsComponent(token: MarkedToken): boolean {\n return _containsComponent(token);\n}\n\nfunction splitTextToken(token: MarkedToken): Tokens.Text[] {\n return _splitTextToken(token);\n}\n\nfunction splitParagraphToken(token: Tokens.Paragraph): TokenOrComponent[] {\n return _splitParagraphToken(token);\n}\n\nfunction parsedComponent(token: MarkedToken): {\n is: string;\n text: string;\n props: Record<string, string>;\n} {\n let text = '';\n if ('text' in token && typeof token.text === 'string') {\n text = token.text;\n } else if ('raw' in token && typeof token.raw === 'string') {\n text = token.raw;\n }\n\n // Try to parse as inline component syntax\n const parsed = parseComponentSyntax(text);\n\n if (parsed) {\n // Successfully parsed as inline component\n return {\n is: parsed.componentName,\n text: '',\n props: parsed.props,\n };\n }\n\n // Backward compatible: {{ }} or {{ || }} -> fillIn component\n return {\n is: 'fillIn',\n text,\n props: {},\n };\n}\n\nfunction getComponent(componentName: string) {\n const component = components[componentName as keyof typeof components];\n\n if (!component) {\n console.warn(\n `[MarkdownRenderer] Unknown component: \"${componentName}\". Available components: ${Object.keys(components).join(', ')}`\n );\n return null;\n }\n\n return component;\n}\n\nfunction decodeBasicEntities(text: string): string {\n return text\n .replace(/&#39;/g, \"'\")\n .replace(/&quot;/g, '\"')\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>');\n}\n\nfunction isText(tok: TokenOrComponent): boolean {\n return (tok as any).inLink === undefined && tok.type === 'text';\n}\n\n// Make these functions and objects available to the template\ndefineExpose({\n isComponent,\n containsComponent,\n splitTextToken,\n splitParagraphToken,\n parsedComponent,\n decodeBasicEntities,\n isText,\n components,\n getComponent,\n});\n</script>\n\n<style lang=\"css\" scoped>\nblockquote {\n border-left: 3px teal solid;\n padding-left: 8px;\n}\n\n.codespan {\n padding-left: 3px;\n padding-right: 3px;\n margin-left: 1px;\n margin-right: 1px;\n}\n\np {\n margin-bottom: 15px;\n margin-top: 15px;\n}\n</style>\n"],"mappings":""}
@@ -0,0 +1,176 @@
1
+ import { __name as e } from "../../_virtual/_rolldown/runtime.mjs";
2
+ import t from "../studentInputs/fillInInput.mjs";
3
+ import { containsComponent as n, isComponent as r, parseComponentSyntax as i, splitParagraphToken as a, splitTextToken as o } from "./MarkdownRendererHelpers.mjs";
4
+ import s from "./CodeBlockRenderer.mjs";
5
+ import { Fragment as c, createBlock as l, createCommentVNode as u, createElementBlock as d, createElementVNode as f, defineComponent as p, inject as ee, markRaw as m, mergeProps as h, openBlock as g, renderList as _, resolveComponent as v, resolveDynamicComponent as y, toDisplayString as b } from "vue";
6
+ //#region src/components/cardRendering/MdTokenRenderer.vue?vue&type=script&setup=true&lang.ts
7
+ var x = { key: 0 }, S = { key: 0 }, C = { key: 0 }, w = {
8
+ key: 1,
9
+ class: "error--text"
10
+ }, T = { key: 1 }, E = { key: 2 }, D = { key: 1 }, O = { key: 1 }, k = {
11
+ key: 0,
12
+ class: "text-h2"
13
+ }, A = {
14
+ key: 1,
15
+ class: "text-h3"
16
+ }, j = {
17
+ key: 2,
18
+ class: "text-h4"
19
+ }, M = { key: 3 }, N = { key: 4 }, te = { key: 5 }, P = { key: 2 }, F = {
20
+ key: 3,
21
+ class: "text-h5"
22
+ }, I = { key: 0 }, L = ["href", "title"], R = { key: 5 }, z = { key: 6 }, B = { key: 7 }, V = ["src", "alt"], H = { key: 9 }, U = { key: 10 }, W = { key: 11 }, G = ["align"], K = ["innerHTML"], q = ["innerHTML"], J = { key: 16 }, Y = { key: 17 }, X = { key: 18 }, Z = /* @__PURE__ */ p({
23
+ __name: "MdTokenRenderer",
24
+ props: {
25
+ token: {
26
+ type: Object,
27
+ required: !0
28
+ },
29
+ last: {
30
+ type: Boolean,
31
+ required: !1,
32
+ default: !1
33
+ }
34
+ },
35
+ setup(p, { expose: Z }) {
36
+ let Q = ee("markdownComponents", {}), $ = {
37
+ fillIn: m(t),
38
+ ...Q
39
+ };
40
+ function isComponent$1(e) {
41
+ return r(e);
42
+ }
43
+ e(isComponent$1, "isComponent");
44
+ function containsComponent$1(e) {
45
+ return n(e);
46
+ }
47
+ e(containsComponent$1, "containsComponent");
48
+ function splitTextToken$1(e) {
49
+ return o(e);
50
+ }
51
+ e(splitTextToken$1, "splitTextToken");
52
+ function splitParagraphToken$1(e) {
53
+ return a(e);
54
+ }
55
+ e(splitParagraphToken$1, "splitParagraphToken");
56
+ function parsedComponent(e) {
57
+ let t = "";
58
+ "text" in e && typeof e.text == "string" ? t = e.text : "raw" in e && typeof e.raw == "string" && (t = e.raw);
59
+ let n = i(t);
60
+ return n ? {
61
+ is: n.componentName,
62
+ text: "",
63
+ props: n.props
64
+ } : {
65
+ is: "fillIn",
66
+ text: t,
67
+ props: {}
68
+ };
69
+ }
70
+ function getComponent(e) {
71
+ return $[e] || (console.warn(`[MarkdownRenderer] Unknown component: "${e}". Available components: ${Object.keys($).join(", ")}`), null);
72
+ }
73
+ function decodeBasicEntities(e) {
74
+ return e.replace(/&#39;/g, "'").replace(/&quot;/g, "\"").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">");
75
+ }
76
+ function isText(e) {
77
+ return e.inLink === void 0 && e.type === "text";
78
+ }
79
+ return Z({
80
+ isComponent: isComponent$1,
81
+ containsComponent: containsComponent$1,
82
+ splitTextToken: splitTextToken$1,
83
+ splitParagraphToken: splitParagraphToken$1,
84
+ parsedComponent,
85
+ decodeBasicEntities,
86
+ isText,
87
+ components: $,
88
+ getComponent
89
+ }), (e, t) => {
90
+ let n = v("md-token-renderer", !0);
91
+ return isText(p.token) ? (g(), d("span", x, [!p.token.tokens || p.token.tokens.length === 0 ? (g(), d("span", S, [isComponent$1(p.token) ? (g(), d("span", C, [!p.last && getComponent(parsedComponent(p.token).is) ? (g(), l(y(getComponent(parsedComponent(p.token).is)), h({
92
+ key: 0,
93
+ text: parsedComponent(p.token).text
94
+ }, parsedComponent(p.token).props), null, 16, ["text"])) : !p.last && !getComponent(parsedComponent(p.token).is) ? (g(), d("span", w, " [Unknown component: " + b(parsedComponent(p.token).is) + "] ", 1)) : u("", !0)])) : containsComponent$1(p.token) ? (g(), d("span", T, [(g(!0), d(c, null, _(splitTextToken$1(p.token), (e, t) => (g(), l(n, {
95
+ key: t,
96
+ token: e
97
+ }, null, 8, ["token"]))), 128))])) : (g(), d("span", E, b(decodeBasicEntities(p.token.text)), 1))])) : p.token.tokens && p.token.tokens.length !== 0 ? (g(), d("span", D, [(g(!0), d(c, null, _(p.token.tokens, (e, t) => (g(), l(n, {
98
+ key: t,
99
+ token: e
100
+ }, null, 8, ["token"]))), 128))])) : u("", !0)])) : p.token.type === "heading" ? (g(), d("span", O, [p.token.depth === 1 ? (g(), d("h1", k, [(g(!0), d(c, null, _(p.token.tokens, (e, t) => (g(), l(n, {
101
+ key: t,
102
+ token: e
103
+ }, null, 8, ["token"]))), 128))])) : p.token.depth === 2 ? (g(), d("h2", A, [(g(!0), d(c, null, _(p.token.tokens, (e, t) => (g(), l(n, {
104
+ key: t,
105
+ token: e
106
+ }, null, 8, ["token"]))), 128))])) : p.token.depth === 3 ? (g(), d("h3", j, [(g(!0), d(c, null, _(p.token.tokens, (e, t) => (g(), l(n, {
107
+ key: t,
108
+ token: e
109
+ }, null, 8, ["token"]))), 128))])) : p.token.depth === 4 ? (g(), d("h4", M, [(g(!0), d(c, null, _(p.token.tokens, (e, t) => (g(), l(n, {
110
+ key: t,
111
+ token: e
112
+ }, null, 8, ["token"]))), 128))])) : p.token.depth === 5 ? (g(), d("h5", N, [(g(!0), d(c, null, _(p.token.tokens, (e, t) => (g(), l(n, {
113
+ key: t,
114
+ token: e
115
+ }, null, 8, ["token"]))), 128))])) : p.token.depth === 6 ? (g(), d("h6", te, [(g(!0), d(c, null, _(p.token.tokens, (e, t) => (g(), l(n, {
116
+ key: t,
117
+ token: e
118
+ }, null, 8, ["token"]))), 128))])) : u("", !0)])) : p.token.type === "strong" ? (g(), d("strong", P, [(g(!0), d(c, null, _(p.token.tokens, (e, t) => (g(), l(n, {
119
+ key: t,
120
+ token: e
121
+ }, null, 8, ["token"]))), 128))])) : p.token.type === "paragraph" ? (g(), d("p", F, [containsComponent$1(p.token) ? (g(), d("span", I, [(g(!0), d(c, null, _(splitParagraphToken$1(p.token), (e, t) => (g(), l(n, {
122
+ key: t,
123
+ token: e,
124
+ last: p.last && p.token.tokens.length === 1 && t === splitParagraphToken$1(p.token).length - 1
125
+ }, null, 8, ["token", "last"]))), 128))])) : (g(!0), d(c, { key: 1 }, _(p.token.tokens, (e, t) => (g(), l(n, {
126
+ key: t,
127
+ token: e,
128
+ last: p.last && p.token.tokens.length === 1
129
+ }, null, 8, ["token", "last"]))), 128))])) : p.token.type === "link" ? (g(), d("a", {
130
+ key: 4,
131
+ href: p.token.href,
132
+ title: p.token.title
133
+ }, [(g(!0), d(c, null, _(p.token.tokens, (e, t) => (g(), l(n, {
134
+ key: t,
135
+ token: e
136
+ }, null, 8, ["token"]))), 128))], 8, L)) : p.token.type === "list" && p.token.ordered === !1 ? (g(), d("ul", R, [(g(!0), d(c, null, _(p.token.items, (e, t) => (g(), l(n, {
137
+ key: t,
138
+ token: e
139
+ }, null, 8, ["token"]))), 128))])) : p.token.type === "list" && p.token.ordered === !0 ? (g(), d("ol", z, [(g(!0), d(c, null, _(p.token.items, (e, t) => (g(), l(n, {
140
+ key: t,
141
+ token: e
142
+ }, null, 8, ["token"]))), 128))])) : p.token.type === "list_item" ? (g(), d("li", B, [(g(!0), d(c, null, _(p.token.tokens, (e, t) => (g(), l(n, {
143
+ key: t,
144
+ token: e
145
+ }, null, 8, ["token"]))), 128))])) : p.token.type === "image" ? (g(), d("img", {
146
+ key: 8,
147
+ src: p.token.href,
148
+ alt: p.token.title
149
+ }, null, 8, V)) : p.token.type === "hr" ? (g(), d("hr", H)) : p.token.type === "br" ? (g(), d("br", U)) : p.token.type === "del" ? (g(), d("del", W)) : p.token.type === "table" ? (g(), d("table", {
150
+ key: 12,
151
+ align: p.token.align
152
+ }, [f("thead", null, [(g(!0), d(c, null, _(p.token.header, (e, t) => (g(), d("th", { key: t }, b(e.text), 1))), 128))]), f("tbody", null, [(g(!0), d(c, null, _(p.token.rows, (e, t) => (g(), d("tr", { key: t }, [(g(!0), d(c, null, _(e, (e, t) => (g(), d("td", { key: t }, b(e.text), 1))), 128))]))), 128))])], 8, G)) : p.token.type === "html" ? (g(), d("span", {
153
+ key: 13,
154
+ innerHTML: p.token.raw
155
+ }, null, 8, K)) : p.token.type === "code" ? (g(), l(s, {
156
+ key: 14,
157
+ code: p.token.text,
158
+ language: p.token.lang
159
+ }, null, 8, ["code", "language"])) : p.token.type === "codespan" ? (g(), d("code", {
160
+ key: 15,
161
+ class: "codespan",
162
+ innerHTML: p.token.text
163
+ }, null, 8, q)) : p.token.type === "blockquote" ? (g(), d("blockquote", J, [(g(!0), d(c, null, _(p.token.tokens, (e, t) => (g(), l(n, {
164
+ key: t,
165
+ token: e
166
+ }, null, 8, ["token"]))), 128))])) : p.token.type === "escape" ? (g(), d("span", Y, b(p.token.text), 1)) : p.token.type === "em" ? (g(), d("em", X, [(g(!0), d(c, null, _(p.token.tokens, (e, t) => (g(), l(n, {
167
+ key: t,
168
+ token: e
169
+ }, null, 8, ["token"]))), 128))])) : u("", !0);
170
+ };
171
+ }
172
+ });
173
+ //#endregion
174
+ export { Z as default };
175
+
176
+ //# sourceMappingURL=MdTokenRenderer.vue_vue_type_script_setup_true_lang.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MdTokenRenderer.vue_vue_type_script_setup_true_lang.mjs","names":[],"sources":["../../../src/components/cardRendering/MdTokenRenderer.vue"],"sourcesContent":["<template>\n <span v-if=\"isText(token)\">\n <span v-if=\"!token.tokens || token.tokens.length === 0\">\n <span v-if=\"isComponent(token)\">\n <!--\n KNOWN LIMITATION: Components cannot be the final token of the entire markdown document\n The v-if=\"!last\" check prevents rendering when this is the last token overall\n Components CAN be the last token in a paragraph (just not the whole document)\n Reason unclear but necessary historically - Chesterton's Fence applies\n Workaround: Add trailing whitespace, punctuation, or newline after component\n See: \"MarkdownRenderer - Known Limitations\" test group\n -->\n <component\n v-if=\"!last && getComponent(parsedComponent(token).is)\"\n :is=\"getComponent(parsedComponent(token).is)\"\n :text=\"parsedComponent(token).text\"\n v-bind=\"parsedComponent(token).props\"\n />\n <span v-else-if=\"!last && !getComponent(parsedComponent(token).is)\" class=\"error--text\">\n [Unknown component: {{ parsedComponent(token).is }}]\n </span>\n </span>\n <span v-else-if=\"containsComponent(token)\">\n <md-token-renderer v-for=\"(subTok, j) in splitTextToken(token)\" :key=\"j\" :token=\"subTok\" />\n </span>\n <span v-else>{{ decodeBasicEntities(token.text) }}</span>\n </span>\n <span v-else-if=\"token.tokens && token.tokens.length !== 0\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </span>\n </span>\n\n <span v-else-if=\"token.type === 'heading'\">\n <h1 v-if=\"token.depth === 1\" class=\"text-h2\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </h1>\n <h2 v-else-if=\"token.depth === 2\" class=\"text-h3\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </h2>\n <h3 v-else-if=\"token.depth === 3\" class=\"text-h4\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </h3>\n <h4 v-else-if=\"token.depth === 4\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </h4>\n <h5 v-else-if=\"token.depth === 5\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </h5>\n <h6 v-else-if=\"token.depth === 6\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </h6>\n </span>\n\n <strong v-else-if=\"token.type === 'strong'\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </strong>\n\n <p v-else-if=\"token.type === 'paragraph'\" class=\"text-h5\">\n <span v-if=\"containsComponent(token)\">\n <md-token-renderer\n v-for=\"(splitTok, j) in splitParagraphToken(token)\"\n :key=\"j\"\n :token=\"splitTok\"\n :last=\"last && token.tokens.length === 1 && j === splitParagraphToken(token).length - 1\"\n />\n </span>\n <template v-else>\n <md-token-renderer\n v-for=\"(subTok, j) in token.tokens\"\n :key=\"j\"\n :token=\"subTok\"\n :last=\"last && token.tokens.length === 1\"\n />\n </template>\n </p>\n\n <a v-else-if=\"token.type === 'link'\" :href=\"token.href\" :title=\"token.title\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </a>\n\n <ul v-else-if=\"token.type === 'list' && token.ordered === false\">\n <md-token-renderer v-for=\"(item, j) in token.items\" :key=\"j\" :token=\"item\" />\n </ul>\n\n <ol v-else-if=\"token.type === 'list' && token.ordered === true\">\n <md-token-renderer v-for=\"(item, j) in token.items\" :key=\"j\" :token=\"item\" />\n </ol>\n\n <li v-else-if=\"token.type === 'list_item'\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </li>\n\n <img v-else-if=\"token.type === 'image'\" :src=\"token.href\" :alt=\"token.title\" />\n <hr v-else-if=\"token.type === 'hr'\" />\n <br v-else-if=\"token.type === 'br'\" />\n <del v-else-if=\"token.type === 'del'\" />\n\n <table v-else-if=\"token.type === 'table'\" :align=\"token.align\">\n <thead>\n <th v-for=\"(h, j) in token.header\" :key=\"j\">{{ h.text }}</th>\n </thead>\n <tbody>\n <tr v-for=\"(row, r) in token.rows\" :key=\"r\">\n <td v-for=\"(cell, c) in row\" :key=\"c\">{{ cell.text }}</td>\n </tr>\n </tbody>\n </table>\n\n <span v-else-if=\"token.type === 'html'\" v-html=\"token.raw\"></span>\n\n <code-block-renderer v-else-if=\"token.type === 'code'\" :code=\"token.text\" :language=\"token.lang\" />\n <!-- <highlightjs v-else-if=\"token.type === 'code'\" class=\"hljs_render pa-2\" :language=\"token.lang\" :code=\"token.text\" /> -->\n\n <code v-else-if=\"token.type === 'codespan'\" class=\"codespan\" v-html=\"token.text\"></code>\n\n <blockquote v-else-if=\"token.type === 'blockquote'\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </blockquote>\n\n <span v-else-if=\"token.type === 'escape'\">{{ token.text }}</span>\n\n <em v-else-if=\"token.type === 'em'\">\n <md-token-renderer v-for=\"(subTok, j) in token.tokens\" :key=\"j\" :token=\"subTok\" />\n </em>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n containsComponent as _containsComponent,\n isComponent as _isComponent,\n splitParagraphToken as _splitParagraphToken,\n splitTextToken as _splitTextToken,\n parseComponentSyntax,\n TokenOrComponent,\n} from './MarkdownRendererHelpers';\nimport CodeBlockRenderer from './CodeBlockRenderer.vue';\nimport FillInInput from '../../components/studentInputs/fillInInput.vue';\nimport { MarkedToken, Tokens } from 'marked';\nimport { markRaw, inject } from 'vue';\nimport { PropType } from 'vue';\n\n// Inject custom components provided at app level (defaults to empty object)\nconst providedComponents = inject<Record<string, any>>('markdownComponents', {});\n\n// Register components to be used in the template\n// In Vue 3 with <script setup>, components used via :is must be explicitly registered\n// Merge built-in components with injected custom components\nconst components = {\n fillIn: markRaw(FillInInput),\n ...providedComponents,\n};\n\n// Define component props\ndefineProps({\n token: {\n type: Object as PropType<TokenOrComponent>,\n required: true,\n },\n last: {\n type: Boolean,\n required: false,\n default: false,\n },\n});\n\n// Methods\nfunction isComponent(token: MarkedToken): boolean {\n return _isComponent(token);\n}\n\nfunction containsComponent(token: MarkedToken): boolean {\n return _containsComponent(token);\n}\n\nfunction splitTextToken(token: MarkedToken): Tokens.Text[] {\n return _splitTextToken(token);\n}\n\nfunction splitParagraphToken(token: Tokens.Paragraph): TokenOrComponent[] {\n return _splitParagraphToken(token);\n}\n\nfunction parsedComponent(token: MarkedToken): {\n is: string;\n text: string;\n props: Record<string, string>;\n} {\n let text = '';\n if ('text' in token && typeof token.text === 'string') {\n text = token.text;\n } else if ('raw' in token && typeof token.raw === 'string') {\n text = token.raw;\n }\n\n // Try to parse as inline component syntax\n const parsed = parseComponentSyntax(text);\n\n if (parsed) {\n // Successfully parsed as inline component\n return {\n is: parsed.componentName,\n text: '',\n props: parsed.props,\n };\n }\n\n // Backward compatible: {{ }} or {{ || }} -> fillIn component\n return {\n is: 'fillIn',\n text,\n props: {},\n };\n}\n\nfunction getComponent(componentName: string) {\n const component = components[componentName as keyof typeof components];\n\n if (!component) {\n console.warn(\n `[MarkdownRenderer] Unknown component: \"${componentName}\". Available components: ${Object.keys(components).join(', ')}`\n );\n return null;\n }\n\n return component;\n}\n\nfunction decodeBasicEntities(text: string): string {\n return text\n .replace(/&#39;/g, \"'\")\n .replace(/&quot;/g, '\"')\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>');\n}\n\nfunction isText(tok: TokenOrComponent): boolean {\n return (tok as any).inLink === undefined && tok.type === 'text';\n}\n\n// Make these functions and objects available to the template\ndefineExpose({\n isComponent,\n containsComponent,\n splitTextToken,\n splitParagraphToken,\n parsedComponent,\n decodeBasicEntities,\n isText,\n components,\n getComponent,\n});\n</script>\n\n<style lang=\"css\" scoped>\nblockquote {\n border-left: 3px teal solid;\n padding-left: 8px;\n}\n\n.codespan {\n padding-left: 3px;\n padding-right: 3px;\n margin-left: 1px;\n margin-right: 1px;\n}\n\np {\n margin-bottom: 15px;\n margin-top: 15px;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8IA,IAAM,IAAqB,GAA4B,sBAAsB,EAAE,CAAC,EAK1E,IAAa;GACjB,QAAQ,EAAQ,EAAY;GAC5B,GAAG;GACJ;EAgBD,SAAS,cAAY,GAA6B;AAChD,UAAO,EAAa,EAAM;;;EAG5B,SAAS,oBAAkB,GAA6B;AACtD,UAAO,EAAmB,EAAM;;;EAGlC,SAAS,iBAAe,GAAmC;AACzD,UAAO,EAAgB,EAAM;;;EAG/B,SAAS,sBAAoB,GAA6C;AACxE,UAAO,EAAqB,EAAM;;;EAGpC,SAAS,gBAAgB,GAIvB;GACA,IAAI,IAAO;AACX,GAAI,UAAU,KAAS,OAAO,EAAM,QAAS,WAC3C,IAAO,EAAM,OACJ,SAAS,KAAS,OAAO,EAAM,OAAQ,aAChD,IAAO,EAAM;GAIf,IAAM,IAAS,EAAqB,EAAK;AAYzC,UAVI,IAEK;IACL,IAAI,EAAO;IACX,MAAM;IACN,OAAO,EAAO;IACf,GAII;IACL,IAAI;IACJ;IACA,OAAO,EAAE;IACV;;EAGH,SAAS,aAAa,GAAuB;AAU3C,UATkB,EAAW,OAG3B,QAAQ,KACN,0CAA0C,EAAc,2BAA2B,OAAO,KAAK,EAAW,CAAC,KAAK,KAAK,GACtH,EACM;;EAMX,SAAS,oBAAoB,GAAsB;AACjD,UAAO,EACJ,QAAQ,UAAU,IAAG,CACrB,QAAQ,WAAW,KAAG,CACtB,QAAQ,UAAU,IAAG,CACrB,QAAQ,SAAS,IAAG,CACpB,QAAQ,SAAS,IAAI;;EAG1B,SAAS,OAAO,GAAgC;AAC9C,UAAQ,EAAY,WAAW,KAAA,KAAa,EAAI,SAAS;;SAI3D,EAAa;GACX,aAAA;GACA,mBAAA;GACA,gBAAA;GACA,qBAAA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC"}
@@ -0,0 +1,54 @@
1
+ import "../../_virtual/_rolldown/runtime.mjs";
2
+ import { isQuestionView as e } from "../../composables/CompositionViewable.mjs";
3
+ import { useCardPreviewModeStore as t } from "../../stores/useCardPreviewModeStore.mjs";
4
+ import { defineComponent as n } from "vue";
5
+ import { log as r } from "@vue-skuilder/common";
6
+ //#region src/components/studentInputs/BaseUserInput.ts
7
+ var i = n({
8
+ name: "UserInput",
9
+ data() {
10
+ return {
11
+ answer: "",
12
+ previewModeStore: null
13
+ };
14
+ },
15
+ mounted() {
16
+ this.previewModeStore = t();
17
+ },
18
+ computed: {
19
+ autofocus() {
20
+ return !this.previewModeStore?.previewMode;
21
+ },
22
+ autoFocus() {
23
+ return this.autofocus;
24
+ }
25
+ },
26
+ methods: {
27
+ submitAnswer(e) {
28
+ return this.submit(e);
29
+ },
30
+ submit(e) {
31
+ return this.getQuestionViewAncestor().submitAnswer(e, this.$options.name ?? "UserInput");
32
+ },
33
+ getQuestionViewAncestor() {
34
+ let t = this.$parent, n = 0;
35
+ for (; t && !e(t);) {
36
+ let e = t.$parent;
37
+ if (!e) {
38
+ let e = "\nUserInput.submit() has failed.\nThe input element has no QuestionView ancestor element.";
39
+ throw r(e), Error(e);
40
+ }
41
+ if (t = e, n++, n > 100) {
42
+ let e = "\nUserInput.submit() has failed.\nExceeded maximum ancestor lookup depth.";
43
+ throw r(e), Error(e);
44
+ }
45
+ }
46
+ if (!t) throw Error("No QuestionView ancestor found");
47
+ return t;
48
+ }
49
+ }
50
+ });
51
+ //#endregion
52
+ export { i as default };
53
+
54
+ //# sourceMappingURL=BaseUserInput.mjs.map