@comark/vue 0.2.1 → 0.3.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.
- package/LICENSE +21 -0
- package/dist/components/Binding.d.ts +24 -0
- package/dist/components/Binding.js +23 -0
- package/dist/components/Comark.d.ts +4 -0
- package/dist/components/Comark.js +8 -0
- package/dist/components/ComarkRenderer.d.ts +4 -0
- package/dist/components/ComarkRenderer.js +29 -33
- package/dist/components/Mermaid.d.ts +1 -1
- package/dist/components/Mermaid.js +1 -1
- package/dist/plugins/binding.d.ts +3 -0
- package/dist/plugins/binding.js +3 -0
- package/dist/plugins/breaks.d.ts +2 -0
- package/dist/plugins/breaks.js +2 -0
- package/dist/plugins/footnotes.d.ts +2 -0
- package/dist/plugins/footnotes.js +2 -0
- package/dist/plugins/punctuation.d.ts +2 -0
- package/dist/plugins/punctuation.js +2 -0
- package/dist/vite.d.ts +3 -1
- package/dist/vite.js +4 -2
- package/package.json +19 -12
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Comark team and contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const Binding: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
2
|
+
value: {
|
|
3
|
+
type: (ArrayConstructor | ObjectConstructor | StringConstructor | NumberConstructor | BooleanConstructor)[];
|
|
4
|
+
default: undefined;
|
|
5
|
+
};
|
|
6
|
+
defaultValue: {
|
|
7
|
+
type: StringConstructor;
|
|
8
|
+
default: undefined;
|
|
9
|
+
};
|
|
10
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
13
|
+
value: {
|
|
14
|
+
type: (ArrayConstructor | ObjectConstructor | StringConstructor | NumberConstructor | BooleanConstructor)[];
|
|
15
|
+
default: undefined;
|
|
16
|
+
};
|
|
17
|
+
defaultValue: {
|
|
18
|
+
type: StringConstructor;
|
|
19
|
+
default: undefined;
|
|
20
|
+
};
|
|
21
|
+
}>> & Readonly<{}>, {
|
|
22
|
+
value: string | number | boolean | Record<string, any> | unknown[];
|
|
23
|
+
defaultValue: string;
|
|
24
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Text, computed, defineComponent, h } from 'vue';
|
|
2
|
+
export const Binding = defineComponent({
|
|
3
|
+
name: 'Binding',
|
|
4
|
+
props: {
|
|
5
|
+
value: {
|
|
6
|
+
type: [String, Number, Boolean, Object, Array],
|
|
7
|
+
default: undefined,
|
|
8
|
+
},
|
|
9
|
+
defaultValue: {
|
|
10
|
+
type: String,
|
|
11
|
+
default: undefined,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
setup(props) {
|
|
15
|
+
const rendered = computed(() => {
|
|
16
|
+
if (props.value !== undefined && props.value !== null) {
|
|
17
|
+
return typeof props.value === 'object' ? JSON.stringify(props.value) : String(props.value);
|
|
18
|
+
}
|
|
19
|
+
return props.defaultValue ?? '';
|
|
20
|
+
});
|
|
21
|
+
return () => h(Text, rendered.value);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -38,6 +38,10 @@ export interface ComarkProps {
|
|
|
38
38
|
caret?: boolean | {
|
|
39
39
|
class: string;
|
|
40
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* Additional data to pass to the renderer
|
|
43
|
+
*/
|
|
44
|
+
data?: Record<string, unknown>;
|
|
41
45
|
}
|
|
42
46
|
type ComarkComponent = ReturnType<typeof defineComponent<ComarkProps>>;
|
|
43
47
|
/**
|
|
@@ -96,6 +96,13 @@ export const Comark = defineComponent({
|
|
|
96
96
|
type: [Boolean, Object],
|
|
97
97
|
default: false,
|
|
98
98
|
},
|
|
99
|
+
/**
|
|
100
|
+
* Additional data to pass to the renderer
|
|
101
|
+
*/
|
|
102
|
+
data: {
|
|
103
|
+
type: Object,
|
|
104
|
+
default: () => ({}),
|
|
105
|
+
},
|
|
99
106
|
},
|
|
100
107
|
async setup(props, ctx) {
|
|
101
108
|
const markdown = computed(() => {
|
|
@@ -123,6 +130,7 @@ export const Comark = defineComponent({
|
|
|
123
130
|
componentsManifest: props.componentsManifest,
|
|
124
131
|
class: props.streaming ? 'comark-stream' : '',
|
|
125
132
|
caret: props.caret,
|
|
133
|
+
data: props.data,
|
|
126
134
|
});
|
|
127
135
|
};
|
|
128
136
|
},
|
|
@@ -26,6 +26,10 @@ export interface ComarkRendererProps {
|
|
|
26
26
|
caret?: boolean | {
|
|
27
27
|
class: string;
|
|
28
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* Additional data to pass to the renderer
|
|
31
|
+
*/
|
|
32
|
+
data?: Record<string, unknown>;
|
|
29
33
|
}
|
|
30
34
|
type ComarkRendererComponent = ReturnType<typeof defineComponent<ComarkRendererProps>>;
|
|
31
35
|
/**
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { computed, defineAsyncComponent, defineComponent, getCurrentInstance, h, inject, onErrorCaptured, ref, toRaw } from 'vue';
|
|
2
2
|
import { findLastTextNodeAndAppendNode, getCaret } from "../utils/caret.js";
|
|
3
|
+
import { pascalCase, resolveAttributes } from 'comark/utils';
|
|
3
4
|
// Cache for dynamically resolved components
|
|
4
5
|
const asyncComponentCache = new Map();
|
|
5
|
-
const camelize = (s) => s.replace(/-(\w)/g, (_, c) => c ? c.toUpperCase() : '');
|
|
6
|
-
const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
7
|
-
const pascalCase = (str) => capitalize(camelize(str));
|
|
8
6
|
/**
|
|
9
7
|
* Helper to get tag from a ComarkNode
|
|
10
8
|
*/
|
|
@@ -23,21 +21,6 @@ function getProps(node) {
|
|
|
23
21
|
}
|
|
24
22
|
return {};
|
|
25
23
|
}
|
|
26
|
-
function parsePropValue(value) {
|
|
27
|
-
if (value === 'true')
|
|
28
|
-
return true;
|
|
29
|
-
if (value === 'false')
|
|
30
|
-
return false;
|
|
31
|
-
if (value === 'null')
|
|
32
|
-
return null;
|
|
33
|
-
try {
|
|
34
|
-
return JSON.parse(value);
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
// noop
|
|
38
|
-
}
|
|
39
|
-
return value;
|
|
40
|
-
}
|
|
41
24
|
/**
|
|
42
25
|
* Helper to get children from a ComarkNode
|
|
43
26
|
*/
|
|
@@ -74,7 +57,7 @@ function resolveComponent(tag, components, componentsManifest) {
|
|
|
74
57
|
/**
|
|
75
58
|
* Render a single Comark node to Vue VNode
|
|
76
59
|
*/
|
|
77
|
-
function renderNode(node, components = {}, key, componentsManifest, parent) {
|
|
60
|
+
function renderNode(node, components = {}, key, componentsManifest, parent, renderData = { frontmatter: {}, meta: {}, data: {}, props: {} }) {
|
|
78
61
|
// Handle text nodes (strings)
|
|
79
62
|
if (typeof node === 'string') {
|
|
80
63
|
return node;
|
|
@@ -97,21 +80,16 @@ function renderNode(node, components = {}, key, componentsManifest, parent) {
|
|
|
97
80
|
}
|
|
98
81
|
}
|
|
99
82
|
const component = customComponent || tag;
|
|
100
|
-
//
|
|
101
|
-
//
|
|
83
|
+
// Resolve `:prefix` bindings and let Vue-specific attribute mapping run
|
|
84
|
+
// on top (e.g. `className` → `class`).
|
|
85
|
+
const resolved = resolveAttributes(nodeProps, renderData, { parseJson: true });
|
|
102
86
|
const props = {};
|
|
103
|
-
for (const k in
|
|
104
|
-
if (k === '$') {
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
87
|
+
for (const k in resolved) {
|
|
107
88
|
if (k === 'className') {
|
|
108
|
-
props.class =
|
|
109
|
-
}
|
|
110
|
-
else if (k.charCodeAt(0) === 58 /* ':' */) {
|
|
111
|
-
props[k.substring(1)] = parsePropValue(nodeProps[k]);
|
|
89
|
+
props.class = resolved[k];
|
|
112
90
|
}
|
|
113
91
|
else {
|
|
114
|
-
props[k] =
|
|
92
|
+
props[k] = resolved[k];
|
|
115
93
|
}
|
|
116
94
|
}
|
|
117
95
|
// @ts-expect-error - component might be a Vue component
|
|
@@ -125,6 +103,11 @@ function renderNode(node, components = {}, key, componentsManifest, parent) {
|
|
|
125
103
|
if (node.length === 2) {
|
|
126
104
|
return h(component, props);
|
|
127
105
|
}
|
|
106
|
+
// Only shadow the parent's `props` scope when the current element has its
|
|
107
|
+
// own attributes. Bare wrappers (`<p>`, `<ul>`, `<li>`, …) must keep the
|
|
108
|
+
// parent's scope so bindings like `{{ props.x }}` reach across them.
|
|
109
|
+
const hasOwnAttrs = Object.keys(resolved).length > 0;
|
|
110
|
+
const childrenRenderData = hasOwnAttrs ? { ...renderData, props } : renderData;
|
|
128
111
|
// Separate template elements (slots) from regular children
|
|
129
112
|
const slots = {};
|
|
130
113
|
const regularChildren = [];
|
|
@@ -154,12 +137,12 @@ function renderNode(node, components = {}, key, componentsManifest, parent) {
|
|
|
154
137
|
if (slotName) {
|
|
155
138
|
const slotChildren = getChildren(child);
|
|
156
139
|
slots[slotName] = () => slotChildren
|
|
157
|
-
.map((slotChild, idx) => renderNode(slotChild, components, idx, componentsManifest, node))
|
|
140
|
+
.map((slotChild, idx) => renderNode(slotChild, components, idx, componentsManifest, node, childrenRenderData))
|
|
158
141
|
.filter((slotChild) => slotChild !== null);
|
|
159
142
|
continue;
|
|
160
143
|
}
|
|
161
144
|
}
|
|
162
|
-
const rendered = renderNode(child, components, i, componentsManifest, node);
|
|
145
|
+
const rendered = renderNode(child, components, i, componentsManifest, node, childrenRenderData);
|
|
163
146
|
if (rendered !== null) {
|
|
164
147
|
regularChildren.push(rendered);
|
|
165
148
|
}
|
|
@@ -244,6 +227,13 @@ export const ComarkRenderer = defineComponent({
|
|
|
244
227
|
type: [Boolean, Object],
|
|
245
228
|
default: false,
|
|
246
229
|
},
|
|
230
|
+
/**
|
|
231
|
+
* Additional data to pass to the renderer
|
|
232
|
+
*/
|
|
233
|
+
data: {
|
|
234
|
+
type: Object,
|
|
235
|
+
default: () => ({}),
|
|
236
|
+
},
|
|
247
237
|
},
|
|
248
238
|
async setup(props) {
|
|
249
239
|
const componentErrors = ref(new Set());
|
|
@@ -278,8 +268,14 @@ export const ComarkRenderer = defineComponent({
|
|
|
278
268
|
nodes.push(caret.value);
|
|
279
269
|
}
|
|
280
270
|
}
|
|
271
|
+
const renderData = {
|
|
272
|
+
frontmatter: props.tree.frontmatter,
|
|
273
|
+
meta: props.tree.meta,
|
|
274
|
+
data: props.data || {},
|
|
275
|
+
props: {},
|
|
276
|
+
};
|
|
281
277
|
const children = nodes
|
|
282
|
-
.map((node, index) => renderNode(node, components.value, index, componentManifest))
|
|
278
|
+
.map((node, index) => renderNode(node, components.value, index, componentManifest, undefined, renderData))
|
|
283
279
|
.filter((child) => child !== null);
|
|
284
280
|
// Wrap in a fragment
|
|
285
281
|
return h('div', { class: 'comark-content' }, children);
|
|
@@ -55,8 +55,8 @@ export declare const Mermaid: import("vue").DefineComponent<import("vue").Extrac
|
|
|
55
55
|
};
|
|
56
56
|
}>> & Readonly<{}>, {
|
|
57
57
|
class: string;
|
|
58
|
+
width: string;
|
|
58
59
|
theme: ThemeNames | DiagramColors;
|
|
59
60
|
themeDark: ThemeNames | DiagramColors;
|
|
60
61
|
height: string;
|
|
61
|
-
width: string;
|
|
62
62
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
package/dist/vite.d.ts
CHANGED
package/dist/vite.js
CHANGED
|
@@ -5,7 +5,7 @@ import { existsSync } from 'node:fs';
|
|
|
5
5
|
const runtimeDir = fileURLToPath(new URL('./utils', import.meta.url));
|
|
6
6
|
function viteComarkSlot(node, context) {
|
|
7
7
|
const isVueSlotWithUnwrap = node.tag === 'slot'
|
|
8
|
-
&& node.props.find(p => p.name === 'unwrap' || p.name === 'mdc-
|
|
8
|
+
&& node.props.find(p => p.name === 'unwrap' || p.name === 'mdc-unwrap' || (p.name === 'bind' && p.rawName === ':comark-unwrap'));
|
|
9
9
|
if (isVueSlotWithUnwrap) {
|
|
10
10
|
const transform = context.ssr
|
|
11
11
|
? context.nodeTransforms.find(nt => nt.name === 'ssrTransformSlotOutlet')
|
|
@@ -96,7 +96,7 @@ function generateComponentsModule(files) {
|
|
|
96
96
|
* })
|
|
97
97
|
* ```
|
|
98
98
|
*/
|
|
99
|
-
export default function comark() {
|
|
99
|
+
export default function comark(opts = {}) {
|
|
100
100
|
let proseDir;
|
|
101
101
|
let proseFilesCache = null;
|
|
102
102
|
async function resolveProseFiles() {
|
|
@@ -146,6 +146,8 @@ export default function comark() {
|
|
|
146
146
|
return generateComponentsModule(files);
|
|
147
147
|
},
|
|
148
148
|
async transform(code) {
|
|
149
|
+
if (opts.prose === false)
|
|
150
|
+
return null;
|
|
149
151
|
if (!code.includes('createApp') || !code.includes('.mount('))
|
|
150
152
|
return null;
|
|
151
153
|
// Skip if already injected
|
package/package.json
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@comark/vue",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.1",
|
|
5
5
|
"description": "Vue components for Comark",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/comarkdown/comark.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/comarkdown/comark/issues"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://comark.dev/rendering/vue",
|
|
6
14
|
"exports": {
|
|
7
15
|
".": "./dist/index.js",
|
|
8
16
|
"./vite": "./dist/vite.js",
|
|
@@ -21,17 +29,9 @@
|
|
|
21
29
|
"publishConfig": {
|
|
22
30
|
"access": "public"
|
|
23
31
|
},
|
|
24
|
-
"scripts": {
|
|
25
|
-
"stub": "node ../../scripts/stub.mjs",
|
|
26
|
-
"build": "tsc",
|
|
27
|
-
"dev": "tsc --watch",
|
|
28
|
-
"test": "vitest run",
|
|
29
|
-
"prepack": "tsc",
|
|
30
|
-
"release": "release-it"
|
|
31
|
-
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"beautiful-mermaid": "^1.1.3",
|
|
34
|
-
"katex": "^0.16.
|
|
34
|
+
"katex": "^0.16.45",
|
|
35
35
|
"shiki": "^4.0.0",
|
|
36
36
|
"vue": "^3.5.0"
|
|
37
37
|
},
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
}
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"comark": "^0.
|
|
50
|
+
"comark": "^0.3.1"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@vue/compiler-core": "^3.5.32",
|
|
@@ -55,5 +55,12 @@
|
|
|
55
55
|
"vite": "^8.0.8",
|
|
56
56
|
"vitest": "^4.1.4",
|
|
57
57
|
"vue": "^3.5.32"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"stub": "node ../../scripts/stub.mjs",
|
|
61
|
+
"build": "tsc",
|
|
62
|
+
"dev": "tsc --watch",
|
|
63
|
+
"test": "vitest run",
|
|
64
|
+
"release": "release-it"
|
|
58
65
|
}
|
|
59
|
-
}
|
|
66
|
+
}
|