@mark-sorcery/vue 0.2.0 → 0.3.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 (88) hide show
  1. package/README.md +141 -7
  2. package/dist/Blockquote-BeOfUsk-.js +41 -0
  3. package/dist/Blockquote-BeOfUsk-.js.map +1 -0
  4. package/dist/Blockquote-RI8XvPhG.cjs +41 -0
  5. package/dist/Blockquote-RI8XvPhG.cjs.map +1 -0
  6. package/dist/Bold-Bi1du8CJ.js +41 -0
  7. package/dist/Bold-Bi1du8CJ.js.map +1 -0
  8. package/dist/Bold-DWA5fzKp.cjs +41 -0
  9. package/dist/Bold-DWA5fzKp.cjs.map +1 -0
  10. package/dist/Code-DPKXUmPC.js +41 -0
  11. package/dist/Code-DPKXUmPC.js.map +1 -0
  12. package/dist/Code-DmkITyUd.cjs +41 -0
  13. package/dist/Code-DmkITyUd.cjs.map +1 -0
  14. package/dist/CodeBlock-CawFy9YT.cjs +45 -0
  15. package/dist/CodeBlock-CawFy9YT.cjs.map +1 -0
  16. package/dist/CodeBlock-Duwcxp3X.js +45 -0
  17. package/dist/CodeBlock-Duwcxp3X.js.map +1 -0
  18. package/dist/Heading-CPB6VryI.js +51 -0
  19. package/dist/Heading-CPB6VryI.js.map +1 -0
  20. package/dist/Heading-CQmmqddk.cjs +51 -0
  21. package/dist/Heading-CQmmqddk.cjs.map +1 -0
  22. package/dist/Italic-DLGLEgQL.cjs +41 -0
  23. package/dist/Italic-DLGLEgQL.cjs.map +1 -0
  24. package/dist/Italic-DmavDuWx.js +41 -0
  25. package/dist/Italic-DmavDuWx.js.map +1 -0
  26. package/dist/Link-9wbnSrks.cjs +41 -0
  27. package/dist/Link-9wbnSrks.cjs.map +1 -0
  28. package/dist/Link-B2nQX8af.js +41 -0
  29. package/dist/Link-B2nQX8af.js.map +1 -0
  30. package/dist/ListItem-L32ueBOJ.cjs +41 -0
  31. package/dist/ListItem-L32ueBOJ.cjs.map +1 -0
  32. package/dist/ListItem-tCoCmS98.js +41 -0
  33. package/dist/ListItem-tCoCmS98.js.map +1 -0
  34. package/dist/NodeList-CXCRf4Sf.cjs +146 -0
  35. package/dist/NodeList-CXCRf4Sf.cjs.map +1 -0
  36. package/dist/NodeList-DliNdSdR.js +123 -0
  37. package/dist/NodeList-DliNdSdR.js.map +1 -0
  38. package/dist/OrderedList-BiBUuBtQ.js +41 -0
  39. package/dist/OrderedList-BiBUuBtQ.js.map +1 -0
  40. package/dist/OrderedList-Otuk3FD-.cjs +41 -0
  41. package/dist/OrderedList-Otuk3FD-.cjs.map +1 -0
  42. package/dist/Paragraph-Cn0qq6eD.cjs +41 -0
  43. package/dist/Paragraph-Cn0qq6eD.cjs.map +1 -0
  44. package/dist/Paragraph-D8vRiJdV.js +41 -0
  45. package/dist/Paragraph-D8vRiJdV.js.map +1 -0
  46. package/dist/Strikethrough-BhFf4qRs.js +41 -0
  47. package/dist/Strikethrough-BhFf4qRs.js.map +1 -0
  48. package/dist/Strikethrough-D6HU-DLr.cjs +41 -0
  49. package/dist/Strikethrough-D6HU-DLr.cjs.map +1 -0
  50. package/dist/Table-Da8GL8er.cjs +41 -0
  51. package/dist/Table-Da8GL8er.cjs.map +1 -0
  52. package/dist/Table-DxMMIS1J.js +41 -0
  53. package/dist/Table-DxMMIS1J.js.map +1 -0
  54. package/dist/TableBody-D6I9wlwE.cjs +41 -0
  55. package/dist/TableBody-D6I9wlwE.cjs.map +1 -0
  56. package/dist/TableBody-DWmHYRny.js +41 -0
  57. package/dist/TableBody-DWmHYRny.js.map +1 -0
  58. package/dist/TableData-8V3hQ4i0.cjs +41 -0
  59. package/dist/TableData-8V3hQ4i0.cjs.map +1 -0
  60. package/dist/TableData-CXjn9U8M.js +41 -0
  61. package/dist/TableData-CXjn9U8M.js.map +1 -0
  62. package/dist/TableHead-DSWO60r-.cjs +41 -0
  63. package/dist/TableHead-DSWO60r-.cjs.map +1 -0
  64. package/dist/TableHead-RMl2XF2I.js +41 -0
  65. package/dist/TableHead-RMl2XF2I.js.map +1 -0
  66. package/dist/TableHeader-CO5WWCf6.js +41 -0
  67. package/dist/TableHeader-CO5WWCf6.js.map +1 -0
  68. package/dist/TableHeader-D4nI4o6p.cjs +41 -0
  69. package/dist/TableHeader-D4nI4o6p.cjs.map +1 -0
  70. package/dist/TableRow-CFEKUaRS.js +41 -0
  71. package/dist/TableRow-CFEKUaRS.js.map +1 -0
  72. package/dist/TableRow-Cso50UW2.cjs +41 -0
  73. package/dist/TableRow-Cso50UW2.cjs.map +1 -0
  74. package/dist/TaskListInput-BlFjVLdG.cjs +33 -0
  75. package/dist/TaskListInput-BlFjVLdG.cjs.map +1 -0
  76. package/dist/TaskListInput-DiQhjFqy.js +33 -0
  77. package/dist/TaskListInput-DiQhjFqy.js.map +1 -0
  78. package/dist/UnorderedList-BCqaq94d.js +41 -0
  79. package/dist/UnorderedList-BCqaq94d.js.map +1 -0
  80. package/dist/UnorderedList-C_w27MXB.cjs +41 -0
  81. package/dist/UnorderedList-C_w27MXB.cjs.map +1 -0
  82. package/dist/index.cjs +18 -70
  83. package/dist/index.cjs.map +1 -1
  84. package/dist/index.d.cts +115 -36
  85. package/dist/index.d.ts +115 -36
  86. package/dist/index.js +17 -71
  87. package/dist/index.js.map +1 -1
  88. package/package.json +5 -3
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as vue from "vue";
2
- import { Component, VNodeArrayChildren } from "vue";
2
+ import { BaseTransitionProps, Component, ComputedRef } from "vue";
3
3
  import * as _mark_sorcery_markdown_parser0 from "@mark-sorcery/markdown-parser";
4
4
  import { CorePluginOptions, MarkdownProcessor, ParseMemory, ParseOptions, ParserPlugin, createCorePlugin } from "@mark-sorcery/markdown-parser";
5
5
 
@@ -318,27 +318,36 @@ interface Text extends Literal {
318
318
  interface TextData extends Data {}
319
319
  //#endregion
320
320
  //#region src/types.d.ts
321
- type MarkdownOptions = Omit<ParseOptions, 'plugins'>;
322
- /** A resolved component value: a Vue component, a tag string, or null/undefined to fall back to the default element. */
323
- type ComponentResolution = Component | string | null | undefined;
324
321
  /**
325
- * Resolves which Vue component or tag to render for a given HAST element node.
326
- *
327
- * Can be:
328
- * - A **record** mapping tag names to components or tag strings (e.g. `{ h1: MyHeading }`)
329
- * - A **function** `(node: Element) => ComponentResolution` — called for every element;
330
- * return `null` or `undefined` to fall back to the default HTML element.
331
- *
332
- * @example — record form
333
- * const components: Components = { h1: MyHeading, code: MyCode }
322
+ * Configuration forwarded to Vue's `<Transition>` component.
323
+ * All props are optional; when `transition: true` is used on `<Markdown>`,
324
+ * defaults to `{}` which activates Vue's default `v-enter-*` classes.
334
325
  *
335
- * @example — function form
336
- * const components: Components = (node) => {
337
- * if (node.tagName === 'h1') return MyHeading
338
- * if (node.properties?.className?.includes('warning')) return MyWarning
339
- * }
326
+ * @see https://vuejs.org/api/built-in-components.html#transition
340
327
  */
341
- type Components = Partial<Record<string, ComponentResolution>> | ((node: Element) => ComponentResolution);
328
+ interface TransitionConfig {
329
+ name?: string;
330
+ css?: boolean;
331
+ mode?: 'in-out' | 'out-in' | 'default';
332
+ enterFromClass?: string;
333
+ enterActiveClass?: string;
334
+ enterToClass?: string;
335
+ leaveFromClass?: string;
336
+ leaveActiveClass?: string;
337
+ leaveToClass?: string;
338
+ appearFromClass?: string;
339
+ appearActiveClass?: string;
340
+ appearToClass?: string;
341
+ onBeforeEnter?: BaseTransitionProps['onBeforeEnter'];
342
+ onEnter?: BaseTransitionProps['onEnter'];
343
+ onAfterEnter?: BaseTransitionProps['onAfterEnter'];
344
+ onEnterCancelled?: BaseTransitionProps['onEnterCancelled'];
345
+ onBeforeLeave?: BaseTransitionProps['onBeforeLeave'];
346
+ onLeave?: BaseTransitionProps['onLeave'];
347
+ onAfterLeave?: BaseTransitionProps['onAfterLeave'];
348
+ onLeaveCancelled?: BaseTransitionProps['onLeaveCancelled'];
349
+ }
350
+ type MarkdownOptions = Omit<ParseOptions, 'plugins'>;
342
351
  /**
343
352
  * Props automatically injected into every custom Vue component rendered by
344
353
  * `<Markdown>`. Use this to type your custom component's `node` prop.
@@ -361,8 +370,40 @@ interface MarkdownProps {
361
370
  /** Enables parse memory so growing markdown streams preserve confirmed blocks. */
362
371
  stream?: boolean;
363
372
  /** Custom Vue components or tags to use in place of default HTML elements. */
364
- components?: Components;
373
+ components?: Record<string, Component>;
374
+ /**
375
+ * Optional Vue `<Transition>` configuration applied to every rendered element node.
376
+ *
377
+ * - `true` — enables transitions with Vue's default classes (`v-enter-*`).
378
+ * - `TransitionConfig` object — forwarded as props to each `<Transition>` wrapper.
379
+ * - `false` / `undefined` — no transitions (default).
380
+ *
381
+ * @example
382
+ * // Basic fade (add CSS: .fade-enter-active { transition: opacity 0.3s } .fade-enter-from { opacity: 0 })
383
+ * :transition="{ name: 'fade', appear: true }"
384
+ */
385
+ transition?: boolean | TransitionConfig;
386
+ }
387
+ interface MarkdownNodeProps {
388
+ /** The HAST element to render. */
389
+ element: Element;
390
+ /** A unique key for the component instance. */
391
+ componentKey: string;
365
392
  }
393
+ type ItemProps = {
394
+ nodeIdx?: number;
395
+ deep?: number;
396
+ nodeKey?: string;
397
+ parentNode?: Nodes;
398
+ };
399
+ type NodeListProps = ItemProps & {
400
+ nodes: Nodes[];
401
+ components: NonNullable<MarkdownProps['components']>;
402
+ transition: MarkdownProps['transition'];
403
+ };
404
+ type ElementProps = ItemProps & {
405
+ element: Element;
406
+ };
366
407
  //#endregion
367
408
  //#region src/Markdown.d.ts
368
409
  declare const Markdown: vue.DefineComponent<vue.ExtractPropTypes<{
@@ -371,7 +412,7 @@ declare const Markdown: vue.DefineComponent<vue.ExtractPropTypes<{
371
412
  required: boolean;
372
413
  };
373
414
  options: {
374
- type: () => MarkdownOptions;
415
+ type: () => MarkdownProps["options"];
375
416
  default: undefined;
376
417
  };
377
418
  plugins: {
@@ -383,9 +424,13 @@ declare const Markdown: vue.DefineComponent<vue.ExtractPropTypes<{
383
424
  default: boolean;
384
425
  };
385
426
  components: {
386
- type: () => Components;
427
+ type: () => MarkdownProps["components"];
387
428
  default: () => {};
388
429
  };
430
+ transition: {
431
+ type: () => MarkdownProps["transition"];
432
+ default: boolean;
433
+ };
389
434
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
390
435
  [key: string]: any;
391
436
  }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
@@ -394,7 +439,7 @@ declare const Markdown: vue.DefineComponent<vue.ExtractPropTypes<{
394
439
  required: boolean;
395
440
  };
396
441
  options: {
397
- type: () => MarkdownOptions;
442
+ type: () => MarkdownProps["options"];
398
443
  default: undefined;
399
444
  };
400
445
  plugins: {
@@ -406,25 +451,59 @@ declare const Markdown: vue.DefineComponent<vue.ExtractPropTypes<{
406
451
  default: boolean;
407
452
  };
408
453
  components: {
409
- type: () => Components;
454
+ type: () => MarkdownProps["components"];
410
455
  default: () => {};
411
456
  };
457
+ transition: {
458
+ type: () => MarkdownProps["transition"];
459
+ default: boolean;
460
+ };
412
461
  }>> & Readonly<{}>, {
413
- options: MarkdownOptions;
462
+ options: MarkdownOptions | undefined;
414
463
  plugins: _mark_sorcery_markdown_parser0.ParserPlugin[] | undefined;
415
464
  stream: boolean;
416
- components: Components;
465
+ components: Record<string, vue.Component> | undefined;
466
+ transition: boolean | TransitionConfig | undefined;
417
467
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
418
468
  //#endregion
419
- //#region src/hast-to-vnodes.d.ts
420
- /**
421
- * Recursively convert a HAST node (or array of nodes) into Vue VNodeArrayChildren.
422
- *
423
- * @param node - Root HAST node or array of nodes to convert.
424
- * @param components - Custom component map or resolver function.
425
- * @param transition - Optional `<Transition>` config applied to every element node.
426
- */
427
- declare function hastToVNodes(node: Nodes | Nodes[], components: Components): VNodeArrayChildren;
469
+ //#region src/components/NodeList.vue.d.ts
470
+ declare const __VLS_export: vue.DefineComponent<NodeListProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<NodeListProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
471
+ declare const _default: typeof __VLS_export;
472
+ //#endregion
473
+ //#region src/components/index.d.ts
474
+ declare const DEFAULT_COMPONENTS: {
475
+ p: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
476
+ h1: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
477
+ h2: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
478
+ h3: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
479
+ h4: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
480
+ h5: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
481
+ h6: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
482
+ strong: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
483
+ em: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
484
+ del: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
485
+ blockquote: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
486
+ ul: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
487
+ ol: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
488
+ li: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
489
+ code: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
490
+ a: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
491
+ input: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
492
+ pre: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
493
+ table: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
494
+ thead: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
495
+ tbody: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
496
+ tr: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
497
+ th: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
498
+ td: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
499
+ };
500
+ //#endregion
501
+ //#region src/composables/markdown.d.ts
502
+ type MarkdownContext = {
503
+ components: ComputedRef<NonNullable<MarkdownProps['components']>>;
504
+ transition: ComputedRef<MarkdownProps['transition']>;
505
+ };
506
+ declare const useMarkdown: () => MarkdownContext;
428
507
  //#endregion
429
- export { type Components, type CorePluginOptions, Markdown, type MarkdownOptions, type MarkdownProcessor, type MarkdownProps, type NodeProps, type ParseMemory, type ParseOptions, type ParserPlugin, createCorePlugin, hastToVNodes };
508
+ export { type CorePluginOptions, DEFAULT_COMPONENTS, type ElementProps, type ItemProps, Markdown, type MarkdownNodeProps, type MarkdownOptions, type MarkdownProcessor, type MarkdownProps, _default as NodeList, type NodeListProps, type NodeProps, type ParseMemory, type ParseOptions, type ParserPlugin, createCorePlugin, useMarkdown };
430
509
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as vue from "vue";
2
- import { Component, VNodeArrayChildren } from "vue";
2
+ import { BaseTransitionProps, Component, ComputedRef } from "vue";
3
3
  import * as _mark_sorcery_markdown_parser0 from "@mark-sorcery/markdown-parser";
4
4
  import { CorePluginOptions, MarkdownProcessor, ParseMemory, ParseOptions, ParserPlugin, createCorePlugin } from "@mark-sorcery/markdown-parser";
5
5
 
@@ -318,27 +318,36 @@ interface Text extends Literal {
318
318
  interface TextData extends Data {}
319
319
  //#endregion
320
320
  //#region src/types.d.ts
321
- type MarkdownOptions = Omit<ParseOptions, 'plugins'>;
322
- /** A resolved component value: a Vue component, a tag string, or null/undefined to fall back to the default element. */
323
- type ComponentResolution = Component | string | null | undefined;
324
321
  /**
325
- * Resolves which Vue component or tag to render for a given HAST element node.
326
- *
327
- * Can be:
328
- * - A **record** mapping tag names to components or tag strings (e.g. `{ h1: MyHeading }`)
329
- * - A **function** `(node: Element) => ComponentResolution` — called for every element;
330
- * return `null` or `undefined` to fall back to the default HTML element.
331
- *
332
- * @example — record form
333
- * const components: Components = { h1: MyHeading, code: MyCode }
322
+ * Configuration forwarded to Vue's `<Transition>` component.
323
+ * All props are optional; when `transition: true` is used on `<Markdown>`,
324
+ * defaults to `{}` which activates Vue's default `v-enter-*` classes.
334
325
  *
335
- * @example — function form
336
- * const components: Components = (node) => {
337
- * if (node.tagName === 'h1') return MyHeading
338
- * if (node.properties?.className?.includes('warning')) return MyWarning
339
- * }
326
+ * @see https://vuejs.org/api/built-in-components.html#transition
340
327
  */
341
- type Components = Partial<Record<string, ComponentResolution>> | ((node: Element) => ComponentResolution);
328
+ interface TransitionConfig {
329
+ name?: string;
330
+ css?: boolean;
331
+ mode?: 'in-out' | 'out-in' | 'default';
332
+ enterFromClass?: string;
333
+ enterActiveClass?: string;
334
+ enterToClass?: string;
335
+ leaveFromClass?: string;
336
+ leaveActiveClass?: string;
337
+ leaveToClass?: string;
338
+ appearFromClass?: string;
339
+ appearActiveClass?: string;
340
+ appearToClass?: string;
341
+ onBeforeEnter?: BaseTransitionProps['onBeforeEnter'];
342
+ onEnter?: BaseTransitionProps['onEnter'];
343
+ onAfterEnter?: BaseTransitionProps['onAfterEnter'];
344
+ onEnterCancelled?: BaseTransitionProps['onEnterCancelled'];
345
+ onBeforeLeave?: BaseTransitionProps['onBeforeLeave'];
346
+ onLeave?: BaseTransitionProps['onLeave'];
347
+ onAfterLeave?: BaseTransitionProps['onAfterLeave'];
348
+ onLeaveCancelled?: BaseTransitionProps['onLeaveCancelled'];
349
+ }
350
+ type MarkdownOptions = Omit<ParseOptions, 'plugins'>;
342
351
  /**
343
352
  * Props automatically injected into every custom Vue component rendered by
344
353
  * `<Markdown>`. Use this to type your custom component's `node` prop.
@@ -361,8 +370,40 @@ interface MarkdownProps {
361
370
  /** Enables parse memory so growing markdown streams preserve confirmed blocks. */
362
371
  stream?: boolean;
363
372
  /** Custom Vue components or tags to use in place of default HTML elements. */
364
- components?: Components;
373
+ components?: Record<string, Component>;
374
+ /**
375
+ * Optional Vue `<Transition>` configuration applied to every rendered element node.
376
+ *
377
+ * - `true` — enables transitions with Vue's default classes (`v-enter-*`).
378
+ * - `TransitionConfig` object — forwarded as props to each `<Transition>` wrapper.
379
+ * - `false` / `undefined` — no transitions (default).
380
+ *
381
+ * @example
382
+ * // Basic fade (add CSS: .fade-enter-active { transition: opacity 0.3s } .fade-enter-from { opacity: 0 })
383
+ * :transition="{ name: 'fade', appear: true }"
384
+ */
385
+ transition?: boolean | TransitionConfig;
386
+ }
387
+ interface MarkdownNodeProps {
388
+ /** The HAST element to render. */
389
+ element: Element;
390
+ /** A unique key for the component instance. */
391
+ componentKey: string;
365
392
  }
393
+ type ItemProps = {
394
+ nodeIdx?: number;
395
+ deep?: number;
396
+ nodeKey?: string;
397
+ parentNode?: Nodes;
398
+ };
399
+ type NodeListProps = ItemProps & {
400
+ nodes: Nodes[];
401
+ components: NonNullable<MarkdownProps['components']>;
402
+ transition: MarkdownProps['transition'];
403
+ };
404
+ type ElementProps = ItemProps & {
405
+ element: Element;
406
+ };
366
407
  //#endregion
367
408
  //#region src/Markdown.d.ts
368
409
  declare const Markdown: vue.DefineComponent<vue.ExtractPropTypes<{
@@ -371,7 +412,7 @@ declare const Markdown: vue.DefineComponent<vue.ExtractPropTypes<{
371
412
  required: boolean;
372
413
  };
373
414
  options: {
374
- type: () => MarkdownOptions;
415
+ type: () => MarkdownProps["options"];
375
416
  default: undefined;
376
417
  };
377
418
  plugins: {
@@ -383,9 +424,13 @@ declare const Markdown: vue.DefineComponent<vue.ExtractPropTypes<{
383
424
  default: boolean;
384
425
  };
385
426
  components: {
386
- type: () => Components;
427
+ type: () => MarkdownProps["components"];
387
428
  default: () => {};
388
429
  };
430
+ transition: {
431
+ type: () => MarkdownProps["transition"];
432
+ default: boolean;
433
+ };
389
434
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
390
435
  [key: string]: any;
391
436
  }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
@@ -394,7 +439,7 @@ declare const Markdown: vue.DefineComponent<vue.ExtractPropTypes<{
394
439
  required: boolean;
395
440
  };
396
441
  options: {
397
- type: () => MarkdownOptions;
442
+ type: () => MarkdownProps["options"];
398
443
  default: undefined;
399
444
  };
400
445
  plugins: {
@@ -406,25 +451,59 @@ declare const Markdown: vue.DefineComponent<vue.ExtractPropTypes<{
406
451
  default: boolean;
407
452
  };
408
453
  components: {
409
- type: () => Components;
454
+ type: () => MarkdownProps["components"];
410
455
  default: () => {};
411
456
  };
457
+ transition: {
458
+ type: () => MarkdownProps["transition"];
459
+ default: boolean;
460
+ };
412
461
  }>> & Readonly<{}>, {
413
- options: MarkdownOptions;
462
+ options: MarkdownOptions | undefined;
414
463
  plugins: _mark_sorcery_markdown_parser0.ParserPlugin[] | undefined;
415
464
  stream: boolean;
416
- components: Components;
465
+ components: Record<string, vue.Component> | undefined;
466
+ transition: boolean | TransitionConfig | undefined;
417
467
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
418
468
  //#endregion
419
- //#region src/hast-to-vnodes.d.ts
420
- /**
421
- * Recursively convert a HAST node (or array of nodes) into Vue VNodeArrayChildren.
422
- *
423
- * @param node - Root HAST node or array of nodes to convert.
424
- * @param components - Custom component map or resolver function.
425
- * @param transition - Optional `<Transition>` config applied to every element node.
426
- */
427
- declare function hastToVNodes(node: Nodes | Nodes[], components: Components): VNodeArrayChildren;
469
+ //#region src/components/NodeList.vue.d.ts
470
+ declare const __VLS_export: vue.DefineComponent<NodeListProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<NodeListProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
471
+ declare const _default: typeof __VLS_export;
472
+ //#endregion
473
+ //#region src/components/index.d.ts
474
+ declare const DEFAULT_COMPONENTS: {
475
+ p: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
476
+ h1: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
477
+ h2: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
478
+ h3: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
479
+ h4: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
480
+ h5: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
481
+ h6: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
482
+ strong: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
483
+ em: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
484
+ del: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
485
+ blockquote: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
486
+ ul: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
487
+ ol: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
488
+ li: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
489
+ code: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
490
+ a: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
491
+ input: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
492
+ pre: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
493
+ table: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
494
+ thead: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
495
+ tbody: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
496
+ tr: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
497
+ th: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
498
+ td: vue.DefineComponent<ElementProps, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<ElementProps> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
499
+ };
500
+ //#endregion
501
+ //#region src/composables/markdown.d.ts
502
+ type MarkdownContext = {
503
+ components: ComputedRef<NonNullable<MarkdownProps['components']>>;
504
+ transition: ComputedRef<MarkdownProps['transition']>;
505
+ };
506
+ declare const useMarkdown: () => MarkdownContext;
428
507
  //#endregion
429
- export { type Components, type CorePluginOptions, Markdown, type MarkdownOptions, type MarkdownProcessor, type MarkdownProps, type NodeProps, type ParseMemory, type ParseOptions, type ParserPlugin, createCorePlugin, hastToVNodes };
508
+ export { type CorePluginOptions, DEFAULT_COMPONENTS, type ElementProps, type ItemProps, Markdown, type MarkdownNodeProps, type MarkdownOptions, type MarkdownProcessor, type MarkdownProps, _default as NodeList, type NodeListProps, type NodeProps, type ParseMemory, type ParseOptions, type ParserPlugin, createCorePlugin, useMarkdown };
430
509
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,71 +1,7 @@
1
- import { Fragment, computed, createCommentVNode, defineComponent, h, markRaw, shallowRef, watchEffect } from "vue";
1
+ import { i as DEFAULT_COMPONENTS, n as useMarkdown, r as useProvideMarkdown, t as _sfc_main } from "./NodeList-DliNdSdR.js";
2
+ import { computed, defineComponent, h, shallowRef, watchEffect } from "vue";
2
3
  import { createCorePlugin, createMemory, createProcessor, parse } from "@mark-sorcery/markdown-parser";
3
4
 
4
- //#region src/hast-to-vnodes.ts
5
- function createNodeKey(node, path) {
6
- const start = node.position?.start?.offset;
7
- const end = node.position?.end?.offset;
8
- if (typeof start === "number" && typeof end === "number") return `${node.tagName}:${start}-${end}`;
9
- if (typeof start === "number") return `${node.tagName}:${start}`;
10
- return path;
11
- }
12
- /**
13
- * Convert HAST node properties to Vue-compatible props.
14
- * - `className` array → `class` string
15
- * - `htmlFor` → `for`
16
- * - All other properties pass through as-is
17
- */
18
- function convertProps(properties) {
19
- const props = {};
20
- for (const [key, value] of Object.entries(properties)) if (key === "className" && Array.isArray(value)) props["class"] = value.join(" ");
21
- else if (key === "htmlFor") props["for"] = value;
22
- else props[key] = value;
23
- return props;
24
- }
25
- /** Resolve the tag/component for an element node from the Components option. */
26
- function resolveTag(node, components) {
27
- return (typeof components === "function" ? components(node) : components[node.tagName]) ?? node.tagName;
28
- }
29
- /**
30
- * Internal recursive converter. `path` is a dot-separated string identifying
31
- * the node's position in the tree (e.g. `"0"`, `"0.1"`, `"0.1.2"`).
32
- */
33
- function toVNodes(node, components, path) {
34
- if (Array.isArray(node)) return node.flatMap((n, i) => toVNodes(n, components, `${path}.${i}`));
35
- switch (node.type) {
36
- case "root": return node.children.flatMap((child, i) => toVNodes(child, components, String(i)));
37
- case "element": {
38
- const { properties = {}, children } = node;
39
- const tag = resolveTag(node, components);
40
- const nodeKey = createNodeKey(node, path);
41
- const props = convertProps(properties);
42
- const childVNodes = children.flatMap((child, i) => toVNodes(child, components, `${path}.${i}`));
43
- return [typeof tag === "string" ? h(tag, {
44
- ...props,
45
- key: nodeKey
46
- }, childVNodes) : h(tag, {
47
- ...props,
48
- key: nodeKey,
49
- node
50
- }, { default: () => childVNodes })];
51
- }
52
- case "text": return [node.value];
53
- case "comment": return [createCommentVNode(node.value)];
54
- default: return [];
55
- }
56
- }
57
- /**
58
- * Recursively convert a HAST node (or array of nodes) into Vue VNodeArrayChildren.
59
- *
60
- * @param node - Root HAST node or array of nodes to convert.
61
- * @param components - Custom component map or resolver function.
62
- * @param transition - Optional `<Transition>` config applied to every element node.
63
- */
64
- function hastToVNodes(node, components) {
65
- return toVNodes(node, components, "");
66
- }
67
-
68
- //#endregion
69
5
  //#region src/Markdown.ts
70
6
  const Markdown = defineComponent({
71
7
  name: "Markdown",
@@ -87,8 +23,12 @@ const Markdown = defineComponent({
87
23
  default: false
88
24
  },
89
25
  components: {
90
- type: [Object, Function],
26
+ type: Object,
91
27
  default: () => ({})
28
+ },
29
+ transition: {
30
+ type: [Boolean, Object],
31
+ default: false
92
32
  }
93
33
  },
94
34
  setup(props) {
@@ -121,14 +61,20 @@ const Markdown = defineComponent({
121
61
  }
122
62
  hast.value = parse(currentProcessor, markdown);
123
63
  });
64
+ const { components: providedComponents, transition: providedTransition } = useProvideMarkdown(computed(() => props.components), computed(() => props.transition));
124
65
  return () => {
125
- const raw = props.components ?? {};
126
- const components = typeof raw === "function" ? raw : Object.fromEntries(Object.entries(raw).map(([k, v]) => [k, typeof v === "string" || v == null ? v : markRaw(v)]));
127
- return h(Fragment, hastToVNodes(hast.value, components));
66
+ return h(_sfc_main, {
67
+ nodes: hast.value.children,
68
+ nodeKey: "root",
69
+ deep: 0,
70
+ parentNode: hast.value,
71
+ components: providedComponents.value,
72
+ transition: providedTransition.value
73
+ });
128
74
  };
129
75
  }
130
76
  });
131
77
 
132
78
  //#endregion
133
- export { Markdown, createCorePlugin, hastToVNodes };
79
+ export { DEFAULT_COMPONENTS, Markdown, _sfc_main as NodeList, createCorePlugin, useMarkdown };
134
80
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/hast-to-vnodes.ts","../src/Markdown.ts"],"sourcesContent":["import { h, createCommentVNode } from 'vue';\nimport type { Element, Nodes } from 'hast';\nimport type { VNodeArrayChildren } from 'vue';\nimport type { ComponentResolution, Components } from './types.ts';\n\nfunction createNodeKey(node: Element, path: string): string {\n const start = node.position?.start?.offset;\n const end = node.position?.end?.offset;\n\n if (typeof start === 'number' && typeof end === 'number') {\n return `${node.tagName}:${start}-${end}`;\n }\n\n if (typeof start === 'number') {\n return `${node.tagName}:${start}`;\n }\n\n return path;\n}\n\n/**\n * Convert HAST node properties to Vue-compatible props.\n * - `className` array → `class` string\n * - `htmlFor` → `for`\n * - All other properties pass through as-is\n */\nfunction convertProps(properties: Record<string, unknown>): Record<string, unknown> {\n const props: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(properties)) {\n if (key === 'className' && Array.isArray(value)) {\n props['class'] = value.join(' ');\n } else if (key === 'htmlFor') {\n props['for'] = value;\n } else {\n props[key] = value;\n }\n }\n\n return props;\n}\n\n/** Resolve the tag/component for an element node from the Components option. */\nfunction resolveTag(node: Element, components: Components): NonNullable<ComponentResolution> {\n const resolved = typeof components === 'function'\n ? components(node)\n : components[node.tagName];\n return resolved ?? node.tagName;\n}\n\n/**\n * Internal recursive converter. `path` is a dot-separated string identifying\n * the node's position in the tree (e.g. `\"0\"`, `\"0.1\"`, `\"0.1.2\"`).\n */\nfunction toVNodes(\n node: Nodes | Nodes[],\n components: Components,\n path: string,\n): VNodeArrayChildren {\n if (Array.isArray(node)) {\n return node.flatMap((n, i) => toVNodes(n, components, `${path}.${i}`));\n }\n\n switch (node.type) {\n case 'root':\n return node.children.flatMap((child, i) =>\n toVNodes(child, components, String(i)),\n );\n\n case 'element': {\n const { properties = {}, children } = node;\n const tag = resolveTag(node, components);\n const nodeKey = createNodeKey(node, path);\n const props = convertProps(properties as Record<string, unknown>);\n const childVNodes: VNodeArrayChildren = children.flatMap((child, i) =>\n toVNodes(child, components, `${path}.${i}`),\n );\n\n // Build the element VNode\n // Custom Vue components also receive the raw HAST `node` prop so they\n // can access the original element (e.g. to extract text content for\n // syntax highlighting or diagram rendering).\n const el = typeof tag === 'string'\n ? h(tag, { ...props, key: nodeKey }, childVNodes)\n : h(tag, { ...props, key: nodeKey, node }, { default: () => childVNodes });\n\n return [el];\n }\n\n case 'text':\n return [node.value];\n\n case 'comment':\n return [createCommentVNode(node.value)];\n\n default:\n return [];\n }\n}\n\n/**\n * Recursively convert a HAST node (or array of nodes) into Vue VNodeArrayChildren.\n *\n * @param node - Root HAST node or array of nodes to convert.\n * @param components - Custom component map or resolver function.\n * @param transition - Optional `<Transition>` config applied to every element node.\n */\nexport function hastToVNodes(\n node: Nodes | Nodes[],\n components: Components,\n): VNodeArrayChildren {\n return toVNodes(node, components, '');\n}\n","import { computed, defineComponent, Fragment, h, markRaw, shallowRef, watchEffect } from 'vue';\nimport { createMemory, createProcessor, parse } from '@mark-sorcery/markdown-parser';\nimport { hastToVNodes } from './hast-to-vnodes.ts';\nimport type {\n Components,\n MarkdownProcessor,\n MarkdownOptions,\n MarkdownProps,\n ParseMemory,\n} from './types.ts';\n\nexport const Markdown = defineComponent({\n name: 'Markdown',\n\n props: {\n markdown: {\n type: String,\n required: true,\n },\n options: {\n type: Object as () => MarkdownOptions,\n default: undefined,\n },\n plugins: {\n type: Array as () => MarkdownProps['plugins'],\n default: undefined,\n },\n stream: {\n type: Boolean,\n default: false,\n },\n components: {\n type: [Object, Function] as unknown as () => Components,\n default: () => ({}),\n },\n } satisfies {\n [K in keyof MarkdownProps]-?: unknown;\n },\n\n setup(props) {\n const getMarkdown = () => props.markdown ?? '';\n\n const processor = computed<MarkdownProcessor>(() => {\n const options = props.options;\n const propPlugins = props.plugins ?? [];\n\n return createProcessor({\n ...options,\n plugins: propPlugins,\n });\n });\n\n const hast = shallowRef(parse(processor.value, getMarkdown()));\n let streamMemory: ParseMemory | undefined;\n let activeProcessor: MarkdownProcessor | undefined;\n\n watchEffect(() => {\n const currentProcessor = processor.value;\n const markdown = getMarkdown();\n\n if (activeProcessor && activeProcessor !== currentProcessor) {\n streamMemory = props.stream ? createMemory() : undefined;\n }\n\n activeProcessor = currentProcessor;\n\n if (props.stream) {\n streamMemory ??= createMemory();\n hast.value = parse(currentProcessor, markdown, streamMemory);\n return;\n }\n\n if (streamMemory) {\n streamMemory.flush = true;\n streamMemory = undefined;\n return;\n }\n\n hast.value = parse(currentProcessor, markdown);\n });\n\n return () => {\n const raw = props.components ?? {};\n // Function resolvers pass through; record values are wrapped in markRaw\n // so Vue doesn't make component objects reactive (perf warning prevention)\n const components: Components = typeof raw === 'function'\n ? raw\n : Object.fromEntries(\n Object.entries(raw).map(([k, v]) =>\n [k, typeof v === 'string' || v == null ? v : markRaw(v)],\n ),\n );\n const vnodes = hastToVNodes(hast.value, components);\n return h(Fragment, vnodes);\n };\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["NodeList"],"sources":["../src/Markdown.ts"],"sourcesContent":["import { computed, defineComponent, h, shallowRef, watchEffect } from 'vue';\nimport { createMemory, createProcessor, parse } from '@mark-sorcery/markdown-parser';\nimport type {\n MarkdownProcessor,\n MarkdownProps,\n ParseMemory,\n} from './types.ts';\nimport NodeList from './components/NodeList.vue';\nimport { useProvideMarkdown } from './composables/markdown.ts';\n\nexport const Markdown = defineComponent({\n name: 'Markdown',\n\n props: {\n markdown: {\n type: String,\n required: true,\n },\n options: {\n type: Object as () => MarkdownProps['options'],\n default: undefined,\n },\n plugins: {\n type: Array as () => MarkdownProps['plugins'],\n default: undefined,\n },\n stream: {\n type: Boolean,\n default: false,\n },\n components: {\n type: Object as unknown as () => MarkdownProps['components'],\n default: () => ({}),\n },\n transition: {\n type: [Boolean, Object] as unknown as () => MarkdownProps['transition'],\n default: false,\n },\n } satisfies {\n [K in keyof MarkdownProps]-?: unknown;\n },\n\n setup(props) {\n const getMarkdown = () => props.markdown ?? '';\n\n const processor = computed<MarkdownProcessor>(() => {\n const options = props.options;\n const propPlugins = props.plugins ?? [];\n\n return createProcessor({\n ...options,\n plugins: propPlugins,\n });\n });\n\n const hast = shallowRef(parse(processor.value, getMarkdown()));\n let streamMemory: ParseMemory | undefined;\n let activeProcessor: MarkdownProcessor | undefined;\n\n watchEffect(() => {\n const currentProcessor = processor.value;\n const markdown = getMarkdown();\n\n if (activeProcessor && activeProcessor !== currentProcessor) {\n streamMemory = props.stream ? createMemory() : undefined;\n }\n\n activeProcessor = currentProcessor;\n\n if (props.stream) {\n streamMemory ??= createMemory();\n hast.value = parse(currentProcessor, markdown, streamMemory);\n return;\n }\n\n if (streamMemory) {\n streamMemory.flush = true;\n streamMemory = undefined;\n return;\n }\n\n hast.value = parse(currentProcessor, markdown);\n });\n\n const { components: providedComponents, transition: providedTransition } = useProvideMarkdown(computed(() => props.components), computed(() => props.transition));\n\n return () => {\n return h(NodeList, {\n nodes: hast.value.children,\n nodeKey: 'root',\n deep: 0,\n parentNode: hast.value,\n components: providedComponents.value,\n transition: providedTransition.value,\n });\n };\n },\n});\n"],"mappings":";;;;;AAUA,MAAa,WAAW,gBAAgB;CACtC,MAAM;CAEN,OAAO;EACL,UAAU;GACR,MAAM;GACN,UAAU;GACX;EACD,SAAS;GACP,MAAM;GACN,SAAS;GACV;EACD,SAAS;GACP,MAAM;GACN,SAAS;GACV;EACD,QAAQ;GACN,MAAM;GACN,SAAS;GACV;EACD,YAAY;GACV,MAAM;GACN,gBAAgB,EAAE;GACnB;EACD,YAAY;GACV,MAAM,CAAC,SAAS,OAAO;GACvB,SAAS;GACV;EACF;CAID,MAAM,OAAO;EACX,MAAM,oBAAoB,MAAM,YAAY;EAE5C,MAAM,YAAY,eAAkC;GAClD,MAAM,UAAU,MAAM;GACtB,MAAM,cAAc,MAAM,WAAW,EAAE;AAEvC,UAAO,gBAAgB;IACrB,GAAG;IACH,SAAS;IACV,CAAC;IACF;EAEF,MAAM,OAAO,WAAW,MAAM,UAAU,OAAO,aAAa,CAAC,CAAC;EAC9D,IAAI;EACJ,IAAI;AAEJ,oBAAkB;GAChB,MAAM,mBAAmB,UAAU;GACnC,MAAM,WAAW,aAAa;AAE9B,OAAI,mBAAmB,oBAAoB,iBACzC,gBAAe,MAAM,SAAS,cAAc,GAAG;AAGjD,qBAAkB;AAElB,OAAI,MAAM,QAAQ;AAChB,qBAAiB,cAAc;AAC/B,SAAK,QAAQ,MAAM,kBAAkB,UAAU,aAAa;AAC5D;;AAGF,OAAI,cAAc;AAChB,iBAAa,QAAQ;AACrB,mBAAe;AACf;;AAGF,QAAK,QAAQ,MAAM,kBAAkB,SAAS;IAC9C;EAEF,MAAM,EAAE,YAAY,oBAAoB,YAAY,uBAAuB,mBAAmB,eAAe,MAAM,WAAW,EAAE,eAAe,MAAM,WAAW,CAAC;AAEjK,eAAa;AACX,UAAO,EAAEA,WAAU;IACjB,OAAO,KAAK,MAAM;IAClB,SAAS;IACT,MAAM;IACN,YAAY,KAAK;IACjB,YAAY,mBAAmB;IAC/B,YAAY,mBAAmB;IAChC,CAAC;;;CAGP,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mark-sorcery/vue",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Vue renderer for Mark Sorcery markdown.",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -27,14 +27,16 @@
27
27
  "test": "vitest run"
28
28
  },
29
29
  "dependencies": {
30
- "@mark-sorcery/markdown-parser": "^0.2.0"
30
+ "@mark-sorcery/markdown-parser": "^0.3.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/hast": "^3.0.4",
34
34
  "@vue/test-utils": "^2.4.6",
35
35
  "happy-dom": "^17.4.4",
36
36
  "tsdown": "^0.21.0",
37
- "vue": "^3.5.25"
37
+ "unplugin-vue": "^7.1.1",
38
+ "vue": "^3.5.25",
39
+ "vue-tsc": "^3.2.5"
38
40
  },
39
41
  "peerDependencies": {
40
42
  "typescript": "^5",