@comark/vue 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.
- package/dist/components/Comark.d.ts +77 -0
- package/dist/components/Comark.js +131 -0
- package/dist/components/ComarkRenderer.d.ts +57 -0
- package/dist/components/ComarkRenderer.js +288 -0
- package/dist/components/Math.d.ts +33 -0
- package/dist/components/Math.js +47 -0
- package/dist/components/Mermaid.d.ts +62 -0
- package/dist/components/Mermaid.js +101 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +164 -0
- package/dist/parse.d.ts +1 -0
- package/dist/parse.js +1 -0
- package/dist/plugins/alert.d.ts +2 -0
- package/dist/plugins/alert.js +2 -0
- package/dist/plugins/emoji.d.ts +2 -0
- package/dist/plugins/emoji.js +2 -0
- package/dist/plugins/headings.d.ts +2 -0
- package/dist/plugins/headings.js +2 -0
- package/dist/plugins/highlight.d.ts +2 -0
- package/dist/plugins/highlight.js +2 -0
- package/dist/plugins/math.d.ts +3 -0
- package/dist/plugins/math.js +3 -0
- package/dist/plugins/mermaid.d.ts +3 -0
- package/dist/plugins/mermaid.js +3 -0
- package/dist/plugins/security.d.ts +2 -0
- package/dist/plugins/security.js +2 -0
- package/dist/plugins/summary.d.ts +2 -0
- package/dist/plugins/summary.js +2 -0
- package/dist/plugins/task-list.d.ts +2 -0
- package/dist/plugins/task-list.js +2 -0
- package/dist/plugins/toc.d.ts +2 -0
- package/dist/plugins/toc.js +2 -0
- package/dist/render.d.ts +1 -0
- package/dist/render.js +1 -0
- package/dist/utils/caret.d.ts +7 -0
- package/dist/utils/caret.js +38 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/node.d.ts +8 -0
- package/dist/utils/node.js +83 -0
- package/dist/utils/slot.d.ts +3 -0
- package/dist/utils/slot.js +8 -0
- package/dist/utils/ssrSlot.d.ts +1 -0
- package/dist/utils/ssrSlot.js +8 -0
- package/dist/vite.d.ts +21 -0
- package/dist/vite.js +175 -0
- package/package.json +58 -0
package/dist/vite.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { readdir } from 'node:fs/promises';
|
|
3
|
+
import { join, basename } from 'node:path';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
const runtimeDir = fileURLToPath(new URL('./utils', import.meta.url));
|
|
6
|
+
function viteComarkSlot(node, context) {
|
|
7
|
+
const isVueSlotWithUnwrap = node.tag === 'slot'
|
|
8
|
+
&& node.props.find(p => p.name === 'unwrap' || p.name === 'mdc-wunwrap' || (p.name === 'bind' && p.rawName === ':comark-unwrap'));
|
|
9
|
+
if (isVueSlotWithUnwrap) {
|
|
10
|
+
const transform = context.ssr
|
|
11
|
+
? context.nodeTransforms.find(nt => nt.name === 'ssrTransformSlotOutlet')
|
|
12
|
+
: context.nodeTransforms.find(nt => nt.name === 'transformSlotOutlet');
|
|
13
|
+
return () => {
|
|
14
|
+
node.tag = 'slot';
|
|
15
|
+
node.type = 1;
|
|
16
|
+
node.tagType = 2;
|
|
17
|
+
transform?.(node, context);
|
|
18
|
+
const codegen = context.ssr ? node.ssrCodegenNode : node.codegenNode;
|
|
19
|
+
codegen.callee = context.ssr ? '_ssrRenderComarkSlot' : '_renderComarkSlot';
|
|
20
|
+
const importExp = context.ssr
|
|
21
|
+
? '{ ssrRenderSlot as _ssrRenderComarkSlot }'
|
|
22
|
+
: '{ renderSlot as _renderComarkSlot }';
|
|
23
|
+
if (!context.imports.some(i => String(i.exp) === importExp)) {
|
|
24
|
+
context.imports.push({
|
|
25
|
+
exp: importExp,
|
|
26
|
+
path: `${runtimeDir}/${context.ssr ? 'ssrSlot' : 'slot'}`,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (context.nodeTransforms[0]?.name !== 'viteComarkSlot') {
|
|
32
|
+
const index = context.nodeTransforms.findIndex(f => f.name === 'viteComarkSlot');
|
|
33
|
+
if (index !== -1) {
|
|
34
|
+
const nt = context.nodeTransforms.splice(index, 1);
|
|
35
|
+
context.nodeTransforms.unshift(nt[0]);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const VIRTUAL_COMPONENTS_ID = 'virtual:comark-vue/components';
|
|
40
|
+
const RESOLVED_COMPONENTS_ID = '\0' + VIRTUAL_COMPONENTS_ID;
|
|
41
|
+
function toPascalCase(str) {
|
|
42
|
+
return str.replace(/(^|[-_.])(\w)/g, (_, __, c) => c.toUpperCase());
|
|
43
|
+
}
|
|
44
|
+
async function getProseFiles(proseDir) {
|
|
45
|
+
const files = [];
|
|
46
|
+
try {
|
|
47
|
+
const entries = await readdir(proseDir, { withFileTypes: true, recursive: true });
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
if (!entry.isFile() || !entry.name.endsWith('.vue'))
|
|
50
|
+
continue;
|
|
51
|
+
// parentPath was added in Node 21.4 / 20.12; path is the legacy name
|
|
52
|
+
const dir = entry.parentPath ?? entry.path;
|
|
53
|
+
files.push(join(dir, entry.name));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// prose directory doesn't exist — that's fine
|
|
58
|
+
}
|
|
59
|
+
return files;
|
|
60
|
+
}
|
|
61
|
+
function generateComponentsModule(files) {
|
|
62
|
+
if (!files.length) {
|
|
63
|
+
return 'export default { install(app) {} }';
|
|
64
|
+
}
|
|
65
|
+
const lines = [];
|
|
66
|
+
for (let i = 0; i < files.length; i++) {
|
|
67
|
+
lines.push(`import __comp_${i} from ${JSON.stringify(files[i].replace(/\\/g, '/'))}`);
|
|
68
|
+
}
|
|
69
|
+
lines.push('');
|
|
70
|
+
lines.push('export default {');
|
|
71
|
+
lines.push(' install(app) {');
|
|
72
|
+
for (let i = 0; i < files.length; i++) {
|
|
73
|
+
const name = toPascalCase(basename(files[i], '.vue'));
|
|
74
|
+
lines.push(` app.component(${JSON.stringify(name)}, __comp_${i})`);
|
|
75
|
+
}
|
|
76
|
+
lines.push(' },');
|
|
77
|
+
lines.push('}');
|
|
78
|
+
return lines.join('\n');
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Vite plugin for @comark/vue.
|
|
82
|
+
*
|
|
83
|
+
* - Adds `<slot unwrap="...">` support inside custom markdown components.
|
|
84
|
+
* - Auto-registers every `.vue` file in `src/components/prose` as a global
|
|
85
|
+
* component
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* // vite.config.ts
|
|
90
|
+
* import { defineConfig } from 'vite'
|
|
91
|
+
* import vue from '@vitejs/plugin-vue'
|
|
92
|
+
* import comark from '@comark/vue/vite'
|
|
93
|
+
*
|
|
94
|
+
* export default defineConfig({
|
|
95
|
+
* plugins: [vue(), comark()],
|
|
96
|
+
* })
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export default function comark() {
|
|
100
|
+
let proseDir;
|
|
101
|
+
let proseFilesCache = null;
|
|
102
|
+
async function resolveProseFiles() {
|
|
103
|
+
if (!proseDir)
|
|
104
|
+
return [];
|
|
105
|
+
if (!proseFilesCache) {
|
|
106
|
+
proseFilesCache = await getProseFiles(proseDir);
|
|
107
|
+
}
|
|
108
|
+
return proseFilesCache;
|
|
109
|
+
}
|
|
110
|
+
function invalidateCache(file) {
|
|
111
|
+
if (file.startsWith(proseDir)) {
|
|
112
|
+
proseFilesCache = null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
name: 'comark-vue',
|
|
117
|
+
enforce: 'pre',
|
|
118
|
+
configResolved(config) {
|
|
119
|
+
if (existsSync(join(config.root, 'src', 'components', 'prose'))) {
|
|
120
|
+
proseDir = join(config.root, 'src', 'components', 'prose');
|
|
121
|
+
}
|
|
122
|
+
if (existsSync(join(config.root, 'components', 'prose'))) {
|
|
123
|
+
proseDir = join(config.root, 'components', 'prose');
|
|
124
|
+
}
|
|
125
|
+
const vuePlugin = config.plugins.find(p => p.name === 'vite:vue');
|
|
126
|
+
if (!vuePlugin) {
|
|
127
|
+
console.warn('[comark-vue] @vitejs/plugin-vue not found. Make sure vue() is in your plugins.');
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const vueOptions = vuePlugin.api?.options;
|
|
131
|
+
if (!vueOptions)
|
|
132
|
+
return;
|
|
133
|
+
vueOptions.template ??= {};
|
|
134
|
+
vueOptions.template.compilerOptions ??= {};
|
|
135
|
+
vueOptions.template.compilerOptions.nodeTransforms ??= [];
|
|
136
|
+
vueOptions.template.compilerOptions.nodeTransforms.unshift(viteComarkSlot);
|
|
137
|
+
},
|
|
138
|
+
resolveId(id) {
|
|
139
|
+
if (id === VIRTUAL_COMPONENTS_ID)
|
|
140
|
+
return RESOLVED_COMPONENTS_ID;
|
|
141
|
+
},
|
|
142
|
+
async load(id) {
|
|
143
|
+
if (id !== RESOLVED_COMPONENTS_ID)
|
|
144
|
+
return;
|
|
145
|
+
const files = await resolveProseFiles();
|
|
146
|
+
return generateComponentsModule(files);
|
|
147
|
+
},
|
|
148
|
+
async transform(code) {
|
|
149
|
+
if (!code.includes('createApp') || !code.includes('.mount('))
|
|
150
|
+
return null;
|
|
151
|
+
// Skip if already injected
|
|
152
|
+
if (code.includes(VIRTUAL_COMPONENTS_ID))
|
|
153
|
+
return null;
|
|
154
|
+
const files = await resolveProseFiles();
|
|
155
|
+
if (!files.length)
|
|
156
|
+
return null;
|
|
157
|
+
const injected = `import __comarkProse from ${JSON.stringify(VIRTUAL_COMPONENTS_ID)};\n`
|
|
158
|
+
+ code.replace(/\.mount\s*\(/, '.use(__comarkProse).mount(');
|
|
159
|
+
return { code: injected, map: null };
|
|
160
|
+
},
|
|
161
|
+
configureServer(server) {
|
|
162
|
+
if (!proseDir)
|
|
163
|
+
return;
|
|
164
|
+
server.watcher.add(proseDir);
|
|
165
|
+
const invalidate = (file) => {
|
|
166
|
+
invalidateCache(file);
|
|
167
|
+
const mod = server.moduleGraph.getModuleById(RESOLVED_COMPONENTS_ID);
|
|
168
|
+
if (mod)
|
|
169
|
+
server.moduleGraph.invalidateModule(mod);
|
|
170
|
+
};
|
|
171
|
+
server.watcher.on('add', invalidate);
|
|
172
|
+
server.watcher.on('unlink', invalidate);
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@comark/vue",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "Vue components for Comark",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./dist/index.js",
|
|
8
|
+
"./vite": "./dist/vite.js",
|
|
9
|
+
"./plugins/*": "./dist/plugins/*.js",
|
|
10
|
+
"./utils": "./dist/utils/index.js",
|
|
11
|
+
"./parse": "./dist/parse.js",
|
|
12
|
+
"./render": "./dist/render.js",
|
|
13
|
+
"./components/*": "./dist/components/*.js"
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"module": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
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
|
+
"peerDependencies": {
|
|
33
|
+
"vue": "^3.5.0",
|
|
34
|
+
"beautiful-mermaid": "^1.1.3",
|
|
35
|
+
"katex": "^0.16.33",
|
|
36
|
+
"shiki": "^3.22.0"
|
|
37
|
+
},
|
|
38
|
+
"peerDependenciesMeta": {
|
|
39
|
+
"shiki": {
|
|
40
|
+
"optional": true
|
|
41
|
+
},
|
|
42
|
+
"beautiful-mermaid": {
|
|
43
|
+
"optional": true
|
|
44
|
+
},
|
|
45
|
+
"katex": {
|
|
46
|
+
"optional": true
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"comark": "^0.0.1"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@vue/server-renderer": "^3.5.30",
|
|
54
|
+
"comark": "workspace:*",
|
|
55
|
+
"vitest": "^4.1.1",
|
|
56
|
+
"vue": "^3.5.30"
|
|
57
|
+
}
|
|
58
|
+
}
|