@ox-content/vite-plugin-react 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 +91 -62
- 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 +92 -63
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -33,51 +33,28 @@ const ISLAND_MARKER_PREFIX = "OXCONTENT-ISLAND-";
|
|
|
33
33
|
const ISLAND_MARKER_SUFFIX = "-PLACEHOLDER";
|
|
34
34
|
async function transformMarkdownWithReact(code, id, options) {
|
|
35
35
|
const components = options.components;
|
|
36
|
-
const usedComponents = [];
|
|
37
|
-
const islands = [];
|
|
38
|
-
let islandIndex = 0;
|
|
39
36
|
const { content: markdownContent, frontmatter } = extractFrontmatter(code);
|
|
40
|
-
const
|
|
41
|
-
let processedContent = "";
|
|
42
|
-
let lastIndex = 0;
|
|
43
|
-
let match;
|
|
44
|
-
COMPONENT_REGEX.lastIndex = 0;
|
|
45
|
-
while ((match = COMPONENT_REGEX.exec(markdownContent)) !== null) {
|
|
46
|
-
const [fullMatch, componentName, propsString, rawIslandContent] = match;
|
|
47
|
-
const matchStart = match.index;
|
|
48
|
-
const matchEnd = matchStart + fullMatch.length;
|
|
49
|
-
if (!Object.prototype.hasOwnProperty.call(components, componentName) || isInRanges(matchStart, matchEnd, fenceRanges)) {
|
|
50
|
-
processedContent += markdownContent.slice(lastIndex, matchEnd);
|
|
51
|
-
lastIndex = matchEnd;
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
if (!usedComponents.includes(componentName)) usedComponents.push(componentName);
|
|
55
|
-
const props = parseProps(propsString);
|
|
56
|
-
const islandId = `ox-island-${islandIndex++}`;
|
|
57
|
-
const islandContent = typeof rawIslandContent === "string" ? rawIslandContent.trim() : void 0;
|
|
58
|
-
islands.push({
|
|
59
|
-
name: componentName,
|
|
60
|
-
props,
|
|
61
|
-
position: matchStart,
|
|
62
|
-
id: islandId,
|
|
63
|
-
content: islandContent
|
|
64
|
-
});
|
|
65
|
-
processedContent += markdownContent.slice(lastIndex, matchStart) + createIslandMarker(islandId);
|
|
66
|
-
lastIndex = matchEnd;
|
|
67
|
-
}
|
|
68
|
-
processedContent += markdownContent.slice(lastIndex);
|
|
37
|
+
const mdx = (0, _ox_content_vite_plugin.resolveMdxForFilePath)(id, options.mdx);
|
|
69
38
|
const baseOptions = {
|
|
70
39
|
srcDir: options.srcDir,
|
|
71
40
|
outDir: options.outDir,
|
|
72
41
|
base: options.base,
|
|
73
42
|
extensions: options.extensions,
|
|
43
|
+
mdx,
|
|
74
44
|
ssg: {
|
|
75
45
|
enabled: false,
|
|
76
46
|
extension: ".html",
|
|
77
47
|
clean: false,
|
|
78
48
|
bare: false,
|
|
79
49
|
generateOgImage: false,
|
|
80
|
-
lastUpdated: false
|
|
50
|
+
lastUpdated: false,
|
|
51
|
+
pagination: false,
|
|
52
|
+
breadcrumbs: false,
|
|
53
|
+
jsonLd: false,
|
|
54
|
+
readerChrome: false,
|
|
55
|
+
localeSwitcher: false,
|
|
56
|
+
a11y: false,
|
|
57
|
+
pageChrome: false
|
|
81
58
|
},
|
|
82
59
|
gfm: options.gfm,
|
|
83
60
|
frontmatter: false,
|
|
@@ -90,8 +67,6 @@ async function transformMarkdownWithReact(code, id, options) {
|
|
|
90
67
|
strikethrough: true,
|
|
91
68
|
autolinks: options.autolinks,
|
|
92
69
|
highlight: false,
|
|
93
|
-
highlightTheme: "github-dark",
|
|
94
|
-
highlightLangs: [],
|
|
95
70
|
mermaid: false,
|
|
96
71
|
ogImage: false,
|
|
97
72
|
ogImageOptions: {
|
|
@@ -114,6 +89,59 @@ async function transformMarkdownWithReact(code, id, options) {
|
|
|
114
89
|
embeds: options.embeds,
|
|
115
90
|
i18n: false
|
|
116
91
|
};
|
|
92
|
+
if (mdx) {
|
|
93
|
+
const transformed = await (0, _ox_content_vite_plugin.transformMarkdown)(markdownContent, id, baseOptions);
|
|
94
|
+
const discovered = await (0, _ox_content_vite_plugin.discoverDocumentMdxIslands)({
|
|
95
|
+
source: markdownContent,
|
|
96
|
+
html: transformed.html,
|
|
97
|
+
components,
|
|
98
|
+
imports: transformed.imports,
|
|
99
|
+
documentPath: id,
|
|
100
|
+
contentRoot: (0, _ox_content_vite_plugin.resolveContentRootPath)({
|
|
101
|
+
srcDir: options.srcDir,
|
|
102
|
+
root: options.root
|
|
103
|
+
}),
|
|
104
|
+
srcDir: options.srcDir
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
code: generateReactModule(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),
|
|
108
|
+
map: null,
|
|
109
|
+
usedComponents: discovered.usedComponents,
|
|
110
|
+
frontmatter
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const usedComponents = [];
|
|
114
|
+
const islands = [];
|
|
115
|
+
let islandIndex = 0;
|
|
116
|
+
const fenceRanges = collectFenceRanges(markdownContent);
|
|
117
|
+
let processedContent = "";
|
|
118
|
+
let lastIndex = 0;
|
|
119
|
+
let match;
|
|
120
|
+
COMPONENT_REGEX.lastIndex = 0;
|
|
121
|
+
while ((match = COMPONENT_REGEX.exec(markdownContent)) !== null) {
|
|
122
|
+
const [fullMatch, componentName, propsString, rawIslandContent] = match;
|
|
123
|
+
const matchStart = match.index;
|
|
124
|
+
const matchEnd = matchStart + fullMatch.length;
|
|
125
|
+
if (!Object.prototype.hasOwnProperty.call(components, componentName) || isInRanges(matchStart, matchEnd, fenceRanges)) {
|
|
126
|
+
processedContent += markdownContent.slice(lastIndex, matchEnd);
|
|
127
|
+
lastIndex = matchEnd;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (!usedComponents.includes(componentName)) usedComponents.push(componentName);
|
|
131
|
+
const props = parseProps(propsString);
|
|
132
|
+
const islandId = `ox-island-${islandIndex++}`;
|
|
133
|
+
const islandContent = typeof rawIslandContent === "string" ? rawIslandContent.trim() : void 0;
|
|
134
|
+
islands.push({
|
|
135
|
+
name: componentName,
|
|
136
|
+
props,
|
|
137
|
+
position: matchStart,
|
|
138
|
+
id: islandId,
|
|
139
|
+
content: islandContent
|
|
140
|
+
});
|
|
141
|
+
processedContent += markdownContent.slice(lastIndex, matchStart) + createIslandMarker(islandId);
|
|
142
|
+
lastIndex = matchEnd;
|
|
143
|
+
}
|
|
144
|
+
processedContent += markdownContent.slice(lastIndex);
|
|
117
145
|
return {
|
|
118
146
|
code: generateReactModule(injectIslandMarkers((await (0, _ox_content_vite_plugin.transformMarkdown)(processedContent, id, baseOptions)).html, islands), usedComponents, islands, frontmatter, options, id),
|
|
119
147
|
map: null,
|
|
@@ -209,34 +237,33 @@ function parseProps(propsString) {
|
|
|
209
237
|
let match;
|
|
210
238
|
while ((match = PROP_REGEX.exec(propsString)) !== null) {
|
|
211
239
|
const [, name, doubleQuoted, singleQuoted, braceValue, bracketValue] = match;
|
|
212
|
-
if (name)
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
240
|
+
if (name) {
|
|
241
|
+
if (doubleQuoted !== void 0) props[name] = doubleQuoted;
|
|
242
|
+
else if (singleQuoted !== void 0) props[name] = singleQuoted;
|
|
243
|
+
else if (braceValue !== void 0) try {
|
|
244
|
+
props[name] = JSON.parse(braceValue);
|
|
245
|
+
} catch {
|
|
246
|
+
props[name] = braceValue;
|
|
247
|
+
}
|
|
248
|
+
else if (bracketValue !== void 0) try {
|
|
249
|
+
props[name] = JSON.parse(`[${bracketValue}]`);
|
|
250
|
+
} catch {
|
|
251
|
+
props[name] = bracketValue;
|
|
252
|
+
}
|
|
253
|
+
else props[name] = true;
|
|
223
254
|
}
|
|
224
|
-
else props[name] = true;
|
|
225
255
|
}
|
|
226
256
|
return props;
|
|
227
257
|
}
|
|
228
|
-
function generateReactModule(content, usedComponents,
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
const relativePath = path.relative(mdDir, absolutePath).replace(/\\/g, "/");
|
|
236
|
-
return `import ${name} from '${relativePath.startsWith(".") ? relativePath : "./" + relativePath}';`;
|
|
237
|
-
}).filter(Boolean).join("\n");
|
|
258
|
+
function generateReactModule(content, usedComponents, _islands, frontmatter, options, id, localBindings) {
|
|
259
|
+
const imports = (0, _ox_content_vite_plugin.renderIslandComponentImports)(usedComponents, {
|
|
260
|
+
globalComponents: options.components,
|
|
261
|
+
localBindings,
|
|
262
|
+
documentPath: id,
|
|
263
|
+
root: options.root
|
|
264
|
+
});
|
|
238
265
|
const componentMap = usedComponents.map((name) => ` ${name},`).join("\n");
|
|
239
|
-
if (
|
|
266
|
+
if (usedComponents.length === 0) return `
|
|
240
267
|
import React, { createElement } from 'react';
|
|
241
268
|
|
|
242
269
|
export const frontmatter = ${JSON.stringify(frontmatter)};
|
|
@@ -253,7 +280,7 @@ export default function MarkdownContent() {
|
|
|
253
280
|
return `
|
|
254
281
|
import React, { useEffect, useRef, createElement } from 'react';
|
|
255
282
|
import { createRoot } from 'react-dom/client';
|
|
256
|
-
import { initIslands } from '@ox-content/islands';
|
|
283
|
+
import { initIslands, readIslandSlotHtml } from '@ox-content/islands';
|
|
257
284
|
${imports}
|
|
258
285
|
|
|
259
286
|
export const frontmatter = ${JSON.stringify(frontmatter)};
|
|
@@ -271,7 +298,7 @@ function createReactHydrate() {
|
|
|
271
298
|
const Component = components[componentName];
|
|
272
299
|
if (!Component) return;
|
|
273
300
|
|
|
274
|
-
const islandContent = element
|
|
301
|
+
const islandContent = readIslandSlotHtml(element);
|
|
275
302
|
const vnode = islandContent
|
|
276
303
|
? createElement(
|
|
277
304
|
Component,
|
|
@@ -413,7 +440,8 @@ function oxContentReact(options = {}) {
|
|
|
413
440
|
const result = await transformMarkdownWithReact(code, id, {
|
|
414
441
|
...resolved,
|
|
415
442
|
components: Object.fromEntries(componentMap),
|
|
416
|
-
root: config.root
|
|
443
|
+
root: config.root,
|
|
444
|
+
renderIsland: options.renderIsland
|
|
417
445
|
});
|
|
418
446
|
return {
|
|
419
447
|
code: result.code,
|
|
@@ -492,7 +520,8 @@ function resolveReactOptions(options) {
|
|
|
492
520
|
tocMaxDepth: options.tocMaxDepth ?? 3,
|
|
493
521
|
codeAnnotations: resolveCodeAnnotationsOptions(options.codeAnnotations),
|
|
494
522
|
jsxRuntime: options.jsxRuntime ?? "automatic",
|
|
495
|
-
embeds: resolveBuiltinEmbedOptions(options.embeds)
|
|
523
|
+
embeds: resolveBuiltinEmbedOptions(options.embeds),
|
|
524
|
+
mdx: options.mdx
|
|
496
525
|
};
|
|
497
526
|
}
|
|
498
527
|
function resolveCodeAnnotationsOptions(options) {
|
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 React integration.
|
|
@@ -93,6 +93,12 @@ interface ReactIntegrationOptions extends OxContentOptions {
|
|
|
93
93
|
* @default { github: true, openGraph: true }
|
|
94
94
|
*/
|
|
95
95
|
embeds?: BuiltinEmbedOptions | false;
|
|
96
|
+
/**
|
|
97
|
+
* Optional adapter hook that replaces island inner HTML at transform time.
|
|
98
|
+
* The core renderer stays framework-neutral; do not import a framework SSR
|
|
99
|
+
* runtime from `@ox-content/vite-plugin`.
|
|
100
|
+
*/
|
|
101
|
+
renderIsland?: RenderIslandFn;
|
|
96
102
|
}
|
|
97
103
|
/**
|
|
98
104
|
* Fetch options for React GitHub embeds.
|
|
@@ -182,7 +188,9 @@ interface ResolvedReactOptions {
|
|
|
182
188
|
components: ComponentsMap;
|
|
183
189
|
jsxRuntime: "automatic" | "classic";
|
|
184
190
|
embeds: ResolvedBuiltinEmbedOptions;
|
|
191
|
+
mdx?: boolean;
|
|
185
192
|
root?: string;
|
|
193
|
+
renderIsland?: RenderIslandFn;
|
|
186
194
|
}
|
|
187
195
|
interface ReactTransformResult {
|
|
188
196
|
code: string;
|
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":";;;;;;;;;;UASiB;;;;;;EAMf;;UAGe;EACf;EACA;;;;;KAMU,gBAAgB;;;;;;;;KAShB,mBAAmB;;;;;;;;;UAUd,gCAAgC;;;;;;;;EAQ/C;;;;;;;;;;;;;;;;;;EAmBA,aAAa;;;;;;;;EASb,4BAA4B;;;;;;;;;EAU5B;;;;;;;;;EAUA,SAAS;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/index.ts"],"mappings":";;;;;;;;;;UASiB;;;;;;EAMf;;UAGe;EACf;EACA;;;;;KAMU,gBAAgB;;;;;;;;KAShB,mBAAmB;;;;;;;;;UAUd,gCAAgC;;;;;;;;EAQ/C;;;;;;;;;;;;;;;;;;EAmBA,aAAa;;;;;;;;EASb,4BAA4B;;;;;;;;;EAU5B;;;;;;;;;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;;UAGI;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,iBAAiB;EACjB,YAAY;EACZ;EACA,QAAQ;EACR;EACA;EACA,eAAe;;UAGA;EACf;EACA;EACA;EACA,aAAa;;UAGE;EACf;EACA,OAAO;EACP;EACA;EACA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCzIc,eAAe,UAAS,0BAA+B"}
|
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
|
/**
|
|
@@ -93,6 +93,12 @@ interface ReactIntegrationOptions extends OxContentOptions {
|
|
|
93
93
|
* @default { github: true, openGraph: true }
|
|
94
94
|
*/
|
|
95
95
|
embeds?: BuiltinEmbedOptions | false;
|
|
96
|
+
/**
|
|
97
|
+
* Optional adapter hook that replaces island inner HTML at transform time.
|
|
98
|
+
* The core renderer stays framework-neutral; do not import a framework SSR
|
|
99
|
+
* runtime from `@ox-content/vite-plugin`.
|
|
100
|
+
*/
|
|
101
|
+
renderIsland?: RenderIslandFn;
|
|
96
102
|
}
|
|
97
103
|
/**
|
|
98
104
|
* Fetch options for React GitHub embeds.
|
|
@@ -182,7 +188,9 @@ interface ResolvedReactOptions {
|
|
|
182
188
|
components: ComponentsMap;
|
|
183
189
|
jsxRuntime: "automatic" | "classic";
|
|
184
190
|
embeds: ResolvedBuiltinEmbedOptions;
|
|
191
|
+
mdx?: boolean;
|
|
185
192
|
root?: string;
|
|
193
|
+
renderIsland?: RenderIslandFn;
|
|
186
194
|
}
|
|
187
195
|
interface ReactTransformResult {
|
|
188
196
|
code: string;
|
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":";;;;;;;;;;UASiB;;;;;;EAMf;;UAGe;EACf;EACA;;;;;KAMU,gBAAgB;;;;;;;;KAShB,mBAAmB;;;;;;;;;UAUd,gCAAgC;;;;;;;;EAQ/C;;;;;;;;;;;;;;;;;;EAmBA,aAAa;;;;;;;;EASb,4BAA4B;;;;;;;;;EAU5B;;;;;;;;;EAUA,SAAS;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/index.ts"],"mappings":";;;;;;;;;;UASiB;;;;;;EAMf;;UAGe;EACf;EACA;;;;;KAMU,gBAAgB;;;;;;;;KAShB,mBAAmB;;;;;;;;;UAUd,gCAAgC;;;;;;;;EAQ/C;;;;;;;;;;;;;;;;;;EAmBA,aAAa;;;;;;;;EASb,4BAA4B;;;;;;;;;EAU5B;;;;;;;;;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;;UAGI;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,iBAAiB;EACjB,YAAY;EACZ;EACA,QAAQ;EACR;EACA;EACA,eAAe;;UAGA;EACf;EACA;EACA;EACA,aAAa;;UAGE;EACf;EACA,OAAO;EACP;EACA;EACA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCzIc,eAAe,UAAS,0BAA+B"}
|
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
|
const COMPONENT_REGEX = /<([A-Z][a-zA-Z0-9]*)\s*([^>]*?)\s*(?:\/>|>([\s\S]*?)<\/\1>)/g;
|
|
6
6
|
const PROP_REGEX = /([a-zA-Z0-9-]+)(?:=(?:"([^"]*)"|'([^']*)'|{([^}]*)}|\[([^\]]*)\]))?/g;
|
|
@@ -8,51 +8,28 @@ const ISLAND_MARKER_PREFIX = "OXCONTENT-ISLAND-";
|
|
|
8
8
|
const ISLAND_MARKER_SUFFIX = "-PLACEHOLDER";
|
|
9
9
|
async function transformMarkdownWithReact(code, id, options) {
|
|
10
10
|
const components = options.components;
|
|
11
|
-
const usedComponents = [];
|
|
12
|
-
const islands = [];
|
|
13
|
-
let islandIndex = 0;
|
|
14
11
|
const { content: markdownContent, frontmatter } = extractFrontmatter(code);
|
|
15
|
-
const
|
|
16
|
-
let processedContent = "";
|
|
17
|
-
let lastIndex = 0;
|
|
18
|
-
let match;
|
|
19
|
-
COMPONENT_REGEX.lastIndex = 0;
|
|
20
|
-
while ((match = COMPONENT_REGEX.exec(markdownContent)) !== null) {
|
|
21
|
-
const [fullMatch, componentName, propsString, rawIslandContent] = match;
|
|
22
|
-
const matchStart = match.index;
|
|
23
|
-
const matchEnd = matchStart + fullMatch.length;
|
|
24
|
-
if (!Object.prototype.hasOwnProperty.call(components, componentName) || isInRanges(matchStart, matchEnd, fenceRanges)) {
|
|
25
|
-
processedContent += markdownContent.slice(lastIndex, matchEnd);
|
|
26
|
-
lastIndex = matchEnd;
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
if (!usedComponents.includes(componentName)) usedComponents.push(componentName);
|
|
30
|
-
const props = parseProps(propsString);
|
|
31
|
-
const islandId = `ox-island-${islandIndex++}`;
|
|
32
|
-
const islandContent = typeof rawIslandContent === "string" ? rawIslandContent.trim() : void 0;
|
|
33
|
-
islands.push({
|
|
34
|
-
name: componentName,
|
|
35
|
-
props,
|
|
36
|
-
position: matchStart,
|
|
37
|
-
id: islandId,
|
|
38
|
-
content: islandContent
|
|
39
|
-
});
|
|
40
|
-
processedContent += markdownContent.slice(lastIndex, matchStart) + createIslandMarker(islandId);
|
|
41
|
-
lastIndex = matchEnd;
|
|
42
|
-
}
|
|
43
|
-
processedContent += markdownContent.slice(lastIndex);
|
|
12
|
+
const mdx = resolveMdxForFilePath(id, options.mdx);
|
|
44
13
|
const baseOptions = {
|
|
45
14
|
srcDir: options.srcDir,
|
|
46
15
|
outDir: options.outDir,
|
|
47
16
|
base: options.base,
|
|
48
17
|
extensions: options.extensions,
|
|
18
|
+
mdx,
|
|
49
19
|
ssg: {
|
|
50
20
|
enabled: false,
|
|
51
21
|
extension: ".html",
|
|
52
22
|
clean: false,
|
|
53
23
|
bare: false,
|
|
54
24
|
generateOgImage: false,
|
|
55
|
-
lastUpdated: false
|
|
25
|
+
lastUpdated: false,
|
|
26
|
+
pagination: false,
|
|
27
|
+
breadcrumbs: false,
|
|
28
|
+
jsonLd: false,
|
|
29
|
+
readerChrome: false,
|
|
30
|
+
localeSwitcher: false,
|
|
31
|
+
a11y: false,
|
|
32
|
+
pageChrome: false
|
|
56
33
|
},
|
|
57
34
|
gfm: options.gfm,
|
|
58
35
|
frontmatter: false,
|
|
@@ -65,8 +42,6 @@ async function transformMarkdownWithReact(code, id, options) {
|
|
|
65
42
|
strikethrough: true,
|
|
66
43
|
autolinks: options.autolinks,
|
|
67
44
|
highlight: false,
|
|
68
|
-
highlightTheme: "github-dark",
|
|
69
|
-
highlightLangs: [],
|
|
70
45
|
mermaid: false,
|
|
71
46
|
ogImage: false,
|
|
72
47
|
ogImageOptions: {
|
|
@@ -89,6 +64,59 @@ async function transformMarkdownWithReact(code, id, options) {
|
|
|
89
64
|
embeds: options.embeds,
|
|
90
65
|
i18n: false
|
|
91
66
|
};
|
|
67
|
+
if (mdx) {
|
|
68
|
+
const transformed = await transformMarkdown(markdownContent, id, baseOptions);
|
|
69
|
+
const discovered = await discoverDocumentMdxIslands({
|
|
70
|
+
source: markdownContent,
|
|
71
|
+
html: transformed.html,
|
|
72
|
+
components,
|
|
73
|
+
imports: transformed.imports,
|
|
74
|
+
documentPath: id,
|
|
75
|
+
contentRoot: resolveContentRootPath({
|
|
76
|
+
srcDir: options.srcDir,
|
|
77
|
+
root: options.root
|
|
78
|
+
}),
|
|
79
|
+
srcDir: options.srcDir
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
code: generateReactModule(options.renderIsland ? await applyIslandSsrHtml(transformed.html, options.renderIsland, id, discovered.usedComponents) : transformed.html, discovered.usedComponents, discovered.usedComponents, frontmatter, options, id, discovered.localBindings),
|
|
83
|
+
map: null,
|
|
84
|
+
usedComponents: discovered.usedComponents,
|
|
85
|
+
frontmatter
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const usedComponents = [];
|
|
89
|
+
const islands = [];
|
|
90
|
+
let islandIndex = 0;
|
|
91
|
+
const fenceRanges = collectFenceRanges(markdownContent);
|
|
92
|
+
let processedContent = "";
|
|
93
|
+
let lastIndex = 0;
|
|
94
|
+
let match;
|
|
95
|
+
COMPONENT_REGEX.lastIndex = 0;
|
|
96
|
+
while ((match = COMPONENT_REGEX.exec(markdownContent)) !== null) {
|
|
97
|
+
const [fullMatch, componentName, propsString, rawIslandContent] = match;
|
|
98
|
+
const matchStart = match.index;
|
|
99
|
+
const matchEnd = matchStart + fullMatch.length;
|
|
100
|
+
if (!Object.prototype.hasOwnProperty.call(components, componentName) || isInRanges(matchStart, matchEnd, fenceRanges)) {
|
|
101
|
+
processedContent += markdownContent.slice(lastIndex, matchEnd);
|
|
102
|
+
lastIndex = matchEnd;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (!usedComponents.includes(componentName)) usedComponents.push(componentName);
|
|
106
|
+
const props = parseProps(propsString);
|
|
107
|
+
const islandId = `ox-island-${islandIndex++}`;
|
|
108
|
+
const islandContent = typeof rawIslandContent === "string" ? rawIslandContent.trim() : void 0;
|
|
109
|
+
islands.push({
|
|
110
|
+
name: componentName,
|
|
111
|
+
props,
|
|
112
|
+
position: matchStart,
|
|
113
|
+
id: islandId,
|
|
114
|
+
content: islandContent
|
|
115
|
+
});
|
|
116
|
+
processedContent += markdownContent.slice(lastIndex, matchStart) + createIslandMarker(islandId);
|
|
117
|
+
lastIndex = matchEnd;
|
|
118
|
+
}
|
|
119
|
+
processedContent += markdownContent.slice(lastIndex);
|
|
92
120
|
return {
|
|
93
121
|
code: generateReactModule(injectIslandMarkers((await transformMarkdown(processedContent, id, baseOptions)).html, islands), usedComponents, islands, frontmatter, options, id),
|
|
94
122
|
map: null,
|
|
@@ -184,34 +212,33 @@ function parseProps(propsString) {
|
|
|
184
212
|
let match;
|
|
185
213
|
while ((match = PROP_REGEX.exec(propsString)) !== null) {
|
|
186
214
|
const [, name, doubleQuoted, singleQuoted, braceValue, bracketValue] = match;
|
|
187
|
-
if (name)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
215
|
+
if (name) {
|
|
216
|
+
if (doubleQuoted !== void 0) props[name] = doubleQuoted;
|
|
217
|
+
else if (singleQuoted !== void 0) props[name] = singleQuoted;
|
|
218
|
+
else if (braceValue !== void 0) try {
|
|
219
|
+
props[name] = JSON.parse(braceValue);
|
|
220
|
+
} catch {
|
|
221
|
+
props[name] = braceValue;
|
|
222
|
+
}
|
|
223
|
+
else if (bracketValue !== void 0) try {
|
|
224
|
+
props[name] = JSON.parse(`[${bracketValue}]`);
|
|
225
|
+
} catch {
|
|
226
|
+
props[name] = bracketValue;
|
|
227
|
+
}
|
|
228
|
+
else props[name] = true;
|
|
198
229
|
}
|
|
199
|
-
else props[name] = true;
|
|
200
230
|
}
|
|
201
231
|
return props;
|
|
202
232
|
}
|
|
203
|
-
function generateReactModule(content, usedComponents,
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const relativePath = path.relative(mdDir, absolutePath).replace(/\\/g, "/");
|
|
211
|
-
return `import ${name} from '${relativePath.startsWith(".") ? relativePath : "./" + relativePath}';`;
|
|
212
|
-
}).filter(Boolean).join("\n");
|
|
233
|
+
function generateReactModule(content, usedComponents, _islands, frontmatter, options, id, localBindings) {
|
|
234
|
+
const imports = renderIslandComponentImports(usedComponents, {
|
|
235
|
+
globalComponents: options.components,
|
|
236
|
+
localBindings,
|
|
237
|
+
documentPath: id,
|
|
238
|
+
root: options.root
|
|
239
|
+
});
|
|
213
240
|
const componentMap = usedComponents.map((name) => ` ${name},`).join("\n");
|
|
214
|
-
if (
|
|
241
|
+
if (usedComponents.length === 0) return `
|
|
215
242
|
import React, { createElement } from 'react';
|
|
216
243
|
|
|
217
244
|
export const frontmatter = ${JSON.stringify(frontmatter)};
|
|
@@ -228,7 +255,7 @@ export default function MarkdownContent() {
|
|
|
228
255
|
return `
|
|
229
256
|
import React, { useEffect, useRef, createElement } from 'react';
|
|
230
257
|
import { createRoot } from 'react-dom/client';
|
|
231
|
-
import { initIslands } from '@ox-content/islands';
|
|
258
|
+
import { initIslands, readIslandSlotHtml } from '@ox-content/islands';
|
|
232
259
|
${imports}
|
|
233
260
|
|
|
234
261
|
export const frontmatter = ${JSON.stringify(frontmatter)};
|
|
@@ -246,7 +273,7 @@ function createReactHydrate() {
|
|
|
246
273
|
const Component = components[componentName];
|
|
247
274
|
if (!Component) return;
|
|
248
275
|
|
|
249
|
-
const islandContent = element
|
|
276
|
+
const islandContent = readIslandSlotHtml(element);
|
|
250
277
|
const vnode = islandContent
|
|
251
278
|
? createElement(
|
|
252
279
|
Component,
|
|
@@ -388,7 +415,8 @@ function oxContentReact(options = {}) {
|
|
|
388
415
|
const result = await transformMarkdownWithReact(code, id, {
|
|
389
416
|
...resolved,
|
|
390
417
|
components: Object.fromEntries(componentMap),
|
|
391
|
-
root: config.root
|
|
418
|
+
root: config.root,
|
|
419
|
+
renderIsland: options.renderIsland
|
|
392
420
|
});
|
|
393
421
|
return {
|
|
394
422
|
code: result.code,
|
|
@@ -467,7 +495,8 @@ function resolveReactOptions(options) {
|
|
|
467
495
|
tocMaxDepth: options.tocMaxDepth ?? 3,
|
|
468
496
|
codeAnnotations: resolveCodeAnnotationsOptions(options.codeAnnotations),
|
|
469
497
|
jsxRuntime: options.jsxRuntime ?? "automatic",
|
|
470
|
-
embeds: resolveBuiltinEmbedOptions(options.embeds)
|
|
498
|
+
embeds: resolveBuiltinEmbedOptions(options.embeds),
|
|
499
|
+
mdx: options.mdx
|
|
471
500
|
};
|
|
472
501
|
}
|
|
473
502
|
function resolveCodeAnnotationsOptions(options) {
|
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":["import * as path from \"path\";\nimport { transformMarkdown as baseTransformMarkdown } from \"@ox-content/vite-plugin\";\nimport type {\n ResolvedReactOptions,\n ReactTransformResult,\n ComponentIsland,\n ComponentsMap,\n} from \"./types\";\n\nconst COMPONENT_REGEX = /<([A-Z][a-zA-Z0-9]*)\\s*([^>]*?)\\s*(?:\\/>|>([\\s\\S]*?)<\\/\\1>)/g;\nconst PROP_REGEX = /([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\nexport async function transformMarkdownWithReact(\n code: string,\n id: string,\n options: ResolvedReactOptions,\n): Promise<ReactTransformResult> {\n const components: ComponentsMap = options.components;\n const usedComponents: string[] = [];\n const islands: ComponentIsland[] = [];\n let islandIndex = 0;\n\n const { content: markdownContent, frontmatter } = extractFrontmatter(code);\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 if (\n !Object.prototype.hasOwnProperty.call(components, componentName) ||\n isInRanges(matchStart, matchEnd, fenceRanges)\n ) {\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 const props = parseProps(propsString);\n const islandId = `ox-island-${islandIndex++}`;\n const islandContent =\n typeof rawIslandContent === \"string\" ? rawIslandContent.trim() : undefined;\n\n islands.push({\n name: componentName,\n props,\n position: matchStart,\n id: islandId,\n content: islandContent,\n });\n\n processedContent += markdownContent.slice(lastIndex, matchStart) + createIslandMarker(islandId);\n lastIndex = matchEnd;\n }\n processedContent += markdownContent.slice(lastIndex);\n\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,\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?: ResolvedReactOptions[\"codeAnnotations\"];\n };\n\n const transformed = await baseTransformMarkdown(processedContent, id, baseOptions);\n\n const htmlWithIslands = injectIslandMarkers(transformed.html, islands);\n const jsxCode = generateReactModule(\n htmlWithIslands,\n usedComponents,\n islands,\n frontmatter,\n options,\n id,\n );\n\n return {\n code: jsxCode,\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\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 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 try {\n value = JSON.parse(value as string);\n } catch {\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 frontmatter[key] = value;\n }\n }\n\n return { content: content.slice(match[0].length), frontmatter };\n}\n\nfunction parseProps(propsString: string): Record<string, unknown> {\n const props: Record<string, unknown> = {};\n if (!propsString) return props;\n\n PROP_REGEX.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = PROP_REGEX.exec(propsString)) !== null) {\n const [, name, doubleQuoted, singleQuoted, braceValue, bracketValue] = match;\n if (name) {\n if (doubleQuoted !== undefined) props[name] = doubleQuoted;\n else if (singleQuoted !== undefined) props[name] = singleQuoted;\n else if (braceValue !== undefined) {\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 props[name] = true;\n }\n }\n return props;\n}\n\nfunction generateReactModule(\n content: string,\n usedComponents: string[],\n islands: ComponentIsland[],\n frontmatter: Record<string, unknown>,\n options: ResolvedReactOptions & { root?: string },\n id: string,\n): string {\n const mdDir = path.dirname(id);\n const root = options.root || process.cwd();\n\n const imports = usedComponents\n .map((name) => {\n const componentPath = options.components[name];\n if (!componentPath) return \"\";\n const absolutePath = path.resolve(root, componentPath.replace(/^\\.\\//, \"\"));\n const relativePath = path.relative(mdDir, absolutePath).replace(/\\\\/g, \"/\");\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 React, { createElement } from 'react';\n\nexport const frontmatter = ${JSON.stringify(frontmatter)};\n\nconst rawHtml = ${JSON.stringify(content)};\n\nexport default function MarkdownContent() {\n return createElement('div', {\n className: 'ox-content',\n dangerouslySetInnerHTML: { __html: rawHtml },\n });\n}\n`;\n }\n\n return `\nimport React, { useEffect, useRef, createElement } from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { initIslands } from '@ox-content/islands';\n${imports}\n\nexport const frontmatter = ${JSON.stringify(frontmatter)};\n\nconst rawHtml = ${JSON.stringify(content)};\nconst components = {\n${componentMap}\n};\n\nfunction createReactHydrate() {\n const mountedRoots = [];\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 vnode = islandContent\n ? createElement(\n Component,\n props,\n createElement('div', { dangerouslySetInnerHTML: { __html: islandContent } })\n )\n : createElement(Component, props);\n\n const root = createRoot(element);\n root.render(vnode);\n mountedRoots.push(root);\n\n return () => root.unmount();\n };\n}\n\nexport default function MarkdownContent() {\n const containerRef = useRef(null);\n\n useEffect(() => {\n if (!containerRef.current) return;\n const controller = initIslands(createReactHydrate(), {\n selector: '.ox-content [data-ox-island]',\n });\n return () => controller.destroy();\n }, []);\n\n return createElement('div', {\n className: 'ox-content',\n ref: containerRef,\n dangerouslySetInnerHTML: { __html: rawHtml },\n });\n}\n`;\n}\n","import type { EnvironmentOptions } from \"vite\";\nimport type { ResolvedReactOptions } from \"./types\";\n\nexport function createReactMarkdownEnvironment(\n mode: \"ssr\" | \"client\",\n options: ResolvedReactOptions,\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 ssr: isSSR,\n rollupOptions: {\n output: {\n format: \"esm\",\n entryFileNames: isSSR ? \"[name].js\" : \"[name].[hash].js\",\n },\n },\n ...(isSSR && { target: \"node18\", minify: false }),\n },\n resolve: {\n conditions: isSSR ? [\"node\", \"import\"] : [\"browser\", \"import\"],\n },\n optimizeDeps: {\n include: isSSR ? [] : [\"react\", \"react-dom\"],\n exclude: [\"@ox-content/vite-plugin\", \"@ox-content/vite-plugin-react\"],\n },\n };\n}\n","/**\n * Vite Plugin for Ox Content React Integration\n *\n * Uses Vite's Environment API to enable embedding React components in Markdown.\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 { transformMarkdownWithReact } from \"./transform\";\nimport { createReactMarkdownEnvironment } from \"./environment\";\nimport type {\n ReactIntegrationOptions,\n ResolvedReactOptions,\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): ResolvedReactOptions[\"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 ReactIntegrationOptions,\n ResolvedReactOptions,\n ComponentsOption,\n ComponentsMap,\n BuiltinEmbedOptions,\n GitHubEmbedOptions,\n OpenGraphEmbedOptions,\n ResolvedBuiltinEmbedOptions,\n ReactTransformResult,\n ComponentIsland,\n} from \"./types\";\n\n/**\n * Creates the Ox Content React integration plugin.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { defineConfig } from 'vite';\n * import react from '@vitejs/plugin-react';\n * import { oxContentReact } from 'vite-plugin-ox-content-react';\n *\n * export default defineConfig({\n * plugins: [\n * react(),\n * oxContentReact({\n * srcDir: 'docs',\n * components: {\n * Counter: './src/components/Counter.tsx',\n * },\n * }),\n * ],\n * });\n * ```\n */\nexport function oxContentReact(options: ReactIntegrationOptions = {}): PluginOption[] {\n const resolved = resolveReactOptions(options);\n let componentMap = new Map<string, string>();\n let config: ResolvedConfig;\n\n if (typeof options.components === \"object\" && !Array.isArray(options.components)) {\n componentMap = new Map(Object.entries(options.components));\n }\n\n const reactTransformPlugin: Plugin = {\n name: \"ox-content:react-transform\",\n enforce: \"pre\",\n\n async configResolved(resolvedConfig) {\n config = resolvedConfig;\n\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 transformMarkdownWithReact(code, id, {\n ...resolved,\n components: Object.fromEntries(componentMap),\n root: config.root,\n });\n\n return {\n code: result.code,\n map: result.map,\n };\n },\n };\n\n const reactEnvironmentPlugin: Plugin = {\n name: \"ox-content:react-environment\",\n\n config() {\n const envOptions = {\n ...resolved,\n components: Object.fromEntries(componentMap),\n };\n return {\n environments: {\n oxcontent_ssr: createReactMarkdownEnvironment(\"ssr\", envOptions),\n oxcontent_client: createReactMarkdownEnvironment(\"client\", envOptions),\n },\n };\n },\n\n resolveId(id) {\n if (id === \"virtual:ox-content-react/runtime\") {\n return \"\\0virtual:ox-content-react/runtime\";\n }\n if (id === \"virtual:ox-content-react/components\") {\n return \"\\0virtual:ox-content-react/components\";\n }\n return null;\n },\n\n load(id) {\n if (id === \"\\0virtual:ox-content-react/runtime\") {\n return generateRuntimeModule();\n }\n if (id === \"\\0virtual:ox-content-react/components\") {\n return generateComponentsModule(componentMap);\n }\n return null;\n },\n\n applyToEnvironment(environment) {\n return [\"oxcontent_ssr\", \"oxcontent_client\", \"client\", \"ssr\"].includes(environment.name);\n },\n };\n\n const reactHmrPlugin: Plugin = {\n name: \"ox-content:react-hmr\",\n apply: \"serve\",\n\n handleHotUpdate({ file, server, modules }) {\n const isComponent = Array.from(componentMap.values()).some((path) =>\n file.endsWith(path.replace(/^\\.\\//, \"\")),\n );\n\n if (isComponent) {\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:react-update\",\n data: { file },\n });\n return [...modules, ...mdModules];\n }\n }\n\n return modules;\n },\n };\n\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[] = [reactTransformPlugin, reactEnvironmentPlugin, reactHmrPlugin];\n\n if (environmentPlugin) {\n plugins.push(environmentPlugin);\n }\n\n return plugins;\n}\n\nfunction resolveReactOptions(\n options: ReactIntegrationOptions,\n): Omit<ResolvedReactOptions, \"components\"> {\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 jsxRuntime: options.jsxRuntime ?? \"automatic\",\n embeds: resolveBuiltinEmbedOptions(options.embeds),\n };\n}\n\nfunction resolveCodeAnnotationsOptions(\n options: ReactIntegrationOptions[\"codeAnnotations\"],\n): ResolvedReactOptions[\"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\nfunction generateRuntimeModule(): string {\n return `\nimport React, { useState, useEffect } from 'react';\n\nexport function OxContentRenderer({ content, components = {} }) {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n if (!content) return null;\n\n const { html, frontmatter, islands } = content;\n\n if (!mounted) {\n return React.createElement('div', {\n className: 'ox-content',\n dangerouslySetInnerHTML: { __html: html },\n });\n }\n\n return React.createElement('div', { className: 'ox-content' },\n islands.map((island) => {\n const Component = components[island.name];\n return Component\n ? React.createElement(Component, { key: island.id, ...island.props })\n : null;\n })\n );\n}\n\nexport function useOxContent() {\n return { OxContentRenderer };\n}\n`;\n}\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\nasync function resolveComponentsGlob(\n componentsOption: ComponentsOption,\n root: string,\n): Promise<ComponentsMap> {\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 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\nasync function globFiles(pattern: string, root: string): Promise<string[]> {\n const files: string[] = [];\n const isGlob = pattern.includes(\"*\");\n\n if (!isGlob) {\n const fullPath = path.resolve(root, pattern);\n if (fs.existsSync(fullPath)) {\n files.push(fullPath);\n }\n return files;\n }\n\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 if (pattern.includes(\"**\")) {\n await walkDir(baseDir, files, ext);\n } else {\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\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\nfunction toPascalCase(str: string): string {\n return str.replace(/[-_](\\w)/g, (_, c) => c.toUpperCase()).replace(/^\\w/, (c) => c.toUpperCase());\n}\n\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":["import {\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 {\n ResolvedReactOptions,\n ReactTransformResult,\n ComponentIsland,\n ComponentsMap,\n} from \"./types\";\n\nconst COMPONENT_REGEX = /<([A-Z][a-zA-Z0-9]*)\\s*([^>]*?)\\s*(?:\\/>|>([\\s\\S]*?)<\\/\\1>)/g;\nconst PROP_REGEX = /([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\nexport async function transformMarkdownWithReact(\n code: string,\n id: string,\n options: ResolvedReactOptions,\n): Promise<ReactTransformResult> {\n const components: ComponentsMap = options.components;\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?: ResolvedReactOptions[\"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: generateReactModule(\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 if (\n !Object.prototype.hasOwnProperty.call(components, componentName) ||\n isInRanges(matchStart, matchEnd, fenceRanges)\n ) {\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 const props = parseProps(propsString);\n const islandId = `ox-island-${islandIndex++}`;\n const islandContent =\n typeof rawIslandContent === \"string\" ? rawIslandContent.trim() : undefined;\n\n islands.push({\n name: componentName,\n props,\n position: matchStart,\n id: islandId,\n content: islandContent,\n });\n\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 const htmlWithIslands = injectIslandMarkers(transformed.html, islands);\n const jsxCode = generateReactModule(\n htmlWithIslands,\n usedComponents,\n islands,\n frontmatter,\n options,\n id,\n );\n\n return {\n code: jsxCode,\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\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 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 try {\n value = JSON.parse(value as string);\n } catch {\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 frontmatter[key] = value;\n }\n }\n\n return { content: content.slice(match[0].length), frontmatter };\n}\n\nfunction parseProps(propsString: string): Record<string, unknown> {\n const props: Record<string, unknown> = {};\n if (!propsString) return props;\n\n PROP_REGEX.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = PROP_REGEX.exec(propsString)) !== null) {\n const [, name, doubleQuoted, singleQuoted, braceValue, bracketValue] = match;\n if (name) {\n if (doubleQuoted !== undefined) props[name] = doubleQuoted;\n else if (singleQuoted !== undefined) props[name] = singleQuoted;\n else if (braceValue !== undefined) {\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 props[name] = true;\n }\n }\n return props;\n}\n\nfunction generateReactModule(\n content: string,\n usedComponents: string[],\n _islands: ComponentIsland[] | string[],\n frontmatter: Record<string, unknown>,\n options: ResolvedReactOptions & { root?: string },\n id: string,\n localBindings?: ReadonlyMap<string, ResolvedDocumentComponentImport>,\n): string {\n const imports = 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 React, { createElement } from 'react';\n\nexport const frontmatter = ${JSON.stringify(frontmatter)};\n\nconst rawHtml = ${JSON.stringify(content)};\n\nexport default function MarkdownContent() {\n return createElement('div', {\n className: 'ox-content',\n dangerouslySetInnerHTML: { __html: rawHtml },\n });\n}\n`;\n }\n\n return `\nimport React, { useEffect, useRef, createElement } from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { initIslands, readIslandSlotHtml } from '@ox-content/islands';\n${imports}\n\nexport const frontmatter = ${JSON.stringify(frontmatter)};\n\nconst rawHtml = ${JSON.stringify(content)};\nconst components = {\n${componentMap}\n};\n\nfunction createReactHydrate() {\n const mountedRoots = [];\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 vnode = islandContent\n ? createElement(\n Component,\n props,\n createElement('div', { dangerouslySetInnerHTML: { __html: islandContent } })\n )\n : createElement(Component, props);\n\n const root = createRoot(element);\n root.render(vnode);\n mountedRoots.push(root);\n\n return () => root.unmount();\n };\n}\n\nexport default function MarkdownContent() {\n const containerRef = useRef(null);\n\n useEffect(() => {\n if (!containerRef.current) return;\n const controller = initIslands(createReactHydrate(), {\n selector: '.ox-content [data-ox-island]',\n });\n return () => controller.destroy();\n }, []);\n\n return createElement('div', {\n className: 'ox-content',\n ref: containerRef,\n dangerouslySetInnerHTML: { __html: rawHtml },\n });\n}\n`;\n}\n","import type { EnvironmentOptions } from \"vite\";\nimport type { ResolvedReactOptions } from \"./types\";\n\nexport function createReactMarkdownEnvironment(\n mode: \"ssr\" | \"client\",\n options: ResolvedReactOptions,\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 ssr: isSSR,\n rollupOptions: {\n output: {\n format: \"esm\",\n entryFileNames: isSSR ? \"[name].js\" : \"[name].[hash].js\",\n },\n },\n ...(isSSR && { target: \"node18\", minify: false }),\n },\n resolve: {\n conditions: isSSR ? [\"node\", \"import\"] : [\"browser\", \"import\"],\n },\n optimizeDeps: {\n include: isSSR ? [] : [\"react\", \"react-dom\"],\n exclude: [\"@ox-content/vite-plugin\", \"@ox-content/vite-plugin-react\"],\n },\n };\n}\n","/**\n * Vite Plugin for Ox Content React Integration\n *\n * Uses Vite's Environment API to enable embedding React components in Markdown.\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 { transformMarkdownWithReact } from \"./transform\";\nimport { createReactMarkdownEnvironment } from \"./environment\";\nimport type {\n ReactIntegrationOptions,\n ResolvedReactOptions,\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): ResolvedReactOptions[\"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 ReactIntegrationOptions,\n ResolvedReactOptions,\n ComponentsOption,\n ComponentsMap,\n BuiltinEmbedOptions,\n GitHubEmbedOptions,\n OpenGraphEmbedOptions,\n ResolvedBuiltinEmbedOptions,\n ReactTransformResult,\n ComponentIsland,\n} from \"./types\";\n\n/**\n * Creates the Ox Content React integration plugin.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { defineConfig } from 'vite';\n * import react from '@vitejs/plugin-react';\n * import { oxContentReact } from 'vite-plugin-ox-content-react';\n *\n * export default defineConfig({\n * plugins: [\n * react(),\n * oxContentReact({\n * srcDir: 'docs',\n * components: {\n * Counter: './src/components/Counter.tsx',\n * },\n * }),\n * ],\n * });\n * ```\n */\nexport function oxContentReact(options: ReactIntegrationOptions = {}): PluginOption[] {\n const resolved = resolveReactOptions(options);\n let componentMap = new Map<string, string>();\n let config: ResolvedConfig;\n\n if (typeof options.components === \"object\" && !Array.isArray(options.components)) {\n componentMap = new Map(Object.entries(options.components));\n }\n\n const reactTransformPlugin: Plugin = {\n name: \"ox-content:react-transform\",\n enforce: \"pre\",\n\n async configResolved(resolvedConfig) {\n config = resolvedConfig;\n\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 transformMarkdownWithReact(code, id, {\n ...resolved,\n components: Object.fromEntries(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 const reactEnvironmentPlugin: Plugin = {\n name: \"ox-content:react-environment\",\n\n config() {\n const envOptions = {\n ...resolved,\n components: Object.fromEntries(componentMap),\n };\n return {\n environments: {\n oxcontent_ssr: createReactMarkdownEnvironment(\"ssr\", envOptions),\n oxcontent_client: createReactMarkdownEnvironment(\"client\", envOptions),\n },\n };\n },\n\n resolveId(id) {\n if (id === \"virtual:ox-content-react/runtime\") {\n return \"\\0virtual:ox-content-react/runtime\";\n }\n if (id === \"virtual:ox-content-react/components\") {\n return \"\\0virtual:ox-content-react/components\";\n }\n return null;\n },\n\n load(id) {\n if (id === \"\\0virtual:ox-content-react/runtime\") {\n return generateRuntimeModule();\n }\n if (id === \"\\0virtual:ox-content-react/components\") {\n return generateComponentsModule(componentMap);\n }\n return null;\n },\n\n applyToEnvironment(environment) {\n return [\"oxcontent_ssr\", \"oxcontent_client\", \"client\", \"ssr\"].includes(environment.name);\n },\n };\n\n const reactHmrPlugin: Plugin = {\n name: \"ox-content:react-hmr\",\n apply: \"serve\",\n\n handleHotUpdate({ file, server, modules }) {\n const isComponent = Array.from(componentMap.values()).some((path) =>\n file.endsWith(path.replace(/^\\.\\//, \"\")),\n );\n\n if (isComponent) {\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:react-update\",\n data: { file },\n });\n return [...modules, ...mdModules];\n }\n }\n\n return modules;\n },\n };\n\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[] = [reactTransformPlugin, reactEnvironmentPlugin, reactHmrPlugin];\n\n if (environmentPlugin) {\n plugins.push(environmentPlugin);\n }\n\n return plugins;\n}\n\nfunction resolveReactOptions(\n options: ReactIntegrationOptions,\n): Omit<ResolvedReactOptions, \"components\"> {\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 jsxRuntime: options.jsxRuntime ?? \"automatic\",\n embeds: resolveBuiltinEmbedOptions(options.embeds),\n mdx: options.mdx,\n };\n}\n\nfunction resolveCodeAnnotationsOptions(\n options: ReactIntegrationOptions[\"codeAnnotations\"],\n): ResolvedReactOptions[\"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\nfunction generateRuntimeModule(): string {\n return `\nimport React, { useState, useEffect } from 'react';\n\nexport function OxContentRenderer({ content, components = {} }) {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n if (!content) return null;\n\n const { html, frontmatter, islands } = content;\n\n if (!mounted) {\n return React.createElement('div', {\n className: 'ox-content',\n dangerouslySetInnerHTML: { __html: html },\n });\n }\n\n return React.createElement('div', { className: 'ox-content' },\n islands.map((island) => {\n const Component = components[island.name];\n return Component\n ? React.createElement(Component, { key: island.id, ...island.props })\n : null;\n })\n );\n}\n\nexport function useOxContent() {\n return { OxContentRenderer };\n}\n`;\n}\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\nasync function resolveComponentsGlob(\n componentsOption: ComponentsOption,\n root: string,\n): Promise<ComponentsMap> {\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 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\nasync function globFiles(pattern: string, root: string): Promise<string[]> {\n const files: string[] = [];\n const isGlob = pattern.includes(\"*\");\n\n if (!isGlob) {\n const fullPath = path.resolve(root, pattern);\n if (fs.existsSync(fullPath)) {\n files.push(fullPath);\n }\n return files;\n }\n\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 if (pattern.includes(\"**\")) {\n await walkDir(baseDir, files, ext);\n } else {\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\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\nfunction toPascalCase(str: string): string {\n return str.replace(/[-_](\\w)/g, (_, c) => c.toUpperCase()).replace(/^\\w/, (c) => c.toUpperCase());\n}\n\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-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.2",
|
|
4
4
|
"description": "React integration for Ox Content - Embed React components in Markdown",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -35,20 +35,20 @@
|
|
|
35
35
|
"provenance": true
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@ox-content/islands": "
|
|
39
|
-
"@ox-content/vite-plugin": "
|
|
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
|
"@types/react": "^19.2.18",
|
|
44
44
|
"@types/react-dom": "^19.2.4",
|
|
45
45
|
"@typescript/native-preview": "^7.0.0-dev.20260707.2",
|
|
46
|
-
"@vitejs/plugin-react": "^6.0
|
|
46
|
+
"@vitejs/plugin-react": "^6.1.0",
|
|
47
47
|
"react": "^19.0.0",
|
|
48
48
|
"react-dom": "^19.0.0",
|
|
49
49
|
"typescript": "^7.0.2",
|
|
50
50
|
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.8",
|
|
51
|
-
"vite-plus": "0.2.
|
|
51
|
+
"vite-plus": "0.2.9"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
54
|
"react": "^19.0.0",
|