@analogjs/content 3.0.0-beta.41 → 3.0.0-beta.42
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.
|
@@ -15,14 +15,14 @@ var Md4xContentRendererService = class Md4xContentRendererService extends Conten
|
|
|
15
15
|
this.options = inject(MD4X_RENDERER_OPTIONS, { optional: true });
|
|
16
16
|
}
|
|
17
17
|
async render(content) {
|
|
18
|
-
const { renderToHtml, parseMeta } = await import("md4x/napi");
|
|
18
|
+
const { renderToHtml, parseMeta, heal } = await import("md4x/napi");
|
|
19
|
+
const source = this.options?.heal ? heal(content) : content;
|
|
19
20
|
return {
|
|
20
|
-
content: renderToHtml(
|
|
21
|
-
heal: this.options?.heal,
|
|
21
|
+
content: renderToHtml(source, {
|
|
22
22
|
highlighter: this.options?.highlighter,
|
|
23
23
|
headingIds: true
|
|
24
24
|
}),
|
|
25
|
-
toc: parseMeta(
|
|
25
|
+
toc: parseMeta(source).headings
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
static {
|
|
@@ -69,13 +69,13 @@ var Md4xWasmContentRendererService = class Md4xWasmContentRendererService extend
|
|
|
69
69
|
const wasm = await import("md4x/wasm");
|
|
70
70
|
if (!this.initPromise) this.initPromise = wasm.init();
|
|
71
71
|
await this.initPromise;
|
|
72
|
+
const source = this.options?.heal ? wasm.heal(content) : content;
|
|
72
73
|
return {
|
|
73
|
-
content: wasm.renderToHtml(
|
|
74
|
-
heal: this.options?.heal,
|
|
74
|
+
content: wasm.renderToHtml(source, {
|
|
75
75
|
highlighter: this.options?.highlighter,
|
|
76
76
|
headingIds: true
|
|
77
77
|
}),
|
|
78
|
-
toc: wasm.parseMeta(
|
|
78
|
+
toc: wasm.parseMeta(source).headings
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
81
|
static {
|
|
@@ -181,7 +181,8 @@ async function streamMarkdown(input, options) {
|
|
|
181
181
|
let buffer = "";
|
|
182
182
|
let closed = false;
|
|
183
183
|
const reader = input.getReader();
|
|
184
|
-
const release = (reason) => {
|
|
184
|
+
const release = async (reason) => {
|
|
185
|
+
if (closed) return;
|
|
185
186
|
closed = true;
|
|
186
187
|
return reader.cancel(reason).finally(() => reader.releaseLock());
|
|
187
188
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analogjs-content-md4x.mjs","names":[],"sources":["../../md4x/src/lib/md4x-content-renderer.service.ts","../../md4x/src/lib/md4x-wasm-content-renderer.service.ts","../../md4x/src/lib/provide-md4x.ts","../../md4x/src/lib/streaming-markdown-renderer.ts"],"sourcesContent":["import { Injectable, inject, InjectionToken } from '@angular/core';\n\nimport {\n ContentRenderer,\n RenderedContent,\n} from '../../../src/lib/content-renderer';\n\n/**\n * Options for the experimental md4x-based content renderer.\n *\n * @experimental md4x integration is experimental and may change in future releases.\n */\nexport interface Md4xRendererOptions {\n /** Heal incomplete markdown (useful for streaming/LLM content). */\n heal?: boolean;\n /** Custom code block highlighter. Receives raw code and block metadata,\n * returns highlighted HTML or undefined to keep default rendering. */\n highlighter?: (\n code: string,\n block: { lang: string; filename?: string; highlights?: number[] },\n ) => string | undefined;\n}\n\nexport const MD4X_RENDERER_OPTIONS: InjectionToken<Md4xRendererOptions> =\n new InjectionToken<Md4xRendererOptions>('md4x_renderer_options');\n\n/**\n * Content renderer backed by md4x (C-based CommonMark parser compiled with Zig).\n * 50-70x faster than marked for complex documents.\n *\n * @experimental md4x integration is experimental and may change in future releases.\n */\n@Injectable()\nexport class Md4xContentRendererService extends ContentRenderer {\n private options = inject(MD4X_RENDERER_OPTIONS, { optional: true });\n\n override async render(content: string): Promise<RenderedContent> {\n const { renderToHtml, parseMeta } = await import('md4x/napi');\n const html = renderToHtml(
|
|
1
|
+
{"version":3,"file":"analogjs-content-md4x.mjs","names":[],"sources":["../../md4x/src/lib/md4x-content-renderer.service.ts","../../md4x/src/lib/md4x-wasm-content-renderer.service.ts","../../md4x/src/lib/provide-md4x.ts","../../md4x/src/lib/streaming-markdown-renderer.ts"],"sourcesContent":["import { Injectable, inject, InjectionToken } from '@angular/core';\n\nimport {\n ContentRenderer,\n RenderedContent,\n} from '../../../src/lib/content-renderer';\n\n/**\n * Options for the experimental md4x-based content renderer.\n *\n * @experimental md4x integration is experimental and may change in future releases.\n */\nexport interface Md4xRendererOptions {\n /** Heal incomplete markdown (useful for streaming/LLM content). */\n heal?: boolean;\n /** Custom code block highlighter. Receives raw code and block metadata,\n * returns highlighted HTML or undefined to keep default rendering. */\n highlighter?: (\n code: string,\n block: { lang: string; filename?: string; highlights?: number[] },\n ) => string | undefined;\n}\n\nexport const MD4X_RENDERER_OPTIONS: InjectionToken<Md4xRendererOptions> =\n new InjectionToken<Md4xRendererOptions>('md4x_renderer_options');\n\n/**\n * Content renderer backed by md4x (C-based CommonMark parser compiled with Zig).\n * 50-70x faster than marked for complex documents.\n *\n * @experimental md4x integration is experimental and may change in future releases.\n */\n@Injectable()\nexport class Md4xContentRendererService extends ContentRenderer {\n private options = inject(MD4X_RENDERER_OPTIONS, { optional: true });\n\n override async render(content: string): Promise<RenderedContent> {\n const { renderToHtml, parseMeta, heal } = await import('md4x/napi');\n const source = this.options?.heal ? heal(content) : content;\n const html = renderToHtml(source, {\n highlighter: this.options?.highlighter,\n headingIds: true,\n });\n return { content: html, toc: parseMeta(source).headings };\n }\n}\n","import { Injectable, inject } from '@angular/core';\n\nimport {\n ContentRenderer,\n RenderedContent,\n} from '../../../src/lib/content-renderer';\nimport {\n MD4X_RENDERER_OPTIONS,\n Md4xRendererOptions,\n} from './md4x-content-renderer.service';\n\n/**\n * Content renderer backed by md4x/wasm for client-side (browser) rendering.\n * ~100KB gzip, 3-6x faster than marked in the browser.\n *\n * @experimental md4x integration is experimental and may change in future releases.\n */\n@Injectable()\nexport class Md4xWasmContentRendererService extends ContentRenderer {\n private options = inject(MD4X_RENDERER_OPTIONS, { optional: true });\n private initPromise: Promise<void> | null = null;\n\n override async render(content: string): Promise<RenderedContent> {\n const wasm = await import('md4x/wasm');\n if (!this.initPromise) {\n this.initPromise = wasm.init();\n }\n await this.initPromise;\n\n const source = this.options?.heal ? wasm.heal(content) : content;\n const html = wasm.renderToHtml(source, {\n highlighter: this.options?.highlighter,\n headingIds: true,\n });\n return { content: html, toc: wasm.parseMeta(source).headings };\n }\n}\n","import { Provider } from '@angular/core';\n\nimport { ContentRenderer } from '../../../src/lib/content-renderer';\nimport { withContentFileLoader } from '../../../src/lib/content-file-loader';\nimport { withContentListLoader } from '../../../src/lib/content-list-loader';\nimport {\n Md4xContentRendererService,\n MD4X_RENDERER_OPTIONS,\n} from './md4x-content-renderer.service';\nimport { Md4xWasmContentRendererService } from './md4x-wasm-content-renderer.service';\nimport type { Md4xRendererOptions } from './md4x-content-renderer.service';\n\n/**\n * Provides the experimental md4x-based content renderer (NAPI, server/build-time).\n *\n * @experimental md4x integration is experimental and may change in future releases.\n *\n * @example\n * ```typescript\n * provideContent(withMd4xRenderer());\n * provideContent(withMd4xRenderer({ heal: true }));\n * ```\n */\nexport function withMd4xRenderer(options?: Md4xRendererOptions): Provider {\n return [\n { provide: ContentRenderer, useClass: Md4xContentRendererService },\n options ? { provide: MD4X_RENDERER_OPTIONS, useValue: options } : [],\n withContentFileLoader(),\n withContentListLoader(),\n ];\n}\n\n/**\n * Provides the experimental md4x WASM content renderer (browser/CSR).\n * ~100KB gzip, 3-6x faster than marked in the browser.\n *\n * @experimental md4x integration is experimental and may change in future releases.\n *\n * @example\n * ```typescript\n * provideContent(withMd4xWasmRenderer());\n * ```\n */\nexport function withMd4xWasmRenderer(options?: Md4xRendererOptions): Provider {\n return [\n { provide: ContentRenderer, useClass: Md4xWasmContentRendererService },\n options ? { provide: MD4X_RENDERER_OPTIONS, useValue: options } : [],\n withContentFileLoader(),\n withContentListLoader(),\n ];\n}\n","/**\n * Transforms a stream of markdown chunks into a stream of rendered HTML.\n * Uses md4x's `heal()` to fix incomplete markdown from streaming sources\n * (LLMs, collaborative editing) so each emitted HTML chunk is valid.\n *\n * @experimental Streaming markdown support is experimental and may change in future releases.\n *\n * @example\n * ```typescript\n * // In a Nitro API route\n * import { streamMarkdown } from '@analogjs/content';\n *\n * export default defineEventHandler(async (event) => {\n * const llmStream = getAIStream(prompt);\n * return streamMarkdown(llmStream, { heal: true });\n * });\n * ```\n */\nexport async function streamMarkdown(\n input: ReadableStream<string>,\n options?: { heal?: boolean },\n): Promise<ReadableStream<string>> {\n const { renderToHtml, heal } = await import('md4x/napi');\n\n let buffer = '';\n let closed = false;\n const reader = input.getReader();\n\n const release = async (reason?: unknown) => {\n if (closed) {\n return;\n }\n closed = true;\n return reader.cancel(reason).finally(() => reader.releaseLock());\n };\n\n return new ReadableStream<string>({\n async pull(controller) {\n try {\n const { done, value } = await reader.read();\n if (closed) {\n return;\n }\n\n if (done) {\n closed = true;\n reader.releaseLock();\n if (buffer) {\n const source = options?.heal ? heal(buffer) : buffer;\n controller.enqueue(renderToHtml(source));\n }\n controller.close();\n return;\n }\n\n buffer += value;\n const source = options?.heal ? heal(buffer) : buffer;\n controller.enqueue(renderToHtml(source));\n } catch (error) {\n controller.error(error);\n await release(error).catch(() => undefined);\n }\n },\n cancel(reason) {\n return release(reason);\n },\n });\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@analogjs/content",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.42",
|
|
4
4
|
"description": "Content Rendering for Analog",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Brandon Roberts <robertsbt@gmail.com>",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"satori": "^0.10.14",
|
|
35
35
|
"satori-html": "^0.3.2",
|
|
36
36
|
"sharp": "^0.34.5",
|
|
37
|
-
"md4x": ">=0.0.
|
|
37
|
+
"md4x": ">=0.0.29"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
|
40
40
|
"@nx/devkit": {
|
|
@@ -91,8 +91,8 @@
|
|
|
91
91
|
"tslib": "^2.3.0"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
|
-
"@analogjs/vite-plugin-angular": "3.0.0-beta.
|
|
95
|
-
"@analogjs/vitest-angular": "3.0.0-beta.
|
|
94
|
+
"@analogjs/vite-plugin-angular": "3.0.0-beta.42",
|
|
95
|
+
"@analogjs/vitest-angular": "3.0.0-beta.42",
|
|
96
96
|
"@nx/devkit": "24.0.0"
|
|
97
97
|
},
|
|
98
98
|
"ng-update": {
|