@ox-content/vite-plugin-vue 2.90.0 → 3.0.0-alpha.2
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/index.cjs +90 -61
- package/dist/index.d.cts +9 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +9 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +91 -62
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -39,51 +39,28 @@ const ISLAND_MARKER_SUFFIX = "-PLACEHOLDER";
|
|
|
39
39
|
*/
|
|
40
40
|
async function transformMarkdownWithVue(code, id, options) {
|
|
41
41
|
const { components } = options;
|
|
42
|
-
const usedComponents = [];
|
|
43
|
-
const islands = [];
|
|
44
|
-
let islandIndex = 0;
|
|
45
42
|
const { content: markdownContent, frontmatter } = extractFrontmatter(code);
|
|
46
|
-
const
|
|
47
|
-
let processedContent = "";
|
|
48
|
-
let lastIndex = 0;
|
|
49
|
-
let match;
|
|
50
|
-
COMPONENT_REGEX.lastIndex = 0;
|
|
51
|
-
while ((match = COMPONENT_REGEX.exec(markdownContent)) !== null) {
|
|
52
|
-
const [fullMatch, componentName, propsString, rawIslandContent] = match;
|
|
53
|
-
const matchStart = match.index;
|
|
54
|
-
const matchEnd = matchStart + fullMatch.length;
|
|
55
|
-
if (!components.has(componentName) || isInRanges(matchStart, matchEnd, fenceRanges)) {
|
|
56
|
-
processedContent += markdownContent.slice(lastIndex, matchEnd);
|
|
57
|
-
lastIndex = matchEnd;
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
if (!usedComponents.includes(componentName)) usedComponents.push(componentName);
|
|
61
|
-
const props = parseProps(propsString);
|
|
62
|
-
const islandId = `ox-island-${islandIndex++}`;
|
|
63
|
-
const islandContent = typeof rawIslandContent === "string" ? rawIslandContent.trim() : void 0;
|
|
64
|
-
islands.push({
|
|
65
|
-
name: componentName,
|
|
66
|
-
props,
|
|
67
|
-
position: matchStart,
|
|
68
|
-
id: islandId,
|
|
69
|
-
content: islandContent
|
|
70
|
-
});
|
|
71
|
-
processedContent += markdownContent.slice(lastIndex, matchStart) + createIslandMarker(islandId);
|
|
72
|
-
lastIndex = matchEnd;
|
|
73
|
-
}
|
|
74
|
-
processedContent += markdownContent.slice(lastIndex);
|
|
43
|
+
const mdx = (0, _ox_content_vite_plugin.resolveMdxForFilePath)(id, options.mdx);
|
|
75
44
|
const baseOptions = {
|
|
76
45
|
srcDir: options.srcDir,
|
|
77
46
|
outDir: options.outDir,
|
|
78
47
|
base: options.base,
|
|
79
48
|
extensions: options.extensions,
|
|
49
|
+
mdx,
|
|
80
50
|
ssg: {
|
|
81
51
|
enabled: false,
|
|
82
52
|
extension: ".html",
|
|
83
53
|
clean: false,
|
|
84
54
|
bare: false,
|
|
85
55
|
generateOgImage: false,
|
|
86
|
-
lastUpdated: false
|
|
56
|
+
lastUpdated: false,
|
|
57
|
+
pagination: false,
|
|
58
|
+
breadcrumbs: false,
|
|
59
|
+
jsonLd: false,
|
|
60
|
+
readerChrome: false,
|
|
61
|
+
localeSwitcher: false,
|
|
62
|
+
a11y: false,
|
|
63
|
+
pageChrome: false
|
|
87
64
|
},
|
|
88
65
|
gfm: options.gfm,
|
|
89
66
|
frontmatter: false,
|
|
@@ -96,8 +73,6 @@ async function transformMarkdownWithVue(code, id, options) {
|
|
|
96
73
|
strikethrough: true,
|
|
97
74
|
autolinks: options.autolinks,
|
|
98
75
|
highlight: false,
|
|
99
|
-
highlightTheme: "github-dark",
|
|
100
|
-
highlightLangs: [],
|
|
101
76
|
mermaid: false,
|
|
102
77
|
ogImage: false,
|
|
103
78
|
ogImageOptions: {
|
|
@@ -120,6 +95,59 @@ async function transformMarkdownWithVue(code, id, options) {
|
|
|
120
95
|
embeds: options.embeds,
|
|
121
96
|
i18n: false
|
|
122
97
|
};
|
|
98
|
+
if (mdx) {
|
|
99
|
+
const transformed = await (0, _ox_content_vite_plugin.transformMarkdown)(markdownContent, id, baseOptions);
|
|
100
|
+
const discovered = await (0, _ox_content_vite_plugin.discoverDocumentMdxIslands)({
|
|
101
|
+
source: markdownContent,
|
|
102
|
+
html: transformed.html,
|
|
103
|
+
components,
|
|
104
|
+
imports: transformed.imports,
|
|
105
|
+
documentPath: id,
|
|
106
|
+
contentRoot: (0, _ox_content_vite_plugin.resolveContentRootPath)({
|
|
107
|
+
srcDir: options.srcDir,
|
|
108
|
+
root: options.root
|
|
109
|
+
}),
|
|
110
|
+
srcDir: options.srcDir
|
|
111
|
+
});
|
|
112
|
+
return {
|
|
113
|
+
code: generateVueSFC(options.renderIsland ? await (0, _ox_content_vite_plugin.applyIslandSsrHtml)(transformed.html, options.renderIsland, id, discovered.usedComponents) : transformed.html, discovered.usedComponents, discovered.usedComponents, frontmatter, options, id, discovered.localBindings),
|
|
114
|
+
map: null,
|
|
115
|
+
usedComponents: discovered.usedComponents,
|
|
116
|
+
frontmatter
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const usedComponents = [];
|
|
120
|
+
const islands = [];
|
|
121
|
+
let islandIndex = 0;
|
|
122
|
+
const fenceRanges = collectFenceRanges(markdownContent);
|
|
123
|
+
let processedContent = "";
|
|
124
|
+
let lastIndex = 0;
|
|
125
|
+
let match;
|
|
126
|
+
COMPONENT_REGEX.lastIndex = 0;
|
|
127
|
+
while ((match = COMPONENT_REGEX.exec(markdownContent)) !== null) {
|
|
128
|
+
const [fullMatch, componentName, propsString, rawIslandContent] = match;
|
|
129
|
+
const matchStart = match.index;
|
|
130
|
+
const matchEnd = matchStart + fullMatch.length;
|
|
131
|
+
if (!components.has(componentName) || isInRanges(matchStart, matchEnd, fenceRanges)) {
|
|
132
|
+
processedContent += markdownContent.slice(lastIndex, matchEnd);
|
|
133
|
+
lastIndex = matchEnd;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (!usedComponents.includes(componentName)) usedComponents.push(componentName);
|
|
137
|
+
const props = parseProps(propsString);
|
|
138
|
+
const islandId = `ox-island-${islandIndex++}`;
|
|
139
|
+
const islandContent = typeof rawIslandContent === "string" ? rawIslandContent.trim() : void 0;
|
|
140
|
+
islands.push({
|
|
141
|
+
name: componentName,
|
|
142
|
+
props,
|
|
143
|
+
position: matchStart,
|
|
144
|
+
id: islandId,
|
|
145
|
+
content: islandContent
|
|
146
|
+
});
|
|
147
|
+
processedContent += markdownContent.slice(lastIndex, matchStart) + createIslandMarker(islandId);
|
|
148
|
+
lastIndex = matchEnd;
|
|
149
|
+
}
|
|
150
|
+
processedContent += markdownContent.slice(lastIndex);
|
|
123
151
|
return {
|
|
124
152
|
code: generateVueSFC(injectIslandMarkers((await (0, _ox_content_vite_plugin.transformMarkdown)(processedContent, id, baseOptions)).html, islands), usedComponents, islands, frontmatter, options, id),
|
|
125
153
|
map: null,
|
|
@@ -220,37 +248,36 @@ function parseProps(propsString) {
|
|
|
220
248
|
let match;
|
|
221
249
|
while ((match = PROP_REGEX.exec(propsString)) !== null) {
|
|
222
250
|
const [, name, doubleQuoted, singleQuoted, braceValue, bracketValue] = match;
|
|
223
|
-
if (name)
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
251
|
+
if (name) {
|
|
252
|
+
if (doubleQuoted !== void 0) props[name] = doubleQuoted;
|
|
253
|
+
else if (singleQuoted !== void 0) props[name] = singleQuoted;
|
|
254
|
+
else if (braceValue !== void 0) try {
|
|
255
|
+
props[name] = JSON.parse(`{${braceValue}}`);
|
|
256
|
+
} catch {
|
|
257
|
+
props[name] = braceValue;
|
|
258
|
+
}
|
|
259
|
+
else if (bracketValue !== void 0) try {
|
|
260
|
+
props[name] = JSON.parse(`[${bracketValue}]`);
|
|
261
|
+
} catch {
|
|
262
|
+
props[name] = bracketValue;
|
|
263
|
+
}
|
|
264
|
+
else props[name] = true;
|
|
234
265
|
}
|
|
235
|
-
else props[name] = true;
|
|
236
266
|
}
|
|
237
267
|
return props;
|
|
238
268
|
}
|
|
239
269
|
/**
|
|
240
270
|
* Generates a Vue component as JavaScript module from the processed Markdown.
|
|
241
271
|
*/
|
|
242
|
-
function generateVueSFC(content, usedComponents,
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
const relativePath = path.relative(mdDir, absolutePath).replace(/\\/g, "/");
|
|
250
|
-
return `import ${name} from '${relativePath.startsWith(".") ? relativePath : "./" + relativePath}';`;
|
|
251
|
-
}).filter(Boolean).join("\n");
|
|
272
|
+
function generateVueSFC(content, usedComponents, _islands, frontmatter, options, id, localBindings) {
|
|
273
|
+
const componentImports = (0, _ox_content_vite_plugin.renderIslandComponentImports)(usedComponents, {
|
|
274
|
+
globalComponents: options.components,
|
|
275
|
+
localBindings,
|
|
276
|
+
documentPath: id,
|
|
277
|
+
root: options.root
|
|
278
|
+
});
|
|
252
279
|
const componentMap = usedComponents.map((name) => ` ${name},`).join("\n");
|
|
253
|
-
if (
|
|
280
|
+
if (usedComponents.length === 0) return `
|
|
254
281
|
import { h, ref, defineComponent } from 'vue';
|
|
255
282
|
|
|
256
283
|
export const frontmatter = ${JSON.stringify(frontmatter)};
|
|
@@ -272,7 +299,7 @@ export default defineComponent({
|
|
|
272
299
|
`;
|
|
273
300
|
return `
|
|
274
301
|
import { h, ref, onMounted, onBeforeUnmount, defineComponent, render } from 'vue';
|
|
275
|
-
import { initIslands } from '@ox-content/islands';
|
|
302
|
+
import { initIslands, readIslandSlotHtml } from '@ox-content/islands';
|
|
276
303
|
${componentImports}
|
|
277
304
|
|
|
278
305
|
export const frontmatter = ${JSON.stringify(frontmatter)};
|
|
@@ -290,7 +317,7 @@ function createVueHydrate(container) {
|
|
|
290
317
|
const Component = components[componentName];
|
|
291
318
|
if (!Component) return;
|
|
292
319
|
|
|
293
|
-
const islandContent = element
|
|
320
|
+
const islandContent = readIslandSlotHtml(element);
|
|
294
321
|
const children = islandContent
|
|
295
322
|
? { default: () => h('div', { innerHTML: islandContent }) }
|
|
296
323
|
: undefined;
|
|
@@ -451,7 +478,8 @@ function oxContentVue(options = {}) {
|
|
|
451
478
|
const result = await transformMarkdownWithVue(code, id, {
|
|
452
479
|
...resolved,
|
|
453
480
|
components: componentMap,
|
|
454
|
-
root: config.root
|
|
481
|
+
root: config.root,
|
|
482
|
+
renderIsland: options.renderIsland
|
|
455
483
|
});
|
|
456
484
|
return {
|
|
457
485
|
code: result.code,
|
|
@@ -531,6 +559,7 @@ function resolveVueOptions(options) {
|
|
|
531
559
|
codeAnnotations: resolveCodeAnnotationsOptions(options.codeAnnotations),
|
|
532
560
|
components: options.components ?? {},
|
|
533
561
|
embeds: resolveBuiltinEmbedOptions(options.embeds),
|
|
562
|
+
mdx: options.mdx,
|
|
534
563
|
reactivityTransform: options.reactivityTransform ?? false,
|
|
535
564
|
customBlocks: options.customBlocks ?? true
|
|
536
565
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PluginOption } from "vite";
|
|
2
|
-
import { OxContentOptions, oxContent } from "@ox-content/vite-plugin";
|
|
2
|
+
import { OxContentOptions, RenderIslandFn, oxContent } from "@ox-content/vite-plugin";
|
|
3
3
|
//#region src/types.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Code annotation options for the Vue integration.
|
|
@@ -117,6 +117,12 @@ interface VueIntegrationOptions extends OxContentOptions {
|
|
|
117
117
|
* @default { github: true, openGraph: true }
|
|
118
118
|
*/
|
|
119
119
|
embeds?: BuiltinEmbedOptions | false;
|
|
120
|
+
/**
|
|
121
|
+
* Optional adapter hook that replaces island inner HTML at transform time.
|
|
122
|
+
* The core renderer stays framework-neutral; do not import a framework SSR
|
|
123
|
+
* runtime from `@ox-content/vite-plugin`.
|
|
124
|
+
*/
|
|
125
|
+
renderIsland?: RenderIslandFn;
|
|
120
126
|
}
|
|
121
127
|
/**
|
|
122
128
|
* Fetch options for Vue GitHub embeds.
|
|
@@ -210,6 +216,8 @@ interface ResolvedVueOptions {
|
|
|
210
216
|
reactivityTransform: boolean;
|
|
211
217
|
customBlocks: boolean;
|
|
212
218
|
embeds: ResolvedBuiltinEmbedOptions;
|
|
219
|
+
mdx?: boolean;
|
|
220
|
+
renderIsland?: RenderIslandFn;
|
|
213
221
|
}
|
|
214
222
|
/**
|
|
215
223
|
* Transform result with Vue component information.
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/index.ts"],"mappings":";;;;;;;;;UAYiB;;;;;;EAMf;;UAGe;EACf;EACA;;;;;;KAOU,gBAAgB;;;;;;;;;;;;;;;;;;;;;;KAuBhB,mBAAmB;;;;;;;;UASd,8BAA8B;;;;;;;;EAQ7C;;;;;;;;;;;;;;;;;;;;EAqBA,aAAa;;;;;;;;EASb,4BAA4B;;;;;;;;;EAU5B;;;;;;;;;EAUA;;;;;;;;;EAUA,SAAS;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/index.ts"],"mappings":";;;;;;;;;UAYiB;;;;;;EAMf;;UAGe;EACf;EACA;;;;;;KAOU,gBAAgB;;;;;;;;;;;;;;;;;;;;;;KAuBhB,mBAAmB;;;;;;;;UASd,8BAA8B;;;;;;;;EAQ7C;;;;;;;;;;;;;;;;;;;;EAqBA,aAAa;;;;;;;;EASb,4BAA4B;;;;;;;;;EAU5B;;;;;;;;;EAUA;;;;;;;;;EAUA,SAAS;;;;;;EAOT,eAAe;;;;;UAMA;;;;;EAKf;;;;;EAMA;;;;;EAMA;;;;;EAMA;;;;;EAMA;;;;;UAMe;;;;;EAKf;;;;;EAMA;;;;;EAMA;;;;;EAMA;;;;;UAMe;;;;;EAKf,mBAAmB;;;;;EAMnB,sBAAsB;;UAGP;EACf,QAAQ;EACR,WAAW;;;;;UAMI;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,iBAAiB;EACjB,YAAY;EACZ;EACA;EACA,QAAQ;EACR;EACA,eAAe;;;;;UAMA;EACf;EACA;;;;EAKA;;;;EAKA,aAAa;;;;;UAME;;;;EAIf;;;;EAKA,OAAO;;;;EAKP;;;;EAKA;;;;EAKA;;;;;UAMe;;;;EAIf;;;;EAKA,SAAS;;;;EAKT,aAAa;;;;EAKb,KAAK;;;;;UAMU;EACf;EACA;EACA;EACA,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;iBC1OG,aAAa,UAAS,wBAA6B"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OxContentOptions, oxContent } from "@ox-content/vite-plugin";
|
|
1
|
+
import { OxContentOptions, RenderIslandFn, oxContent } from "@ox-content/vite-plugin";
|
|
2
2
|
import { PluginOption } from "vite";
|
|
3
3
|
//#region src/types.d.ts
|
|
4
4
|
/**
|
|
@@ -117,6 +117,12 @@ interface VueIntegrationOptions extends OxContentOptions {
|
|
|
117
117
|
* @default { github: true, openGraph: true }
|
|
118
118
|
*/
|
|
119
119
|
embeds?: BuiltinEmbedOptions | false;
|
|
120
|
+
/**
|
|
121
|
+
* Optional adapter hook that replaces island inner HTML at transform time.
|
|
122
|
+
* The core renderer stays framework-neutral; do not import a framework SSR
|
|
123
|
+
* runtime from `@ox-content/vite-plugin`.
|
|
124
|
+
*/
|
|
125
|
+
renderIsland?: RenderIslandFn;
|
|
120
126
|
}
|
|
121
127
|
/**
|
|
122
128
|
* Fetch options for Vue GitHub embeds.
|
|
@@ -210,6 +216,8 @@ interface ResolvedVueOptions {
|
|
|
210
216
|
reactivityTransform: boolean;
|
|
211
217
|
customBlocks: boolean;
|
|
212
218
|
embeds: ResolvedBuiltinEmbedOptions;
|
|
219
|
+
mdx?: boolean;
|
|
220
|
+
renderIsland?: RenderIslandFn;
|
|
213
221
|
}
|
|
214
222
|
/**
|
|
215
223
|
* Transform result with Vue component information.
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/index.ts"],"mappings":";;;;;;;;;UAYiB;;;;;;EAMf;;UAGe;EACf;EACA;;;;;;KAOU,gBAAgB;;;;;;;;;;;;;;;;;;;;;;KAuBhB,mBAAmB;;;;;;;;UASd,8BAA8B;;;;;;;;EAQ7C;;;;;;;;;;;;;;;;;;;;EAqBA,aAAa;;;;;;;;EASb,4BAA4B;;;;;;;;;EAU5B;;;;;;;;;EAUA;;;;;;;;;EAUA,SAAS;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/index.ts"],"mappings":";;;;;;;;;UAYiB;;;;;;EAMf;;UAGe;EACf;EACA;;;;;;KAOU,gBAAgB;;;;;;;;;;;;;;;;;;;;;;KAuBhB,mBAAmB;;;;;;;;UASd,8BAA8B;;;;;;;;EAQ7C;;;;;;;;;;;;;;;;;;;;EAqBA,aAAa;;;;;;;;EASb,4BAA4B;;;;;;;;;EAU5B;;;;;;;;;EAUA;;;;;;;;;EAUA,SAAS;;;;;;EAOT,eAAe;;;;;UAMA;;;;;EAKf;;;;;EAMA;;;;;EAMA;;;;;EAMA;;;;;EAMA;;;;;UAMe;;;;;EAKf;;;;;EAMA;;;;;EAMA;;;;;EAMA;;;;;UAMe;;;;;EAKf,mBAAmB;;;;;EAMnB,sBAAsB;;UAGP;EACf,QAAQ;EACR,WAAW;;;;;UAMI;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,iBAAiB;EACjB,YAAY;EACZ;EACA;EACA,QAAQ;EACR;EACA,eAAe;;;;;UAMA;EACf;EACA;;;;EAKA;;;;EAKA,aAAa;;;;;UAME;;;;EAIf;;;;EAKA,OAAO;;;;EAKP;;;;EAKA;;;;EAKA;;;;;UAMe;;;;EAIf;;;;EAKA,SAAS;;;;EAKT,aAAa;;;;EAKb,KAAK;;;;;UAMU;EACf;EACA;EACA;EACA,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;iBC1OG,aAAa,UAAS,wBAA6B"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
|
-
import { oxContent, oxContent as oxContent$1, transformMarkdown } from "@ox-content/vite-plugin";
|
|
3
|
+
import { applyIslandSsrHtml, discoverDocumentMdxIslands, oxContent, oxContent as oxContent$1, renderIslandComponentImports, resolveContentRootPath, resolveMdxForFilePath, transformMarkdown } from "@ox-content/vite-plugin";
|
|
4
4
|
//#region src/transform.ts
|
|
5
5
|
/**
|
|
6
6
|
* Markdown to Vue SFC transformation.
|
|
@@ -14,51 +14,28 @@ const ISLAND_MARKER_SUFFIX = "-PLACEHOLDER";
|
|
|
14
14
|
*/
|
|
15
15
|
async function transformMarkdownWithVue(code, id, options) {
|
|
16
16
|
const { components } = options;
|
|
17
|
-
const usedComponents = [];
|
|
18
|
-
const islands = [];
|
|
19
|
-
let islandIndex = 0;
|
|
20
17
|
const { content: markdownContent, frontmatter } = extractFrontmatter(code);
|
|
21
|
-
const
|
|
22
|
-
let processedContent = "";
|
|
23
|
-
let lastIndex = 0;
|
|
24
|
-
let match;
|
|
25
|
-
COMPONENT_REGEX.lastIndex = 0;
|
|
26
|
-
while ((match = COMPONENT_REGEX.exec(markdownContent)) !== null) {
|
|
27
|
-
const [fullMatch, componentName, propsString, rawIslandContent] = match;
|
|
28
|
-
const matchStart = match.index;
|
|
29
|
-
const matchEnd = matchStart + fullMatch.length;
|
|
30
|
-
if (!components.has(componentName) || isInRanges(matchStart, matchEnd, fenceRanges)) {
|
|
31
|
-
processedContent += markdownContent.slice(lastIndex, matchEnd);
|
|
32
|
-
lastIndex = matchEnd;
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
if (!usedComponents.includes(componentName)) usedComponents.push(componentName);
|
|
36
|
-
const props = parseProps(propsString);
|
|
37
|
-
const islandId = `ox-island-${islandIndex++}`;
|
|
38
|
-
const islandContent = typeof rawIslandContent === "string" ? rawIslandContent.trim() : void 0;
|
|
39
|
-
islands.push({
|
|
40
|
-
name: componentName,
|
|
41
|
-
props,
|
|
42
|
-
position: matchStart,
|
|
43
|
-
id: islandId,
|
|
44
|
-
content: islandContent
|
|
45
|
-
});
|
|
46
|
-
processedContent += markdownContent.slice(lastIndex, matchStart) + createIslandMarker(islandId);
|
|
47
|
-
lastIndex = matchEnd;
|
|
48
|
-
}
|
|
49
|
-
processedContent += markdownContent.slice(lastIndex);
|
|
18
|
+
const mdx = resolveMdxForFilePath(id, options.mdx);
|
|
50
19
|
const baseOptions = {
|
|
51
20
|
srcDir: options.srcDir,
|
|
52
21
|
outDir: options.outDir,
|
|
53
22
|
base: options.base,
|
|
54
23
|
extensions: options.extensions,
|
|
24
|
+
mdx,
|
|
55
25
|
ssg: {
|
|
56
26
|
enabled: false,
|
|
57
27
|
extension: ".html",
|
|
58
28
|
clean: false,
|
|
59
29
|
bare: false,
|
|
60
30
|
generateOgImage: false,
|
|
61
|
-
lastUpdated: false
|
|
31
|
+
lastUpdated: false,
|
|
32
|
+
pagination: false,
|
|
33
|
+
breadcrumbs: false,
|
|
34
|
+
jsonLd: false,
|
|
35
|
+
readerChrome: false,
|
|
36
|
+
localeSwitcher: false,
|
|
37
|
+
a11y: false,
|
|
38
|
+
pageChrome: false
|
|
62
39
|
},
|
|
63
40
|
gfm: options.gfm,
|
|
64
41
|
frontmatter: false,
|
|
@@ -71,8 +48,6 @@ async function transformMarkdownWithVue(code, id, options) {
|
|
|
71
48
|
strikethrough: true,
|
|
72
49
|
autolinks: options.autolinks,
|
|
73
50
|
highlight: false,
|
|
74
|
-
highlightTheme: "github-dark",
|
|
75
|
-
highlightLangs: [],
|
|
76
51
|
mermaid: false,
|
|
77
52
|
ogImage: false,
|
|
78
53
|
ogImageOptions: {
|
|
@@ -95,6 +70,59 @@ async function transformMarkdownWithVue(code, id, options) {
|
|
|
95
70
|
embeds: options.embeds,
|
|
96
71
|
i18n: false
|
|
97
72
|
};
|
|
73
|
+
if (mdx) {
|
|
74
|
+
const transformed = await transformMarkdown(markdownContent, id, baseOptions);
|
|
75
|
+
const discovered = await discoverDocumentMdxIslands({
|
|
76
|
+
source: markdownContent,
|
|
77
|
+
html: transformed.html,
|
|
78
|
+
components,
|
|
79
|
+
imports: transformed.imports,
|
|
80
|
+
documentPath: id,
|
|
81
|
+
contentRoot: resolveContentRootPath({
|
|
82
|
+
srcDir: options.srcDir,
|
|
83
|
+
root: options.root
|
|
84
|
+
}),
|
|
85
|
+
srcDir: options.srcDir
|
|
86
|
+
});
|
|
87
|
+
return {
|
|
88
|
+
code: generateVueSFC(options.renderIsland ? await applyIslandSsrHtml(transformed.html, options.renderIsland, id, discovered.usedComponents) : transformed.html, discovered.usedComponents, discovered.usedComponents, frontmatter, options, id, discovered.localBindings),
|
|
89
|
+
map: null,
|
|
90
|
+
usedComponents: discovered.usedComponents,
|
|
91
|
+
frontmatter
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const usedComponents = [];
|
|
95
|
+
const islands = [];
|
|
96
|
+
let islandIndex = 0;
|
|
97
|
+
const fenceRanges = collectFenceRanges(markdownContent);
|
|
98
|
+
let processedContent = "";
|
|
99
|
+
let lastIndex = 0;
|
|
100
|
+
let match;
|
|
101
|
+
COMPONENT_REGEX.lastIndex = 0;
|
|
102
|
+
while ((match = COMPONENT_REGEX.exec(markdownContent)) !== null) {
|
|
103
|
+
const [fullMatch, componentName, propsString, rawIslandContent] = match;
|
|
104
|
+
const matchStart = match.index;
|
|
105
|
+
const matchEnd = matchStart + fullMatch.length;
|
|
106
|
+
if (!components.has(componentName) || isInRanges(matchStart, matchEnd, fenceRanges)) {
|
|
107
|
+
processedContent += markdownContent.slice(lastIndex, matchEnd);
|
|
108
|
+
lastIndex = matchEnd;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (!usedComponents.includes(componentName)) usedComponents.push(componentName);
|
|
112
|
+
const props = parseProps(propsString);
|
|
113
|
+
const islandId = `ox-island-${islandIndex++}`;
|
|
114
|
+
const islandContent = typeof rawIslandContent === "string" ? rawIslandContent.trim() : void 0;
|
|
115
|
+
islands.push({
|
|
116
|
+
name: componentName,
|
|
117
|
+
props,
|
|
118
|
+
position: matchStart,
|
|
119
|
+
id: islandId,
|
|
120
|
+
content: islandContent
|
|
121
|
+
});
|
|
122
|
+
processedContent += markdownContent.slice(lastIndex, matchStart) + createIslandMarker(islandId);
|
|
123
|
+
lastIndex = matchEnd;
|
|
124
|
+
}
|
|
125
|
+
processedContent += markdownContent.slice(lastIndex);
|
|
98
126
|
return {
|
|
99
127
|
code: generateVueSFC(injectIslandMarkers((await transformMarkdown(processedContent, id, baseOptions)).html, islands), usedComponents, islands, frontmatter, options, id),
|
|
100
128
|
map: null,
|
|
@@ -195,37 +223,36 @@ function parseProps(propsString) {
|
|
|
195
223
|
let match;
|
|
196
224
|
while ((match = PROP_REGEX.exec(propsString)) !== null) {
|
|
197
225
|
const [, name, doubleQuoted, singleQuoted, braceValue, bracketValue] = match;
|
|
198
|
-
if (name)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
226
|
+
if (name) {
|
|
227
|
+
if (doubleQuoted !== void 0) props[name] = doubleQuoted;
|
|
228
|
+
else if (singleQuoted !== void 0) props[name] = singleQuoted;
|
|
229
|
+
else if (braceValue !== void 0) try {
|
|
230
|
+
props[name] = JSON.parse(`{${braceValue}}`);
|
|
231
|
+
} catch {
|
|
232
|
+
props[name] = braceValue;
|
|
233
|
+
}
|
|
234
|
+
else if (bracketValue !== void 0) try {
|
|
235
|
+
props[name] = JSON.parse(`[${bracketValue}]`);
|
|
236
|
+
} catch {
|
|
237
|
+
props[name] = bracketValue;
|
|
238
|
+
}
|
|
239
|
+
else props[name] = true;
|
|
209
240
|
}
|
|
210
|
-
else props[name] = true;
|
|
211
241
|
}
|
|
212
242
|
return props;
|
|
213
243
|
}
|
|
214
244
|
/**
|
|
215
245
|
* Generates a Vue component as JavaScript module from the processed Markdown.
|
|
216
246
|
*/
|
|
217
|
-
function generateVueSFC(content, usedComponents,
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const relativePath = path.relative(mdDir, absolutePath).replace(/\\/g, "/");
|
|
225
|
-
return `import ${name} from '${relativePath.startsWith(".") ? relativePath : "./" + relativePath}';`;
|
|
226
|
-
}).filter(Boolean).join("\n");
|
|
247
|
+
function generateVueSFC(content, usedComponents, _islands, frontmatter, options, id, localBindings) {
|
|
248
|
+
const componentImports = renderIslandComponentImports(usedComponents, {
|
|
249
|
+
globalComponents: options.components,
|
|
250
|
+
localBindings,
|
|
251
|
+
documentPath: id,
|
|
252
|
+
root: options.root
|
|
253
|
+
});
|
|
227
254
|
const componentMap = usedComponents.map((name) => ` ${name},`).join("\n");
|
|
228
|
-
if (
|
|
255
|
+
if (usedComponents.length === 0) return `
|
|
229
256
|
import { h, ref, defineComponent } from 'vue';
|
|
230
257
|
|
|
231
258
|
export const frontmatter = ${JSON.stringify(frontmatter)};
|
|
@@ -247,7 +274,7 @@ export default defineComponent({
|
|
|
247
274
|
`;
|
|
248
275
|
return `
|
|
249
276
|
import { h, ref, onMounted, onBeforeUnmount, defineComponent, render } from 'vue';
|
|
250
|
-
import { initIslands } from '@ox-content/islands';
|
|
277
|
+
import { initIslands, readIslandSlotHtml } from '@ox-content/islands';
|
|
251
278
|
${componentImports}
|
|
252
279
|
|
|
253
280
|
export const frontmatter = ${JSON.stringify(frontmatter)};
|
|
@@ -265,7 +292,7 @@ function createVueHydrate(container) {
|
|
|
265
292
|
const Component = components[componentName];
|
|
266
293
|
if (!Component) return;
|
|
267
294
|
|
|
268
|
-
const islandContent = element
|
|
295
|
+
const islandContent = readIslandSlotHtml(element);
|
|
269
296
|
const children = islandContent
|
|
270
297
|
? { default: () => h('div', { innerHTML: islandContent }) }
|
|
271
298
|
: undefined;
|
|
@@ -426,7 +453,8 @@ function oxContentVue(options = {}) {
|
|
|
426
453
|
const result = await transformMarkdownWithVue(code, id, {
|
|
427
454
|
...resolved,
|
|
428
455
|
components: componentMap,
|
|
429
|
-
root: config.root
|
|
456
|
+
root: config.root,
|
|
457
|
+
renderIsland: options.renderIsland
|
|
430
458
|
});
|
|
431
459
|
return {
|
|
432
460
|
code: result.code,
|
|
@@ -506,6 +534,7 @@ function resolveVueOptions(options) {
|
|
|
506
534
|
codeAnnotations: resolveCodeAnnotationsOptions(options.codeAnnotations),
|
|
507
535
|
components: options.components ?? {},
|
|
508
536
|
embeds: resolveBuiltinEmbedOptions(options.embeds),
|
|
537
|
+
mdx: options.mdx,
|
|
509
538
|
reactivityTransform: options.reactivityTransform ?? false,
|
|
510
539
|
customBlocks: options.customBlocks ?? true
|
|
511
540
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["baseTransformMarkdown","oxContent"],"sources":["../src/transform.ts","../src/environment.ts","../src/index.ts"],"sourcesContent":["/**\n * Markdown to Vue SFC transformation.\n */\n\nimport * as path from \"path\";\nimport { transformMarkdown as baseTransformMarkdown } from \"@ox-content/vite-plugin\";\nimport type { ResolvedVueOptions, VueTransformResult, ComponentIsland } from \"./types\";\n\n// Regex to match Vue-like component tags in Markdown\nconst COMPONENT_REGEX = /<([A-Z][a-zA-Z0-9]*)\\s*([^>]*?)\\s*(?:\\/>|>([\\s\\S]*?)<\\/\\1>)/g;\n\n// Regex to parse component props\nconst PROP_REGEX =\n /(?::|v-bind:)?([a-zA-Z0-9-]+)(?:=(?:\"([^\"]*)\"|'([^']*)'|{([^}]*)}|\\[([^\\]]*)\\]))?/g;\n\nconst ISLAND_MARKER_PREFIX = \"OXCONTENT-ISLAND-\";\nconst ISLAND_MARKER_SUFFIX = \"-PLACEHOLDER\";\n\ninterface Range {\n start: number;\n end: number;\n}\n\n/**\n * Options for transformMarkdownWithVue.\n */\ninterface TransformOptions extends Omit<ResolvedVueOptions, \"components\"> {\n components: Map<string, string>;\n root?: string;\n}\n\n/**\n * Transforms Markdown content with Vue component support.\n */\nexport async function transformMarkdownWithVue(\n code: string,\n id: string,\n options: TransformOptions,\n): Promise<VueTransformResult> {\n const { components } = options;\n const usedComponents: string[] = [];\n const islands: ComponentIsland[] = [];\n let islandIndex = 0;\n\n // Extract frontmatter\n const { content: markdownContent, frontmatter } = extractFrontmatter(code);\n\n // Find and extract component usages\n const fenceRanges = collectFenceRanges(markdownContent);\n let processedContent = \"\";\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n COMPONENT_REGEX.lastIndex = 0;\n while ((match = COMPONENT_REGEX.exec(markdownContent)) !== null) {\n const [fullMatch, componentName, propsString, rawIslandContent] = match;\n const matchStart = match.index;\n const matchEnd = matchStart + fullMatch.length;\n\n // Check if component is registered\n if (!components.has(componentName) || isInRanges(matchStart, matchEnd, fenceRanges)) {\n processedContent += markdownContent.slice(lastIndex, matchEnd);\n lastIndex = matchEnd;\n continue;\n }\n\n if (!usedComponents.includes(componentName)) {\n usedComponents.push(componentName);\n }\n\n // Parse props\n const props = parseProps(propsString);\n\n // Create island placeholder\n const islandId = `ox-island-${islandIndex++}`;\n const islandContent =\n typeof rawIslandContent === \"string\" ? rawIslandContent.trim() : undefined;\n islands.push({\n name: componentName,\n props,\n position: matchStart,\n id: islandId,\n content: islandContent,\n });\n\n // Replace component with island marker text\n processedContent += markdownContent.slice(lastIndex, matchStart) + createIslandMarker(islandId);\n lastIndex = matchEnd;\n }\n processedContent += markdownContent.slice(lastIndex);\n\n // Transform Markdown to HTML using ox-content\n const baseOptions = {\n srcDir: options.srcDir,\n outDir: options.outDir,\n base: options.base,\n extensions: options.extensions,\n ssg: {\n enabled: false,\n extension: \".html\",\n clean: false,\n bare: false,\n generateOgImage: false,\n lastUpdated: false,\n },\n gfm: options.gfm,\n frontmatter: false, // Already extracted\n toc: options.toc,\n tocMaxDepth: options.tocMaxDepth,\n codeAnnotations: options.codeAnnotations,\n footnotes: true,\n tables: true,\n taskLists: true,\n strikethrough: true,\n autolinks: options.autolinks,\n highlight: false,\n highlightTheme: \"github-dark\",\n highlightLangs: [],\n mermaid: false,\n ogImage: false,\n ogImageOptions: {\n vuePlugin: \"vitejs\",\n width: 1200,\n height: 630,\n cache: true,\n concurrency: 1,\n },\n transformers: [],\n docs: false,\n ogViewer: false,\n search: {\n enabled: false,\n limit: 10,\n prefix: true,\n placeholder: \"Search...\",\n hotkey: \"k\",\n },\n embeds: options.embeds,\n i18n: false,\n } as unknown as Parameters<typeof baseTransformMarkdown>[2] & {\n codeAnnotations?: TransformOptions[\"codeAnnotations\"];\n };\n\n const transformed = await baseTransformMarkdown(processedContent, id, baseOptions);\n\n // Generate Vue SFC code\n const htmlWithIslands = injectIslandMarkers(transformed.html, islands);\n const sfcCode = generateVueSFC(\n htmlWithIslands,\n usedComponents,\n islands,\n frontmatter,\n options,\n id,\n );\n\n return {\n code: sfcCode,\n map: null,\n usedComponents,\n frontmatter,\n };\n}\n\nfunction createIslandMarker(islandId: string): string {\n return `${ISLAND_MARKER_PREFIX}${islandId}${ISLAND_MARKER_SUFFIX}`;\n}\n\nfunction collectFenceRanges(content: string): Range[] {\n const ranges: Range[] = [];\n let inFence = false;\n let fenceChar = \"\";\n let fenceLength = 0;\n let fenceStart = 0;\n let pos = 0;\n\n while (pos < content.length) {\n const lineEnd = content.indexOf(\"\\n\", pos);\n const next = lineEnd === -1 ? content.length : lineEnd + 1;\n const line = content.slice(pos, lineEnd === -1 ? content.length : lineEnd);\n const fenceMatch = line.match(/^\\s{0,3}([`~]{3,})/);\n\n if (fenceMatch) {\n const marker = fenceMatch[1];\n if (!inFence) {\n inFence = true;\n fenceChar = marker[0];\n fenceLength = marker.length;\n fenceStart = pos;\n } else if (marker[0] === fenceChar && marker.length >= fenceLength) {\n inFence = false;\n ranges.push({ start: fenceStart, end: next });\n fenceChar = \"\";\n fenceLength = 0;\n }\n }\n\n pos = next;\n }\n\n if (inFence) {\n ranges.push({ start: fenceStart, end: content.length });\n }\n\n return ranges;\n}\n\nfunction isInRanges(start: number, end: number, ranges: Range[]): boolean {\n for (const range of ranges) {\n if (start < range.end && end > range.start) {\n return true;\n }\n }\n return false;\n}\n\nfunction injectIslandMarkers(html: string, islands: ComponentIsland[]): string {\n let output = html;\n\n for (const island of islands) {\n const marker = createIslandMarker(island.id);\n const propsAttr =\n Object.keys(island.props).length > 0\n ? ` data-ox-props='${JSON.stringify(island.props).replace(/'/g, \"'\")}'`\n : \"\";\n const contentAttr = island.content\n ? ` data-ox-content='${island.content.replace(/'/g, \"'\")}'`\n : \"\";\n const attrs = `data-ox-island=\"${island.name}\"${propsAttr}${contentAttr}`;\n output = output.replaceAll(`<p>${marker}</p>`, `<div ${attrs}></div>`);\n output = output.replaceAll(marker, `<span ${attrs}></span>`);\n }\n\n return output;\n}\n\n/**\n * Extracts frontmatter from Markdown content.\n */\nfunction extractFrontmatter(content: string): {\n content: string;\n frontmatter: Record<string, unknown>;\n} {\n const frontmatterRegex = /^---\\n([\\s\\S]*?)\\n---\\n/;\n const match = frontmatterRegex.exec(content);\n\n if (!match) {\n return { content, frontmatter: {} };\n }\n\n const frontmatterStr = match[1];\n const frontmatter: Record<string, unknown> = {};\n\n // Simple YAML-like parsing\n for (const line of frontmatterStr.split(\"\\n\")) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex > 0) {\n const key = line.slice(0, colonIndex).trim();\n let value: unknown = line.slice(colonIndex + 1).trim();\n\n // Try to parse as JSON for complex values\n try {\n value = JSON.parse(value as string);\n } catch {\n // Keep as string if not valid JSON\n // Remove quotes if present\n if (\n typeof value === \"string\" &&\n ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\")))\n ) {\n value = value.slice(1, -1);\n }\n }\n\n frontmatter[key] = value;\n }\n }\n\n return {\n content: content.slice(match[0].length),\n frontmatter,\n };\n}\n\n/**\n * Parses component props from a string.\n */\nfunction parseProps(propsString: string): Record<string, unknown> {\n const props: Record<string, unknown> = {};\n\n if (!propsString) return props;\n\n let match: RegExpExecArray | null;\n while ((match = PROP_REGEX.exec(propsString)) !== null) {\n const [, name, doubleQuoted, singleQuoted, braceValue, bracketValue] = match;\n\n if (name) {\n if (doubleQuoted !== undefined) {\n props[name] = doubleQuoted;\n } else if (singleQuoted !== undefined) {\n props[name] = singleQuoted;\n } else if (braceValue !== undefined) {\n // Try to parse as JSON\n try {\n props[name] = JSON.parse(`{${braceValue}}`);\n } catch {\n props[name] = braceValue;\n }\n } else if (bracketValue !== undefined) {\n try {\n props[name] = JSON.parse(`[${bracketValue}]`);\n } catch {\n props[name] = bracketValue;\n }\n } else {\n // Boolean prop\n props[name] = true;\n }\n }\n }\n\n return props;\n}\n\n/**\n * Generates a Vue component as JavaScript module from the processed Markdown.\n */\nfunction generateVueSFC(\n content: string,\n usedComponents: string[],\n islands: ComponentIsland[],\n frontmatter: Record<string, unknown>,\n options: TransformOptions,\n id: string,\n): string {\n const mdDir = path.dirname(id);\n const root = options.root || process.cwd();\n\n const componentImports = usedComponents\n .map((name) => {\n const componentPath = options.components.get(name);\n if (!componentPath) return \"\";\n // Convert relative-to-root path to relative-to-md-file path\n const absolutePath = path.resolve(root, componentPath.replace(/^\\.\\//, \"\"));\n const relativePath = path.relative(mdDir, absolutePath).replace(/\\\\/g, \"/\");\n // Ensure the path starts with ./ or ../\n const importPath = relativePath.startsWith(\".\") ? relativePath : \"./\" + relativePath;\n return `import ${name} from '${importPath}';`;\n })\n .filter(Boolean)\n .join(\"\\n\");\n\n const componentMap = usedComponents.map((name) => ` ${name},`).join(\"\\n\");\n\n // If no islands, generate simpler code without island runtime\n if (islands.length === 0) {\n return `\nimport { h, ref, defineComponent } from 'vue';\n\nexport const frontmatter = ${JSON.stringify(frontmatter)};\n\nconst rawHtml = ${JSON.stringify(content)};\n\nexport default defineComponent({\n name: 'MarkdownContent',\n setup(_, { expose }) {\n expose({ frontmatter });\n\n return () =>\n h('div', {\n class: 'ox-content',\n innerHTML: rawHtml,\n });\n },\n});\n`;\n }\n\n return `\nimport { h, ref, onMounted, onBeforeUnmount, defineComponent, render } from 'vue';\nimport { initIslands } from '@ox-content/islands';\n${componentImports}\n\nexport const frontmatter = ${JSON.stringify(frontmatter)};\n\nconst rawHtml = ${JSON.stringify(content)};\nconst components = {\n${componentMap}\n};\n\nfunction createVueHydrate(container) {\n const mountedTargets = [];\n\n return (element, props) => {\n const componentName = element.dataset.oxIsland;\n const Component = components[componentName];\n if (!Component) return;\n\n const islandContent = element.dataset.oxContent || element.innerHTML;\n const children = islandContent\n ? { default: () => h('div', { innerHTML: islandContent }) }\n : undefined;\n\n const vnode = h(Component, props, children);\n render(vnode, element);\n mountedTargets.push(element);\n\n return () => render(null, element);\n };\n}\n\nexport default defineComponent({\n name: 'MarkdownContent',\n setup(_, { expose }) {\n const container = ref(null);\n let controller;\n\n onMounted(() => {\n if (container.value) {\n controller = initIslands(createVueHydrate(container.value), {\n selector: '.ox-content [data-ox-island]',\n });\n }\n });\n\n onBeforeUnmount(() => {\n if (controller) controller.destroy();\n });\n\n expose({ frontmatter });\n\n return () =>\n h('div', {\n class: 'ox-content',\n ref: container,\n innerHTML: rawHtml,\n });\n },\n});\n`;\n}\n","/**\n * Vite Environment API configuration for Vue integration.\n */\n\nimport type { EnvironmentOptions } from \"vite\";\nimport type { ResolvedVueOptions } from \"./types\";\n\n/**\n * Creates a Vite environment for Vue markdown processing.\n *\n * @param mode - 'ssr' for server-side rendering, 'client' for client hydration\n * @param options - Resolved Vue integration options\n */\nexport function createVueMarkdownEnvironment(\n mode: \"ssr\" | \"client\",\n options: ResolvedVueOptions,\n): EnvironmentOptions {\n const isSSR = mode === \"ssr\";\n\n return {\n build: {\n outDir: isSSR ? `${options.outDir}/.ox-content/ssr` : `${options.outDir}/.ox-content/client`,\n\n ssr: isSSR,\n\n rollupOptions: {\n input: isSSR ? undefined : undefined,\n output: {\n format: isSSR ? \"esm\" : \"esm\",\n entryFileNames: isSSR ? \"[name].js\" : \"[name].[hash].js\",\n chunkFileNames: isSSR ? \"chunks/[name].js\" : \"chunks/[name].[hash].js\",\n },\n },\n\n // SSR-specific optimizations\n ...(isSSR && {\n target: \"node18\",\n minify: false,\n }),\n },\n\n resolve: {\n conditions: isSSR ? [\"node\", \"import\"] : [\"browser\", \"import\"],\n },\n\n optimizeDeps: {\n // Pre-bundle Vue for faster cold starts\n include: isSSR ? [] : [\"vue\"],\n\n // Exclude ox-content packages from optimization (they're local)\n exclude: [\"@ox-content/vite-plugin\", \"@ox-content/vite-plugin-vue\"],\n },\n\n // Development server options (client only)\n ...(!isSSR && {\n dev: {\n warmup: [\"./src/**/*.vue\", \"./docs/**/*.{md,markdown,mdx}\"],\n },\n }),\n };\n}\n\n/**\n * Creates environment-specific virtual modules.\n */\nexport function createVirtualModules(\n mode: \"ssr\" | \"client\",\n _options: ResolvedVueOptions,\n): Record<string, string> {\n const isSSR = mode === \"ssr\";\n\n return {\n // Environment detection module\n \"virtual:ox-content/env\": `\n export const isSSR = ${isSSR};\n export const isClient = ${!isSSR};\n export const mode = '${mode}';\n `,\n\n // Hydration utilities\n \"virtual:ox-content/hydration\": isSSR\n ? `\n // SSR: No-op hydration\n export function hydrate() {}\n export function createSSRApp(component) {\n return component;\n }\n `\n : `\n import { createApp } from 'vue';\n\n export function hydrate(component, container, props = {}) {\n const app = createApp(component, props);\n app.mount(container);\n return app;\n }\n\n export function createClientApp(component) {\n return createApp(component);\n }\n `,\n };\n}\n","/**\n * Vite Plugin for Ox Content Vue Integration\n *\n * Uses Vite's Environment API to enable embedding Vue components in Markdown.\n * Provides SSR and client environments for proper hydration.\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { Plugin, PluginOption, ResolvedConfig } from \"vite\";\nimport { oxContent } from \"@ox-content/vite-plugin\";\nimport { transformMarkdownWithVue } from \"./transform\";\nimport { createVueMarkdownEnvironment } from \"./environment\";\nimport type {\n VueIntegrationOptions,\n ResolvedVueOptions,\n ComponentsMap,\n ComponentsOption,\n BuiltinEmbedOptions,\n} from \"./types\";\n\nconst DEFAULT_MARKDOWN_EXTENSIONS = [\".md\", \".markdown\", \".mdx\"] as const;\n\nfunction normalizeMarkdownExtensions(extensions?: readonly string[]): string[] {\n const values = extensions?.length ? extensions : DEFAULT_MARKDOWN_EXTENSIONS;\n return Array.from(\n new Map(\n values.map((extension) => {\n const value = extension.startsWith(\".\") ? extension : `.${extension}`;\n return [value.toLowerCase(), value] as const;\n }),\n ).values(),\n );\n}\n\nfunction isMarkdownFilePath(filePath: string, extensions: readonly string[]): boolean {\n const pathname = filePath.split(\"?\")[0].split(\"#\")[0].toLowerCase();\n return extensions.some((extension) => pathname.endsWith(extension.toLowerCase()));\n}\n\nfunction resolveBuiltinEmbedOptions(\n options: BuiltinEmbedOptions | false | undefined,\n): ResolvedVueOptions[\"embeds\"] {\n if (options === false) return { github: false, openGraph: false };\n return {\n github: resolveSingleEmbedOptions(options?.github),\n openGraph: resolveSingleEmbedOptions(options?.openGraph),\n };\n}\n\nfunction resolveSingleEmbedOptions<T extends object>(options: boolean | T | undefined): T | false {\n if (options === false) return false;\n if (options === true || options === undefined) return {} as T;\n return options;\n}\n\nexport type {\n VueIntegrationOptions,\n ResolvedVueOptions,\n ComponentsOption,\n ComponentsMap,\n BuiltinEmbedOptions,\n GitHubEmbedOptions,\n OpenGraphEmbedOptions,\n ResolvedBuiltinEmbedOptions,\n VueTransformResult,\n ComponentIsland,\n ParsedMarkdownContent,\n TocEntry,\n} from \"./types\";\n\n/**\n * Creates the Ox Content Vue integration plugin with Environment API support.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { defineConfig } from 'vite';\n * import vue from '@vitejs/plugin-vue';\n * import { oxContentVue } from 'vite-plugin-ox-content-vue';\n *\n * export default defineConfig({\n * plugins: [\n * vue(),\n * oxContentVue({\n * srcDir: 'docs',\n * components: {\n * Counter: './src/components/Counter.vue',\n * },\n * }),\n * ],\n * });\n * ```\n */\nexport function oxContentVue(options: VueIntegrationOptions = {}): PluginOption[] {\n const resolved = resolveVueOptions(options);\n let componentMap = new Map<string, string>();\n let config: ResolvedConfig;\n\n // Pre-resolve components if it's a map (not glob)\n if (typeof options.components === \"object\" && !Array.isArray(options.components)) {\n componentMap = new Map(Object.entries(options.components));\n }\n\n // Main Vue transformation plugin\n const vueTransformPlugin: Plugin = {\n name: \"ox-content:vue-transform\",\n enforce: \"pre\",\n\n async configResolved(resolvedConfig) {\n config = resolvedConfig;\n\n // Resolve glob patterns for components\n const componentsOption = options.components;\n if (componentsOption) {\n const resolvedComponents = await resolveComponentsGlob(componentsOption, config.root);\n componentMap = new Map(Object.entries(resolvedComponents));\n }\n },\n\n async transform(code, id) {\n if (!isMarkdownFilePath(id, resolved.extensions)) {\n return null;\n }\n\n const result = await transformMarkdownWithVue(code, id, {\n ...resolved,\n components: componentMap,\n root: config.root,\n });\n\n return {\n code: result.code,\n map: result.map,\n };\n },\n };\n\n // Environment API plugin for Vue-specific SSR/client handling\n const vueEnvironmentPlugin: Plugin = {\n name: \"ox-content:vue-environment\",\n\n config() {\n return {\n environments: {\n // SSR environment for Vue component rendering\n oxcontent_ssr: createVueMarkdownEnvironment(\"ssr\", resolved),\n // Client environment for hydration\n oxcontent_client: createVueMarkdownEnvironment(\"client\", resolved),\n },\n };\n },\n\n // Environment-specific module resolution\n resolveId: {\n order: \"pre\",\n async handler(id, _importer, _options) {\n // Handle virtual modules for Vue markdown runtime\n if (id === \"virtual:ox-content-vue/runtime\") {\n return \"\\0virtual:ox-content-vue/runtime\";\n }\n\n if (id === \"virtual:ox-content-vue/components\") {\n return \"\\0virtual:ox-content-vue/components\";\n }\n\n return null;\n },\n },\n\n load: {\n order: \"pre\",\n async handler(id) {\n if (id === \"\\0virtual:ox-content-vue/runtime\") {\n return generateRuntimeModule(resolved);\n }\n\n if (id === \"\\0virtual:ox-content-vue/components\") {\n return generateComponentsModule(componentMap);\n }\n\n return null;\n },\n },\n\n // Per-environment build hooks\n applyToEnvironment(environment) {\n return (\n environment.name === \"oxcontent_ssr\" ||\n environment.name === \"oxcontent_client\" ||\n environment.name === \"client\" ||\n environment.name === \"ssr\"\n );\n },\n };\n\n // HMR plugin for component updates\n const vueHmrPlugin: Plugin = {\n name: \"ox-content:vue-hmr\",\n apply: \"serve\",\n\n handleHotUpdate({ file, server, modules }) {\n // Check if updated file is a registered component\n const isComponent = Array.from(componentMap.values()).some((path) =>\n file.endsWith(path.replace(/^\\.\\//, \"\")),\n );\n\n if (isComponent) {\n // Invalidate all Markdown modules that might use this component\n const mdModules = Array.from(server.moduleGraph.idToModuleMap.values()).filter(\n (mod) => mod.file && isMarkdownFilePath(mod.file, resolved.extensions),\n );\n\n if (mdModules.length > 0) {\n server.ws.send({\n type: \"custom\",\n event: \"ox-content:vue-update\",\n data: { file },\n });\n return [...modules, ...mdModules];\n }\n }\n\n return modules;\n },\n };\n\n // Get base ox-content plugins (environment plugin only)\n const basePlugins = oxContent(options).flatMap((plugin) =>\n Array.isArray(plugin) ? plugin : [plugin],\n ) as Plugin[];\n const environmentPlugin = basePlugins.find((plugin) => plugin.name === \"ox-content:environment\");\n const plugins: Plugin[] = [vueTransformPlugin, vueEnvironmentPlugin, vueHmrPlugin];\n\n if (environmentPlugin) {\n plugins.push(environmentPlugin);\n }\n\n return plugins;\n}\n\n/**\n * Resolves Vue integration options with defaults.\n */\nfunction resolveVueOptions(options: VueIntegrationOptions): ResolvedVueOptions {\n return {\n srcDir: options.srcDir ?? \"docs\",\n outDir: options.outDir ?? \"dist\",\n base: options.base ?? \"/\",\n extensions: normalizeMarkdownExtensions(options.extensions),\n gfm: options.gfm ?? true,\n autolinks: options.autolinks ?? options.gfm ?? true,\n frontmatter: options.frontmatter ?? true,\n toc: options.toc ?? true,\n tocMaxDepth: options.tocMaxDepth ?? 3,\n codeAnnotations: resolveCodeAnnotationsOptions(options.codeAnnotations),\n components: options.components ?? {},\n embeds: resolveBuiltinEmbedOptions(options.embeds),\n // Vue-specific options\n reactivityTransform: options.reactivityTransform ?? false,\n customBlocks: options.customBlocks ?? true,\n };\n}\n\nfunction resolveCodeAnnotationsOptions(\n options: VueIntegrationOptions[\"codeAnnotations\"],\n): ResolvedVueOptions[\"codeAnnotations\"] {\n if (!options) {\n return {\n enabled: false,\n metaKey: \"annotate\",\n };\n }\n\n if (options === true) {\n return {\n enabled: true,\n metaKey: \"annotate\",\n };\n }\n\n return {\n enabled: true,\n metaKey: options.metaKey ?? \"annotate\",\n };\n}\n\n/**\n * Generates the runtime module for Vue markdown rendering.\n */\nfunction generateRuntimeModule(_options: ResolvedVueOptions): string {\n return `\nimport { h, defineComponent, ref, onMounted } from 'vue';\n\nexport const OxContentRenderer = defineComponent({\n name: 'OxContentRenderer',\n props: {\n content: { type: Object, required: true },\n components: { type: Object, default: () => ({}) },\n },\n setup(props) {\n const mounted = ref(false);\n\n onMounted(() => {\n mounted.value = true;\n });\n\n return () => {\n if (!props.content) return null;\n\n const { html, frontmatter, toc, islands } = props.content;\n\n // Render static HTML with component islands\n return h('div', {\n class: 'ox-content',\n innerHTML: mounted.value ? undefined : html,\n }, mounted.value ? renderWithIslands(html, islands, props.components) : undefined);\n };\n },\n});\n\nfunction renderWithIslands(html, islands, components) {\n // Parse and render islands with Vue components\n // This is a simplified version - full implementation would use proper parsing\n return h('div', { innerHTML: html });\n}\n\nexport function useOxContent() {\n return {\n OxContentRenderer,\n };\n}\n`;\n}\n\n/**\n * Generates the components registration module.\n */\nfunction generateComponentsModule(componentMap: Map<string, string>): string {\n const imports: string[] = [];\n const exports: string[] = [];\n\n componentMap.forEach((path, name) => {\n imports.push(`import ${name} from '${path}';`);\n exports.push(` ${name},`);\n });\n\n return `\n${imports.join(\"\\n\")}\n\nexport const components = {\n${exports.join(\"\\n\")}\n};\n\nexport default components;\n`;\n}\n\n/**\n * Resolves component glob patterns to a component map.\n */\nasync function resolveComponentsGlob(\n componentsOption: ComponentsOption,\n root: string,\n): Promise<ComponentsMap> {\n // If it's already a map, return as-is\n if (typeof componentsOption === \"object\" && !Array.isArray(componentsOption)) {\n return componentsOption;\n }\n\n const patterns = Array.isArray(componentsOption) ? componentsOption : [componentsOption];\n\n const result: ComponentsMap = {};\n\n for (const pattern of patterns) {\n const files = await globFiles(pattern, root);\n\n for (const file of files) {\n // Derive component name from file name (PascalCase)\n const baseName = path.basename(file, path.extname(file));\n const componentName = toPascalCase(baseName);\n const relativePath = \"./\" + path.relative(root, file).replace(/\\\\/g, \"/\");\n\n result[componentName] = relativePath;\n }\n }\n\n return result;\n}\n\n/**\n * Simple glob matcher for component files.\n */\nasync function globFiles(pattern: string, root: string): Promise<string[]> {\n const files: string[] = [];\n\n // Parse glob pattern\n const isGlob = pattern.includes(\"*\");\n\n if (!isGlob) {\n // It's a direct path\n const fullPath = path.resolve(root, pattern);\n if (fs.existsSync(fullPath)) {\n files.push(fullPath);\n }\n return files;\n }\n\n // Handle glob patterns like './src/components/*.vue'\n const parts = pattern.split(\"*\");\n const baseDir = path.resolve(root, parts[0]);\n const ext = parts[1] || \"\";\n\n if (!fs.existsSync(baseDir)) {\n return files;\n }\n\n // Handle ** recursive pattern\n if (pattern.includes(\"**\")) {\n await walkDir(baseDir, files, ext);\n } else {\n // Single level glob\n const entries = await fs.promises.readdir(baseDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith(ext)) {\n files.push(path.join(baseDir, entry.name));\n }\n }\n }\n\n return files;\n}\n\n/**\n * Recursively walks a directory.\n */\nasync function walkDir(dir: string, files: string[], ext: string): Promise<void> {\n const entries = await fs.promises.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n await walkDir(fullPath, files, ext);\n } else if (entry.isFile() && entry.name.endsWith(ext)) {\n files.push(fullPath);\n }\n }\n}\n\n/**\n * Converts a string to PascalCase.\n */\nfunction toPascalCase(str: string): string {\n return str.replace(/[-_](\\w)/g, (_, c) => c.toUpperCase()).replace(/^\\w/, (c) => c.toUpperCase());\n}\n\n// Re-export\nexport { oxContent } from \"@ox-content/vite-plugin\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["baseTransformMarkdown","oxContent"],"sources":["../src/transform.ts","../src/environment.ts","../src/index.ts"],"sourcesContent":["/**\n * Markdown to Vue SFC transformation.\n */\n\nimport {\n applyIslandSsrHtml,\n discoverDocumentMdxIslands,\n renderIslandComponentImports,\n resolveContentRootPath,\n resolveMdxForFilePath,\n transformMarkdown as baseTransformMarkdown,\n type ResolvedDocumentComponentImport,\n} from \"@ox-content/vite-plugin\";\nimport type { ResolvedVueOptions, VueTransformResult, ComponentIsland } from \"./types\";\n\n// Regex to match Vue-like component tags in Markdown\nconst COMPONENT_REGEX = /<([A-Z][a-zA-Z0-9]*)\\s*([^>]*?)\\s*(?:\\/>|>([\\s\\S]*?)<\\/\\1>)/g;\n\n// Regex to parse component props\nconst PROP_REGEX =\n /(?::|v-bind:)?([a-zA-Z0-9-]+)(?:=(?:\"([^\"]*)\"|'([^']*)'|{([^}]*)}|\\[([^\\]]*)\\]))?/g;\n\nconst ISLAND_MARKER_PREFIX = \"OXCONTENT-ISLAND-\";\nconst ISLAND_MARKER_SUFFIX = \"-PLACEHOLDER\";\n\ninterface Range {\n start: number;\n end: number;\n}\n\n/**\n * Options for transformMarkdownWithVue.\n */\ninterface TransformOptions extends Omit<ResolvedVueOptions, \"components\"> {\n components: Map<string, string>;\n root?: string;\n}\n\n/**\n * Transforms Markdown content with Vue component support.\n */\nexport async function transformMarkdownWithVue(\n code: string,\n id: string,\n options: TransformOptions,\n): Promise<VueTransformResult> {\n const { components } = options;\n const { content: markdownContent, frontmatter } = extractFrontmatter(code);\n const mdx = resolveMdxForFilePath(id, options.mdx);\n\n const baseOptions = {\n srcDir: options.srcDir,\n outDir: options.outDir,\n base: options.base,\n extensions: options.extensions,\n mdx,\n ssg: {\n enabled: false,\n extension: \".html\",\n clean: false,\n bare: false,\n generateOgImage: false,\n lastUpdated: false,\n pagination: false,\n breadcrumbs: false,\n jsonLd: false,\n readerChrome: false,\n localeSwitcher: false,\n a11y: false,\n pageChrome: false,\n },\n gfm: options.gfm,\n frontmatter: false,\n toc: options.toc,\n tocMaxDepth: options.tocMaxDepth,\n codeAnnotations: options.codeAnnotations,\n footnotes: true,\n tables: true,\n taskLists: true,\n strikethrough: true,\n autolinks: options.autolinks,\n highlight: false,\n mermaid: false,\n ogImage: false,\n ogImageOptions: {\n vuePlugin: \"vitejs\",\n width: 1200,\n height: 630,\n cache: true,\n concurrency: 1,\n },\n transformers: [],\n docs: false,\n ogViewer: false,\n search: {\n enabled: false,\n limit: 10,\n prefix: true,\n placeholder: \"Search...\",\n hotkey: \"k\",\n },\n embeds: options.embeds,\n i18n: false,\n } as unknown as Parameters<typeof baseTransformMarkdown>[2] & {\n codeAnnotations?: TransformOptions[\"codeAnnotations\"];\n };\n\n if (mdx) {\n const transformed = await baseTransformMarkdown(markdownContent, id, baseOptions);\n const discovered = await discoverDocumentMdxIslands({\n source: markdownContent,\n html: transformed.html,\n components,\n imports: transformed.imports,\n documentPath: id,\n contentRoot: resolveContentRootPath({ srcDir: options.srcDir, root: options.root }),\n srcDir: options.srcDir,\n });\n const html = options.renderIsland\n ? await applyIslandSsrHtml(\n transformed.html,\n options.renderIsland,\n id,\n discovered.usedComponents,\n )\n : transformed.html;\n return {\n code: generateVueSFC(\n html,\n discovered.usedComponents,\n discovered.usedComponents,\n frontmatter,\n options,\n id,\n discovered.localBindings,\n ),\n map: null,\n usedComponents: discovered.usedComponents,\n frontmatter,\n };\n }\n\n const usedComponents: string[] = [];\n const islands: ComponentIsland[] = [];\n let islandIndex = 0;\n\n const fenceRanges = collectFenceRanges(markdownContent);\n let processedContent = \"\";\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n COMPONENT_REGEX.lastIndex = 0;\n while ((match = COMPONENT_REGEX.exec(markdownContent)) !== null) {\n const [fullMatch, componentName, propsString, rawIslandContent] = match;\n const matchStart = match.index;\n const matchEnd = matchStart + fullMatch.length;\n\n // Check if component is registered\n if (!components.has(componentName) || isInRanges(matchStart, matchEnd, fenceRanges)) {\n processedContent += markdownContent.slice(lastIndex, matchEnd);\n lastIndex = matchEnd;\n continue;\n }\n\n if (!usedComponents.includes(componentName)) {\n usedComponents.push(componentName);\n }\n\n // Parse props\n const props = parseProps(propsString);\n\n // Create island placeholder\n const islandId = `ox-island-${islandIndex++}`;\n const islandContent =\n typeof rawIslandContent === \"string\" ? rawIslandContent.trim() : undefined;\n islands.push({\n name: componentName,\n props,\n position: matchStart,\n id: islandId,\n content: islandContent,\n });\n\n // Replace component with island marker text\n processedContent += markdownContent.slice(lastIndex, matchStart) + createIslandMarker(islandId);\n lastIndex = matchEnd;\n }\n processedContent += markdownContent.slice(lastIndex);\n\n const transformed = await baseTransformMarkdown(processedContent, id, baseOptions);\n\n // Generate Vue SFC code\n const htmlWithIslands = injectIslandMarkers(transformed.html, islands);\n const sfcCode = generateVueSFC(\n htmlWithIslands,\n usedComponents,\n islands,\n frontmatter,\n options,\n id,\n );\n\n return {\n code: sfcCode,\n map: null,\n usedComponents,\n frontmatter,\n };\n}\n\nfunction createIslandMarker(islandId: string): string {\n return `${ISLAND_MARKER_PREFIX}${islandId}${ISLAND_MARKER_SUFFIX}`;\n}\n\nfunction collectFenceRanges(content: string): Range[] {\n const ranges: Range[] = [];\n let inFence = false;\n let fenceChar = \"\";\n let fenceLength = 0;\n let fenceStart = 0;\n let pos = 0;\n\n while (pos < content.length) {\n const lineEnd = content.indexOf(\"\\n\", pos);\n const next = lineEnd === -1 ? content.length : lineEnd + 1;\n const line = content.slice(pos, lineEnd === -1 ? content.length : lineEnd);\n const fenceMatch = line.match(/^\\s{0,3}([`~]{3,})/);\n\n if (fenceMatch) {\n const marker = fenceMatch[1];\n if (!inFence) {\n inFence = true;\n fenceChar = marker[0];\n fenceLength = marker.length;\n fenceStart = pos;\n } else if (marker[0] === fenceChar && marker.length >= fenceLength) {\n inFence = false;\n ranges.push({ start: fenceStart, end: next });\n fenceChar = \"\";\n fenceLength = 0;\n }\n }\n\n pos = next;\n }\n\n if (inFence) {\n ranges.push({ start: fenceStart, end: content.length });\n }\n\n return ranges;\n}\n\nfunction isInRanges(start: number, end: number, ranges: Range[]): boolean {\n for (const range of ranges) {\n if (start < range.end && end > range.start) {\n return true;\n }\n }\n return false;\n}\n\nfunction injectIslandMarkers(html: string, islands: ComponentIsland[]): string {\n let output = html;\n\n for (const island of islands) {\n const marker = createIslandMarker(island.id);\n const propsAttr =\n Object.keys(island.props).length > 0\n ? ` data-ox-props='${JSON.stringify(island.props).replace(/'/g, \"'\")}'`\n : \"\";\n const contentAttr = island.content\n ? ` data-ox-content='${island.content.replace(/'/g, \"'\")}'`\n : \"\";\n const attrs = `data-ox-island=\"${island.name}\"${propsAttr}${contentAttr}`;\n output = output.replaceAll(`<p>${marker}</p>`, `<div ${attrs}></div>`);\n output = output.replaceAll(marker, `<span ${attrs}></span>`);\n }\n\n return output;\n}\n\n/**\n * Extracts frontmatter from Markdown content.\n */\nfunction extractFrontmatter(content: string): {\n content: string;\n frontmatter: Record<string, unknown>;\n} {\n const frontmatterRegex = /^---\\n([\\s\\S]*?)\\n---\\n/;\n const match = frontmatterRegex.exec(content);\n\n if (!match) {\n return { content, frontmatter: {} };\n }\n\n const frontmatterStr = match[1];\n const frontmatter: Record<string, unknown> = {};\n\n // Simple YAML-like parsing\n for (const line of frontmatterStr.split(\"\\n\")) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex > 0) {\n const key = line.slice(0, colonIndex).trim();\n let value: unknown = line.slice(colonIndex + 1).trim();\n\n // Try to parse as JSON for complex values\n try {\n value = JSON.parse(value as string);\n } catch {\n // Keep as string if not valid JSON\n // Remove quotes if present\n if (\n typeof value === \"string\" &&\n ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\")))\n ) {\n value = value.slice(1, -1);\n }\n }\n\n frontmatter[key] = value;\n }\n }\n\n return {\n content: content.slice(match[0].length),\n frontmatter,\n };\n}\n\n/**\n * Parses component props from a string.\n */\nfunction parseProps(propsString: string): Record<string, unknown> {\n const props: Record<string, unknown> = {};\n\n if (!propsString) return props;\n\n let match: RegExpExecArray | null;\n while ((match = PROP_REGEX.exec(propsString)) !== null) {\n const [, name, doubleQuoted, singleQuoted, braceValue, bracketValue] = match;\n\n if (name) {\n if (doubleQuoted !== undefined) {\n props[name] = doubleQuoted;\n } else if (singleQuoted !== undefined) {\n props[name] = singleQuoted;\n } else if (braceValue !== undefined) {\n // Try to parse as JSON\n try {\n props[name] = JSON.parse(`{${braceValue}}`);\n } catch {\n props[name] = braceValue;\n }\n } else if (bracketValue !== undefined) {\n try {\n props[name] = JSON.parse(`[${bracketValue}]`);\n } catch {\n props[name] = bracketValue;\n }\n } else {\n // Boolean prop\n props[name] = true;\n }\n }\n }\n\n return props;\n}\n\n/**\n * Generates a Vue component as JavaScript module from the processed Markdown.\n */\nfunction generateVueSFC(\n content: string,\n usedComponents: string[],\n _islands: ComponentIsland[] | string[],\n frontmatter: Record<string, unknown>,\n options: TransformOptions,\n id: string,\n localBindings?: ReadonlyMap<string, ResolvedDocumentComponentImport>,\n): string {\n const componentImports = renderIslandComponentImports(usedComponents, {\n globalComponents: options.components,\n localBindings,\n documentPath: id,\n root: options.root,\n });\n\n const componentMap = usedComponents.map((name) => ` ${name},`).join(\"\\n\");\n\n // If no registered islands, generate simpler code without island runtime\n if (usedComponents.length === 0) {\n return `\nimport { h, ref, defineComponent } from 'vue';\n\nexport const frontmatter = ${JSON.stringify(frontmatter)};\n\nconst rawHtml = ${JSON.stringify(content)};\n\nexport default defineComponent({\n name: 'MarkdownContent',\n setup(_, { expose }) {\n expose({ frontmatter });\n\n return () =>\n h('div', {\n class: 'ox-content',\n innerHTML: rawHtml,\n });\n },\n});\n`;\n }\n\n return `\nimport { h, ref, onMounted, onBeforeUnmount, defineComponent, render } from 'vue';\nimport { initIslands, readIslandSlotHtml } from '@ox-content/islands';\n${componentImports}\n\nexport const frontmatter = ${JSON.stringify(frontmatter)};\n\nconst rawHtml = ${JSON.stringify(content)};\nconst components = {\n${componentMap}\n};\n\nfunction createVueHydrate(container) {\n const mountedTargets = [];\n\n return (element, props) => {\n const componentName = element.dataset.oxIsland;\n const Component = components[componentName];\n if (!Component) return;\n\n const islandContent = readIslandSlotHtml(element);\n const children = islandContent\n ? { default: () => h('div', { innerHTML: islandContent }) }\n : undefined;\n\n const vnode = h(Component, props, children);\n render(vnode, element);\n mountedTargets.push(element);\n\n return () => render(null, element);\n };\n}\n\nexport default defineComponent({\n name: 'MarkdownContent',\n setup(_, { expose }) {\n const container = ref(null);\n let controller;\n\n onMounted(() => {\n if (container.value) {\n controller = initIslands(createVueHydrate(container.value), {\n selector: '.ox-content [data-ox-island]',\n });\n }\n });\n\n onBeforeUnmount(() => {\n if (controller) controller.destroy();\n });\n\n expose({ frontmatter });\n\n return () =>\n h('div', {\n class: 'ox-content',\n ref: container,\n innerHTML: rawHtml,\n });\n },\n});\n`;\n}\n","/**\n * Vite Environment API configuration for Vue integration.\n */\n\nimport type { EnvironmentOptions } from \"vite\";\nimport type { ResolvedVueOptions } from \"./types\";\n\n/**\n * Creates a Vite environment for Vue markdown processing.\n *\n * @param mode - 'ssr' for server-side rendering, 'client' for client hydration\n * @param options - Resolved Vue integration options\n */\nexport function createVueMarkdownEnvironment(\n mode: \"ssr\" | \"client\",\n options: ResolvedVueOptions,\n): EnvironmentOptions {\n const isSSR = mode === \"ssr\";\n\n return {\n build: {\n outDir: isSSR ? `${options.outDir}/.ox-content/ssr` : `${options.outDir}/.ox-content/client`,\n\n ssr: isSSR,\n\n rollupOptions: {\n input: isSSR ? undefined : undefined,\n output: {\n format: isSSR ? \"esm\" : \"esm\",\n entryFileNames: isSSR ? \"[name].js\" : \"[name].[hash].js\",\n chunkFileNames: isSSR ? \"chunks/[name].js\" : \"chunks/[name].[hash].js\",\n },\n },\n\n // SSR-specific optimizations\n ...(isSSR && {\n target: \"node18\",\n minify: false,\n }),\n },\n\n resolve: {\n conditions: isSSR ? [\"node\", \"import\"] : [\"browser\", \"import\"],\n },\n\n optimizeDeps: {\n // Pre-bundle Vue for faster cold starts\n include: isSSR ? [] : [\"vue\"],\n\n // Exclude ox-content packages from optimization (they're local)\n exclude: [\"@ox-content/vite-plugin\", \"@ox-content/vite-plugin-vue\"],\n },\n\n // Development server options (client only)\n ...(!isSSR && {\n dev: {\n warmup: [\"./src/**/*.vue\", \"./docs/**/*.{md,markdown,mdx}\"],\n },\n }),\n };\n}\n\n/**\n * Creates environment-specific virtual modules.\n */\nexport function createVirtualModules(\n mode: \"ssr\" | \"client\",\n _options: ResolvedVueOptions,\n): Record<string, string> {\n const isSSR = mode === \"ssr\";\n\n return {\n // Environment detection module\n \"virtual:ox-content/env\": `\n export const isSSR = ${isSSR};\n export const isClient = ${!isSSR};\n export const mode = '${mode}';\n `,\n\n // Hydration utilities\n \"virtual:ox-content/hydration\": isSSR\n ? `\n // SSR: No-op hydration\n export function hydrate() {}\n export function createSSRApp(component) {\n return component;\n }\n `\n : `\n import { createApp } from 'vue';\n\n export function hydrate(component, container, props = {}) {\n const app = createApp(component, props);\n app.mount(container);\n return app;\n }\n\n export function createClientApp(component) {\n return createApp(component);\n }\n `,\n };\n}\n","/**\n * Vite Plugin for Ox Content Vue Integration\n *\n * Uses Vite's Environment API to enable embedding Vue components in Markdown.\n * Provides SSR and client environments for proper hydration.\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { Plugin, PluginOption, ResolvedConfig } from \"vite\";\nimport { oxContent } from \"@ox-content/vite-plugin\";\nimport { transformMarkdownWithVue } from \"./transform\";\nimport { createVueMarkdownEnvironment } from \"./environment\";\nimport type {\n VueIntegrationOptions,\n ResolvedVueOptions,\n ComponentsMap,\n ComponentsOption,\n BuiltinEmbedOptions,\n} from \"./types\";\n\nconst DEFAULT_MARKDOWN_EXTENSIONS = [\".md\", \".markdown\", \".mdx\"] as const;\n\nfunction normalizeMarkdownExtensions(extensions?: readonly string[]): string[] {\n const values = extensions?.length ? extensions : DEFAULT_MARKDOWN_EXTENSIONS;\n return Array.from(\n new Map(\n values.map((extension) => {\n const value = extension.startsWith(\".\") ? extension : `.${extension}`;\n return [value.toLowerCase(), value] as const;\n }),\n ).values(),\n );\n}\n\nfunction isMarkdownFilePath(filePath: string, extensions: readonly string[]): boolean {\n const pathname = filePath.split(\"?\")[0].split(\"#\")[0].toLowerCase();\n return extensions.some((extension) => pathname.endsWith(extension.toLowerCase()));\n}\n\nfunction resolveBuiltinEmbedOptions(\n options: BuiltinEmbedOptions | false | undefined,\n): ResolvedVueOptions[\"embeds\"] {\n if (options === false) return { github: false, openGraph: false };\n return {\n github: resolveSingleEmbedOptions(options?.github),\n openGraph: resolveSingleEmbedOptions(options?.openGraph),\n };\n}\n\nfunction resolveSingleEmbedOptions<T extends object>(options: boolean | T | undefined): T | false {\n if (options === false) return false;\n if (options === true || options === undefined) return {} as T;\n return options;\n}\n\nexport type {\n VueIntegrationOptions,\n ResolvedVueOptions,\n ComponentsOption,\n ComponentsMap,\n BuiltinEmbedOptions,\n GitHubEmbedOptions,\n OpenGraphEmbedOptions,\n ResolvedBuiltinEmbedOptions,\n VueTransformResult,\n ComponentIsland,\n ParsedMarkdownContent,\n TocEntry,\n} from \"./types\";\n\n/**\n * Creates the Ox Content Vue integration plugin with Environment API support.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { defineConfig } from 'vite';\n * import vue from '@vitejs/plugin-vue';\n * import { oxContentVue } from 'vite-plugin-ox-content-vue';\n *\n * export default defineConfig({\n * plugins: [\n * vue(),\n * oxContentVue({\n * srcDir: 'docs',\n * components: {\n * Counter: './src/components/Counter.vue',\n * },\n * }),\n * ],\n * });\n * ```\n */\nexport function oxContentVue(options: VueIntegrationOptions = {}): PluginOption[] {\n const resolved = resolveVueOptions(options);\n let componentMap = new Map<string, string>();\n let config: ResolvedConfig;\n\n // Pre-resolve components if it's a map (not glob)\n if (typeof options.components === \"object\" && !Array.isArray(options.components)) {\n componentMap = new Map(Object.entries(options.components));\n }\n\n // Main Vue transformation plugin\n const vueTransformPlugin: Plugin = {\n name: \"ox-content:vue-transform\",\n enforce: \"pre\",\n\n async configResolved(resolvedConfig) {\n config = resolvedConfig;\n\n // Resolve glob patterns for components\n const componentsOption = options.components;\n if (componentsOption) {\n const resolvedComponents = await resolveComponentsGlob(componentsOption, config.root);\n componentMap = new Map(Object.entries(resolvedComponents));\n }\n },\n\n async transform(code, id) {\n if (!isMarkdownFilePath(id, resolved.extensions)) {\n return null;\n }\n\n const result = await transformMarkdownWithVue(code, id, {\n ...resolved,\n components: componentMap,\n root: config.root,\n renderIsland: options.renderIsland,\n });\n\n return {\n code: result.code,\n map: result.map,\n };\n },\n };\n\n // Environment API plugin for Vue-specific SSR/client handling\n const vueEnvironmentPlugin: Plugin = {\n name: \"ox-content:vue-environment\",\n\n config() {\n return {\n environments: {\n // SSR environment for Vue component rendering\n oxcontent_ssr: createVueMarkdownEnvironment(\"ssr\", resolved),\n // Client environment for hydration\n oxcontent_client: createVueMarkdownEnvironment(\"client\", resolved),\n },\n };\n },\n\n // Environment-specific module resolution\n resolveId: {\n order: \"pre\",\n async handler(id, _importer, _options) {\n // Handle virtual modules for Vue markdown runtime\n if (id === \"virtual:ox-content-vue/runtime\") {\n return \"\\0virtual:ox-content-vue/runtime\";\n }\n\n if (id === \"virtual:ox-content-vue/components\") {\n return \"\\0virtual:ox-content-vue/components\";\n }\n\n return null;\n },\n },\n\n load: {\n order: \"pre\",\n async handler(id) {\n if (id === \"\\0virtual:ox-content-vue/runtime\") {\n return generateRuntimeModule(resolved);\n }\n\n if (id === \"\\0virtual:ox-content-vue/components\") {\n return generateComponentsModule(componentMap);\n }\n\n return null;\n },\n },\n\n // Per-environment build hooks\n applyToEnvironment(environment) {\n return (\n environment.name === \"oxcontent_ssr\" ||\n environment.name === \"oxcontent_client\" ||\n environment.name === \"client\" ||\n environment.name === \"ssr\"\n );\n },\n };\n\n // HMR plugin for component updates\n const vueHmrPlugin: Plugin = {\n name: \"ox-content:vue-hmr\",\n apply: \"serve\",\n\n handleHotUpdate({ file, server, modules }) {\n // Check if updated file is a registered component\n const isComponent = Array.from(componentMap.values()).some((path) =>\n file.endsWith(path.replace(/^\\.\\//, \"\")),\n );\n\n if (isComponent) {\n // Invalidate all Markdown modules that might use this component\n const mdModules = Array.from(server.moduleGraph.idToModuleMap.values()).filter(\n (mod) => mod.file && isMarkdownFilePath(mod.file, resolved.extensions),\n );\n\n if (mdModules.length > 0) {\n server.ws.send({\n type: \"custom\",\n event: \"ox-content:vue-update\",\n data: { file },\n });\n return [...modules, ...mdModules];\n }\n }\n\n return modules;\n },\n };\n\n // Get base ox-content plugins (environment plugin only)\n const basePlugins = oxContent(options).flatMap((plugin) =>\n Array.isArray(plugin) ? plugin : [plugin],\n ) as Plugin[];\n const environmentPlugin = basePlugins.find((plugin) => plugin.name === \"ox-content:environment\");\n const plugins: Plugin[] = [vueTransformPlugin, vueEnvironmentPlugin, vueHmrPlugin];\n\n if (environmentPlugin) {\n plugins.push(environmentPlugin);\n }\n\n return plugins;\n}\n\n/**\n * Resolves Vue integration options with defaults.\n */\nfunction resolveVueOptions(options: VueIntegrationOptions): ResolvedVueOptions {\n return {\n srcDir: options.srcDir ?? \"docs\",\n outDir: options.outDir ?? \"dist\",\n base: options.base ?? \"/\",\n extensions: normalizeMarkdownExtensions(options.extensions),\n gfm: options.gfm ?? true,\n autolinks: options.autolinks ?? options.gfm ?? true,\n frontmatter: options.frontmatter ?? true,\n toc: options.toc ?? true,\n tocMaxDepth: options.tocMaxDepth ?? 3,\n codeAnnotations: resolveCodeAnnotationsOptions(options.codeAnnotations),\n components: options.components ?? {},\n embeds: resolveBuiltinEmbedOptions(options.embeds),\n mdx: options.mdx,\n // Vue-specific options\n reactivityTransform: options.reactivityTransform ?? false,\n customBlocks: options.customBlocks ?? true,\n };\n}\n\nfunction resolveCodeAnnotationsOptions(\n options: VueIntegrationOptions[\"codeAnnotations\"],\n): ResolvedVueOptions[\"codeAnnotations\"] {\n if (!options) {\n return {\n enabled: false,\n metaKey: \"annotate\",\n };\n }\n\n if (options === true) {\n return {\n enabled: true,\n metaKey: \"annotate\",\n };\n }\n\n return {\n enabled: true,\n metaKey: options.metaKey ?? \"annotate\",\n };\n}\n\n/**\n * Generates the runtime module for Vue markdown rendering.\n */\nfunction generateRuntimeModule(_options: ResolvedVueOptions): string {\n return `\nimport { h, defineComponent, ref, onMounted } from 'vue';\n\nexport const OxContentRenderer = defineComponent({\n name: 'OxContentRenderer',\n props: {\n content: { type: Object, required: true },\n components: { type: Object, default: () => ({}) },\n },\n setup(props) {\n const mounted = ref(false);\n\n onMounted(() => {\n mounted.value = true;\n });\n\n return () => {\n if (!props.content) return null;\n\n const { html, frontmatter, toc, islands } = props.content;\n\n // Render static HTML with component islands\n return h('div', {\n class: 'ox-content',\n innerHTML: mounted.value ? undefined : html,\n }, mounted.value ? renderWithIslands(html, islands, props.components) : undefined);\n };\n },\n});\n\nfunction renderWithIslands(html, islands, components) {\n // Parse and render islands with Vue components\n // This is a simplified version - full implementation would use proper parsing\n return h('div', { innerHTML: html });\n}\n\nexport function useOxContent() {\n return {\n OxContentRenderer,\n };\n}\n`;\n}\n\n/**\n * Generates the components registration module.\n */\nfunction generateComponentsModule(componentMap: Map<string, string>): string {\n const imports: string[] = [];\n const exports: string[] = [];\n\n componentMap.forEach((path, name) => {\n imports.push(`import ${name} from '${path}';`);\n exports.push(` ${name},`);\n });\n\n return `\n${imports.join(\"\\n\")}\n\nexport const components = {\n${exports.join(\"\\n\")}\n};\n\nexport default components;\n`;\n}\n\n/**\n * Resolves component glob patterns to a component map.\n */\nasync function resolveComponentsGlob(\n componentsOption: ComponentsOption,\n root: string,\n): Promise<ComponentsMap> {\n // If it's already a map, return as-is\n if (typeof componentsOption === \"object\" && !Array.isArray(componentsOption)) {\n return componentsOption;\n }\n\n const patterns = Array.isArray(componentsOption) ? componentsOption : [componentsOption];\n\n const result: ComponentsMap = {};\n\n for (const pattern of patterns) {\n const files = await globFiles(pattern, root);\n\n for (const file of files) {\n // Derive component name from file name (PascalCase)\n const baseName = path.basename(file, path.extname(file));\n const componentName = toPascalCase(baseName);\n const relativePath = \"./\" + path.relative(root, file).replace(/\\\\/g, \"/\");\n\n result[componentName] = relativePath;\n }\n }\n\n return result;\n}\n\n/**\n * Simple glob matcher for component files.\n */\nasync function globFiles(pattern: string, root: string): Promise<string[]> {\n const files: string[] = [];\n\n // Parse glob pattern\n const isGlob = pattern.includes(\"*\");\n\n if (!isGlob) {\n // It's a direct path\n const fullPath = path.resolve(root, pattern);\n if (fs.existsSync(fullPath)) {\n files.push(fullPath);\n }\n return files;\n }\n\n // Handle glob patterns like './src/components/*.vue'\n const parts = pattern.split(\"*\");\n const baseDir = path.resolve(root, parts[0]);\n const ext = parts[1] || \"\";\n\n if (!fs.existsSync(baseDir)) {\n return files;\n }\n\n // Handle ** recursive pattern\n if (pattern.includes(\"**\")) {\n await walkDir(baseDir, files, ext);\n } else {\n // Single level glob\n const entries = await fs.promises.readdir(baseDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith(ext)) {\n files.push(path.join(baseDir, entry.name));\n }\n }\n }\n\n return files;\n}\n\n/**\n * Recursively walks a directory.\n */\nasync function walkDir(dir: string, files: string[], ext: string): Promise<void> {\n const entries = await fs.promises.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n await walkDir(fullPath, files, ext);\n } else if (entry.isFile() && entry.name.endsWith(ext)) {\n files.push(fullPath);\n }\n }\n}\n\n/**\n * Converts a string to PascalCase.\n */\nfunction toPascalCase(str: string): string {\n return str.replace(/[-_](\\w)/g, (_, c) => c.toUpperCase()).replace(/^\\w/, (c) => c.toUpperCase());\n}\n\n// Re-export\nexport { oxContent } from \"@ox-content/vite-plugin\";\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ox-content/vite-plugin-vue",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.2",
|
|
4
4
|
"description": "Vue integration for Ox Content - Embed Vue components in Markdown",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -35,16 +35,16 @@
|
|
|
35
35
|
"provenance": true
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@ox-content/
|
|
39
|
-
"@ox-content/
|
|
38
|
+
"@ox-content/islands": "3.0.0-alpha.2",
|
|
39
|
+
"@ox-content/vite-plugin": "3.0.0-alpha.2"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@types/node": "^26.
|
|
42
|
+
"@types/node": "^26.2.0",
|
|
43
43
|
"@typescript/native-preview": "^7.0.0-dev.20260707.2",
|
|
44
44
|
"@vitejs/plugin-vue": "^6.0.8",
|
|
45
45
|
"typescript": "^7.0.2",
|
|
46
46
|
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.8",
|
|
47
|
-
"vite-plus": "0.2.
|
|
47
|
+
"vite-plus": "0.2.9",
|
|
48
48
|
"vue": "^3.5.41"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|