@lapismd/mira 0.0.4 → 0.1.0

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 (305) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/extensions/index.d.ts +13 -1
  3. package/dist/extensions/index.d.ts.map +1 -1
  4. package/dist/extensions/index.js +13 -3
  5. package/dist/extensions/inline-links.d.ts +8 -0
  6. package/dist/extensions/inline-links.d.ts.map +1 -0
  7. package/dist/extensions/inline-links.js +120 -0
  8. package/dist/extensions/markdown-editing.d.ts +32 -0
  9. package/dist/extensions/markdown-editing.d.ts.map +1 -0
  10. package/dist/extensions/markdown-editing.js +1 -0
  11. package/dist/internal/codemirror/base/index.d.ts.map +1 -1
  12. package/dist/internal/codemirror/base/index.js +3 -0
  13. package/dist/internal/codemirror/markdown/index.d.ts.map +1 -1
  14. package/dist/internal/codemirror/markdown/index.js +2 -1
  15. package/dist/internal/codemirror/rich/block-controls.d.ts.map +1 -1
  16. package/dist/internal/codemirror/rich/block-controls.js +2 -0
  17. package/dist/internal/codemirror/rich/block-gutter-accessibility.d.ts +15 -0
  18. package/dist/internal/codemirror/rich/block-gutter-accessibility.d.ts.map +1 -0
  19. package/dist/internal/codemirror/rich/block-gutter-accessibility.js +67 -0
  20. package/dist/internal/codemirror/rich/index.d.ts.map +1 -1
  21. package/dist/internal/codemirror/rich/index.js +43 -9
  22. package/dist/internal/codemirror/rich/utils/images.d.ts +6 -3
  23. package/dist/internal/codemirror/rich/utils/images.d.ts.map +1 -1
  24. package/dist/internal/codemirror/rich/utils/images.js +16 -29
  25. package/dist/internal/codemirror/rich/utils/references.d.ts +15 -0
  26. package/dist/internal/codemirror/rich/utils/references.d.ts.map +1 -0
  27. package/dist/internal/codemirror/rich/utils/references.js +86 -0
  28. package/dist/internal/codemirror/rich/widgets/preview-widgets.d.ts +3 -0
  29. package/dist/internal/codemirror/rich/widgets/preview-widgets.d.ts.map +1 -1
  30. package/dist/internal/codemirror/rich/widgets/preview-widgets.js +31 -3
  31. package/dist/internal/inline-links/icons.d.ts +115 -0
  32. package/dist/internal/inline-links/icons.d.ts.map +1 -0
  33. package/dist/internal/inline-links/icons.js +148 -0
  34. package/dist/internal/inline-links/live-preview.d.ts +5 -0
  35. package/dist/internal/inline-links/live-preview.d.ts.map +1 -0
  36. package/dist/internal/inline-links/live-preview.js +135 -0
  37. package/dist/internal/inline-links/registry.d.ts +44 -0
  38. package/dist/internal/inline-links/registry.d.ts.map +1 -0
  39. package/dist/internal/inline-links/registry.js +153 -0
  40. package/dist/mira.svelte.d.ts +1 -1
  41. package/dist/preview/asset-url-lease.d.ts +6 -0
  42. package/dist/preview/asset-url-lease.d.ts.map +1 -0
  43. package/dist/preview/asset-url-lease.js +28 -0
  44. package/dist/preview/components/embed.svelte +10 -5
  45. package/dist/preview/components/embed.svelte.d.ts.map +1 -1
  46. package/dist/preview/components/image.svelte +7 -2
  47. package/dist/preview/components/image.svelte.d.ts.map +1 -1
  48. package/dist/preview/components/inline-link.svelte +94 -0
  49. package/dist/preview/components/inline-link.svelte.d.ts +16 -0
  50. package/dist/preview/components/inline-link.svelte.d.ts.map +1 -0
  51. package/dist/preview/components/link-destination-tooltip.svelte +63 -0
  52. package/dist/preview/components/link-destination-tooltip.svelte.d.ts +7 -0
  53. package/dist/preview/components/link-destination-tooltip.svelte.d.ts.map +1 -0
  54. package/dist/preview/components/link-site-icon.svelte +39 -0
  55. package/dist/preview/components/link-site-icon.svelte.d.ts +10 -0
  56. package/dist/preview/components/link-site-icon.svelte.d.ts.map +1 -0
  57. package/dist/preview/components/link.svelte +19 -9
  58. package/dist/preview/components/link.svelte.d.ts.map +1 -1
  59. package/dist/preview/editable-markdown-preview/editable-markdown-surface.svelte +26 -10
  60. package/dist/preview/editable-markdown-preview/editable-markdown-surface.svelte.d.ts.map +1 -1
  61. package/dist/preview/editable-markdown-preview/editing-session.d.ts +15 -0
  62. package/dist/preview/editable-markdown-preview/editing-session.d.ts.map +1 -0
  63. package/dist/preview/editable-markdown-preview/editing-session.js +103 -0
  64. package/dist/preview/editable-markdown-preview/editor-surface.svelte +13 -4
  65. package/dist/preview/editable-markdown-preview/editor-surface.svelte.d.ts +1 -0
  66. package/dist/preview/editable-markdown-preview/editor-surface.svelte.d.ts.map +1 -1
  67. package/dist/preview/editable-markdown-preview/serialized-writer.d.ts +10 -8
  68. package/dist/preview/editable-markdown-preview/serialized-writer.d.ts.map +1 -1
  69. package/dist/preview/editable-markdown-preview/serialized-writer.js +105 -6
  70. package/dist/preview/editable-markdown-preview.svelte +8 -6
  71. package/dist/preview/editable-markdown-preview.svelte.d.ts.map +1 -1
  72. package/dist/preview/index.d.ts +2 -0
  73. package/dist/preview/index.d.ts.map +1 -1
  74. package/dist/preview/index.js +2 -0
  75. package/dist/preview/markdown-preview.svelte +11 -0
  76. package/dist/preview/markdown-preview.svelte.d.ts.map +1 -1
  77. package/dist/preview/renderer/utils.js +0 -2
  78. package/dist/preview/styles/inline-links.css +38 -0
  79. package/dist/preview/styles/links-embeds-tags.css +2 -2
  80. package/dist/preview/styles/mermaid-highlight.css +4 -3
  81. package/dist/preview/styles/references.css +72 -0
  82. package/dist/preview/styles.css +2 -0
  83. package/dist/tables/editor-column.svelte +20 -7
  84. package/dist/tables/editor-column.svelte.d.ts +2 -0
  85. package/dist/tables/editor-column.svelte.d.ts.map +1 -1
  86. package/dist/tables/editor-table.svelte +4 -0
  87. package/dist/tables/editor-table.svelte.d.ts +2 -0
  88. package/dist/tables/editor-table.svelte.d.ts.map +1 -1
  89. package/dist/tables/grid-editor-column.svelte +6 -2
  90. package/dist/tables/grid-editor-column.svelte.d.ts +2 -0
  91. package/dist/tables/grid-editor-column.svelte.d.ts.map +1 -1
  92. package/dist/tables/grid-editor-table.svelte +4 -0
  93. package/dist/tables/grid-editor-table.svelte.d.ts +2 -0
  94. package/dist/tables/grid-editor-table.svelte.d.ts.map +1 -1
  95. package/dist/tables/index.d.ts +1 -0
  96. package/dist/tables/index.d.ts.map +1 -1
  97. package/dist/tables/index.js +1 -0
  98. package/dist/tables/markdown-table-data-cell.svelte +4 -0
  99. package/dist/tables/markdown-table-data-cell.svelte.d.ts +2 -0
  100. package/dist/tables/markdown-table-data-cell.svelte.d.ts.map +1 -1
  101. package/dist/tables/table-reader.svelte +101 -0
  102. package/dist/tables/table-reader.svelte.d.ts +21 -0
  103. package/dist/tables/table-reader.svelte.d.ts.map +1 -0
  104. package/dist/tables/types.d.ts +2 -0
  105. package/dist/tables/types.d.ts.map +1 -1
  106. package/dist/tables/widgets/grid-table-widget.d.ts +1 -1
  107. package/dist/tables/widgets/grid-table-widget.d.ts.map +1 -1
  108. package/dist/tables/widgets/grid-table-widget.js +5 -2
  109. package/dist/tables/widgets/lifecycle.d.ts +4 -0
  110. package/dist/tables/widgets/lifecycle.d.ts.map +1 -0
  111. package/dist/tables/widgets/lifecycle.js +13 -0
  112. package/dist/tables/widgets/pipe-table-widget.d.ts +1 -1
  113. package/dist/tables/widgets/pipe-table-widget.d.ts.map +1 -1
  114. package/dist/tables/widgets/pipe-table-widget.js +5 -2
  115. package/dist/ui/context-menu/context-menu-radio-group.svelte.d.ts +1 -1
  116. package/dist/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +1 -1
  117. package/dist/ui/toolbar/toolbar-group.svelte.d.ts +1 -1
  118. package/inline-links-NOTICE.md +31 -0
  119. package/package.json +6 -2
  120. package/dist/core/code-mirror.test.d.ts +0 -2
  121. package/dist/core/code-mirror.test.d.ts.map +0 -1
  122. package/dist/core/code-mirror.test.js +0 -68
  123. package/dist/core/images.test.d.ts +0 -2
  124. package/dist/core/images.test.d.ts.map +0 -1
  125. package/dist/core/images.test.js +0 -109
  126. package/dist/core/index.test.d.ts +0 -2
  127. package/dist/core/index.test.d.ts.map +0 -1
  128. package/dist/core/index.test.js +0 -11
  129. package/dist/core/markdown-actions.test.d.ts +0 -2
  130. package/dist/core/markdown-actions.test.d.ts.map +0 -1
  131. package/dist/core/markdown-actions.test.js +0 -182
  132. package/dist/extensions/doodle-dividers.test.d.ts +0 -2
  133. package/dist/extensions/doodle-dividers.test.d.ts.map +0 -1
  134. package/dist/extensions/doodle-dividers.test.js +0 -296
  135. package/dist/extensions/index.test.d.ts +0 -2
  136. package/dist/extensions/index.test.d.ts.map +0 -1
  137. package/dist/extensions/index.test.js +0 -283
  138. package/dist/index.test.d.ts +0 -2
  139. package/dist/index.test.d.ts.map +0 -1
  140. package/dist/index.test.js +0 -64
  141. package/dist/internal/appearance-context.test.d.ts +0 -2
  142. package/dist/internal/appearance-context.test.d.ts.map +0 -1
  143. package/dist/internal/appearance-context.test.js +0 -31
  144. package/dist/internal/codemirror/base/index.test.d.ts +0 -2
  145. package/dist/internal/codemirror/base/index.test.d.ts.map +0 -1
  146. package/dist/internal/codemirror/base/index.test.js +0 -303
  147. package/dist/internal/codemirror/base/search.test.d.ts +0 -2
  148. package/dist/internal/codemirror/base/search.test.d.ts.map +0 -1
  149. package/dist/internal/codemirror/base/search.test.js +0 -155
  150. package/dist/internal/codemirror/base/selection-toolbar.test.d.ts +0 -2
  151. package/dist/internal/codemirror/base/selection-toolbar.test.d.ts.map +0 -1
  152. package/dist/internal/codemirror/base/selection-toolbar.test.js +0 -149
  153. package/dist/internal/codemirror/markdown/authoring.test.d.ts +0 -2
  154. package/dist/internal/codemirror/markdown/authoring.test.d.ts.map +0 -1
  155. package/dist/internal/codemirror/markdown/authoring.test.js +0 -222
  156. package/dist/internal/codemirror/markdown/index.test.d.ts +0 -2
  157. package/dist/internal/codemirror/markdown/index.test.d.ts.map +0 -1
  158. package/dist/internal/codemirror/markdown/index.test.js +0 -158
  159. package/dist/internal/codemirror/markdown/showcase-fixture.test.d.ts +0 -2
  160. package/dist/internal/codemirror/markdown/showcase-fixture.test.d.ts.map +0 -1
  161. package/dist/internal/codemirror/markdown/showcase-fixture.test.js +0 -50
  162. package/dist/internal/codemirror/rich/block-controls.test.d.ts +0 -2
  163. package/dist/internal/codemirror/rich/block-controls.test.d.ts.map +0 -1
  164. package/dist/internal/codemirror/rich/block-controls.test.js +0 -401
  165. package/dist/internal/codemirror/rich/block-ranges.test.d.ts +0 -2
  166. package/dist/internal/codemirror/rich/block-ranges.test.d.ts.map +0 -1
  167. package/dist/internal/codemirror/rich/block-ranges.test.js +0 -310
  168. package/dist/internal/codemirror/rich/block-toolbar.test.d.ts +0 -2
  169. package/dist/internal/codemirror/rich/block-toolbar.test.d.ts.map +0 -1
  170. package/dist/internal/codemirror/rich/block-toolbar.test.js +0 -178
  171. package/dist/internal/codemirror/rich/decorations/fold-indicators.test.d.ts +0 -2
  172. package/dist/internal/codemirror/rich/decorations/fold-indicators.test.d.ts.map +0 -1
  173. package/dist/internal/codemirror/rich/decorations/fold-indicators.test.js +0 -8
  174. package/dist/internal/codemirror/rich/index.test.d.ts +0 -2
  175. package/dist/internal/codemirror/rich/index.test.d.ts.map +0 -1
  176. package/dist/internal/codemirror/rich/index.test.js +0 -607
  177. package/dist/internal/codemirror/rich/utils/code-block-lines.test.d.ts +0 -2
  178. package/dist/internal/codemirror/rich/utils/code-block-lines.test.d.ts.map +0 -1
  179. package/dist/internal/codemirror/rich/utils/code-block-lines.test.js +0 -82
  180. package/dist/internal/codemirror/rich/utils/fenced-code.test.d.ts +0 -2
  181. package/dist/internal/codemirror/rich/utils/fenced-code.test.d.ts.map +0 -1
  182. package/dist/internal/codemirror/rich/utils/fenced-code.test.js +0 -12
  183. package/dist/internal/codemirror/rich/utils/headings.test.d.ts +0 -2
  184. package/dist/internal/codemirror/rich/utils/headings.test.d.ts.map +0 -1
  185. package/dist/internal/codemirror/rich/utils/headings.test.js +0 -27
  186. package/dist/internal/codemirror/rich/utils/height-estimates.test.d.ts +0 -2
  187. package/dist/internal/codemirror/rich/utils/height-estimates.test.d.ts.map +0 -1
  188. package/dist/internal/codemirror/rich/utils/height-estimates.test.js +0 -10
  189. package/dist/internal/codemirror/rich/utils/images.test.d.ts +0 -2
  190. package/dist/internal/codemirror/rich/utils/images.test.d.ts.map +0 -1
  191. package/dist/internal/codemirror/rich/utils/images.test.js +0 -37
  192. package/dist/internal/codemirror/rich/utils/indent.test.d.ts +0 -2
  193. package/dist/internal/codemirror/rich/utils/indent.test.d.ts.map +0 -1
  194. package/dist/internal/codemirror/rich/utils/indent.test.js +0 -169
  195. package/dist/internal/codemirror/rich/utils/inline-math.test.d.ts +0 -2
  196. package/dist/internal/codemirror/rich/utils/inline-math.test.d.ts.map +0 -1
  197. package/dist/internal/codemirror/rich/utils/inline-math.test.js +0 -15
  198. package/dist/internal/codemirror/rich/utils/links.test.d.ts +0 -2
  199. package/dist/internal/codemirror/rich/utils/links.test.d.ts.map +0 -1
  200. package/dist/internal/codemirror/rich/utils/links.test.js +0 -28
  201. package/dist/internal/codemirror/rich/utils/list-callouts.test.d.ts +0 -2
  202. package/dist/internal/codemirror/rich/utils/list-callouts.test.d.ts.map +0 -1
  203. package/dist/internal/codemirror/rich/utils/list-callouts.test.js +0 -47
  204. package/dist/internal/codemirror/rich/utils/measured-indent.test.d.ts +0 -2
  205. package/dist/internal/codemirror/rich/utils/measured-indent.test.d.ts.map +0 -1
  206. package/dist/internal/codemirror/rich/utils/measured-indent.test.js +0 -102
  207. package/dist/internal/codemirror/rich/utils/ranges.test.d.ts +0 -2
  208. package/dist/internal/codemirror/rich/utils/ranges.test.d.ts.map +0 -1
  209. package/dist/internal/codemirror/rich/utils/ranges.test.js +0 -22
  210. package/dist/internal/codemirror/rich/utils/tasks.test.d.ts +0 -2
  211. package/dist/internal/codemirror/rich/utils/tasks.test.d.ts.map +0 -1
  212. package/dist/internal/codemirror/rich/utils/tasks.test.js +0 -57
  213. package/dist/internal/task-states.test.d.ts +0 -2
  214. package/dist/internal/task-states.test.d.ts.map +0 -1
  215. package/dist/internal/task-states.test.js +0 -36
  216. package/dist/mira-code-editor.test.d.ts +0 -2
  217. package/dist/mira-code-editor.test.d.ts.map +0 -1
  218. package/dist/mira-code-editor.test.js +0 -93
  219. package/dist/mode-position.test.d.ts +0 -2
  220. package/dist/mode-position.test.d.ts.map +0 -1
  221. package/dist/mode-position.test.js +0 -60
  222. package/dist/preview/code-language.test.d.ts +0 -2
  223. package/dist/preview/code-language.test.d.ts.map +0 -1
  224. package/dist/preview/code-language.test.js +0 -12
  225. package/dist/preview/components/icon.test.d.ts +0 -2
  226. package/dist/preview/components/icon.test.d.ts.map +0 -1
  227. package/dist/preview/components/icon.test.js +0 -20
  228. package/dist/preview/editable-markdown-preview/behavior.test.d.ts +0 -2
  229. package/dist/preview/editable-markdown-preview/behavior.test.d.ts.map +0 -1
  230. package/dist/preview/editable-markdown-preview/behavior.test.js +0 -36
  231. package/dist/preview/editable-markdown-preview/serialized-writer.test.d.ts +0 -2
  232. package/dist/preview/editable-markdown-preview/serialized-writer.test.d.ts.map +0 -1
  233. package/dist/preview/editable-markdown-preview/serialized-writer.test.js +0 -59
  234. package/dist/preview/embed-target.test.d.ts +0 -2
  235. package/dist/preview/embed-target.test.d.ts.map +0 -1
  236. package/dist/preview/embed-target.test.js +0 -78
  237. package/dist/preview/frontmatter/frontmatter.test.d.ts +0 -2
  238. package/dist/preview/frontmatter/frontmatter.test.d.ts.map +0 -1
  239. package/dist/preview/frontmatter/frontmatter.test.js +0 -190
  240. package/dist/preview/frontmatter/suggestions.test.d.ts +0 -2
  241. package/dist/preview/frontmatter/suggestions.test.d.ts.map +0 -1
  242. package/dist/preview/frontmatter/suggestions.test.js +0 -45
  243. package/dist/preview/outline.test.d.ts +0 -2
  244. package/dist/preview/outline.test.d.ts.map +0 -1
  245. package/dist/preview/outline.test.js +0 -98
  246. package/dist/preview/portable-surfaces.test.d.ts +0 -2
  247. package/dist/preview/portable-surfaces.test.d.ts.map +0 -1
  248. package/dist/preview/portable-surfaces.test.js +0 -513
  249. package/dist/preview/preview.test.d.ts +0 -2
  250. package/dist/preview/preview.test.d.ts.map +0 -1
  251. package/dist/preview/preview.test.js +0 -154
  252. package/dist/preview/remark/callouts.test.d.ts +0 -2
  253. package/dist/preview/remark/callouts.test.d.ts.map +0 -1
  254. package/dist/preview/remark/callouts.test.js +0 -23
  255. package/dist/preview/remark/custom-checklists.test.d.ts +0 -2
  256. package/dist/preview/remark/custom-checklists.test.d.ts.map +0 -1
  257. package/dist/preview/remark/custom-checklists.test.js +0 -51
  258. package/dist/preview/remark/links.test.d.ts +0 -2
  259. package/dist/preview/remark/links.test.d.ts.map +0 -1
  260. package/dist/preview/remark/links.test.js +0 -62
  261. package/dist/preview/remark/parity.test.d.ts +0 -2
  262. package/dist/preview/remark/parity.test.d.ts.map +0 -1
  263. package/dist/preview/remark/parity.test.js +0 -105
  264. package/dist/preview/styles/frontmatter-properties.test.d.ts +0 -2
  265. package/dist/preview/styles/frontmatter-properties.test.d.ts.map +0 -1
  266. package/dist/preview/styles/frontmatter-properties.test.js +0 -57
  267. package/dist/preview/styles/source-mode.test.d.ts +0 -2
  268. package/dist/preview/styles/source-mode.test.d.ts.map +0 -1
  269. package/dist/preview/styles/source-mode.test.js +0 -28
  270. package/dist/tables/extension.test.d.ts +0 -2
  271. package/dist/tables/extension.test.d.ts.map +0 -1
  272. package/dist/tables/extension.test.js +0 -100
  273. package/dist/tables/grid-editor-column.test.d.ts +0 -2
  274. package/dist/tables/grid-editor-column.test.d.ts.map +0 -1
  275. package/dist/tables/grid-editor-column.test.js +0 -27
  276. package/dist/tables/grid-table.test.d.ts +0 -2
  277. package/dist/tables/grid-table.test.d.ts.map +0 -1
  278. package/dist/tables/grid-table.test.js +0 -140
  279. package/dist/tables/index.test.d.ts +0 -2
  280. package/dist/tables/index.test.d.ts.map +0 -1
  281. package/dist/tables/index.test.js +0 -7
  282. package/dist/tables/inline-editor-extensions.test.d.ts +0 -2
  283. package/dist/tables/inline-editor-extensions.test.d.ts.map +0 -1
  284. package/dist/tables/inline-editor-extensions.test.js +0 -23
  285. package/dist/tables/pipe-table.test.d.ts +0 -2
  286. package/dist/tables/pipe-table.test.d.ts.map +0 -1
  287. package/dist/tables/pipe-table.test.js +0 -13
  288. package/dist/tables/table-node.test.d.ts +0 -2
  289. package/dist/tables/table-node.test.d.ts.map +0 -1
  290. package/dist/tables/table-node.test.js +0 -167
  291. package/dist/tables/widgets/source-button.test.d.ts +0 -2
  292. package/dist/tables/widgets/source-button.test.d.ts.map +0 -1
  293. package/dist/tables/widgets/source-button.test.js +0 -11
  294. package/dist/themes/theme-contract.test.d.ts +0 -2
  295. package/dist/themes/theme-contract.test.d.ts.map +0 -1
  296. package/dist/themes/theme-contract.test.js +0 -88
  297. package/dist/ui/index.test.d.ts +0 -2
  298. package/dist/ui/index.test.d.ts.map +0 -1
  299. package/dist/ui/index.test.js +0 -7
  300. package/dist/ui/styles.test.d.ts +0 -2
  301. package/dist/ui/styles.test.d.ts.map +0 -1
  302. package/dist/ui/styles.test.js +0 -26
  303. package/dist/ui/table-dnd/table-dnd-utils.test.d.ts +0 -2
  304. package/dist/ui/table-dnd/table-dnd-utils.test.d.ts.map +0 -1
  305. package/dist/ui/table-dnd/table-dnd-utils.test.js +0 -46
@@ -1,513 +0,0 @@
1
- import { mount, tick, unmount } from "svelte";
2
- import { describe, expect, it, vi } from "vitest";
3
- import { defineMiraExtension, doodleDividersExtension, } from "@lapismd/mira/extensions";
4
- import FileEmbed from "./file-embed.svelte";
5
- import EditableMarkdownPreview from "./editable-markdown-preview.svelte";
6
- import MarkdownEmbed from "./markdown-embed.svelte";
7
- import MarkdownPreview from "./markdown-preview.svelte";
8
- import NoteLink from "./note-link.svelte";
9
- import FrontmatterEditor from "./components/frontmatter.svelte";
10
- import { FrontmatterController } from "./frontmatter";
11
- const fileAdapter = {
12
- resolveLink(target) {
13
- return {
14
- path: target.path,
15
- name: target.path.replace(/\.md$/u, ""),
16
- kind: "markdown",
17
- };
18
- },
19
- readMarkdown() {
20
- return "# Embedded note\n\nPortable content.";
21
- },
22
- };
23
- async function settle() {
24
- await Promise.resolve();
25
- await tick();
26
- await Promise.resolve();
27
- await tick();
28
- }
29
- describe("portable preview surfaces", () => {
30
- it("reports rendered task-checkbox source ranges", async () => {
31
- const target = document.createElement("div");
32
- const onChange = vi.fn();
33
- const component = mount(MarkdownEmbed, {
34
- target,
35
- props: {
36
- value: "# Checklist\n\n- [ ] Confirm release notes.\n",
37
- onChange,
38
- },
39
- });
40
- await settle();
41
- const checkbox = target.querySelector('input[aria-label="Toggle task"]');
42
- expect(checkbox?.disabled).toBe(false);
43
- checkbox.checked = true;
44
- checkbox.dispatchEvent(new Event("change", { bubbles: true }));
45
- await settle();
46
- expect(onChange).toHaveBeenCalledOnce();
47
- expect(onChange).toHaveBeenCalledWith("x", 16, 17);
48
- await unmount(component);
49
- });
50
- it("keeps adapters without writeMarkdown read-only", async () => {
51
- const target = document.createElement("div");
52
- const component = mount(EditableMarkdownPreview, {
53
- target,
54
- props: {
55
- file: {
56
- kind: "markdown",
57
- name: "Portable",
58
- path: "notes/portable.md",
59
- },
60
- fileAdapter,
61
- },
62
- });
63
- await settle();
64
- target
65
- .querySelector('[data-editable-markdown-preview] [role="button"]')
66
- ?.click();
67
- await settle();
68
- expect(target.querySelector("[data-editable-markdown-editor]")).toBeNull();
69
- expect(target
70
- .querySelector("[data-editable-markdown-preview]")
71
- ?.getAttribute("data-editing")).toBe("false");
72
- await unmount(component);
73
- });
74
- it("enters a live-preview editor only for writable Markdown adapters", async () => {
75
- const target = document.createElement("div");
76
- const component = mount(EditableMarkdownPreview, {
77
- target,
78
- props: {
79
- file: {
80
- kind: "markdown",
81
- name: "Portable",
82
- path: "notes/portable.md",
83
- },
84
- fileAdapter: { ...fileAdapter, writeMarkdown: vi.fn() },
85
- },
86
- });
87
- await settle();
88
- target
89
- .querySelector('[data-editable-markdown-preview] [role="button"]')
90
- ?.click();
91
- await settle();
92
- expect(target.querySelector("[data-editable-markdown-editor]")).toBeTruthy();
93
- expect(target.querySelector(".cm-editor")).toBeTruthy();
94
- expect(target.querySelector(".cm-activeLine")?.textContent).toContain("Embedded note");
95
- await unmount(component);
96
- });
97
- it("persists rendered task-checkbox changes through a writable adapter", async () => {
98
- const target = document.createElement("div");
99
- const writeMarkdown = vi.fn();
100
- const component = mount(EditableMarkdownPreview, {
101
- target,
102
- props: {
103
- file: {
104
- kind: "markdown",
105
- name: "Checklist",
106
- path: "notes/checklist.md",
107
- },
108
- fileAdapter: {
109
- ...fileAdapter,
110
- readMarkdown: () => "# Checklist\n\n- [ ] Confirm release notes.\n",
111
- writeMarkdown,
112
- },
113
- activateOnPreviewInteraction: false,
114
- },
115
- });
116
- await settle();
117
- const checkbox = target.querySelector('input[aria-label="Toggle task"]');
118
- expect(checkbox).not.toBeNull();
119
- expect(checkbox?.disabled).toBe(false);
120
- checkbox.checked = true;
121
- checkbox.dispatchEvent(new Event("change", { bubbles: true }));
122
- await settle();
123
- expect(checkbox?.checked).toBe(true);
124
- expect(target
125
- .querySelector("[data-editable-markdown-preview]")
126
- ?.getAttribute("data-save-state")).toBe("dirty");
127
- await expect(component.flush()).resolves.toBe(true);
128
- expect(writeMarkdown).toHaveBeenCalledOnce();
129
- expect(writeMarkdown).toHaveBeenCalledWith({
130
- kind: "markdown",
131
- name: "Checklist",
132
- path: "notes/checklist.md",
133
- }, "# Checklist\n\n- [x] Confirm release notes.\n");
134
- await unmount(component);
135
- });
136
- it("exits through the public editable-preview contract", async () => {
137
- const target = document.createElement("div");
138
- const writeMarkdown = vi.fn();
139
- const component = mount(EditableMarkdownPreview, {
140
- target,
141
- props: {
142
- file: {
143
- kind: "markdown",
144
- name: "Portable",
145
- path: "notes/portable.md",
146
- },
147
- fileAdapter: { ...fileAdapter, writeMarkdown },
148
- },
149
- });
150
- await settle();
151
- target
152
- .querySelector('[data-editable-markdown-preview] [role="button"]')
153
- ?.click();
154
- await settle();
155
- expect(await component.exit()).toBe(true);
156
- expect(target.querySelector("[data-editable-markdown-editor]")).toBeNull();
157
- await unmount(component);
158
- });
159
- it("renders standalone Markdown embeds", async () => {
160
- const target = document.createElement("div");
161
- const component = mount(MarkdownEmbed, {
162
- target,
163
- props: {
164
- value: "## Embedded Markdown",
165
- },
166
- });
167
- await settle();
168
- expect(target.querySelector("[data-markdown-embed]")).toBeTruthy();
169
- expect(target.querySelector("h2")?.textContent).toContain("Embedded Markdown");
170
- await unmount(component);
171
- });
172
- it("renders adapter-backed file embeds and note links", async () => {
173
- const embedTarget = document.createElement("div");
174
- const linkTarget = document.createElement("div");
175
- const embed = mount(FileEmbed, {
176
- target: embedTarget,
177
- props: {
178
- id: "notes/portable.md#Embedded note",
179
- label: "Portable section",
180
- fileAdapter,
181
- },
182
- });
183
- const link = mount(NoteLink, {
184
- target: linkTarget,
185
- props: {
186
- id: "notes/portable.md",
187
- text: "Portable note",
188
- fileAdapter,
189
- },
190
- });
191
- await settle();
192
- expect(embedTarget.querySelector("[data-embed-fragment='heading']")).toBeTruthy();
193
- expect(embedTarget.textContent).toContain("Embedded note");
194
- expect(linkTarget.querySelector("[data-link-preview-path='notes/portable.md']")).toBeTruthy();
195
- expect(linkTarget.textContent).toContain("Portable note");
196
- await unmount(embed);
197
- await unmount(link);
198
- });
199
- it("does not repeat an image embed caption as its alternative text", async () => {
200
- const target = document.createElement("div");
201
- const imageAdapter = {
202
- resolveLink() {
203
- return {
204
- kind: "image",
205
- name: "Service topology",
206
- path: "assets/service-topology.svg",
207
- };
208
- },
209
- readAssetUrl() {
210
- return "/service-topology.svg";
211
- },
212
- };
213
- const component = mount(FileEmbed, {
214
- target,
215
- props: {
216
- id: "assets/service-topology.svg",
217
- label: "Service topology",
218
- fileAdapter: imageAdapter,
219
- },
220
- });
221
- await settle();
222
- expect(target.querySelector("figcaption")?.textContent).toBe("Service topology");
223
- expect(target.querySelector("img")?.alt).toBe("");
224
- await unmount(component);
225
- });
226
- it("loads internal-link preview content only after interaction", async () => {
227
- const target = document.createElement("div");
228
- target.dataset.miraTheme = "obsidian company-brand";
229
- target.dataset.miraColorMode = "dark";
230
- document.body.append(target);
231
- const readMarkdown = vi.fn(() => "[[notes/portable.md|Nested link]]");
232
- const component = mount(NoteLink, {
233
- target,
234
- props: {
235
- id: "notes/portable.md",
236
- text: "Portable note",
237
- fileAdapter: { ...fileAdapter, readMarkdown },
238
- },
239
- });
240
- await settle();
241
- expect(readMarkdown).not.toHaveBeenCalled();
242
- expect(target.querySelectorAll("[data-link-preview-trigger]")).toHaveLength(1);
243
- expect(target
244
- .querySelector("[data-link-preview-trigger]")
245
- ?.getAttribute("aria-haspopup")).toBe("dialog");
246
- target
247
- .querySelector("[data-link-preview-trigger]")
248
- ?.dispatchEvent(new PointerEvent("pointerenter"));
249
- await settle();
250
- expect(readMarkdown).toHaveBeenCalledOnce();
251
- await new Promise((resolve) => setTimeout(resolve, 750));
252
- await settle();
253
- const preview = document.body.querySelector("[data-mira-link-preview-content][data-link-preview-path='notes/portable.md']");
254
- expect(preview).not.toBeNull();
255
- expect(target.contains(preview)).toBe(false);
256
- expect(preview?.dataset.miraTheme).toBe("obsidian company-brand");
257
- expect(preview?.dataset.miraColorMode).toBe("dark");
258
- expect(preview?.querySelectorAll("[data-link-preview-trigger]")).toHaveLength(1);
259
- await unmount(component);
260
- target.remove();
261
- });
262
- it("keeps a writable internal-link card open while its preview is editing", async () => {
263
- const target = document.createElement("div");
264
- const outside = document.createElement("button");
265
- document.body.append(target);
266
- document.body.append(outside);
267
- const component = mount(NoteLink, {
268
- target,
269
- props: {
270
- id: "notes/portable.md",
271
- text: "Portable note",
272
- fileAdapter: { ...fileAdapter, writeMarkdown: vi.fn() },
273
- },
274
- });
275
- await settle();
276
- const trigger = target.querySelector("[data-link-preview-trigger]");
277
- trigger?.dispatchEvent(new PointerEvent("pointerenter"));
278
- await new Promise((resolve) => setTimeout(resolve, 750));
279
- await settle();
280
- const selector = "[data-mira-link-preview-content][data-link-preview-path='notes/portable.md']";
281
- const preview = document.body.querySelector(selector);
282
- preview?.querySelector("p")?.click();
283
- await settle();
284
- expect(preview?.querySelector("[data-editable-markdown-editor]")).toBeTruthy();
285
- trigger?.dispatchEvent(new PointerEvent("pointerleave"));
286
- await new Promise((resolve) => setTimeout(resolve, 350));
287
- await settle();
288
- expect(document.body.querySelector(selector)).toBe(preview);
289
- expect(preview?.querySelector('[data-editing="true"]')).toBeTruthy();
290
- outside.focus();
291
- await settle();
292
- expect(document.body.querySelector(selector)).toBe(preview);
293
- expect(preview?.querySelector('[data-editing="true"]')).toBeTruthy();
294
- outside.dispatchEvent(new PointerEvent("pointerdown", {
295
- bubbles: true,
296
- composed: true,
297
- pointerType: "mouse",
298
- button: 0,
299
- isPrimary: true,
300
- clientX: 100,
301
- clientY: 100,
302
- }));
303
- await vi.waitFor(() => {
304
- expect(document.body.querySelector(selector)).toBeNull();
305
- });
306
- await unmount(component);
307
- target.remove();
308
- outside.remove();
309
- });
310
- it("falls back to portable Markdown when a custom embed renderer declines", async () => {
311
- const target = document.createElement("div");
312
- const renderEmbed = vi.fn(() => false);
313
- const component = mount(FileEmbed, {
314
- target,
315
- props: {
316
- id: "notes/portable.md",
317
- fileAdapter: { ...fileAdapter, renderEmbed },
318
- },
319
- });
320
- await settle();
321
- expect(renderEmbed).toHaveBeenCalledOnce();
322
- expect(target.querySelector("[data-markdown-embed]")).toBeTruthy();
323
- expect(target.textContent).toContain("Portable content");
324
- await unmount(component);
325
- });
326
- it("runs and cleans up extension postprocessors", async () => {
327
- const cleanup = vi.fn();
328
- const target = document.createElement("div");
329
- const component = mount(MarkdownPreview, {
330
- target,
331
- props: {
332
- value: "Portable diagnostics.",
333
- extensions: [
334
- defineMiraExtension({
335
- name: "diagnostics",
336
- postProcessors: [
337
- (element) => {
338
- if (element.tagName === "P") {
339
- element.dataset.diagnostic = "checked";
340
- }
341
- return cleanup;
342
- },
343
- ],
344
- }),
345
- ],
346
- },
347
- });
348
- await settle();
349
- expect(target.querySelector("p")?.dataset.diagnostic).toBe("checked");
350
- await unmount(component);
351
- expect(cleanup).toHaveBeenCalled();
352
- });
353
- it("renders seeded doodle dividers while retaining bare native rules", async () => {
354
- const target = document.createElement("div");
355
- const component = mount(MarkdownPreview, {
356
- target,
357
- props: {
358
- value: `<!-- mira-divider:v1:4f32a91c -->
359
- ---
360
-
361
- ---`,
362
- extensions: [doodleDividersExtension()],
363
- },
364
- });
365
- await settle();
366
- const rules = target.querySelectorAll("hr");
367
- expect(rules).toHaveLength(2);
368
- expect(rules[0]?.dataset.miraDoodleDivider).toBe("true");
369
- expect(rules[1]?.dataset.miraDoodleDivider).toBeUndefined();
370
- expect(target.querySelectorAll(".mira-doodle-divider")).toHaveLength(1);
371
- expect(target.querySelector(".mira-doodle-divider")?.getAttribute("aria-hidden")).toBe("true");
372
- await unmount(component);
373
- });
374
- it("keeps rendered frontmatter chrome locally collapsible", async () => {
375
- const target = document.createElement("div");
376
- const component = mount(MarkdownPreview, {
377
- target,
378
- props: {
379
- value: "---\ntitle: Portable\n---\n\n# Note",
380
- },
381
- });
382
- await settle();
383
- const collapse = target.querySelector(".md-frontmatter__trigger");
384
- expect(collapse?.getAttribute("aria-label")).toBe("Collapse properties");
385
- expect(target.querySelector(".md-frontmatter__content")).not.toBeNull();
386
- collapse?.click();
387
- await settle();
388
- expect(collapse?.getAttribute("aria-label")).toBe("Expand properties");
389
- expect(collapse?.getAttribute("aria-expanded")).toBe("false");
390
- expect(target.querySelector(".md-frontmatter__content")).toBeNull();
391
- collapse?.click();
392
- await settle();
393
- expect(collapse?.getAttribute("aria-label")).toBe("Collapse properties");
394
- expect(collapse?.getAttribute("aria-expanded")).toBe("true");
395
- expect(target.querySelector(".md-frontmatter__content")).not.toBeNull();
396
- await unmount(component);
397
- });
398
- it("opens the frontmatter property type menu and applies a selected type", async () => {
399
- const target = document.createElement("div");
400
- const controller = new FrontmatterController({
401
- record: { title: "Portable" },
402
- });
403
- const component = mount(FrontmatterEditor, {
404
- target,
405
- props: {
406
- controller,
407
- },
408
- });
409
- await settle();
410
- const trigger = target.querySelector('button[aria-label="Property options for title"]');
411
- expect(trigger).not.toBeNull();
412
- expect(trigger?.getAttribute("aria-expanded")).toBe("false");
413
- trigger?.click();
414
- await settle();
415
- const optionsMenu = document.body.querySelector('[role="menu"][aria-label="Property options for title"]');
416
- const propertyType = Array.from(optionsMenu?.querySelectorAll('[role="menuitem"]') ?? []).find((item) => item.textContent?.trim() === "Property type");
417
- const actionLabels = Array.from(optionsMenu?.querySelectorAll('[role="menuitem"]') ?? []).map((item) => item.textContent?.trim());
418
- expect(trigger?.getAttribute("aria-expanded")).toBe("true");
419
- expect(optionsMenu).not.toBeNull();
420
- expect(target.contains(optionsMenu)).toBe(false);
421
- expect(propertyType).toBeDefined();
422
- expect(actionLabels).toEqual([
423
- "Property type",
424
- "Cut",
425
- "Copy",
426
- "Paste",
427
- "Remove",
428
- ]);
429
- expect(optionsMenu?.textContent).not.toContain("Number");
430
- propertyType?.focus();
431
- propertyType?.dispatchEvent(new KeyboardEvent("keydown", { key: "ArrowRight", bubbles: true }));
432
- await settle();
433
- const typeMenu = document.body.querySelector('[role="menu"][aria-label="Property type for title"]');
434
- const numberType = Array.from(typeMenu?.querySelectorAll('[role="menuitemcheckbox"]') ??
435
- []).find((item) => item.textContent?.trim() === "Number");
436
- const textType = Array.from(typeMenu?.querySelectorAll('[role="menuitemcheckbox"]') ??
437
- []).find((item) => item.textContent?.trim() === "Text");
438
- expect(typeMenu).not.toBeNull();
439
- expect(target.contains(typeMenu)).toBe(false);
440
- expect(numberType).toBeDefined();
441
- expect(numberType?.getAttribute("aria-checked")).toBe("false");
442
- expect(numberType?.firstElementChild?.querySelector("svg")).toBeNull();
443
- expect(numberType?.querySelector(".metadata-property-type-menu__type-icon")).not.toBeNull();
444
- expect(textType?.getAttribute("aria-checked")).toBe("true");
445
- expect(textType?.firstElementChild?.querySelector("svg")).not.toBeNull();
446
- expect(textType?.querySelector(".metadata-property-type-menu__type-icon")).not.toBeNull();
447
- numberType?.click();
448
- await settle();
449
- expect(trigger?.getAttribute("aria-expanded")).toBe("false");
450
- expect(document.body.querySelector('[role="menu"][aria-label="Property options for title"]')).toBeNull();
451
- expect(controller.propertyManager.properties(controller.getRecord())[0]?.kind).toBe("number");
452
- await unmount(component);
453
- });
454
- it("refreshes an edited text property after focus leaves the control", async () => {
455
- const target = document.createElement("div");
456
- document.body.append(target);
457
- const controller = new FrontmatterController({
458
- record: { status: "ready" },
459
- });
460
- const component = mount(FrontmatterEditor, {
461
- target,
462
- props: {
463
- controller,
464
- },
465
- });
466
- await settle();
467
- const status = target.querySelector('[role="combobox"][aria-label="status value"]');
468
- expect(status?.textContent).toBe("ready");
469
- status?.focus();
470
- expect(document.activeElement).toBe(status);
471
- if (status)
472
- status.textContent = "local";
473
- status?.dispatchEvent(new InputEvent("input", { bubbles: true }));
474
- controller.syncRecord({ status: "planned" }, { commit: false });
475
- await settle();
476
- expect(status?.textContent).toBe("local");
477
- status?.blur();
478
- await settle();
479
- controller.syncRecord({ status: "review" }, { commit: false });
480
- await settle();
481
- expect(status?.textContent).toBe("review");
482
- await unmount(component);
483
- target.remove();
484
- });
485
- it("keeps read-only list callouts passive and makes editable markers selectable", async () => {
486
- const readOnlyTarget = document.createElement("div");
487
- const editableTarget = document.createElement("div");
488
- document.body.append(readOnlyTarget, editableTarget);
489
- const readOnly = mount(MarkdownPreview, {
490
- target: readOnlyTarget,
491
- props: {
492
- value: "- & Highlighted",
493
- },
494
- });
495
- const editable = mount(MarkdownPreview, {
496
- target: editableTarget,
497
- props: {
498
- value: "- & Highlighted",
499
- onChange: vi.fn(),
500
- },
501
- });
502
- await settle();
503
- expect(readOnlyTarget.querySelector("[data-list-callout-marker]")).not.toBeNull();
504
- expect(readOnlyTarget.querySelector(".mira-list-callout-trigger")).toBeNull();
505
- const editableTrigger = editableTarget.querySelector(".mira-list-callout-trigger");
506
- expect(editableTrigger?.tagName).toBe("BUTTON");
507
- expect(editableTrigger?.getAttribute("aria-label")).toBe("Change list highlight (&)");
508
- await unmount(readOnly);
509
- await unmount(editable);
510
- readOnlyTarget.remove();
511
- editableTarget.remove();
512
- });
513
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=preview.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"preview.test.d.ts","sourceRoot":"","sources":["../../src/preview/preview.test.ts"],"names":[],"mappings":""}
@@ -1,154 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import remarkGridTables from "@adobe/remark-gridtables";
3
- import rehypeRaw from "rehype-raw";
4
- import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
5
- import remarkEmoji from "remark-emoji";
6
- import remarkGfm from "remark-gfm";
7
- import remarkMath from "remark-math";
8
- import rehypeKatex from "rehype-katex";
9
- import { TYPE_TABLE, mdast2hastGridTablesHandler, } from "@adobe/mdast-util-gridtables";
10
- import { remarkHeadings, remarkWikiLinks } from "./remark";
11
- import { createParser } from "./renderer/utils";
12
- import { findElement } from "./test-utils";
13
- describe("preview exports", () => {
14
- it("exports built-in remark plugins", () => {
15
- expect(typeof remarkWikiLinks).toBe("function");
16
- });
17
- });
18
- describe("patched math renderer", () => {
19
- it("renders inline and display math through the preview pipeline", () => {
20
- const parser = createParser([remarkMath], [rehypeKatex]);
21
- const ast = parser("Inline $x^2$.\n\n$$\nx^2 + y^2 = z^2\n$$");
22
- const rendered = JSON.stringify(ast);
23
- expect(rendered).toContain("katex-mathml");
24
- expect(rendered).toContain("katex-display");
25
- expect(findElement(ast, "math")).toBeDefined();
26
- });
27
- it("does not inherit polluted trust options when rendering authored math", () => {
28
- const descriptor = Object.getOwnPropertyDescriptor(Object.prototype, "trust");
29
- try {
30
- Object.defineProperty(Object.prototype, "trust", {
31
- value: true,
32
- configurable: true,
33
- });
34
- const parser = createParser([remarkMath], [rehypeKatex]);
35
- const ast = parser("$\\href{https://example.com}{untrusted}$");
36
- expect(findElement(ast, "a")).toBeUndefined();
37
- }
38
- finally {
39
- if (descriptor)
40
- Object.defineProperty(Object.prototype, "trust", descriptor);
41
- else
42
- Reflect.deleteProperty(Object.prototype, "trust");
43
- }
44
- });
45
- });
46
- describe("Carta markdown parity", () => {
47
- const dataPng = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
48
- it("renders reference-style base64 embedded images", () => {
49
- const parser = createParser([remarkGfm]);
50
- const ast = parser([
51
- "Here is my embedded image: ![Alt Text][my-image]",
52
- "",
53
- "And the document continues normally here.",
54
- "",
55
- `[my-image]: ${dataPng}`,
56
- ].join("\n"));
57
- const image = findElement(ast, "img");
58
- expect(image?.properties?.src).toBe(dataPng);
59
- expect(image?.properties?.alt).toBe("Alt Text");
60
- expect(JSON.stringify(ast)).toContain("And the document continues normally here.");
61
- });
62
- it("renders inline base64 images", () => {
63
- const parser = createParser([remarkGfm]);
64
- const ast = parser(`![Alt Text](${dataPng})`);
65
- const image = findElement(ast, "img");
66
- expect(image?.properties?.src).toBe(dataPng);
67
- });
68
- it("adds stable heading ids when enabled", () => {
69
- const parser = createParser([
70
- [remarkHeadings, { ids: true, prefix: "doc-" }],
71
- ]);
72
- const ast = parser(["# Title", "", "# Title"].join("\n"));
73
- const headings = ast.children.filter((node) => node.type === "element" && node.tagName === "h1");
74
- expect(headings[0]?.properties?.id).toBe("doc-title");
75
- expect(headings[1]?.properties?.id).toBe("doc-title-1");
76
- });
77
- it("supports opt-in emoji shortcodes", () => {
78
- const parser = createParser([remarkEmoji]);
79
- const ast = parser("Ship it :rocket:");
80
- expect(JSON.stringify(ast)).toContain("🚀");
81
- });
82
- it("sanitizes raw HTML in safe mode while preserving data images", () => {
83
- const parser = createParser([], [
84
- rehypeRaw,
85
- [
86
- rehypeSanitize,
87
- {
88
- ...defaultSchema,
89
- attributes: {
90
- ...defaultSchema.attributes,
91
- img: [...(defaultSchema.attributes?.img ?? []), "src", "alt"],
92
- },
93
- protocols: {
94
- ...defaultSchema.protocols,
95
- src: ["http", "https", "data"],
96
- },
97
- },
98
- ],
99
- ], { allowDangerousHtml: true });
100
- const ast = parser(`<img src="${dataPng}" onerror="alert(1)" alt="ok"><script>alert(1)</script>`);
101
- const image = findElement(ast, "img");
102
- expect(image?.properties?.src).toBe(dataPng);
103
- expect(image?.properties?.onerror).toBeUndefined();
104
- expect(JSON.stringify(ast)).not.toContain("script");
105
- });
106
- });
107
- describe("grid table rendering", () => {
108
- it("renders Adobe grid tables through the preview pipeline", () => {
109
- const parser = createParser([remarkGridTables], [], {
110
- allowDangerousHtml: true,
111
- handlers: {
112
- [TYPE_TABLE]: mdast2hastGridTablesHandler(),
113
- },
114
- });
115
- const ast = parser([
116
- "+---------+----------+",
117
- "| Feature | Behavior |",
118
- "+=========+==========+",
119
- "| Menus | Actions |",
120
- "+---------+----------+",
121
- ].join("\n"));
122
- expect(findElement(ast, "table")).toBeDefined();
123
- expect(JSON.stringify(ast)).toContain("Feature");
124
- });
125
- });
126
- describe("renderer prop normalization", () => {
127
- it("normalizes props added by rehype plugins", () => {
128
- const parser = createParser([], [
129
- () => (tree) => {
130
- const root = tree;
131
- const paragraph = root.children[0];
132
- paragraph.properties = {
133
- className: ["from-plugin"],
134
- ariaDescribedBy: "details",
135
- ariaSelected: true,
136
- colSpan: 2,
137
- dataSourceOffset: 4,
138
- rowSpan: 3,
139
- };
140
- },
141
- ]);
142
- const ast = parser("Hello");
143
- const paragraph = ast.children[0];
144
- expect(paragraph.properties?.class).toBe("from-plugin");
145
- expect(paragraph.properties?.["aria-describedby"]).toBe("details");
146
- expect(paragraph.properties?.["aria-selected"]).toBe(true);
147
- expect(paragraph.properties?.colspan).toBe(2);
148
- expect(paragraph.properties?.["data-source-offset"]).toBe(4);
149
- expect(paragraph.properties?.rowspan).toBe(3);
150
- expect(paragraph.properties?.className).toBeUndefined();
151
- expect(paragraph.properties?.colSpan).toBeUndefined();
152
- expect(paragraph.properties?.rowSpan).toBeUndefined();
153
- });
154
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=callouts.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"callouts.test.d.ts","sourceRoot":"","sources":["../../../src/preview/remark/callouts.test.ts"],"names":[],"mappings":""}