nuxt-ai-ready 2.5.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -12
- package/dist/chunks/agent-skills.mjs +35 -12
- package/dist/chunks/prerender.mjs +35 -24
- package/dist/cli.mjs +5 -2
- package/dist/module.d.mts +4 -0
- package/dist/module.json +2 -2
- package/dist/module.mjs +8 -4
- package/dist/runtime/app/index.d.ts +3 -0
- package/dist/runtime/app/index.js +2 -0
- package/dist/runtime/cache-control.d.ts +2 -0
- package/dist/runtime/cache-control.js +11 -0
- package/dist/runtime/llms-txt-utils.js +1 -1
- package/dist/runtime/server/db/context.d.ts +13 -0
- package/dist/runtime/server/db/drizzle/client.d.ts +6 -7
- package/dist/runtime/server/db/drizzle/client.js +13 -2
- package/dist/runtime/server/db/drizzle/providers/bun.d.ts +2 -2
- package/dist/runtime/server/db/drizzle/providers/bun.js +2 -2
- package/dist/runtime/server/db/drizzle/providers/d1.d.ts +2 -2
- package/dist/runtime/server/db/drizzle/providers/d1.js +3 -2
- package/dist/runtime/server/db/drizzle/providers/libsql.d.ts +2 -2
- package/dist/runtime/server/db/drizzle/providers/libsql.js +2 -2
- package/dist/runtime/server/db/drizzle/providers/neon.d.ts +2 -2
- package/dist/runtime/server/db/drizzle/providers/neon.js +2 -2
- package/dist/runtime/server/db/drizzle/providers/node-sqlite.d.ts +2 -2
- package/dist/runtime/server/db/drizzle/providers/node-sqlite.js +2 -2
- package/dist/runtime/server/db/drizzle/providers/postgres.d.ts +2 -2
- package/dist/runtime/server/db/drizzle/providers/postgres.js +2 -2
- package/dist/runtime/server/db/drizzle/queries.d.ts +27 -27
- package/dist/runtime/server/db/drizzle/queries.js +6 -5
- package/dist/runtime/server/db/drizzle/raw.d.ts +2 -6
- package/dist/runtime/server/db/index.d.ts +1 -1
- package/dist/runtime/server/db/index.js +1 -1
- package/dist/runtime/server/db/queries.d.ts +36 -36
- package/dist/runtime/server/db/queries.js +8 -9
- package/dist/runtime/server/db/seed.d.ts +2 -2
- package/dist/runtime/server/db/seed.js +4 -3
- package/dist/runtime/server/db/shared.d.ts +8 -0
- package/dist/runtime/server/db/shared.js +8 -2
- package/dist/runtime/server/index.d.ts +2 -0
- package/dist/runtime/server/index.js +17 -0
- package/dist/runtime/server/mcp/tools/get-page-markdown.js +1 -1
- package/dist/runtime/server/mcp/tools/list-pages.js +1 -1
- package/dist/runtime/server/mcp/tools/search-pages.js +1 -1
- package/dist/runtime/server/middleware/markdown.js +3 -3
- package/dist/runtime/server/middleware/markdown.prerender.js +1 -1
- package/dist/runtime/server/plugins/db-lifecycle-nitro3.d.ts +2 -0
- package/dist/runtime/server/plugins/db-lifecycle-nitro3.js +16 -0
- package/dist/runtime/server/plugins/html-capture.prerender.js +6 -4
- package/dist/runtime/server/plugins/link-header-nitro3.d.ts +2 -0
- package/dist/runtime/server/plugins/link-header-nitro3.js +20 -0
- package/dist/runtime/server/plugins/link-header.d.ts +6 -0
- package/dist/runtime/server/plugins/link-header.js +7 -11
- package/dist/runtime/server/plugins/markdown-negotiation.js +8 -1
- package/dist/runtime/server/plugins/sitemap-seeder.js +3 -3
- package/dist/runtime/server/routes/agent-skills-artifact.d.ts +1 -1
- package/dist/runtime/server/routes/agent-skills-artifact.js +10 -10
- package/dist/runtime/server/routes/agent-skills-index.d.ts +1 -1
- package/dist/runtime/server/routes/agent-skills-index.js +7 -6
- package/dist/runtime/server/routes/ai-catalog.d.ts +2 -1
- package/dist/runtime/server/routes/ai-catalog.js +7 -8
- package/dist/runtime/server/routes/api-catalog.d.ts +3 -1
- package/dist/runtime/server/routes/api-catalog.js +12 -12
- package/dist/runtime/server/routes/llms-full.txt.get.js +1 -1
- package/dist/runtime/server/routes/mcp-server-card.d.ts +1 -1
- package/dist/runtime/server/routes/mcp-server-card.js +7 -8
- package/dist/runtime/server/utils/checkStale.d.ts +2 -2
- package/dist/runtime/server/utils/cloudflare-prerendered.d.ts +3 -0
- package/dist/runtime/server/utils/cloudflare-prerendered.js +23 -0
- package/dist/runtime/server/utils/cloudflare.d.ts +5 -5
- package/dist/runtime/server/utils/cloudflare.js +31 -7
- package/dist/runtime/server/utils/content-negotiation.d.ts +5 -3
- package/dist/runtime/server/utils/content-negotiation.js +8 -7
- package/dist/runtime/server/utils/context.d.ts +3 -3
- package/dist/runtime/server/utils/context.js +1 -1
- package/dist/runtime/server/utils/discovery-response.d.ts +2 -0
- package/dist/runtime/server/utils/link-header.d.ts +5 -3
- package/dist/runtime/server/utils/link-header.js +26 -2
- package/dist/runtime/server/utils/markdown-request.d.ts +4 -3
- package/dist/runtime/server/utils/markdown-request.js +15 -13
- package/dist/runtime/server/utils/negotiation-decision.d.ts +4 -0
- package/dist/runtime/server/utils/negotiation-decision.js +6 -5
- package/dist/runtime/server/utils/negotiation-response.d.ts +1 -1
- package/dist/runtime/server/utils/negotiation-response.js +63 -23
- package/dist/runtime/server/utils/prerender-html.d.ts +2 -1
- package/dist/runtime/server/utils/prerender-html.js +3 -1
- package/dist/runtime/types.d.ts +15 -7
- package/dist/shared/nuxt-ai-ready.B3hAuOLQ.mjs +29 -0
- package/dist/shared/{nuxt-ai-ready.CLSWou20.mjs → nuxt-ai-ready.C34F0LJo.mjs} +560 -219
- package/package.json +85 -20
- package/skills/nuxt-ai-ready/SKILL.md +26 -12
- package/skills/nuxt-ai-ready/references/runtime-indexing.md +7 -6
- package/dist/runtime/server/db/drizzle/providers/sqlite.d.ts +0 -8
- package/dist/runtime/server/db/drizzle/providers/sqlite.js +0 -15
- package/node_modules/@mdream/js/LICENSE.md +0 -9
- package/node_modules/@mdream/js/README.md +0 -792
- package/node_modules/@mdream/js/bin/mdream.mjs +0 -2
- package/node_modules/@mdream/js/dist/_chunks/const.mjs +0 -134
- package/node_modules/@mdream/js/dist/_chunks/index.d.mts +0 -9
- package/node_modules/@mdream/js/dist/_chunks/markdown-processor.mjs +0 -1968
- package/node_modules/@mdream/js/dist/_chunks/minimal.d.mts +0 -6
- package/node_modules/@mdream/js/dist/_chunks/parse.mjs +0 -2756
- package/node_modules/@mdream/js/dist/_chunks/plugins.mjs +0 -725
- package/node_modules/@mdream/js/dist/_chunks/resolve-plugins.mjs +0 -44
- package/node_modules/@mdream/js/dist/_chunks/stream.mjs +0 -37
- package/node_modules/@mdream/js/dist/_chunks/types.d.mts +0 -473
- package/node_modules/@mdream/js/dist/cli.d.mts +0 -1
- package/node_modules/@mdream/js/dist/cli.mjs +0 -32
- package/node_modules/@mdream/js/dist/core.d.mts +0 -15
- package/node_modules/@mdream/js/dist/core.mjs +0 -28
- package/node_modules/@mdream/js/dist/index.d.mts +0 -4
- package/node_modules/@mdream/js/dist/index.mjs +0 -58
- package/node_modules/@mdream/js/dist/llms-txt.d.mts +0 -86
- package/node_modules/@mdream/js/dist/llms-txt.mjs +0 -308
- package/node_modules/@mdream/js/dist/negotiate.d.mts +0 -35
- package/node_modules/@mdream/js/dist/negotiate.mjs +0 -121
- package/node_modules/@mdream/js/dist/parse.d.mts +0 -90
- package/node_modules/@mdream/js/dist/parse.mjs +0 -2
- package/node_modules/@mdream/js/dist/plugins.d.mts +0 -85
- package/node_modules/@mdream/js/dist/plugins.mjs +0 -2
- package/node_modules/@mdream/js/dist/preset/minimal.d.mts +0 -2
- package/node_modules/@mdream/js/dist/preset/minimal.mjs +0 -33
- package/node_modules/@mdream/js/dist/splitter.d.mts +0 -18
- package/node_modules/@mdream/js/dist/splitter.mjs +0 -194
- package/node_modules/@mdream/js/package.json +0 -103
- package/node_modules/cac/LICENSE +0 -21
- package/node_modules/cac/README.md +0 -492
- package/node_modules/cac/dist/index.d.ts +0 -196
- package/node_modules/cac/dist/index.js +0 -638
- package/node_modules/cac/package.json +0 -72
- package/node_modules/mdream/LICENSE.md +0 -9
- package/node_modules/mdream/README.md +0 -1091
- package/node_modules/mdream/bin/mdream.mjs +0 -46
- package/node_modules/mdream/dist/browser.d.mts +0 -105
- package/node_modules/mdream/dist/browser.mjs +0 -262
- package/node_modules/mdream/dist/edge.d.mts +0 -100
- package/node_modules/mdream/dist/edge.mjs +0 -250
- package/node_modules/mdream/dist/iife.js +0 -605
- package/node_modules/mdream/dist/index.d.mts +0 -89
- package/node_modules/mdream/dist/index.mjs +0 -184
- package/node_modules/mdream/dist/wasm.d.mts +0 -100
- package/node_modules/mdream/dist/wasm.mjs +0 -140
- package/node_modules/mdream/dist/worker.d.mts +0 -101
- package/node_modules/mdream/dist/worker.mjs +0 -217
- package/node_modules/mdream/napi/index.d.mts +0 -127
- package/node_modules/mdream/napi/index.d.ts +0 -127
- package/node_modules/mdream/napi/index.mjs +0 -725
- package/node_modules/mdream/napi/rust.android-arm-eabi.node +0 -0
- package/node_modules/mdream/napi/rust.android-arm64.node +0 -0
- package/node_modules/mdream/napi/rust.darwin-arm64.node +0 -0
- package/node_modules/mdream/napi/rust.darwin-x64.node +0 -0
- package/node_modules/mdream/napi/rust.freebsd-x64.node +0 -0
- package/node_modules/mdream/napi/rust.linux-arm-gnueabihf.node +0 -0
- package/node_modules/mdream/napi/rust.linux-arm64-gnu.node +0 -0
- package/node_modules/mdream/napi/rust.linux-arm64-musl.node +0 -0
- package/node_modules/mdream/napi/rust.linux-x64-gnu.node +0 -0
- package/node_modules/mdream/napi/rust.linux-x64-musl.node +0 -0
- package/node_modules/mdream/napi/rust.wasi.cjs +0 -2144
- package/node_modules/mdream/napi/rust.wasm32-wasi.wasm +0 -0
- package/node_modules/mdream/napi/rust.win32-arm64-msvc.node +0 -0
- package/node_modules/mdream/napi/rust.win32-x64-msvc.node +0 -0
- package/node_modules/mdream/node_modules/@emnapi/core/LICENSE +0 -21
- package/node_modules/mdream/node_modules/@emnapi/core/README.md +0 -1
- package/node_modules/mdream/node_modules/@emnapi/core/dist/emnapi-core.d.ts +0 -392
- package/node_modules/mdream/node_modules/@emnapi/core/dist/emnapi-core.full.d.ts +0 -392
- package/node_modules/mdream/node_modules/@emnapi/core/dist/emnapi-core.full.js +0 -8351
- package/node_modules/mdream/node_modules/@emnapi/core/dist/emnapi-core.js +0 -7268
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/async-work.d.ts +0 -5
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/async-work.js +0 -843
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/index.d.ts +0 -4
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/index.js +0 -3
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/threadsafe-function.d.ts +0 -5
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/threadsafe-function.js +0 -1010
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/v8.d.ts +0 -5
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/v8.js +0 -1446
- package/node_modules/mdream/node_modules/@emnapi/core/package.json +0 -39
- package/node_modules/mdream/node_modules/@emnapi/core/rollup.config.js +0 -60
- package/node_modules/mdream/node_modules/@emnapi/runtime/LICENSE +0 -21
- package/node_modules/mdream/node_modules/@emnapi/runtime/README.md +0 -1
- package/node_modules/mdream/node_modules/@emnapi/runtime/dist/emnapi.d.ts +0 -833
- package/node_modules/mdream/node_modules/@emnapi/runtime/dist/emnapi.js +0 -2306
- package/node_modules/mdream/node_modules/@emnapi/runtime/dist/emnapi.js.map +0 -1
- package/node_modules/mdream/node_modules/@emnapi/runtime/index.cjs +0 -63
- package/node_modules/mdream/node_modules/@emnapi/runtime/package.json +0 -39
- package/node_modules/mdream/node_modules/@emnapi/runtime/rollup.config.js +0 -25
- package/node_modules/mdream/node_modules/@emnapi/wasi-threads/LICENSE +0 -21
- package/node_modules/mdream/node_modules/@emnapi/wasi-threads/README.md +0 -203
- package/node_modules/mdream/node_modules/@emnapi/wasi-threads/dist/wasi-threads.d.ts +0 -236
- package/node_modules/mdream/node_modules/@emnapi/wasi-threads/dist/wasi-threads.js +0 -1086
- package/node_modules/mdream/node_modules/@emnapi/wasi-threads/package.json +0 -35
- package/node_modules/mdream/node_modules/@emnapi/wasi-threads/rollup.config.js +0 -6
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/dist/emnapi-plugins.cjs +0 -1472
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/dist/emnapi-plugins.js +0 -1470
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/dist/fs-proxy.cjs +0 -237
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/dist/fs.js +0 -18260
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/fs-proxy.js +0 -317
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/package.json +0 -67
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/runtime.cjs +0 -39
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/runtime.js +0 -36
- package/node_modules/mdream/node_modules/@tybys/wasm-util/LICENSE +0 -21
- package/node_modules/mdream/node_modules/@tybys/wasm-util/README.md +0 -193
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/tsdoc-metadata.json +0 -11
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.d.ts +0 -423
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.esm-bundler.js +0 -2932
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.esm.js +0 -2932
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.esm.min.js +0 -1
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.js +0 -2954
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.min.js +0 -1
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/asyncify.js +0 -158
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/index.js +0 -13
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/jspi.js +0 -46
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/load.js +0 -97
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/memory.js +0 -35
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/error.js +0 -103
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/fd.js +0 -268
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/fs.js +0 -3
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/index.js +0 -192
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/path.js +0 -316
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/preview1.js +0 -1599
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/rights.js +0 -141
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/types.js +0 -220
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/util.js +0 -128
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/webassembly.js +0 -13
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/asyncify.mjs +0 -153
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/index.mjs +0 -9
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/jspi.mjs +0 -39
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/load.mjs +0 -89
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/memory.mjs +0 -28
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/error.mjs +0 -97
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/fd.mjs +0 -256
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/fs.mjs +0 -1
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/index.mjs +0 -186
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/path.mjs +0 -310
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/preview1.mjs +0 -1593
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/rights.mjs +0 -135
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/types.mjs +0 -216
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/util.mjs +0 -113
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/webassembly.mjs +0 -9
- package/node_modules/mdream/node_modules/@tybys/wasm-util/package.json +0 -58
- package/node_modules/mdream/node_modules/tslib/CopyrightNotice.txt +0 -15
- package/node_modules/mdream/node_modules/tslib/LICENSE.txt +0 -12
- package/node_modules/mdream/node_modules/tslib/README.md +0 -164
- package/node_modules/mdream/node_modules/tslib/SECURITY.md +0 -41
- package/node_modules/mdream/node_modules/tslib/modules/index.d.ts +0 -38
- package/node_modules/mdream/node_modules/tslib/modules/index.js +0 -70
- package/node_modules/mdream/node_modules/tslib/modules/package.json +0 -3
- package/node_modules/mdream/node_modules/tslib/package.json +0 -47
- package/node_modules/mdream/node_modules/tslib/tslib.d.ts +0 -460
- package/node_modules/mdream/node_modules/tslib/tslib.es6.html +0 -1
- package/node_modules/mdream/node_modules/tslib/tslib.es6.js +0 -402
- package/node_modules/mdream/node_modules/tslib/tslib.es6.mjs +0 -401
- package/node_modules/mdream/node_modules/tslib/tslib.html +0 -1
- package/node_modules/mdream/node_modules/tslib/tslib.js +0 -484
- package/node_modules/mdream/package.json +0 -110
- package/node_modules/mdream/skills/mdream/SKILL.md +0 -124
- package/node_modules/mdream/skills/mdream/references/runtimes.md +0 -49
- package/node_modules/mdream/wasm/mdream_edge.d.ts +0 -90
- package/node_modules/mdream/wasm/mdream_edge.js +0 -517
- package/node_modules/mdream/wasm/mdream_edge_bg.wasm +0 -0
- package/node_modules/mdream/wasm/mdream_edge_bg.wasm.d.ts +0 -20
- package/node_modules/mdream/wasm/package.json +0 -17
- package/node_modules/mdream/wasm-bundler/mdream_edge.d.ts +0 -45
- package/node_modules/mdream/wasm-bundler/mdream_edge.js +0 -13
- package/node_modules/mdream/wasm-bundler/mdream_edge_bg.js +0 -413
- package/node_modules/mdream/wasm-bundler/mdream_edge_bg.wasm +0 -0
- package/node_modules/mdream/wasm-bundler/mdream_edge_bg.wasm.d.ts +0 -20
- package/node_modules/mdream/wasm-bundler/package.json +0 -19
- package/node_modules/pathe/LICENSE +0 -70
- package/node_modules/pathe/README.md +0 -73
- package/node_modules/pathe/dist/index.cjs +0 -39
- package/node_modules/pathe/dist/index.d.cts +0 -47
- package/node_modules/pathe/dist/index.d.mts +0 -47
- package/node_modules/pathe/dist/index.d.ts +0 -47
- package/node_modules/pathe/dist/index.mjs +0 -19
- package/node_modules/pathe/dist/shared/pathe.BSlhyZSM.cjs +0 -266
- package/node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs +0 -249
- package/node_modules/pathe/dist/utils.cjs +0 -82
- package/node_modules/pathe/dist/utils.d.cts +0 -32
- package/node_modules/pathe/dist/utils.d.mts +0 -32
- package/node_modules/pathe/dist/utils.d.ts +0 -32
- package/node_modules/pathe/dist/utils.mjs +0 -77
- package/node_modules/pathe/package.json +0 -61
- package/node_modules/pathe/utils.d.ts +0 -1
|
@@ -1,1091 +0,0 @@
|
|
|
1
|
-
# mdream
|
|
2
|
-
|
|
3
|
-
[](https://npmjs.com/package/mdream)
|
|
4
|
-
[](https://npm.chart.dev/mdream)
|
|
5
|
-
[](https://github.com/harlan-zw/mdream/blob/main/LICENSE.md)
|
|
6
|
-
<a href="https://skilld.dev/gh/harlan-zw/mdream">
|
|
7
|
-
<picture>
|
|
8
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://skilld.dev/b/harlan-zw/mdream?theme=dark">
|
|
9
|
-
<source media="(prefers-color-scheme: light)" srcset="https://skilld.dev/b/harlan-zw/mdream?theme=light">
|
|
10
|
-
<img alt="Skill repository on skilld.dev" src="https://skilld.dev/b/harlan-zw/mdream?theme=light">
|
|
11
|
-
</picture>
|
|
12
|
-
</a>
|
|
13
|
-
|
|
14
|
-
## Installation
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
# npm
|
|
18
|
-
npm install mdream
|
|
19
|
-
|
|
20
|
-
# pnpm
|
|
21
|
-
pnpm add mdream
|
|
22
|
-
|
|
23
|
-
# yarn
|
|
24
|
-
yarn add mdream
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
> [!TIP]
|
|
28
|
-
> Using an AI agent? Get the mdream Skill on [skilld.dev/gh/harlan-zw/mdream](https://skilld.dev/gh/harlan-zw/mdream).
|
|
29
|
-
|
|
30
|
-
For the JavaScript-only engine (hook-based plugins, splitter, pure HTML parser):
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
pnpm add @mdream/js
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### Bundler Compatibility
|
|
37
|
-
|
|
38
|
-
The `mdream` package uses native Node.js bindings (NAPI-RS) which cannot be statically bundled. If your bundler fails to resolve `mdream`, mark it as external:
|
|
39
|
-
|
|
40
|
-
**Next.js / Turbopack:**
|
|
41
|
-
```js
|
|
42
|
-
// next.config.js
|
|
43
|
-
const nextConfig = {
|
|
44
|
-
serverExternalPackages: ['mdream'],
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
**Webpack / other bundlers:**
|
|
49
|
-
```js
|
|
50
|
-
externals: ['mdream']
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
> [!TIP]
|
|
54
|
-
> [`@mdream/js`](https://github.com/harlan-zw/mdream/tree/main/packages/js) has zero native dependencies and works with all bundlers without configuration.
|
|
55
|
-
|
|
56
|
-
> [!TIP]
|
|
57
|
-
> Using Vite? [`@mdream/vite`](https://github.com/harlan-zw/mdream/tree/main/packages/vite) handles this automatically.
|
|
58
|
-
|
|
59
|
-
## Table of Contents
|
|
60
|
-
|
|
61
|
-
- [API Reference](#api-reference)
|
|
62
|
-
- [htmlToMarkdown()](#htmltomarkdown)
|
|
63
|
-
- [streamHtmlToMarkdown()](#streamhtmltomarkdown)
|
|
64
|
-
- [Engines](#engines)
|
|
65
|
-
- [Options](#options)
|
|
66
|
-
- [MdreamOptions (Rust engine)](#mdreamoptions-rust-engine)
|
|
67
|
-
- [MdreamOptions (JS engine)](#mdreamoptions-js-engine)
|
|
68
|
-
- [CleanOptions](#cleanoptions)
|
|
69
|
-
- [FrontmatterConfig](#frontmatterconfig)
|
|
70
|
-
- [TagOverride](#tagoverride)
|
|
71
|
-
- [FilterOptions](#filteroptions)
|
|
72
|
-
- [Presets](#presets)
|
|
73
|
-
- [Minimal Preset](#minimal-preset)
|
|
74
|
-
- [Built-in Plugins](#built-in-plugins)
|
|
75
|
-
- [Frontmatter](#frontmatter-plugin)
|
|
76
|
-
- [Isolate Main](#isolate-main-plugin)
|
|
77
|
-
- [Tailwind](#tailwind-plugin)
|
|
78
|
-
- [Filter](#filter-plugin)
|
|
79
|
-
- [Extraction](#extraction-plugin)
|
|
80
|
-
- [Hook-Based Plugins (JS Engine)](#hook-based-plugins-js-engine)
|
|
81
|
-
- [Plugin Hooks](#plugin-hooks)
|
|
82
|
-
- [createPlugin()](#createplugin)
|
|
83
|
-
- [Markdown Splitting (JS Engine)](#markdown-splitting-js-engine)
|
|
84
|
-
- [Basic Chunking](#basic-chunking)
|
|
85
|
-
- [Streaming Chunks](#streaming-chunks-memory-efficient)
|
|
86
|
-
- [Splitter Options](#splitter-options)
|
|
87
|
-
- [Chunk Metadata](#chunk-metadata)
|
|
88
|
-
- [Content Negotiation](#content-negotiation)
|
|
89
|
-
- [Pure HTML Parser (JS Engine)](#pure-html-parser-js-engine)
|
|
90
|
-
- [CLI Usage](#cli-usage)
|
|
91
|
-
- [Browser and Edge Usage](#browser-and-edge-usage)
|
|
92
|
-
- [Edge / Cloudflare Workers](#edge--cloudflare-workers)
|
|
93
|
-
- [Browser CDN (IIFE)](#browser-cdn-iife)
|
|
94
|
-
- [Web Worker](#web-worker)
|
|
95
|
-
- [llms.txt Generation](#llmstxt-generation)
|
|
96
|
-
- [Related Packages](#related-packages)
|
|
97
|
-
|
|
98
|
-
## API Reference
|
|
99
|
-
|
|
100
|
-
### `htmlToMarkdown()`
|
|
101
|
-
|
|
102
|
-
Converts a complete HTML string to Markdown, plain text, or HTML. It is synchronous in Node and on edge runtimes.
|
|
103
|
-
|
|
104
|
-
**Rust engine** (`mdream`):
|
|
105
|
-
|
|
106
|
-
```ts
|
|
107
|
-
import { htmlToMarkdown } from 'mdream'
|
|
108
|
-
|
|
109
|
-
function htmlToMarkdown(html: string, options?: Partial<MdreamOptions>): string
|
|
110
|
-
|
|
111
|
-
// Browser bundles and the CDN script load the WASM binary first
|
|
112
|
-
function htmlToMarkdown(html: string, options?: Partial<MdreamOptions>): Promise<string>
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
**JS engine** (`@mdream/js`):
|
|
116
|
-
|
|
117
|
-
```ts
|
|
118
|
-
import { htmlToMarkdown } from '@mdream/js'
|
|
119
|
-
|
|
120
|
-
function htmlToMarkdown(html: string, options?: Partial<MdreamOptions>): string
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
**Example:**
|
|
124
|
-
|
|
125
|
-
```ts
|
|
126
|
-
import { htmlToMarkdown } from 'mdream'
|
|
127
|
-
|
|
128
|
-
const markdown = htmlToMarkdown('<h1>Hello World</h1><p>Some content.</p>')
|
|
129
|
-
// # Hello World
|
|
130
|
-
//
|
|
131
|
-
// Some content.
|
|
132
|
-
|
|
133
|
-
const text = htmlToMarkdown('<h1>Hello <strong>World</strong></h1>', {
|
|
134
|
-
format: 'text',
|
|
135
|
-
})
|
|
136
|
-
// Hello World
|
|
137
|
-
|
|
138
|
-
const html = htmlToMarkdown('<h1>Hello <strong>World</strong></h1>', {
|
|
139
|
-
format: 'html',
|
|
140
|
-
})
|
|
141
|
-
// <h1 id="hello-world">Hello <strong>World</strong></h1>
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### `streamHtmlToMarkdown()`
|
|
145
|
-
|
|
146
|
-
Converts an HTML `ReadableStream` to Markdown, plain text, or HTML incrementally. Returns an `AsyncIterable<string>` that yields output chunks as they are processed.
|
|
147
|
-
|
|
148
|
-
It takes the same options as `htmlToMarkdown()`. The `frontmatter` callback and the `extraction` handlers run once, after the stream ends and before the last chunk is yielded.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
```ts
|
|
152
|
-
import { streamHtmlToMarkdown } from 'mdream'
|
|
153
|
-
|
|
154
|
-
function streamHtmlToMarkdown(
|
|
155
|
-
htmlStream: ReadableStream<Uint8Array | string> | null,
|
|
156
|
-
options?: Partial<MdreamOptions>,
|
|
157
|
-
): AsyncIterable<string>
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
**Example:**
|
|
162
|
-
|
|
163
|
-
```ts
|
|
164
|
-
import { streamHtmlToMarkdown } from 'mdream'
|
|
165
|
-
|
|
166
|
-
const response = await fetch('https://example.com')
|
|
167
|
-
const stream = response.body
|
|
168
|
-
|
|
169
|
-
for await (const chunk of streamHtmlToMarkdown(stream, {
|
|
170
|
-
origin: 'https://example.com',
|
|
171
|
-
})) {
|
|
172
|
-
process.stdout.write(chunk)
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## Engines
|
|
177
|
-
|
|
178
|
-
Mdream includes two rendering engines, automatically selecting the best one for your environment:
|
|
179
|
-
|
|
180
|
-
| Engine | Package | Plugins | Use case |
|
|
181
|
-
|--------|---------|---------|----------|
|
|
182
|
-
| **Rust** (NAPI) | `mdream` | Declarative config only | Node.js (default) |
|
|
183
|
-
| **Rust** (WASM) | `mdream` | Declarative config only | Edge, browser |
|
|
184
|
-
| **JavaScript** | `@mdream/js` | Hook-based + declarative | Custom plugins, splitter |
|
|
185
|
-
|
|
186
|
-
```ts
|
|
187
|
-
// JavaScript engine (required for hook-based plugins)
|
|
188
|
-
import { htmlToMarkdown } from '@mdream/js'
|
|
189
|
-
|
|
190
|
-
// Rust NAPI engine (auto-selected in Node.js)
|
|
191
|
-
import { htmlToMarkdown } from 'mdream'
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
Both engines support the same declarative plugins, but the option shape differs. The Rust engine takes `minimal`, `frontmatter`, `isolateMain`, `tailwind`, `filter`, `extraction`, and `tagOverrides` at the top level. The JS engine reads the plugins from `options.plugins` and has no `minimal` option: use `withMinimalPreset()` from `@mdream/js/preset/minimal`. If the JS engine gets one of these options at the top level, it throws a `TypeError` that names the fix. The JS engine also supports `hooks` for imperative plugin transforms.
|
|
195
|
-
|
|
196
|
-
## Options
|
|
197
|
-
|
|
198
|
-
### MdreamOptions (Rust engine)
|
|
199
|
-
|
|
200
|
-
Defined in `mdream`:
|
|
201
|
-
|
|
202
|
-
```ts
|
|
203
|
-
interface MdreamOptions {
|
|
204
|
-
/** Base URL for resolving relative links and images. */
|
|
205
|
-
origin?: string
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Enable minimal preset (frontmatter, isolateMain, tailwind, filter).
|
|
209
|
-
* Default: false
|
|
210
|
-
*/
|
|
211
|
-
minimal?: boolean
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Post-processing cleanup. Pass `true` for all cleanup, or an object for specific features.
|
|
215
|
-
* Enabled by default when `minimal` is true.
|
|
216
|
-
*/
|
|
217
|
-
clean?: boolean | CleanOptions
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Extract frontmatter from HTML <head>.
|
|
221
|
-
* - `true`: enable with defaults
|
|
222
|
-
* - `(fm) => void`: enable and receive structured data via callback
|
|
223
|
-
* - `FrontmatterConfig`: enable with config and optional callback
|
|
224
|
-
*/
|
|
225
|
-
frontmatter?: boolean | ((frontmatter: Record<string, string>) => void) | FrontmatterConfig
|
|
226
|
-
|
|
227
|
-
/** Isolate main content area. Default when minimal: true */
|
|
228
|
-
isolateMain?: boolean
|
|
229
|
-
|
|
230
|
-
/** Convert Tailwind utility classes to Markdown. Default when minimal: true */
|
|
231
|
-
tailwind?: boolean
|
|
232
|
-
|
|
233
|
-
/** Filter elements by CSS selectors. Default when minimal: excludes form, nav, footer, etc. */
|
|
234
|
-
filter?: false | { include?: string[], exclude?: string[], processChildren?: boolean }
|
|
235
|
-
|
|
236
|
-
/** Extract elements matching CSS selectors during conversion. */
|
|
237
|
-
extraction?: Record<string, (element: ExtractedElement) => void>
|
|
238
|
-
|
|
239
|
-
/** Override tag rendering behavior. String values act as aliases. */
|
|
240
|
-
tagOverrides?: Record<string, TagOverride | string>
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Hard-wrap prose at this many characters, breaking on word boundaries.
|
|
244
|
-
* Applied inline during conversion (zero-cost when unset). Code blocks,
|
|
245
|
-
* tables, and headings are never wrapped. `0` (or unset) disables wrapping.
|
|
246
|
-
*/
|
|
247
|
-
wrapWidth?: number
|
|
248
|
-
|
|
249
|
-
/** Output Markdown, plain text, or HTML. Default: 'markdown' */
|
|
250
|
-
format?: 'markdown' | 'text' | 'html'
|
|
251
|
-
}
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
### MdreamOptions (JS engine)
|
|
255
|
-
|
|
256
|
-
The JS engine extends the shared `EngineOptions` with hook-based plugin support:
|
|
257
|
-
|
|
258
|
-
```ts
|
|
259
|
-
interface MdreamOptions extends EngineOptions {
|
|
260
|
-
/** Imperative hook-based transform plugins. JS engine only. */
|
|
261
|
-
hooks?: TransformPlugin[]
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
interface EngineOptions {
|
|
265
|
-
origin?: string
|
|
266
|
-
clean?: boolean | CleanOptions
|
|
267
|
-
plugins?: BuiltinPlugins
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Hard-wrap prose at this many characters, breaking on word boundaries.
|
|
271
|
-
* Code blocks, tables, and headings are never wrapped. `0` (or unset)
|
|
272
|
-
* disables wrapping.
|
|
273
|
-
*/
|
|
274
|
-
wrapWidth?: number
|
|
275
|
-
|
|
276
|
-
/** Output Markdown, plain text, or HTML. Default: 'markdown' */
|
|
277
|
-
format?: 'markdown' | 'text' | 'html'
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
interface BuiltinPlugins {
|
|
281
|
-
filter?: false | { include?: (string | number)[], exclude?: (string | number)[], processChildren?: boolean }
|
|
282
|
-
frontmatter?: boolean | ((fm: Record<string, string>) => void) | FrontmatterConfig
|
|
283
|
-
isolateMain?: boolean
|
|
284
|
-
tailwind?: boolean
|
|
285
|
-
extraction?: Record<string, (element: ExtractedElement) => void>
|
|
286
|
-
tagOverrides?: Record<string, TagOverride | string>
|
|
287
|
-
}
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
Note: The JS engine uses `options.plugins.filter` while the Rust engine uses `options.filter` directly.
|
|
291
|
-
|
|
292
|
-
### CleanOptions
|
|
293
|
-
|
|
294
|
-
Post-processing cleanup applied to the final Markdown output. All options default to `false` unless `clean: true` is set.
|
|
295
|
-
|
|
296
|
-
```ts
|
|
297
|
-
interface CleanOptions {
|
|
298
|
-
/** Strip tracking query parameters (utm_*, fbclid, gclid, etc.) from URLs */
|
|
299
|
-
urls?: boolean
|
|
300
|
-
/** Strip fragment-only links that don't match any heading in the output */
|
|
301
|
-
fragments?: boolean
|
|
302
|
-
/** Strip links with meaningless hrefs (#, javascript:void(0)) to plain text */
|
|
303
|
-
emptyLinks?: boolean
|
|
304
|
-
/** Collapse 3+ consecutive blank lines to 2 */
|
|
305
|
-
blankLines?: boolean
|
|
306
|
-
/** Strip links where text equals URL: [https://x.com](https://x.com) becomes https://x.com */
|
|
307
|
-
redundantLinks?: boolean
|
|
308
|
-
/** Strip self-referencing heading anchors: ## [Title](#title) becomes ## Title */
|
|
309
|
-
selfLinkHeadings?: boolean
|
|
310
|
-
/** Strip images with no alt text (decorative/tracking pixels) */
|
|
311
|
-
emptyImages?: boolean
|
|
312
|
-
/** Drop links that produce no visible text: [](url) is removed entirely */
|
|
313
|
-
emptyLinkText?: boolean
|
|
314
|
-
}
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
**Example:**
|
|
318
|
-
|
|
319
|
-
```ts
|
|
320
|
-
const markdown = htmlToMarkdown(html, {
|
|
321
|
-
clean: {
|
|
322
|
-
urls: true,
|
|
323
|
-
emptyLinks: true,
|
|
324
|
-
emptyImages: true,
|
|
325
|
-
},
|
|
326
|
-
})
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
### FrontmatterConfig
|
|
330
|
-
|
|
331
|
-
```ts
|
|
332
|
-
interface FrontmatterConfig {
|
|
333
|
-
/** Additional static fields to include in frontmatter */
|
|
334
|
-
additionalFields?: Record<string, string>
|
|
335
|
-
/**
|
|
336
|
-
* Meta tag names to extract beyond the defaults.
|
|
337
|
-
* Defaults: description, keywords, author, date,
|
|
338
|
-
* og:title, og:description, twitter:title, twitter:description
|
|
339
|
-
*/
|
|
340
|
-
metaFields?: string[]
|
|
341
|
-
/** Callback to receive structured frontmatter data after conversion */
|
|
342
|
-
onExtract?: (frontmatter: Record<string, string>) => void
|
|
343
|
-
}
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
### TagOverride
|
|
347
|
-
|
|
348
|
-
Override how specific HTML tags are rendered in Markdown. String values act as aliases.
|
|
349
|
-
|
|
350
|
-
> **Unknown tags pass through as plain text.** Tag matching is strict: only the standard HTML tags ship with built-in Markdown semantics. Custom elements (`<my-widget>`), web components, and any non-standard tag emit their text content verbatim, with the surrounding tag dropped. To render a custom tag with Markdown semantics, alias it with `tagOverrides`:
|
|
351
|
-
>
|
|
352
|
-
> ```ts
|
|
353
|
-
> htmlToMarkdown('<my-em>hi</my-em>', { tagOverrides: { 'my-em': 'em' } })
|
|
354
|
-
> // → "*hi*"
|
|
355
|
-
> ```
|
|
356
|
-
|
|
357
|
-
```ts
|
|
358
|
-
interface TagOverride {
|
|
359
|
-
/** Markdown string to insert when entering this tag */
|
|
360
|
-
enter?: string
|
|
361
|
-
/** Markdown string to insert when exiting this tag */
|
|
362
|
-
exit?: string
|
|
363
|
-
/** Spacing: [newlines before, newlines after] */
|
|
364
|
-
spacing?: number[]
|
|
365
|
-
/** Whether this tag should be treated as inline */
|
|
366
|
-
isInline?: boolean
|
|
367
|
-
/** Whether this tag is self-closing */
|
|
368
|
-
isSelfClosing?: boolean
|
|
369
|
-
/** Whether whitespace inside this tag should be collapsed */
|
|
370
|
-
collapsesInnerWhiteSpace?: boolean
|
|
371
|
-
/** Alias this tag to another tag's handler */
|
|
372
|
-
alias?: string
|
|
373
|
-
}
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
**Example:**
|
|
377
|
-
|
|
378
|
-
```ts
|
|
379
|
-
const markdown = htmlToMarkdown(html, {
|
|
380
|
-
tagOverrides: {
|
|
381
|
-
// Treat <x-heading> like <h2>
|
|
382
|
-
'x-heading': 'h2',
|
|
383
|
-
// Custom rendering for <callout>
|
|
384
|
-
'callout': {
|
|
385
|
-
enter: '> **Note:** ',
|
|
386
|
-
exit: '',
|
|
387
|
-
spacing: [2, 2],
|
|
388
|
-
},
|
|
389
|
-
},
|
|
390
|
-
})
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
**Output is GitHub Flavored Markdown.** Mdream emits a fixed GFM dialect tuned for LLM input: ATX headings (`#`), fenced code blocks (` ``` `), `-` bullets, `*` emphasis, `**` strong, `---` horizontal rules, inline links. These are not configurable. For simple delimiter swaps you can use `tagOverrides`:
|
|
394
|
-
|
|
395
|
-
```ts
|
|
396
|
-
htmlToMarkdown(html, {
|
|
397
|
-
tagOverrides: {
|
|
398
|
-
em: { enter: '_', exit: '_', isInline: true }, // *x* → _x_
|
|
399
|
-
strong: { enter: '__', exit: '__', isInline: true }, // **x** → __x__
|
|
400
|
-
hr: { enter: '* * *', exit: '' }, // --- → * * *
|
|
401
|
-
},
|
|
402
|
-
})
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
Structural style differences (setext headings, indented code blocks, reference-style links, `~~~` fences, dynamic list markers) are out of scope. If you need turndown-style configurability, use [turndown](https://github.com/mixmark-io/turndown). If you have a use case for these in mdream, please open an issue.
|
|
406
|
-
|
|
407
|
-
### FilterOptions
|
|
408
|
-
|
|
409
|
-
```ts
|
|
410
|
-
interface FilterOptions {
|
|
411
|
-
/** CSS selectors, tag names, or TAG_* constants for elements to include (all others excluded) */
|
|
412
|
-
include?: (string | number)[]
|
|
413
|
-
/** CSS selectors, tag names, or TAG_* constants for elements to exclude */
|
|
414
|
-
exclude?: (string | number)[]
|
|
415
|
-
/** Whether to also process children of matched elements. Default: true */
|
|
416
|
-
processChildren?: boolean
|
|
417
|
-
}
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
## Presets
|
|
421
|
-
|
|
422
|
-
### Minimal Preset
|
|
423
|
-
|
|
424
|
-
The `minimal` preset enables the following plugins together:
|
|
425
|
-
|
|
426
|
-
- **frontmatter**: Extracts metadata from HTML `<head>` into YAML frontmatter
|
|
427
|
-
- **isolateMain**: Extracts the main content area, skipping navigation, headers, and footers
|
|
428
|
-
- **tailwind**: Converts Tailwind utility classes to Markdown formatting
|
|
429
|
-
- **filter**: Excludes `form`, `fieldset`, `object`, `embed`, `footer`, `aside`, `iframe`, `input`, `textarea`, `select`, `button`, `nav`
|
|
430
|
-
- **clean**: All post-processing cleanup enabled
|
|
431
|
-
|
|
432
|
-
A `filter` passed with `minimal` adds to the preset's excludes. It does not replace them. To turn the preset's filter off, pass `filter: false`. `withMinimalPreset()` in the JS engine works the same way.
|
|
433
|
-
|
|
434
|
-
```ts
|
|
435
|
-
// Excludes h1 as well as form, nav, footer, and the rest
|
|
436
|
-
htmlToMarkdown(html, { minimal: true, filter: { exclude: ['h1'] } })
|
|
437
|
-
|
|
438
|
-
// Keeps forms and nav
|
|
439
|
-
htmlToMarkdown(html, { minimal: true, filter: false })
|
|
440
|
-
```
|
|
441
|
-
|
|
442
|
-
**Rust engine:**
|
|
443
|
-
|
|
444
|
-
```ts
|
|
445
|
-
import { htmlToMarkdown } from 'mdream'
|
|
446
|
-
|
|
447
|
-
const markdown = htmlToMarkdown(html, {
|
|
448
|
-
origin: 'https://example.com',
|
|
449
|
-
minimal: true,
|
|
450
|
-
})
|
|
451
|
-
```
|
|
452
|
-
|
|
453
|
-
**JS engine (using `withMinimalPreset`):**
|
|
454
|
-
|
|
455
|
-
```ts
|
|
456
|
-
import { htmlToMarkdown } from '@mdream/js'
|
|
457
|
-
import { withMinimalPreset } from '@mdream/js/preset/minimal'
|
|
458
|
-
|
|
459
|
-
const markdown = htmlToMarkdown(html, withMinimalPreset({
|
|
460
|
-
origin: 'https://example.com',
|
|
461
|
-
}))
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
`withMinimalPreset()` returns an `EngineOptions` object with all plugin defaults applied. You can override individual plugins. A `filter` adds to the preset's excludes:
|
|
465
|
-
|
|
466
|
-
```ts
|
|
467
|
-
const markdown = htmlToMarkdown(html, withMinimalPreset({
|
|
468
|
-
plugins: {
|
|
469
|
-
frontmatter: false,
|
|
470
|
-
filter: { exclude: ['.cookie-banner'] },
|
|
471
|
-
},
|
|
472
|
-
}))
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
## Built-in Plugins
|
|
476
|
-
|
|
477
|
-
All built-in plugins work with both the Rust and JS engines through declarative configuration.
|
|
478
|
-
|
|
479
|
-
### Frontmatter Plugin
|
|
480
|
-
|
|
481
|
-
Extracts metadata from the HTML `<head>` element and generates YAML frontmatter.
|
|
482
|
-
|
|
483
|
-
**Extracted fields by default:** `title`, `description`, `keywords`, `author`, `date`, `og:title`, `og:description`, `twitter:title`, `twitter:description`.
|
|
484
|
-
|
|
485
|
-
```ts
|
|
486
|
-
// Enable with defaults
|
|
487
|
-
htmlToMarkdown(html, { frontmatter: true })
|
|
488
|
-
|
|
489
|
-
// With callback to receive structured data
|
|
490
|
-
htmlToMarkdown(html, {
|
|
491
|
-
frontmatter: (fm) => {
|
|
492
|
-
console.log(fm.title)
|
|
493
|
-
console.log(fm.description)
|
|
494
|
-
},
|
|
495
|
-
})
|
|
496
|
-
|
|
497
|
-
// With full config
|
|
498
|
-
htmlToMarkdown(html, {
|
|
499
|
-
frontmatter: {
|
|
500
|
-
additionalFields: { source: 'https://example.com' },
|
|
501
|
-
metaFields: ['robots', 'viewport'],
|
|
502
|
-
onExtract: fm => console.log(fm),
|
|
503
|
-
},
|
|
504
|
-
})
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
**Output example:**
|
|
508
|
-
|
|
509
|
-
```yaml
|
|
510
|
-
---
|
|
511
|
-
title: My Page Title
|
|
512
|
-
meta:
|
|
513
|
-
description: A page description
|
|
514
|
-
'og:title': My Page Title
|
|
515
|
-
---
|
|
516
|
-
```
|
|
517
|
-
|
|
518
|
-
### Isolate Main Plugin
|
|
519
|
-
|
|
520
|
-
Isolates the main content area using the following priority:
|
|
521
|
-
|
|
522
|
-
1. If an explicit `<main>` element exists (within 5 depth levels), use its content exclusively
|
|
523
|
-
2. Otherwise, find content between the first header tag (`h1`-`h6`) and the first `<footer>`
|
|
524
|
-
3. Headings inside `<header>` tags are skipped during fallback detection
|
|
525
|
-
4. The `<head>` section is always passed through for other plugins (e.g., frontmatter)
|
|
526
|
-
|
|
527
|
-
```ts
|
|
528
|
-
htmlToMarkdown(html, { isolateMain: true })
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
### Tailwind Plugin
|
|
532
|
-
|
|
533
|
-
Converts Tailwind CSS utility classes to semantic Markdown formatting:
|
|
534
|
-
|
|
535
|
-
| Tailwind Class | Markdown Output |
|
|
536
|
-
|---|---|
|
|
537
|
-
| `font-bold`, `font-semibold`, `font-medium`, `font-extrabold`, `font-black` | `**bold**` |
|
|
538
|
-
| `italic`, `font-italic` | `*italic*` |
|
|
539
|
-
| `line-through` | `~~strikethrough~~` |
|
|
540
|
-
| `hidden`, `invisible` | Content removed |
|
|
541
|
-
| `absolute`, `fixed`, `sticky` | Content removed |
|
|
542
|
-
|
|
543
|
-
Supports responsive breakpoint prefixes (`sm:`, `md:`, `lg:`, `xl:`, `2xl:`) with mobile-first resolution.
|
|
544
|
-
|
|
545
|
-
```ts
|
|
546
|
-
htmlToMarkdown(html, { tailwind: true })
|
|
547
|
-
```
|
|
548
|
-
|
|
549
|
-
### Filter Plugin
|
|
550
|
-
|
|
551
|
-
Filters HTML elements by CSS selectors, tag names, or `TAG_*` constants.
|
|
552
|
-
|
|
553
|
-
```ts
|
|
554
|
-
// Exclude navigation, sidebar, footer
|
|
555
|
-
htmlToMarkdown(html, {
|
|
556
|
-
filter: {
|
|
557
|
-
exclude: ['nav', '#sidebar', '.footer', 'aside'],
|
|
558
|
-
},
|
|
559
|
-
})
|
|
560
|
-
|
|
561
|
-
// Include only specific elements
|
|
562
|
-
htmlToMarkdown(html, {
|
|
563
|
-
filter: {
|
|
564
|
-
include: ['article', 'main'],
|
|
565
|
-
},
|
|
566
|
-
})
|
|
567
|
-
```
|
|
568
|
-
|
|
569
|
-
The JS engine also supports `TAG_*` integer constants for filtering:
|
|
570
|
-
|
|
571
|
-
```ts
|
|
572
|
-
import { TAG_FOOTER, TAG_NAV } from '@mdream/js'
|
|
573
|
-
|
|
574
|
-
htmlToMarkdown(html, {
|
|
575
|
-
plugins: {
|
|
576
|
-
filter: { exclude: [TAG_NAV, TAG_FOOTER] },
|
|
577
|
-
},
|
|
578
|
-
})
|
|
579
|
-
```
|
|
580
|
-
|
|
581
|
-
Elements with `style="position: absolute"` or `style="position: fixed"` are also automatically excluded when the filter plugin is active.
|
|
582
|
-
|
|
583
|
-
### Extraction Plugin
|
|
584
|
-
|
|
585
|
-
Extracts elements matching CSS selectors during conversion. Callbacks receive the matched element with its accumulated text content and attributes.
|
|
586
|
-
|
|
587
|
-
```ts
|
|
588
|
-
htmlToMarkdown(html, {
|
|
589
|
-
extraction: {
|
|
590
|
-
'h2': (el) => {
|
|
591
|
-
console.log('Heading:', el.textContent)
|
|
592
|
-
},
|
|
593
|
-
'img[alt]': (el) => {
|
|
594
|
-
console.log('Image:', el.attributes.src, el.attributes.alt)
|
|
595
|
-
},
|
|
596
|
-
'a[href]': (el) => {
|
|
597
|
-
console.log('Link:', el.textContent, el.attributes.href)
|
|
598
|
-
},
|
|
599
|
-
},
|
|
600
|
-
})
|
|
601
|
-
```
|
|
602
|
-
|
|
603
|
-
The `ExtractedElement` interface:
|
|
604
|
-
|
|
605
|
-
```ts
|
|
606
|
-
interface ExtractedElement {
|
|
607
|
-
selector: string
|
|
608
|
-
tagName: string
|
|
609
|
-
textContent: string
|
|
610
|
-
attributes: Record<string, string>
|
|
611
|
-
}
|
|
612
|
-
```
|
|
613
|
-
|
|
614
|
-
## Hook-Based Plugins (JS Engine)
|
|
615
|
-
|
|
616
|
-
The JS engine (`@mdream/js`) supports imperative hook-based plugins for custom transform logic. These allow you to intercept and modify the conversion pipeline at multiple stages.
|
|
617
|
-
|
|
618
|
-
```ts
|
|
619
|
-
import { htmlToMarkdown } from '@mdream/js'
|
|
620
|
-
import { createPlugin } from '@mdream/js/plugins'
|
|
621
|
-
|
|
622
|
-
const myPlugin = createPlugin({
|
|
623
|
-
onNodeEnter(node) {
|
|
624
|
-
if (node.name === 'h1')
|
|
625
|
-
return '** '
|
|
626
|
-
},
|
|
627
|
-
processTextNode(textNode) {
|
|
628
|
-
if (textNode.parent?.attributes?.id === 'highlight') {
|
|
629
|
-
return { content: `**${textNode.value}**`, skip: false }
|
|
630
|
-
}
|
|
631
|
-
},
|
|
632
|
-
})
|
|
633
|
-
|
|
634
|
-
const markdown = htmlToMarkdown(html, { hooks: [myPlugin] })
|
|
635
|
-
```
|
|
636
|
-
|
|
637
|
-
### Plugin Hooks
|
|
638
|
-
|
|
639
|
-
```ts
|
|
640
|
-
interface TransformPlugin {
|
|
641
|
-
/**
|
|
642
|
-
* Called before any node processing. Return { skip: true } to skip the node.
|
|
643
|
-
*/
|
|
644
|
-
beforeNodeProcess?: (
|
|
645
|
-
event: NodeEvent,
|
|
646
|
-
state: MdreamRuntimeState,
|
|
647
|
-
) => undefined | void | { skip: boolean }
|
|
648
|
-
|
|
649
|
-
/**
|
|
650
|
-
* Called when entering an element node.
|
|
651
|
-
* Return a string to prepend to the output.
|
|
652
|
-
*/
|
|
653
|
-
onNodeEnter?: (
|
|
654
|
-
node: ElementNode,
|
|
655
|
-
state: MdreamRuntimeState,
|
|
656
|
-
) => string | undefined | void
|
|
657
|
-
|
|
658
|
-
/**
|
|
659
|
-
* Called when exiting an element node.
|
|
660
|
-
* Return a string to append to the output.
|
|
661
|
-
*/
|
|
662
|
-
onNodeExit?: (
|
|
663
|
-
node: ElementNode,
|
|
664
|
-
state: MdreamRuntimeState,
|
|
665
|
-
) => string | undefined | void
|
|
666
|
-
|
|
667
|
-
/**
|
|
668
|
-
* Called to process element attributes (e.g., extracting Tailwind classes).
|
|
669
|
-
*/
|
|
670
|
-
processAttributes?: (
|
|
671
|
-
node: ElementNode,
|
|
672
|
-
state: MdreamRuntimeState,
|
|
673
|
-
) => void
|
|
674
|
-
|
|
675
|
-
/**
|
|
676
|
-
* Called for each text node. Return { content, skip } to transform text.
|
|
677
|
-
* Return undefined for no transformation.
|
|
678
|
-
*/
|
|
679
|
-
processTextNode?: (
|
|
680
|
-
node: TextNode,
|
|
681
|
-
state: MdreamRuntimeState,
|
|
682
|
-
) => { content: string, skip: boolean } | undefined
|
|
683
|
-
}
|
|
684
|
-
```
|
|
685
|
-
|
|
686
|
-
### `createPlugin()`
|
|
687
|
-
|
|
688
|
-
A typed identity function for creating plugins with full TypeScript inference:
|
|
689
|
-
|
|
690
|
-
```ts
|
|
691
|
-
import { createPlugin } from '@mdream/js/plugins'
|
|
692
|
-
|
|
693
|
-
const plugin = createPlugin({
|
|
694
|
-
beforeNodeProcess({ node }) {
|
|
695
|
-
// Skip all div elements with class "ad"
|
|
696
|
-
if (node.type === 1 && node.attributes?.class?.includes('ad')) {
|
|
697
|
-
return { skip: true }
|
|
698
|
-
}
|
|
699
|
-
},
|
|
700
|
-
})
|
|
701
|
-
```
|
|
702
|
-
|
|
703
|
-
### Built-in Plugin Functions (JS Engine)
|
|
704
|
-
|
|
705
|
-
The following plugin factory functions are available from `@mdream/js/plugins`:
|
|
706
|
-
|
|
707
|
-
```ts
|
|
708
|
-
import {
|
|
709
|
-
createPlugin,
|
|
710
|
-
extractionCollectorPlugin,
|
|
711
|
-
extractionPlugin,
|
|
712
|
-
filterPlugin,
|
|
713
|
-
frontmatterPlugin,
|
|
714
|
-
isolateMainPlugin,
|
|
715
|
-
tailwindPlugin,
|
|
716
|
-
} from '@mdream/js/plugins'
|
|
717
|
-
```
|
|
718
|
-
|
|
719
|
-
## Markdown Splitting (JS Engine)
|
|
720
|
-
|
|
721
|
-
Split HTML into Markdown chunks during conversion. Compatible with the LangChain `Document` structure.
|
|
722
|
-
|
|
723
|
-
Available from `@mdream/js/splitter`.
|
|
724
|
-
|
|
725
|
-
### Basic Chunking
|
|
726
|
-
|
|
727
|
-
```ts
|
|
728
|
-
import { TAG_H2 } from '@mdream/js'
|
|
729
|
-
import { htmlToMarkdownSplitChunks } from '@mdream/js/splitter'
|
|
730
|
-
|
|
731
|
-
const html = `
|
|
732
|
-
<h1>Documentation</h1>
|
|
733
|
-
<h2>Installation</h2>
|
|
734
|
-
<p>Install via npm...</p>
|
|
735
|
-
<h2>Usage</h2>
|
|
736
|
-
<p>Use it like this...</p>
|
|
737
|
-
`
|
|
738
|
-
|
|
739
|
-
const chunks = htmlToMarkdownSplitChunks(html, {
|
|
740
|
-
headersToSplitOn: [TAG_H2],
|
|
741
|
-
chunkSize: 1000,
|
|
742
|
-
chunkOverlap: 200,
|
|
743
|
-
stripHeaders: true,
|
|
744
|
-
})
|
|
745
|
-
|
|
746
|
-
chunks.forEach((chunk) => {
|
|
747
|
-
console.log(chunk.content)
|
|
748
|
-
console.log(chunk.metadata.headers) // { h1: "Documentation", h2: "Installation" }
|
|
749
|
-
console.log(chunk.metadata.code) // Language if chunk contains code
|
|
750
|
-
console.log(chunk.metadata.loc) // { lines: { from: 1, to: 5 } }
|
|
751
|
-
})
|
|
752
|
-
```
|
|
753
|
-
|
|
754
|
-
### Streaming Chunks (Memory Efficient)
|
|
755
|
-
|
|
756
|
-
For large documents, use the generator version to process chunks one at a time:
|
|
757
|
-
|
|
758
|
-
```ts
|
|
759
|
-
import { htmlToMarkdownSplitChunksStream } from '@mdream/js/splitter'
|
|
760
|
-
|
|
761
|
-
for (const chunk of htmlToMarkdownSplitChunksStream(html, options)) {
|
|
762
|
-
await processChunk(chunk)
|
|
763
|
-
|
|
764
|
-
// Early termination supported
|
|
765
|
-
if (foundTarget)
|
|
766
|
-
break
|
|
767
|
-
}
|
|
768
|
-
```
|
|
769
|
-
|
|
770
|
-
### Splitter Options
|
|
771
|
-
|
|
772
|
-
```ts
|
|
773
|
-
interface SplitterOptions {
|
|
774
|
-
// --- Structural splitting ---
|
|
775
|
-
|
|
776
|
-
/**
|
|
777
|
-
* Header tag IDs to split on (TAG_H1 through TAG_H6).
|
|
778
|
-
* Default: [TAG_H2, TAG_H3, TAG_H4, TAG_H5, TAG_H6]
|
|
779
|
-
*/
|
|
780
|
-
headersToSplitOn?: number[]
|
|
781
|
-
|
|
782
|
-
// --- Size-based splitting ---
|
|
783
|
-
|
|
784
|
-
/** Maximum chunk size in characters. Default: 1000 */
|
|
785
|
-
chunkSize?: number
|
|
786
|
-
|
|
787
|
-
/** Overlap between chunks for context preservation. Default: 200 */
|
|
788
|
-
chunkOverlap?: number
|
|
789
|
-
|
|
790
|
-
/**
|
|
791
|
-
* Custom length function (e.g., a token counter for LLM applications).
|
|
792
|
-
* Default: (text) => text.length
|
|
793
|
-
*/
|
|
794
|
-
lengthFunction?: (text: string) => number
|
|
795
|
-
|
|
796
|
-
// --- Output formatting ---
|
|
797
|
-
|
|
798
|
-
/** Remove headers from chunk content. Default: true */
|
|
799
|
-
stripHeaders?: boolean
|
|
800
|
-
|
|
801
|
-
/** Split into individual lines. Default: false */
|
|
802
|
-
returnEachLine?: boolean
|
|
803
|
-
|
|
804
|
-
/** Keep separators in the split chunks. Default: false */
|
|
805
|
-
keepSeparator?: boolean
|
|
806
|
-
|
|
807
|
-
// --- Standard options ---
|
|
808
|
-
|
|
809
|
-
/** Base URL for resolving relative links/images */
|
|
810
|
-
origin?: string
|
|
811
|
-
|
|
812
|
-
/** Declarative built-in plugin config */
|
|
813
|
-
plugins?: BuiltinPlugins
|
|
814
|
-
|
|
815
|
-
/** Hook-based plugins (JS engine only) */
|
|
816
|
-
hooks?: TransformPlugin[]
|
|
817
|
-
|
|
818
|
-
/** Post-processing cleanup */
|
|
819
|
-
clean?: boolean | CleanOptions
|
|
820
|
-
}
|
|
821
|
-
```
|
|
822
|
-
|
|
823
|
-
### Chunk Metadata
|
|
824
|
-
|
|
825
|
-
Each chunk includes metadata for context:
|
|
826
|
-
|
|
827
|
-
```ts
|
|
828
|
-
interface MarkdownChunk {
|
|
829
|
-
content: string
|
|
830
|
-
metadata: {
|
|
831
|
-
/** Header hierarchy at this chunk position */
|
|
832
|
-
headers?: Record<string, string> // { h1: "Title", h2: "Section" }
|
|
833
|
-
/** Code block language if chunk contains code */
|
|
834
|
-
code?: string
|
|
835
|
-
/** Line number range in the original document */
|
|
836
|
-
loc?: {
|
|
837
|
-
lines: { from: number, to: number }
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
```
|
|
842
|
-
|
|
843
|
-
### Use with Presets
|
|
844
|
-
|
|
845
|
-
Combine splitting with presets:
|
|
846
|
-
|
|
847
|
-
```ts
|
|
848
|
-
import { TAG_H2 } from '@mdream/js'
|
|
849
|
-
import { withMinimalPreset } from '@mdream/js/preset/minimal'
|
|
850
|
-
import { htmlToMarkdownSplitChunks } from '@mdream/js/splitter'
|
|
851
|
-
|
|
852
|
-
const chunks = htmlToMarkdownSplitChunks(html, withMinimalPreset({
|
|
853
|
-
headersToSplitOn: [TAG_H2],
|
|
854
|
-
chunkSize: 500,
|
|
855
|
-
origin: 'https://example.com',
|
|
856
|
-
}))
|
|
857
|
-
```
|
|
858
|
-
|
|
859
|
-
## Content Negotiation
|
|
860
|
-
|
|
861
|
-
The `@mdream/js/negotiate` module provides HTTP content negotiation utilities for serving Markdown to LLM clients:
|
|
862
|
-
|
|
863
|
-
```ts
|
|
864
|
-
import { parseAcceptHeader, shouldServeMarkdown } from '@mdream/js/negotiate'
|
|
865
|
-
|
|
866
|
-
// Check if client prefers markdown
|
|
867
|
-
const serveMarkdown = shouldServeMarkdown(
|
|
868
|
-
request.headers.get('accept'),
|
|
869
|
-
request.headers.get('sec-fetch-dest'),
|
|
870
|
-
)
|
|
871
|
-
|
|
872
|
-
if (serveMarkdown) {
|
|
873
|
-
return new Response(markdown, {
|
|
874
|
-
headers: { 'Content-Type': 'text/markdown' },
|
|
875
|
-
})
|
|
876
|
-
}
|
|
877
|
-
```
|
|
878
|
-
|
|
879
|
-
`shouldServeMarkdown()` uses Accept header quality weights and position ordering. It returns `true` when `text/markdown` or `text/plain` has higher priority than `text/html`. Browser navigation requests (`sec-fetch-dest: document`) always return `false`.
|
|
880
|
-
|
|
881
|
-
## Pure HTML Parser (JS Engine)
|
|
882
|
-
|
|
883
|
-
If you only need to parse HTML into a DOM-like event stream without converting to Markdown, use `parseHtml` from the JS engine:
|
|
884
|
-
|
|
885
|
-
```ts
|
|
886
|
-
import { parseHtml } from '@mdream/js/parse'
|
|
887
|
-
|
|
888
|
-
const html = '<div><h1>Title</h1><p>Content</p></div>'
|
|
889
|
-
const { events, remainingHtml } = parseHtml(html)
|
|
890
|
-
|
|
891
|
-
events.forEach((event) => {
|
|
892
|
-
if (event.type === 0 && event.node.type === 1) { // Enter + Element
|
|
893
|
-
console.log('Entering element:', event.node.name)
|
|
894
|
-
}
|
|
895
|
-
})
|
|
896
|
-
```
|
|
897
|
-
|
|
898
|
-
The parser provides:
|
|
899
|
-
- Pure AST event stream with no markdown generation overhead
|
|
900
|
-
- Enter/exit events for each element and text node
|
|
901
|
-
- Plugin support during parsing
|
|
902
|
-
- Streaming compatible via `parseHtmlStream()`
|
|
903
|
-
|
|
904
|
-
## CLI Usage
|
|
905
|
-
|
|
906
|
-
Mdream provides a CLI that works with Unix pipes.
|
|
907
|
-
|
|
908
|
-
**Pipe site to Markdown:**
|
|
909
|
-
|
|
910
|
-
```bash
|
|
911
|
-
curl -s https://en.wikipedia.org/wiki/Markdown \
|
|
912
|
-
| npx mdream --origin https://en.wikipedia.org --preset minimal \
|
|
913
|
-
| tee output.md
|
|
914
|
-
```
|
|
915
|
-
|
|
916
|
-
**Local file to Markdown:**
|
|
917
|
-
|
|
918
|
-
```bash
|
|
919
|
-
cat index.html \
|
|
920
|
-
| npx mdream --preset minimal \
|
|
921
|
-
| tee output.md
|
|
922
|
-
```
|
|
923
|
-
|
|
924
|
-
**Plain text output:**
|
|
925
|
-
|
|
926
|
-
```bash
|
|
927
|
-
cat index.html \
|
|
928
|
-
| npx mdream --format text \
|
|
929
|
-
| tee output.txt
|
|
930
|
-
```
|
|
931
|
-
|
|
932
|
-
**HTML output:**
|
|
933
|
-
|
|
934
|
-
```bash
|
|
935
|
-
cat index.html \
|
|
936
|
-
| npx mdream --format html \
|
|
937
|
-
| tee output.html
|
|
938
|
-
```
|
|
939
|
-
|
|
940
|
-
### CLI Options
|
|
941
|
-
|
|
942
|
-
| Option | Description |
|
|
943
|
-
|--------|-------------|
|
|
944
|
-
| `--origin <url>` | Base URL for resolving relative links and images |
|
|
945
|
-
| `--preset minimal` | Enable the minimal preset |
|
|
946
|
-
| `--wrap-width <n>` | Hard-wrap prose at `n` characters (code, tables, and headings are never wrapped) |
|
|
947
|
-
| `--format <format>` | Output format: `markdown`, `text`, `html` |
|
|
948
|
-
| `--text` | Alias for `--format text` |
|
|
949
|
-
| `-h`, `--help` | Display help information |
|
|
950
|
-
|
|
951
|
-
The CLI reads HTML from stdin and writes Markdown, plain text, or HTML to stdout. It uses the streaming API internally.
|
|
952
|
-
|
|
953
|
-
## Browser and Edge Usage
|
|
954
|
-
|
|
955
|
-
Every entry takes the same `MdreamOptions` and produces the same Markdown string. In Node and edge runtimes, `htmlToMarkdown` is synchronous. In browser bundles, the CDN script, and `mdream/worker`, it returns `Promise<string>`, because the WASM binary loads first. Each export condition ships its own types, so TypeScript shows the right return type when it resolves the `browser` condition (for example, with `customConditions: ["browser"]`).
|
|
956
|
-
|
|
957
|
-
```ts
|
|
958
|
-
import { htmlToMarkdown } from 'mdream'
|
|
959
|
-
|
|
960
|
-
// In a browser bundle
|
|
961
|
-
const markdown = await htmlToMarkdown('<h1>Hello</h1>', { minimal: true })
|
|
962
|
-
```
|
|
963
|
-
|
|
964
|
-
### Edge / Cloudflare Workers
|
|
965
|
-
|
|
966
|
-
For edge runtimes (Cloudflare Workers, Vercel Edge), `mdream` automatically selects the WASM build via export conditions (`workerd`, `edge-light`). Both `htmlToMarkdown` and `streamHtmlToMarkdown` are available:
|
|
967
|
-
|
|
968
|
-
```ts
|
|
969
|
-
import { htmlToMarkdown, streamHtmlToMarkdown } from 'mdream'
|
|
970
|
-
|
|
971
|
-
// WASM engine auto-selected via export conditions
|
|
972
|
-
const markdown = htmlToMarkdown('<h1>Hello World</h1>')
|
|
973
|
-
|
|
974
|
-
// Streaming works the same as Node.js
|
|
975
|
-
const response = await fetch('https://example.com')
|
|
976
|
-
for await (const chunk of streamHtmlToMarkdown(response.body)) {
|
|
977
|
-
// process chunk
|
|
978
|
-
}
|
|
979
|
-
```
|
|
980
|
-
|
|
981
|
-
Conversion errors are catchable. WASM has no unwinding, so an internal Rust panic aborts the call, but the message is preserved and re-thrown as a normal `Error` (with the raw WASM trap as `cause`), and the instance keeps working for later requests:
|
|
982
|
-
|
|
983
|
-
```ts
|
|
984
|
-
try {
|
|
985
|
-
return new Response(htmlToMarkdown(html))
|
|
986
|
-
}
|
|
987
|
-
catch (error) {
|
|
988
|
-
// "mdream WASM panic, please report this at ...\npanicked at ..."
|
|
989
|
-
console.error(error)
|
|
990
|
-
return new Response('conversion failed', { status: 500 })
|
|
991
|
-
}
|
|
992
|
-
```
|
|
993
|
-
|
|
994
|
-
If your toolchain doesn't resolve the export conditions, the wasm-bindgen build (web target) is exposed at `mdream/wasm` for manual initialization. Its `htmlToMarkdown` takes the same `MdreamOptions` as the `mdream` entry. Its `MarkdownStream` runs the callbacks in `finish()`.
|
|
995
|
-
|
|
996
|
-
```ts
|
|
997
|
-
import init, { htmlToMarkdown } from 'mdream/wasm'
|
|
998
|
-
import wasmModule from 'mdream/wasm/mdream_edge_bg.wasm'
|
|
999
|
-
|
|
1000
|
-
await init({ module_or_path: wasmModule })
|
|
1001
|
-
const markdown = htmlToMarkdown('<h1>Hello</h1>', { minimal: true })
|
|
1002
|
-
```
|
|
1003
|
-
|
|
1004
|
-
`mdream/worker` is not an edge entry. It runs the conversion in a browser Web Worker; see [Web Worker](#web-worker).
|
|
1005
|
-
|
|
1006
|
-
### Browser CDN (IIFE)
|
|
1007
|
-
|
|
1008
|
-
Use mdream directly via CDN with no build step. The script inlines the WASM binary and initializes it on load, so `window.mdream.htmlToMarkdown()` is ready at once. It takes the same `MdreamOptions` as the `mdream` entry and returns `Promise<string>`, the same as the browser bundle.
|
|
1009
|
-
|
|
1010
|
-
```html
|
|
1011
|
-
<script src="https://unpkg.com/mdream/dist/iife.js"></script>
|
|
1012
|
-
<script>
|
|
1013
|
-
window.mdream.htmlToMarkdown('<h1>Hello</h1><p>World</p>')
|
|
1014
|
-
.then(markdown => console.log(markdown)) // # Hello\n\nWorld
|
|
1015
|
-
</script>
|
|
1016
|
-
```
|
|
1017
|
-
|
|
1018
|
-
**CDN Options:**
|
|
1019
|
-
- **unpkg**: `https://unpkg.com/mdream/dist/iife.js`
|
|
1020
|
-
- **jsDelivr**: `https://cdn.jsdelivr.net/npm/mdream/dist/iife.js`
|
|
1021
|
-
|
|
1022
|
-
### Web Worker
|
|
1023
|
-
|
|
1024
|
-
For browser environments, `mdream/worker` runs conversions off the main thread using a Web Worker:
|
|
1025
|
-
|
|
1026
|
-
```ts
|
|
1027
|
-
import { htmlToMarkdown, initWorker, terminateWorker } from 'mdream/worker'
|
|
1028
|
-
|
|
1029
|
-
await initWorker('/path/to/mdream_edge_bg.wasm')
|
|
1030
|
-
|
|
1031
|
-
// Takes the same options as the mdream entry. Callbacks run on this thread.
|
|
1032
|
-
const markdown = await htmlToMarkdown('<h1>Hello</h1>', { minimal: true })
|
|
1033
|
-
|
|
1034
|
-
// Clean up
|
|
1035
|
-
terminateWorker()
|
|
1036
|
-
```
|
|
1037
|
-
|
|
1038
|
-
## Content Extraction with Readability
|
|
1039
|
-
|
|
1040
|
-
For advanced content extraction (article detection, boilerplate removal), use [@mozilla/readability](https://github.com/mozilla/readability) before mdream:
|
|
1041
|
-
|
|
1042
|
-
```ts
|
|
1043
|
-
import { Readability } from '@mozilla/readability'
|
|
1044
|
-
import { JSDOM } from 'jsdom'
|
|
1045
|
-
import { htmlToMarkdown } from 'mdream'
|
|
1046
|
-
|
|
1047
|
-
const dom = new JSDOM(html, { url: 'https://example.com' })
|
|
1048
|
-
const article = new Readability(dom.window.document).parse()
|
|
1049
|
-
|
|
1050
|
-
if (article) {
|
|
1051
|
-
const markdown = htmlToMarkdown(article.content)
|
|
1052
|
-
// article.title, article.excerpt, article.byline also available
|
|
1053
|
-
}
|
|
1054
|
-
```
|
|
1055
|
-
|
|
1056
|
-
## llms.txt Generation
|
|
1057
|
-
|
|
1058
|
-
For llms.txt artifact generation, use `@mdream/js/llms-txt` from the `@mdream/js` package. It accepts pre-converted Markdown and generates `llms.txt` and `llms-full.txt` artifacts.
|
|
1059
|
-
|
|
1060
|
-
```ts
|
|
1061
|
-
import { generateLlmsTxtArtifacts } from '@mdream/js/llms-txt'
|
|
1062
|
-
import { htmlToMarkdown } from 'mdream'
|
|
1063
|
-
|
|
1064
|
-
const result = await generateLlmsTxtArtifacts({
|
|
1065
|
-
files: [
|
|
1066
|
-
{ title: 'Home', url: '/', content: htmlToMarkdown(homeHtml) },
|
|
1067
|
-
{ title: 'About', url: '/about', content: htmlToMarkdown(aboutHtml) },
|
|
1068
|
-
],
|
|
1069
|
-
siteName: 'My Site',
|
|
1070
|
-
origin: 'https://example.com',
|
|
1071
|
-
generateFull: true,
|
|
1072
|
-
})
|
|
1073
|
-
|
|
1074
|
-
console.log(result.llmsTxt) // llms.txt content
|
|
1075
|
-
console.log(result.llmsFullTxt) // llms-full.txt content
|
|
1076
|
-
```
|
|
1077
|
-
|
|
1078
|
-
## Related Packages
|
|
1079
|
-
|
|
1080
|
-
| Package | Description |
|
|
1081
|
-
|---------|-------------|
|
|
1082
|
-
| [`mdream`](https://npmjs.com/package/mdream) | Core HTML to Markdown converter (Rust + WASM engine) |
|
|
1083
|
-
| [`@mdream/js`](https://npmjs.com/package/@mdream/js) | JavaScript engine with hook-based plugins, splitter, and llms.txt generation (`@mdream/js/llms-txt`) |
|
|
1084
|
-
| [`@mdream/crawl`](https://github.com/harlan-zw/mdream/tree/main/packages/crawl) | Site-wide crawler for llms.txt generation |
|
|
1085
|
-
| [`@mdream/vite`](https://github.com/harlan-zw/mdream/tree/main/packages/vite) | Vite plugin integration |
|
|
1086
|
-
| [`@mdream/nuxt`](https://github.com/harlan-zw/mdream/tree/main/packages/nuxt) | Nuxt module integration |
|
|
1087
|
-
| [`@mdream/action`](https://github.com/harlan-zw/mdream/tree/main/packages/action) | GitHub Actions integration |
|
|
1088
|
-
|
|
1089
|
-
## License
|
|
1090
|
-
|
|
1091
|
-
Licensed under the [MIT license](https://github.com/harlan-zw/mdream/blob/main/LICENSE.md).
|