veryfront 0.1.369 → 0.1.370

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.
Files changed (80) hide show
  1. package/esm/cli/commands/build/command.d.ts.map +1 -1
  2. package/esm/cli/commands/build/command.js +2 -0
  3. package/esm/cli/shared/ensure-content-transformer.d.ts +10 -0
  4. package/esm/cli/shared/ensure-content-transformer.d.ts.map +1 -0
  5. package/esm/cli/shared/ensure-content-transformer.js +16 -0
  6. package/esm/cli/shared/server-startup.d.ts.map +1 -1
  7. package/esm/cli/shared/server-startup.js +10 -3
  8. package/esm/deno.js +2 -1
  9. package/esm/extensions/ext-mdx/src/compiler/markdown-compile.d.ts +3 -0
  10. package/esm/extensions/ext-mdx/src/compiler/markdown-compile.d.ts.map +1 -0
  11. package/esm/extensions/ext-mdx/src/compiler/markdown-compile.js +99 -0
  12. package/esm/extensions/ext-mdx/src/compiler/mdx-compile.d.ts +3 -0
  13. package/esm/extensions/ext-mdx/src/compiler/mdx-compile.d.ts.map +1 -0
  14. package/esm/extensions/ext-mdx/src/compiler/mdx-compile.js +47 -0
  15. package/esm/extensions/ext-mdx/src/index.d.ts +30 -0
  16. package/esm/extensions/ext-mdx/src/index.d.ts.map +1 -0
  17. package/esm/extensions/ext-mdx/src/index.js +52 -0
  18. package/esm/extensions/ext-mdx/src/plugins/plugin-loader.d.ts +4 -0
  19. package/esm/extensions/ext-mdx/src/plugins/plugin-loader.d.ts.map +1 -0
  20. package/esm/extensions/ext-mdx/src/plugins/plugin-loader.js +18 -0
  21. package/esm/extensions/ext-mdx/src/plugins/rehype-node-positions.d.ts.map +1 -0
  22. package/esm/extensions/ext-mdx/src/plugins/remark-headings.d.ts.map +1 -0
  23. package/esm/extensions/ext-mdx/src/plugins/remark-mdx-utils.d.ts.map +1 -0
  24. package/esm/src/agent/fork-runtime-stream.d.ts +4 -4
  25. package/esm/src/agent/fork-runtime-stream.d.ts.map +1 -1
  26. package/esm/src/extensions/interfaces/content-transformer.d.ts +75 -24
  27. package/esm/src/extensions/interfaces/content-transformer.d.ts.map +1 -1
  28. package/esm/src/extensions/interfaces/content-transformer.js +13 -0
  29. package/esm/src/extensions/interfaces/index.d.ts +1 -1
  30. package/esm/src/extensions/interfaces/index.d.ts.map +1 -1
  31. package/esm/src/integrations/schema.d.ts +4 -4
  32. package/esm/src/transforms/md/compiler/md-compiler.d.ts +2 -2
  33. package/esm/src/transforms/md/compiler/md-compiler.d.ts.map +1 -1
  34. package/esm/src/transforms/md/compiler/md-compiler.js +11 -106
  35. package/esm/src/transforms/mdx/compiler/import-rewriter.d.ts +1 -1
  36. package/esm/src/transforms/mdx/compiler/import-rewriter.d.ts.map +1 -1
  37. package/esm/src/transforms/mdx/compiler/index.d.ts +3 -3
  38. package/esm/src/transforms/mdx/compiler/index.d.ts.map +1 -1
  39. package/esm/src/transforms/mdx/compiler/mdx-compiler.d.ts +2 -2
  40. package/esm/src/transforms/mdx/compiler/mdx-compiler.d.ts.map +1 -1
  41. package/esm/src/transforms/mdx/compiler/mdx-compiler.js +10 -52
  42. package/esm/src/transforms/plugins/plugin-loader.d.ts +15 -0
  43. package/esm/src/transforms/plugins/plugin-loader.d.ts.map +1 -1
  44. package/esm/src/transforms/plugins/plugin-loader.js +20 -14
  45. package/esm/src/utils/version-constant.d.ts +1 -1
  46. package/esm/src/utils/version-constant.js +1 -1
  47. package/package.json +1 -1
  48. package/src/cli/commands/build/command.ts +2 -0
  49. package/src/cli/shared/ensure-content-transformer.ts +17 -0
  50. package/src/cli/shared/server-startup.ts +10 -3
  51. package/src/deno.js +2 -1
  52. package/src/extensions/ext-mdx/src/compiler/markdown-compile.ts +127 -0
  53. package/src/extensions/ext-mdx/src/compiler/mdx-compile.ts +73 -0
  54. package/src/extensions/ext-mdx/src/index.ts +63 -0
  55. package/src/extensions/ext-mdx/src/plugins/plugin-loader.ts +21 -0
  56. package/src/src/agent/fork-runtime-stream.ts +9 -4
  57. package/src/src/extensions/interfaces/content-transformer.ts +74 -20
  58. package/src/src/extensions/interfaces/index.ts +5 -2
  59. package/src/src/transforms/md/compiler/md-compiler.ts +17 -137
  60. package/src/src/transforms/mdx/compiler/import-rewriter.ts +1 -1
  61. package/src/src/transforms/mdx/compiler/index.ts +11 -3
  62. package/src/src/transforms/mdx/compiler/mdx-compiler.ts +15 -70
  63. package/src/src/transforms/plugins/plugin-loader.ts +22 -24
  64. package/src/src/utils/version-constant.ts +1 -1
  65. package/esm/src/transforms/mdx/compiler/types.d.ts +0 -16
  66. package/esm/src/transforms/mdx/compiler/types.d.ts.map +0 -1
  67. package/esm/src/transforms/mdx/compiler/types.js +0 -1
  68. package/esm/src/transforms/plugins/rehype-node-positions.d.ts.map +0 -1
  69. package/esm/src/transforms/plugins/remark-headings.d.ts.map +0 -1
  70. package/esm/src/transforms/plugins/remark-mdx-utils.d.ts.map +0 -1
  71. package/src/src/transforms/mdx/compiler/types.ts +0 -12
  72. /package/esm/{src/transforms → extensions/ext-mdx/src}/plugins/rehype-node-positions.d.ts +0 -0
  73. /package/esm/{src/transforms → extensions/ext-mdx/src}/plugins/rehype-node-positions.js +0 -0
  74. /package/esm/{src/transforms → extensions/ext-mdx/src}/plugins/remark-headings.d.ts +0 -0
  75. /package/esm/{src/transforms → extensions/ext-mdx/src}/plugins/remark-headings.js +0 -0
  76. /package/esm/{src/transforms → extensions/ext-mdx/src}/plugins/remark-mdx-utils.d.ts +0 -0
  77. /package/esm/{src/transforms → extensions/ext-mdx/src}/plugins/remark-mdx-utils.js +0 -0
  78. /package/src/{src/transforms → extensions/ext-mdx/src}/plugins/rehype-node-positions.ts +0 -0
  79. /package/src/{src/transforms → extensions/ext-mdx/src}/plugins/remark-headings.ts +0 -0
  80. /package/src/{src/transforms → extensions/ext-mdx/src}/plugins/remark-mdx-utils.ts +0 -0
@@ -11,7 +11,7 @@ export type { ImportSpecifier, ModuleLexer } from "./module-lexer.js";
11
11
  export type { CacheStore } from "./cache-store.js";
12
12
  export type { TokenCacheEntry, TokenCacheStats, TokenCacheStore } from "./token-cache-store.js";
13
13
  export type { CSSCompileOptions, CSSCompiler, CSSModuleSource, CSSProcessor, CSSStylesheetSource, } from "./css-processor.js";
14
- export type { ContentTransformer, ContentTransformOptions, ContentTransformResult, } from "./content-transformer.js";
14
+ export type { CompilationMode, CompilationTarget, ContentCompileOptions, ContentPlugin, ContentRuntimeBundle, ContentTransformer, } from "./content-transformer.js";
15
15
  export type { DatabaseClient, QueryResult } from "./database-client.js";
16
16
  export type { AuthProvider, SignOptions, TokenHeader, TokenPayload, VerifyOptions, } from "./auth-provider.js";
17
17
  export type { SpanData, TracerProvider, TracingExporter } from "./tracing-exporter.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/extensions/interfaces/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,4BAA4B,CAAC;AAEpC,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,aAAa,EACb,kBAAkB,EAClB,MAAM,EACN,QAAQ,EACR,aAAa,EACb,cAAc,EACd,UAAU,EACV,YAAY,EACZ,aAAa,EACb,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGtE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGhG,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,YAAY,EACZ,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxE,YAAY,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,GACd,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGvF,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAGpG,YAAY,EACV,OAAO,EACP,UAAU,EACV,eAAe,EACf,cAAc,EACd,6BAA6B,EAC7B,QAAQ,EACR,YAAY,EACZ,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,WAAW,EACX,UAAU,EACV,MAAM,EACN,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EACV,kBAAkB,EAClB,UAAU,EACV,wBAAwB,EACxB,eAAe,GAChB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/extensions/interfaces/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,4BAA4B,CAAC;AAEpC,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,aAAa,EACb,kBAAkB,EAClB,MAAM,EACN,QAAQ,EACR,aAAa,EACb,cAAc,EACd,UAAU,EACV,YAAY,EACZ,aAAa,EACb,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGtE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGhG,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,YAAY,EACZ,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxE,YAAY,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,GACd,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGvF,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAGpG,YAAY,EACV,OAAO,EACP,UAAU,EACV,eAAe,EACf,cAAc,EACd,6BAA6B,EAC7B,QAAQ,EACR,YAAY,EACZ,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,WAAW,EACX,UAAU,EACV,MAAM,EACN,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EACV,kBAAkB,EAClB,UAAU,EACV,wBAAwB,EACxB,eAAe,GAChB,MAAM,kBAAkB,CAAC"}
@@ -119,8 +119,8 @@ export declare const IntegrationEndpointParamSchema: z.ZodObject<{
119
119
  in: z.ZodEnum<{
120
120
  path: "path";
121
121
  body: "body";
122
- header: "header";
123
122
  query: "query";
123
+ header: "header";
124
124
  }>;
125
125
  description: z.ZodString;
126
126
  required: z.ZodOptional<z.ZodBoolean>;
@@ -164,8 +164,8 @@ export declare const IntegrationEndpointSchema: z.ZodObject<{
164
164
  in: z.ZodEnum<{
165
165
  path: "path";
166
166
  body: "body";
167
- header: "header";
168
167
  query: "query";
168
+ header: "header";
169
169
  }>;
170
170
  description: z.ZodString;
171
171
  required: z.ZodOptional<z.ZodBoolean>;
@@ -220,8 +220,8 @@ export declare const IntegrationToolSchema: z.ZodObject<{
220
220
  in: z.ZodEnum<{
221
221
  path: "path";
222
222
  body: "body";
223
- header: "header";
224
223
  query: "query";
224
+ header: "header";
225
225
  }>;
226
226
  description: z.ZodString;
227
227
  required: z.ZodOptional<z.ZodBoolean>;
@@ -389,8 +389,8 @@ export declare const IntegrationConfigSchema: z.ZodObject<{
389
389
  in: z.ZodEnum<{
390
390
  path: "path";
391
391
  body: "body";
392
- header: "header";
393
392
  query: "query";
393
+ header: "header";
394
394
  }>;
395
395
  description: z.ZodString;
396
396
  required: z.ZodOptional<z.ZodBoolean>;
@@ -1,3 +1,3 @@
1
- import type { CompilationMode, CompilationTarget, MdxRuntimeBundle } from "../../mdx/compiler/types.js";
2
- export declare function compileMarkdownRuntime(_mode: CompilationMode, _projectDir: string, content: string, frontmatter?: Record<string, unknown>, filePath?: string, _target?: CompilationTarget, _baseUrl?: string, studioEmbed?: boolean): Promise<MdxRuntimeBundle>;
1
+ import type { CompilationMode, CompilationTarget, ContentRuntimeBundle } from "../../../extensions/interfaces/index.js";
2
+ export declare function compileMarkdownRuntime(mode: CompilationMode, projectDir: string, content: string, frontmatter?: Record<string, unknown>, filePath?: string, target?: CompilationTarget, baseUrl?: string, studioEmbed?: boolean): Promise<ContentRuntimeBundle>;
3
3
  //# sourceMappingURL=md-compiler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"md-compiler.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/md/compiler/md-compiler.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,6BAA6B,CAAC;AAoDrC,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,eAAe,EACtB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,GAAE,iBAA4B,EACrC,QAAQ,CAAC,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,gBAAgB,CAAC,CAmG3B"}
1
+ {"version":3,"file":"md-compiler.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/md/compiler/md-compiler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EAErB,MAAM,yCAAyC,CAAC;AAMjD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,eAAe,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,GAAE,iBAA4B,EACpC,OAAO,CAAC,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,oBAAoB,CAAC,CAsC/B"}
@@ -1,117 +1,22 @@
1
- import { unified } from "unified";
2
- import remarkParse from "remark-parse";
3
- import remarkGfm from "remark-gfm";
4
- import remarkFrontmatter from "remark-frontmatter";
5
- import remarkRehype from "remark-rehype";
6
- import rehypeStarryNight from "rehype-starry-night";
7
- import rehypeSlug from "rehype-slug";
8
- import rehypeRaw from "rehype-raw";
9
- import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
10
- import rehypeStringify from "rehype-stringify";
11
- import { visit } from "unist-util-visit";
12
- import { toString } from "mdast-util-to-string";
13
1
  import { rendererLogger } from "../../../utils/index.js";
14
- import { rehypeNodePositions } from "../../plugins/rehype-node-positions.js";
15
- import { extractFrontmatter } from "../../mdx/compiler/frontmatter-extractor.js";
16
- import { isMarkdownPreview as checkMarkdownPreview } from "../utils.js";
2
+ import { resolve as resolveContract } from "../../../extensions/contracts.js";
17
3
  import { createError, toError } from "../../../errors/veryfront-error.js";
18
4
  import { withSpan } from "../../../observability/tracing/otlp-setup.js";
19
- import Slugger from "github-slugger";
20
5
  const logger = rendererLogger.component("md-compiler");
21
- function remarkExtractHeadings(headings) {
22
- const slugger = new Slugger();
23
- return (tree) => {
24
- visit(tree, "heading", (node) => {
25
- const text = toString(node);
26
- const id = slugger.slug(text);
27
- headings.push({ id, text, level: node.depth });
28
- });
29
- };
30
- }
31
- function escapeForJsString(str) {
32
- return str.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
33
- }
34
- function createCompiledCode(escapedHtml, isPreview) {
35
- if (isPreview) {
36
- return `import { jsx as _jsx } from "react/jsx-runtime";
37
- export default function MDContent({ components, params, ...props }) {
38
- return _jsx("div", {
39
- className: "markdown-body",
40
- dangerouslySetInnerHTML: { __html: \`${escapedHtml}\` }
41
- });
42
- }
43
- `;
44
- }
45
- return `import { jsx as _jsx } from "react/jsx-runtime";
46
- export default function MDContent({ components, params, className, ...props }) {
47
- return _jsx("div", {
48
- className,
49
- dangerouslySetInnerHTML: { __html: \`${escapedHtml}\` }
50
- });
51
- }
52
- `;
53
- }
54
- export function compileMarkdownRuntime(_mode, _projectDir, content, frontmatter, filePath, _target = "server", _baseUrl, studioEmbed) {
6
+ export function compileMarkdownRuntime(mode, projectDir, content, frontmatter, filePath, target = "server", baseUrl, studioEmbed) {
55
7
  return withSpan("transforms.compileMarkdownRuntime", async () => {
56
8
  try {
57
- const { body, frontmatter: extractedFrontmatter } = extractFrontmatter(content, frontmatter);
58
- const headings = [];
59
- const pipeline = unified()
60
- .use(remarkParse)
61
- .use(remarkGfm)
62
- .use(remarkFrontmatter)
63
- .use(remarkExtractHeadings, headings)
64
- .use(remarkRehype, { allowDangerousHtml: true })
65
- .use(rehypeStarryNight)
66
- .use(rehypeSlug);
67
- // Parse raw HTML nodes into proper elements before sanitizing.
68
- pipeline.use(rehypeRaw);
69
- // Add node positions after rehype-raw so attributes survive re-parsing.
70
- if (studioEmbed && filePath) {
71
- pipeline.use(rehypeNodePositions, { filePath });
72
- }
73
- // Extend the sanitize schema in studio embed mode to preserve
74
- // data-node-* attributes used for element-to-source mapping.
75
- const sanitizeSchema = studioEmbed
76
- ? {
77
- ...defaultSchema,
78
- attributes: {
79
- ...defaultSchema.attributes,
80
- "*": [
81
- ...(defaultSchema.attributes?.["*"] ?? []),
82
- "data-node-file",
83
- "data-node-name",
84
- "data-node-line",
85
- "data-node-column",
86
- "data-node-source",
87
- ],
88
- },
89
- }
90
- : defaultSchema;
91
- const result = await pipeline
92
- .use(rehypeSanitize, sanitizeSchema)
93
- .use(rehypeStringify)
94
- .process(body);
95
- const html = String(result);
96
- logger.debug("Compiled markdown:", {
9
+ const transformer = resolveContract("ContentTransformer");
10
+ return await transformer.compileMarkdown({
11
+ mode,
12
+ projectDir,
13
+ content,
14
+ frontmatter,
97
15
  filePath,
98
- htmlLength: html.length,
99
- headingsCount: headings.length,
16
+ target,
17
+ baseUrl,
18
+ studioEmbed,
100
19
  });
101
- const escapedHtml = escapeForJsString(html);
102
- // Use GitHub-style wrapper for standalone markdown files (not in pages/ or app/)
103
- // unless prose: false in frontmatter
104
- const isPreview = checkMarkdownPreview(filePath, extractedFrontmatter);
105
- // Note: destructure params/components to prevent them from spreading to DOM
106
- const compiledCode = createCompiledCode(escapedHtml, isPreview);
107
- return {
108
- compiledCode,
109
- frontmatter: extractedFrontmatter,
110
- globals: {},
111
- headings,
112
- nodeMap: new Map(),
113
- rawHtml: html,
114
- };
115
20
  }
116
21
  catch (error) {
117
22
  const err = error instanceof Error ? error : new Error(String(error));
@@ -1,4 +1,4 @@
1
- import type { CompilationTarget } from "./types.js";
1
+ import type { CompilationTarget } from "../../../extensions/interfaces/index.js";
2
2
  export interface ImportRewriterConfig {
3
3
  filePath: string;
4
4
  target: CompilationTarget;
@@ -1 +1 @@
1
- {"version":3,"file":"import-rewriter.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/compiler/import-rewriter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA8ED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAWrF;AAED,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAyBjG"}
1
+ {"version":3,"file":"import-rewriter.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/compiler/import-rewriter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAEjF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA8ED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAWrF;AAED,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAyBjG"}
@@ -6,9 +6,9 @@
6
6
  export { compileMDXRuntime } from "./mdx-compiler.js";
7
7
  export { extractFrontmatter } from "./frontmatter-extractor.js";
8
8
  export { rewriteBodyImports, rewriteCompiledImports } from "./import-rewriter.js";
9
- export type { CompilationMode, CompilationTarget, MdxRuntimeBundle } from "./types.js";
9
+ export type { CompilationMode, CompilationTarget, ContentRuntimeBundle, } from "../../../extensions/interfaces/index.js";
10
10
  export type { FrontmatterExtractionResult } from "./frontmatter-extractor.js";
11
11
  export type { ImportRewriterConfig } from "./import-rewriter.js";
12
- import type { CompilationMode, CompilationTarget, MdxRuntimeBundle } from "./types.js";
13
- export declare function compileContent(mode: CompilationMode, projectDir: string, content: string, frontmatter?: Record<string, unknown>, filePath?: string, target?: CompilationTarget, baseUrl?: string, studioEmbed?: boolean): Promise<MdxRuntimeBundle>;
12
+ import type { CompilationMode, CompilationTarget, ContentRuntimeBundle } from "../../../extensions/interfaces/index.js";
13
+ export declare function compileContent(mode: CompilationMode, projectDir: string, content: string, frontmatter?: Record<string, unknown>, filePath?: string, target?: CompilationTarget, baseUrl?: string, studioEmbed?: boolean): Promise<ContentRuntimeBundle>;
14
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/compiler/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAClF,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACvF,YAAY,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAC9E,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAIjE,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAMvF,wBAAgB,cAAc,CAC5B,IAAI,EAAE,eAAe,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,GAAE,iBAA4B,EACpC,OAAO,CAAC,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,gBAAgB,CAAC,CAwB3B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/compiler/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAClF,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,yCAAyC,CAAC;AACjD,YAAY,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAC9E,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAIjE,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,yCAAyC,CAAC;AAMjD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,eAAe,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,GAAE,iBAA4B,EACpC,OAAO,CAAC,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,oBAAoB,CAAC,CAwB/B"}
@@ -1,3 +1,3 @@
1
- import type { CompilationMode, CompilationTarget, MdxRuntimeBundle } from "./types.js";
2
- export declare function compileMDXRuntime(_mode: CompilationMode, projectDir: string, content: string, frontmatter?: Record<string, unknown>, filePath?: string, target?: CompilationTarget, baseUrl?: string, studioEmbed?: boolean): Promise<MdxRuntimeBundle>;
1
+ import type { CompilationMode, CompilationTarget, ContentRuntimeBundle } from "../../../extensions/interfaces/index.js";
2
+ export declare function compileMDXRuntime(mode: CompilationMode, projectDir: string, content: string, frontmatter?: Record<string, unknown>, filePath?: string, target?: CompilationTarget, baseUrl?: string, studioEmbed?: boolean): Promise<ContentRuntimeBundle>;
3
3
  //# sourceMappingURL=mdx-compiler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mdx-compiler.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/compiler/mdx-compiler.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAQvF,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,eAAe,EACtB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,GAAE,iBAA4B,EACpC,OAAO,CAAC,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA6F3B"}
1
+ {"version":3,"file":"mdx-compiler.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/compiler/mdx-compiler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EAErB,MAAM,yCAAyC,CAAC;AAMjD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,eAAe,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,GAAE,iBAA4B,EACpC,OAAO,CAAC,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,oBAAoB,CAAC,CAuC/B"}
@@ -1,64 +1,22 @@
1
1
  import { rendererLogger } from "../../../utils/index.js";
2
- import { getRehypePlugins, getRemarkPlugins } from "../../plugins/plugin-loader.js";
3
- import { rehypeNodePositions } from "../../plugins/rehype-node-positions.js";
4
- import { extractFrontmatter } from "./frontmatter-extractor.js";
5
- import { rewriteBodyImports, rewriteCompiledImports } from "./import-rewriter.js";
2
+ import { resolve as resolveContract } from "../../../extensions/contracts.js";
6
3
  import { createError, toError } from "../../../errors/veryfront-error.js";
7
4
  import { withSpan } from "../../../observability/tracing/otlp-setup.js";
8
5
  const logger = rendererLogger.component("mdx-compiler");
9
- export function compileMDXRuntime(_mode, projectDir, content, frontmatter, filePath, target = "server", baseUrl, studioEmbed) {
6
+ export function compileMDXRuntime(mode, projectDir, content, frontmatter, filePath, target = "server", baseUrl, studioEmbed) {
10
7
  return withSpan("transforms.compileMDXRuntime", async () => {
11
8
  try {
12
- const { compile } = await import("@mdx-js/mdx");
13
- const remarkPlugins = (await getRemarkPlugins());
14
- const rehypePlugins = (await getRehypePlugins());
15
- if (studioEmbed && filePath) {
16
- rehypePlugins.push([rehypeNodePositions, { filePath }]);
17
- }
18
- const { body: extractedBody, frontmatter: extractedFrontmatter } = extractFrontmatter(content, frontmatter);
19
- const shouldRewriteImports = Boolean(filePath) &&
20
- (target === "browser" || target === "server");
21
- const body = shouldRewriteImports
22
- ? rewriteBodyImports(extractedBody, { filePath: filePath, target, baseUrl, projectDir })
23
- : extractedBody;
24
- logger.debug("Body metrics:", {
9
+ const transformer = resolveContract("ContentTransformer");
10
+ return await transformer.compileMdx({
11
+ mode,
12
+ projectDir,
13
+ content,
14
+ frontmatter,
25
15
  filePath,
26
16
  target,
27
- contentLength: content.length,
28
- bodyBeforeLength: extractedBody.length,
29
- bodyAfterLength: body.length,
30
- hasImport: body.includes("import"),
31
- importMatch: body.match(/^import\s+/m)?.[0] ?? "none",
17
+ baseUrl,
18
+ studioEmbed,
32
19
  });
33
- const compiled = await compile(body, {
34
- outputFormat: "program",
35
- development: false,
36
- remarkPlugins,
37
- rehypePlugins,
38
- providerImportSource: undefined,
39
- jsxImportSource: "react",
40
- });
41
- const headings = compiled.data?.headings ??
42
- [];
43
- logger.debug("MDX compiled output preview:", String(compiled).substring(0, 200));
44
- logger.debug("Extracted frontmatter:", extractedFrontmatter);
45
- logger.debug("Extracted headings count:", headings.length);
46
- const compiledString = String(compiled);
47
- const compiledCode = shouldRewriteImports
48
- ? rewriteCompiledImports(compiledString, {
49
- filePath: filePath,
50
- target,
51
- baseUrl,
52
- projectDir,
53
- })
54
- : compiledString;
55
- return {
56
- compiledCode,
57
- frontmatter: extractedFrontmatter,
58
- globals: {},
59
- headings,
60
- nodeMap: new Map(),
61
- };
62
20
  }
63
21
  catch (error) {
64
22
  logger.error("Compilation failed:", {
@@ -1,3 +1,18 @@
1
+ /**
2
+ * Shim that routes MDX plugin lookups through the `ContentTransformer`
3
+ * extension contract (default implementation: `@veryfront/ext-mdx`).
4
+ *
5
+ * Build-time MDX compilers (`src/build/compiler/mdx-compiler/mdx-processor.ts`,
6
+ * `src/build/renderer/services/mdx-bundler.ts`, `layout-applicator.ts`)
7
+ * historically imported `getRemarkPlugins` / `getRehypePlugins` directly.
8
+ * Now those callers get the canonical plugin list from whichever
9
+ * `ContentTransformer` implementation is registered.
10
+ *
11
+ * When no implementation is registered, the lookup throws with an
12
+ * actionable install message pointing at `@veryfront/ext-mdx`.
13
+ *
14
+ * @module transforms/plugins/plugin-loader
15
+ */
1
16
  import type { Pluggable } from "unified";
2
17
  export declare function getRemarkPlugins(): Pluggable[];
3
18
  export declare function getRehypePlugins(): Pluggable[];
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/plugins/plugin-loader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAgBzC,wBAAgB,gBAAgB,IAAI,SAAS,EAAE,CAQ9C;AAED,wBAAgB,gBAAgB,IAAI,SAAS,EAAE,CAE9C"}
1
+ {"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/plugins/plugin-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIzC,wBAAgB,gBAAgB,IAAI,SAAS,EAAE,CAG9C;AAED,wBAAgB,gBAAgB,IAAI,SAAS,EAAE,CAG9C"}
@@ -1,18 +1,24 @@
1
- import rehypeHighlight from "rehype-highlight";
2
- import rehypeSlug from "rehype-slug";
3
- import remarkFrontmatter from "remark-frontmatter";
4
- import remarkGfm from "remark-gfm";
5
- import { remarkMdxHeadings } from "./remark-headings.js";
6
- import { remarkCodeBlocks, remarkMdxRemoveParagraphs } from "./remark-mdx-utils.js";
1
+ /**
2
+ * Shim that routes MDX plugin lookups through the `ContentTransformer`
3
+ * extension contract (default implementation: `@veryfront/ext-mdx`).
4
+ *
5
+ * Build-time MDX compilers (`src/build/compiler/mdx-compiler/mdx-processor.ts`,
6
+ * `src/build/renderer/services/mdx-bundler.ts`, `layout-applicator.ts`)
7
+ * historically imported `getRemarkPlugins` / `getRehypePlugins` directly.
8
+ * Now those callers get the canonical plugin list from whichever
9
+ * `ContentTransformer` implementation is registered.
10
+ *
11
+ * When no implementation is registered, the lookup throws with an
12
+ * actionable install message pointing at `@veryfront/ext-mdx`.
13
+ *
14
+ * @module transforms/plugins/plugin-loader
15
+ */
16
+ import { resolve as resolveContract } from "../../extensions/contracts.js";
7
17
  export function getRemarkPlugins() {
8
- return [
9
- remarkGfm,
10
- remarkFrontmatter,
11
- remarkMdxHeadings,
12
- remarkMdxRemoveParagraphs,
13
- remarkCodeBlocks,
14
- ];
18
+ const transformer = resolveContract("ContentTransformer");
19
+ return transformer.getRemarkPlugins();
15
20
  }
16
21
  export function getRehypePlugins() {
17
- return [rehypeHighlight, rehypeSlug];
22
+ const transformer = resolveContract("ContentTransformer");
23
+ return transformer.getRehypePlugins();
18
24
  }
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.1.369";
1
+ export declare const VERSION = "0.1.370";
2
2
  //# sourceMappingURL=version-constant.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
- export const VERSION = "0.1.369";
3
+ export const VERSION = "0.1.370";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.369",
3
+ "version": "0.1.370",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
@@ -8,6 +8,7 @@ import { handleBuildError } from "./error-handler.js";
8
8
  import { displayBuildSuccess } from "./stats-display.js";
9
9
  import type { BuildOptions } from "./types.js";
10
10
  import { isJsonMode, streamJsonLine } from "../../shared/json-output.js";
11
+ import { ensureBuiltinContentTransformer } from "../../shared/ensure-content-transformer.js";
11
12
 
12
13
  export function buildCommand(options: BuildOptions): Promise<void> {
13
14
  return withSpan(
@@ -26,6 +27,7 @@ export function buildCommand(options: BuildOptions): Promise<void> {
26
27
 
27
28
  const adapter = await runtime.get();
28
29
  await getConfig(options.projectDir, adapter);
30
+ ensureBuiltinContentTransformer();
29
31
 
30
32
  if (isJsonMode()) {
31
33
  streamJsonLine({ type: "step", name: "config", status: "completed" });
@@ -0,0 +1,17 @@
1
+ import { tryResolve } from "../../src/extensions/index.js";
2
+ import { register } from "../../src/extensions/contracts.js";
3
+ import type { ContentTransformer } from "../../src/extensions/interfaces/index.js";
4
+ import { MdxContentTransformer } from "../../extensions/ext-mdx/src/index.js";
5
+
6
+ /**
7
+ * The CLI ships ext-mdx baked in so the compiled binary can render MDX/Markdown
8
+ * pages out of the box. Library consumers (programmatic `startProductionServer`)
9
+ * still opt in via `veryfront.config.ts` extensions. Bootstrap's
10
+ * `setupAll → teardownAll → reset()` clears the contract registry, so this
11
+ * must run *after* the server-start (or `getConfig`) call returns. We skip
12
+ * registration when a user-provided extension already supplied the contract.
13
+ */
14
+ export function ensureBuiltinContentTransformer(): void {
15
+ if (tryResolve<ContentTransformer>("ContentTransformer")) return;
16
+ register<ContentTransformer>("ContentTransformer", new MdxContentTransformer());
17
+ }
@@ -7,6 +7,7 @@ import {
7
7
  type StartProductionServerOptions,
8
8
  } from "../../src/server/index.js";
9
9
  import type { RuntimeAdapter } from "../../src/platform/index.js";
10
+ import { ensureBuiltinContentTransformer } from "./ensure-content-transformer.js";
10
11
 
11
12
  export interface StartCliProxyModeServerOptions {
12
13
  port: number;
@@ -43,7 +44,7 @@ export async function startCliProxyModeServer(
43
44
  setEnv("NODE_ENV", "development");
44
45
  }
45
46
 
46
- return await startProductionServer({
47
+ const result = await startProductionServer({
47
48
  port: options.port,
48
49
  projectDir: options.projectDir,
49
50
  signal: options.signal,
@@ -52,6 +53,8 @@ export async function startCliProxyModeServer(
52
53
  defaultProjectId: options.defaultProjectId,
53
54
  discoveryConfig: buildDiscoveryConfig(options),
54
55
  });
56
+ ensureBuiltinContentTransformer();
57
+ return result;
55
58
  }
56
59
 
57
60
  export interface StartCliDevServerOptions {
@@ -72,7 +75,9 @@ export async function startCliDevServer(
72
75
  enableFastRefresh: options.enableFastRefresh,
73
76
  signal: options.signal,
74
77
  };
75
- return await startDevServer(devOptions);
78
+ const result = await startDevServer(devOptions);
79
+ ensureBuiltinContentTransformer();
80
+ return result;
76
81
  }
77
82
 
78
83
  export interface StartCliProductionServerOptions {
@@ -108,5 +113,7 @@ export async function startCliProductionServer(
108
113
  // through `/_veryfront/rsc/module?` for non-local deployments, so no
109
114
  // `localProjects` entry is required for the compiled binary to work.
110
115
  };
111
- return await startProductionServer(serverOptions);
116
+ const result = await startProductionServer(serverOptions);
117
+ ensureBuiltinContentTransformer();
118
+ return result;
112
119
  }
package/src/deno.js CHANGED
@@ -1,12 +1,13 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.369",
3
+ "version": "0.1.370",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "workspace": [
7
7
  "./extensions/ext-anthropic",
8
8
  "./extensions/ext-babel",
9
9
  "./extensions/ext-jwt",
10
+ "./extensions/ext-mdx",
10
11
  "./extensions/ext-node-compat",
11
12
  "./extensions/ext-openai",
12
13
  "./extensions/ext-opentelemetry",
@@ -0,0 +1,127 @@
1
+ import { unified } from "unified";
2
+ import remarkParse from "remark-parse";
3
+ import remarkGfm from "remark-gfm";
4
+ import remarkFrontmatter from "remark-frontmatter";
5
+ import remarkRehype from "remark-rehype";
6
+ import rehypeStarryNight from "rehype-starry-night";
7
+ import rehypeSlug from "rehype-slug";
8
+ import rehypeRaw from "rehype-raw";
9
+ import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
10
+ import rehypeStringify from "rehype-stringify";
11
+ import { visit } from "unist-util-visit";
12
+ import { toString } from "mdast-util-to-string";
13
+ import Slugger from "github-slugger";
14
+ import type { Heading, Root as MdastRoot } from "@types/mdast";
15
+ import type { ContentCompileOptions, ContentRuntimeBundle } from "../../../../src/extensions/interfaces/index.js";
16
+ import { extractFrontmatter } from "../../../../src/transforms/mdx/compiler/frontmatter-extractor.js";
17
+ import { isMarkdownPreview } from "../../../../src/transforms/md/utils.js";
18
+ import { rehypeNodePositions } from "../plugins/rehype-node-positions.js";
19
+
20
+ interface ExtractedHeading {
21
+ id: string;
22
+ text: string;
23
+ level: number;
24
+ }
25
+
26
+ function remarkExtractHeadings(headings: ExtractedHeading[]) {
27
+ const slugger = new Slugger();
28
+
29
+ return (tree: MdastRoot): void => {
30
+ visit(tree, "heading", (node: Heading) => {
31
+ const text = toString(node);
32
+ const id = slugger.slug(text);
33
+ headings.push({ id, text, level: node.depth });
34
+ });
35
+ };
36
+ }
37
+
38
+ function escapeForJsString(str: string): string {
39
+ return str.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
40
+ }
41
+
42
+ function createCompiledCode(escapedHtml: string, isPreview: boolean): string {
43
+ const injector = `dangerouslySetInnerHTML: { __html: \`${escapedHtml}\` }`;
44
+ if (isPreview) {
45
+ return `import { jsx as _jsx } from "react/jsx-runtime";
46
+ export default function MDContent({ components, params, ...props }) {
47
+ return _jsx("div", {
48
+ className: "markdown-body",
49
+ ${injector}
50
+ });
51
+ }
52
+ `;
53
+ }
54
+
55
+ return `import { jsx as _jsx } from "react/jsx-runtime";
56
+ export default function MDContent({ components, params, className, ...props }) {
57
+ return _jsx("div", {
58
+ className,
59
+ ${injector}
60
+ });
61
+ }
62
+ `;
63
+ }
64
+
65
+ export async function compileMarkdown(
66
+ options: ContentCompileOptions,
67
+ ): Promise<ContentRuntimeBundle> {
68
+ const { content, frontmatter: providedFrontmatter, filePath, studioEmbed } = options;
69
+
70
+ const { body, frontmatter: extractedFrontmatter } = extractFrontmatter(
71
+ content,
72
+ providedFrontmatter,
73
+ );
74
+
75
+ const headings: ExtractedHeading[] = [];
76
+
77
+ const pipeline = unified()
78
+ .use(remarkParse)
79
+ .use(remarkGfm)
80
+ .use(remarkFrontmatter)
81
+ .use(remarkExtractHeadings, headings)
82
+ .use(remarkRehype, { allowDangerousHtml: true })
83
+ .use(rehypeStarryNight)
84
+ .use(rehypeSlug);
85
+
86
+ pipeline.use(rehypeRaw);
87
+
88
+ if (studioEmbed && filePath) {
89
+ pipeline.use(rehypeNodePositions, { filePath });
90
+ }
91
+
92
+ const sanitizeSchema = studioEmbed
93
+ ? {
94
+ ...defaultSchema,
95
+ attributes: {
96
+ ...defaultSchema.attributes,
97
+ "*": [
98
+ ...(defaultSchema.attributes?.["*"] ?? []),
99
+ "data-node-file",
100
+ "data-node-name",
101
+ "data-node-line",
102
+ "data-node-column",
103
+ "data-node-source",
104
+ ],
105
+ },
106
+ }
107
+ : defaultSchema;
108
+
109
+ const result = await pipeline
110
+ .use(rehypeSanitize, sanitizeSchema)
111
+ .use(rehypeStringify)
112
+ .process(body);
113
+ const html = String(result);
114
+
115
+ const escapedHtml = escapeForJsString(html);
116
+ const isPreview = isMarkdownPreview(filePath, extractedFrontmatter);
117
+ const compiledCode = createCompiledCode(escapedHtml, isPreview);
118
+
119
+ return {
120
+ compiledCode,
121
+ frontmatter: extractedFrontmatter,
122
+ globals: {},
123
+ headings,
124
+ nodeMap: new Map(),
125
+ rawHtml: html,
126
+ };
127
+ }