comark 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
1
  import type { State } from 'comark/render';
2
2
  import type { ComarkElement } from 'comark';
3
- export declare function hr(_: ComarkElement, state: State): string;
3
+ export declare function hr(_: ComarkElement, state: State, parent?: ComarkElement): string;
@@ -1,3 +1,6 @@
1
- export function hr(_, state) {
1
+ export function hr(_, state, parent) {
2
+ if (parent?.[0] === 'p') {
3
+ return ':hr';
4
+ }
2
5
  return '---' + state.context.blockSeparator;
3
6
  }
@@ -37,7 +37,7 @@ export async function html(node, state, parent) {
37
37
  for (let i = 0; i < children.length; i++) {
38
38
  const childContent = childrenContent[i];
39
39
  const child = children[i];
40
- const isBlock = blockTags.has(String(child?.[0])) || (!inlineTags.has(String(child?.[0])) && !hasTextSibling);
40
+ const isBlock = typeof child !== 'string' && (blockTags.has(String(child?.[0])) || (!inlineTags.has(String(child?.[0])) && !hasTextSibling));
41
41
  if (i > 0 && !isPrevBlock && isBlock) {
42
42
  content += state.context.blockSeparator;
43
43
  }
@@ -28,7 +28,8 @@ export async function mdc(node, state, parent) {
28
28
  content = content.trimEnd();
29
29
  const attrs = attributeEntries.length > 0 ? comarkAttributes(attributes) : '';
30
30
  if (tag === 'span') {
31
- return `[${content}]${attrs}`;
31
+ return `[${content}]${attrs}`
32
+ + (inline ? '' : state.context.blockSeparator);
32
33
  }
33
34
  const fence = ':'.repeat((state.nodeDepthInTree || 0) + 2);
34
35
  let result = `:${tag}${content && `[${content}]`}${attrs}` + (!parent ? state.context.blockSeparator : '');
@@ -1,4 +1,4 @@
1
- import type { LanguageRegistration, ShikiTransformer, ShikiInternal, ThemeRegistration } from 'shiki';
1
+ import type { LanguageRegistration, ShikiTransformer, ShikiPrimitive, ThemeRegistration } from 'shiki';
2
2
  import type { ComarkNode, ComarkTree } from 'comark';
3
3
  export interface HighlightOptions {
4
4
  /**
@@ -45,7 +45,7 @@ export interface CodeBlockAttributes {
45
45
  * Get or create the Shiki highlighter instance
46
46
  * Uses a singleton pattern to avoid creating multiple highlighters
47
47
  */
48
- export declare function getHighlighter(options?: HighlightOptions): Promise<ShikiInternal>;
48
+ export declare function getHighlighter(options?: HighlightOptions): Promise<ShikiPrimitive>;
49
49
  /**
50
50
  * Highlight code using Shiki with codeToTokens
51
51
  * Returns comark nodes built from hast
@@ -1,5 +1,5 @@
1
1
  import { defineComarkPlugin } from "../utils/helpers.js";
2
- import { createShikiInternal } from 'shiki';
2
+ import { createShikiPrimitive } from 'shiki';
3
3
  import { createJavaScriptRegexEngine } from 'shiki/engine/javascript';
4
4
  import { codeToHast } from 'shiki/core';
5
5
  let highlighter = null;
@@ -24,7 +24,7 @@ export async function getHighlighter(options = {}) {
24
24
  try {
25
25
  highlighterPromise = (async () => {
26
26
  const { themes, languages } = await registerDefaults(options);
27
- const hl = await createShikiInternal({
27
+ const hl = await createShikiPrimitive({
28
28
  themes: themes,
29
29
  langs: languages,
30
30
  langAlias: {
@@ -0,0 +1,53 @@
1
+ interface JsonRenderConfig {
2
+ }
3
+ /**
4
+ * Plugin for rendering [JSON Render](https://json-render.dev/) specs as UI components.
5
+ *
6
+ * Transforms `json-render` fenced code blocks into Comark AST nodes at parse time.
7
+ * Supports both full specs (with `root` and `elements`) and single-element shorthand.
8
+ *
9
+ * @param config - Plugin configuration options
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { parse } from 'comark'
14
+ * import jsonRender from 'comark/plugins/json-render'
15
+ *
16
+ * const result = await parse(`
17
+ * \`\`\`json-render
18
+ * {
19
+ * "root": "card",
20
+ * "elements": {
21
+ * "card": {
22
+ * "type": "Card",
23
+ * "props": { "title": "Hello" },
24
+ * "children": ["text"]
25
+ * },
26
+ * "text": {
27
+ * "type": "Text",
28
+ * "props": { "content": "World" }
29
+ * }
30
+ * }
31
+ * }
32
+ * \`\`\`
33
+ * `, {
34
+ * plugins: [jsonRender()]
35
+ * })
36
+ * ```
37
+ *
38
+ * @example
39
+ * ```vue
40
+ * <script setup>
41
+ * import { Comark } from '@comark/vue'
42
+ * import jsonRender from '@comark/vue/plugins/json-render'
43
+ * </script>
44
+ *
45
+ * <template>
46
+ * <Suspense>
47
+ * <Comark :plugins="[jsonRender()]">{{ content }}</Comark>
48
+ * </Suspense>
49
+ * </template>
50
+ * ```
51
+ */
52
+ declare const _default: import("..").ComarkPluginFactory<JsonRenderConfig>;
53
+ export default _default;
@@ -0,0 +1,99 @@
1
+ import { defineComarkPlugin } from '../parse';
2
+ import { textContent, visit } from '../utils';
3
+ import { parseYaml } from '../internal/yaml';
4
+ function jsonRenderToAst(jrt) {
5
+ if (!jrt.root) {
6
+ jrt = {
7
+ root: 'template',
8
+ elements: { template: jrt },
9
+ };
10
+ }
11
+ const tree = jrt;
12
+ const root = tree.elements[tree.root];
13
+ return jsonRenderElementToAst(root, tree.elements);
14
+ }
15
+ function jsonRenderElementToAst(element, elements) {
16
+ if (element.type === 'Text') {
17
+ return String(element.props.content);
18
+ }
19
+ const children = element.children?.map(childName => elements[childName])
20
+ .filter(Boolean) || [];
21
+ return [
22
+ element.type,
23
+ element.props,
24
+ ...children.map(child => jsonRenderElementToAst(child, elements)),
25
+ ];
26
+ }
27
+ /**
28
+ * Plugin for rendering [JSON Render](https://json-render.dev/) specs as UI components.
29
+ *
30
+ * Transforms `json-render` fenced code blocks into Comark AST nodes at parse time.
31
+ * Supports both full specs (with `root` and `elements`) and single-element shorthand.
32
+ *
33
+ * @param config - Plugin configuration options
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * import { parse } from 'comark'
38
+ * import jsonRender from 'comark/plugins/json-render'
39
+ *
40
+ * const result = await parse(`
41
+ * \`\`\`json-render
42
+ * {
43
+ * "root": "card",
44
+ * "elements": {
45
+ * "card": {
46
+ * "type": "Card",
47
+ * "props": { "title": "Hello" },
48
+ * "children": ["text"]
49
+ * },
50
+ * "text": {
51
+ * "type": "Text",
52
+ * "props": { "content": "World" }
53
+ * }
54
+ * }
55
+ * }
56
+ * \`\`\`
57
+ * `, {
58
+ * plugins: [jsonRender()]
59
+ * })
60
+ * ```
61
+ *
62
+ * @example
63
+ * ```vue
64
+ * <script setup>
65
+ * import { Comark } from '@comark/vue'
66
+ * import jsonRender from '@comark/vue/plugins/json-render'
67
+ * </script>
68
+ *
69
+ * <template>
70
+ * <Suspense>
71
+ * <Comark :plugins="[jsonRender()]">{{ content }}</Comark>
72
+ * </Suspense>
73
+ * </template>
74
+ * ```
75
+ */
76
+ export default defineComarkPlugin((_config = {}) => ({
77
+ name: 'json-render',
78
+ post: async (state) => {
79
+ visit(state.tree, node => node[0] === 'pre' && (node[1].language === 'json-render'
80
+ || node[1].language === 'yaml-render'), (preNode) => {
81
+ const language = preNode[1].language;
82
+ try {
83
+ let spec = undefined;
84
+ if (language === 'json-render') {
85
+ spec = JSON.parse(textContent(preNode));
86
+ }
87
+ else if (language === 'yaml-render') {
88
+ spec = parseYaml(textContent(preNode));
89
+ }
90
+ if (spec) {
91
+ return jsonRenderToAst(spec);
92
+ }
93
+ }
94
+ catch {
95
+ // nothing to do
96
+ }
97
+ });
98
+ },
99
+ }));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "comark",
3
3
  "type": "module",
4
- "version": "0.2.0",
4
+ "version": "0.2.1",
5
5
  "description": "Components in Markdown (Comark) parser with streaming support for Vue, React, Svelte and HTML",
6
6
  "author": "",
7
7
  "license": "MIT",
@@ -42,7 +42,7 @@
42
42
  "peerDependencies": {
43
43
  "beautiful-mermaid": "^1.1.3",
44
44
  "katex": "^0.16.33",
45
- "shiki": "^3.22.0"
45
+ "shiki": "^4.0.0"
46
46
  },
47
47
  "peerDependenciesMeta": {
48
48
  "shiki": {
@@ -56,6 +56,7 @@
56
56
  }
57
57
  },
58
58
  "devDependencies": {
59
+ "@json-render/core": "^0.16.0",
59
60
  "@nuxt/kit": "^4.4.2",
60
61
  "@shikijs/primitive": "^4.0.2",
61
62
  "@shikijs/twoslash": "^4.0.2",
@@ -67,10 +68,10 @@
67
68
  "mitata": "^1.0.34",
68
69
  "tsx": "^4.21.0",
69
70
  "twoslash": "^0.3.6",
70
- "vitest": "^4.1.1"
71
+ "vitest": "^4.1.4"
71
72
  },
72
73
  "dependencies": {
73
- "@comark/markdown-it": "^0.3.2",
74
+ "@comark/markdown-it": "^0.3.3",
74
75
  "entities": "^8.0.0",
75
76
  "htmlparser2": "^12.0.0",
76
77
  "js-yaml": "^4.1.1",