nuxt-ai-ready 2.4.1 → 2.5.1

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 (216) hide show
  1. package/README.md +8 -4
  2. package/dist/chunks/agent-skills.mjs +1 -1
  3. package/dist/chunks/prerender.mjs +1 -1
  4. package/dist/module.json +1 -1
  5. package/dist/module.mjs +1 -1
  6. package/dist/runtime/app/plugins/md-hints.prerender.js +4 -4
  7. package/dist/runtime/llms-txt-utils.js +2 -6
  8. package/dist/runtime/markdown-path.d.ts +7 -3
  9. package/dist/runtime/markdown-path.js +6 -6
  10. package/dist/runtime/server/db/queries.js +28 -5
  11. package/dist/runtime/server/middleware/markdown.js +1 -1
  12. package/dist/runtime/server/middleware/markdown.prerender.js +1 -0
  13. package/dist/runtime/server/utils/checkStale.js +13 -2
  14. package/dist/runtime/server/utils/cloudflare.js +3 -1
  15. package/dist/runtime/server/utils/frontmatter.d.ts +6 -0
  16. package/dist/runtime/server/utils/frontmatter.js +23 -1
  17. package/dist/runtime/server/utils/indexPage.js +4 -1
  18. package/dist/runtime/server/utils/sitemap-routes.js +2 -1
  19. package/dist/runtime/server/utils.d.ts +8 -4
  20. package/dist/runtime/server/utils.js +15 -19
  21. package/dist/runtime/types.d.ts +8 -4
  22. package/dist/shared/{nuxt-ai-ready.CxJE2WLA.mjs → nuxt-ai-ready.CLSWou20.mjs} +6 -10
  23. package/node_modules/@mdream/js/LICENSE.md +9 -0
  24. package/node_modules/@mdream/js/README.md +792 -0
  25. package/node_modules/@mdream/js/bin/mdream.mjs +2 -0
  26. package/node_modules/@mdream/js/dist/_chunks/const.mjs +134 -0
  27. package/node_modules/@mdream/js/dist/_chunks/index.d.mts +9 -0
  28. package/node_modules/@mdream/js/dist/_chunks/markdown-processor.mjs +1968 -0
  29. package/node_modules/@mdream/js/dist/_chunks/minimal.d.mts +6 -0
  30. package/node_modules/@mdream/js/dist/_chunks/parse.mjs +2756 -0
  31. package/node_modules/@mdream/js/dist/_chunks/plugins.mjs +725 -0
  32. package/node_modules/@mdream/js/dist/_chunks/resolve-plugins.mjs +44 -0
  33. package/node_modules/@mdream/js/dist/_chunks/stream.mjs +37 -0
  34. package/node_modules/@mdream/js/dist/_chunks/types.d.mts +473 -0
  35. package/node_modules/@mdream/js/dist/cli.d.mts +1 -0
  36. package/node_modules/@mdream/js/dist/cli.mjs +32 -0
  37. package/node_modules/@mdream/js/dist/core.d.mts +15 -0
  38. package/node_modules/@mdream/js/dist/core.mjs +28 -0
  39. package/node_modules/@mdream/js/dist/index.d.mts +4 -0
  40. package/node_modules/@mdream/js/dist/index.mjs +58 -0
  41. package/node_modules/@mdream/js/dist/llms-txt.d.mts +86 -0
  42. package/node_modules/@mdream/js/dist/llms-txt.mjs +308 -0
  43. package/node_modules/@mdream/js/dist/negotiate.d.mts +35 -0
  44. package/node_modules/@mdream/js/dist/negotiate.mjs +121 -0
  45. package/node_modules/@mdream/js/dist/parse.d.mts +90 -0
  46. package/node_modules/@mdream/js/dist/parse.mjs +2 -0
  47. package/node_modules/@mdream/js/dist/plugins.d.mts +85 -0
  48. package/node_modules/@mdream/js/dist/plugins.mjs +2 -0
  49. package/node_modules/@mdream/js/dist/preset/minimal.d.mts +2 -0
  50. package/node_modules/@mdream/js/dist/preset/minimal.mjs +33 -0
  51. package/node_modules/@mdream/js/dist/splitter.d.mts +18 -0
  52. package/node_modules/@mdream/js/dist/splitter.mjs +194 -0
  53. package/node_modules/@mdream/js/package.json +103 -0
  54. package/node_modules/cac/LICENSE +21 -0
  55. package/node_modules/cac/README.md +492 -0
  56. package/node_modules/cac/dist/index.d.ts +196 -0
  57. package/node_modules/cac/dist/index.js +638 -0
  58. package/node_modules/cac/package.json +72 -0
  59. package/node_modules/mdream/LICENSE.md +9 -0
  60. package/node_modules/mdream/README.md +1091 -0
  61. package/node_modules/mdream/bin/mdream.mjs +46 -0
  62. package/node_modules/mdream/dist/browser.d.mts +105 -0
  63. package/node_modules/mdream/dist/browser.mjs +262 -0
  64. package/node_modules/mdream/dist/edge.d.mts +100 -0
  65. package/node_modules/mdream/dist/edge.mjs +250 -0
  66. package/node_modules/mdream/dist/iife.js +605 -0
  67. package/node_modules/mdream/dist/index.d.mts +89 -0
  68. package/node_modules/mdream/dist/index.mjs +184 -0
  69. package/node_modules/mdream/dist/wasm.d.mts +100 -0
  70. package/node_modules/mdream/dist/wasm.mjs +140 -0
  71. package/node_modules/mdream/dist/worker.d.mts +101 -0
  72. package/node_modules/mdream/dist/worker.mjs +217 -0
  73. package/node_modules/mdream/napi/index.d.mts +127 -0
  74. package/node_modules/mdream/napi/index.d.ts +127 -0
  75. package/node_modules/mdream/napi/index.mjs +725 -0
  76. package/node_modules/mdream/napi/rust.android-arm-eabi.node +0 -0
  77. package/node_modules/mdream/napi/rust.android-arm64.node +0 -0
  78. package/node_modules/mdream/napi/rust.darwin-arm64.node +0 -0
  79. package/node_modules/mdream/napi/rust.darwin-x64.node +0 -0
  80. package/node_modules/mdream/napi/rust.freebsd-x64.node +0 -0
  81. package/node_modules/mdream/napi/rust.linux-arm-gnueabihf.node +0 -0
  82. package/node_modules/mdream/napi/rust.linux-arm64-gnu.node +0 -0
  83. package/node_modules/mdream/napi/rust.linux-arm64-musl.node +0 -0
  84. package/node_modules/mdream/napi/rust.linux-x64-gnu.node +0 -0
  85. package/node_modules/mdream/napi/rust.linux-x64-musl.node +0 -0
  86. package/node_modules/mdream/napi/rust.wasi.cjs +2144 -0
  87. package/node_modules/mdream/napi/rust.wasm32-wasi.wasm +0 -0
  88. package/node_modules/mdream/napi/rust.win32-arm64-msvc.node +0 -0
  89. package/node_modules/mdream/napi/rust.win32-x64-msvc.node +0 -0
  90. package/node_modules/mdream/node_modules/@emnapi/core/LICENSE +21 -0
  91. package/node_modules/mdream/node_modules/@emnapi/core/README.md +1 -0
  92. package/node_modules/mdream/node_modules/@emnapi/core/dist/emnapi-core.d.ts +392 -0
  93. package/node_modules/mdream/node_modules/@emnapi/core/dist/emnapi-core.full.d.ts +392 -0
  94. package/node_modules/mdream/node_modules/@emnapi/core/dist/emnapi-core.full.js +8351 -0
  95. package/node_modules/mdream/node_modules/@emnapi/core/dist/emnapi-core.js +7268 -0
  96. package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/async-work.d.ts +5 -0
  97. package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/async-work.js +843 -0
  98. package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/index.d.ts +4 -0
  99. package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/index.js +3 -0
  100. package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/threadsafe-function.d.ts +5 -0
  101. package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/threadsafe-function.js +1010 -0
  102. package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/v8.d.ts +5 -0
  103. package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/v8.js +1446 -0
  104. package/node_modules/mdream/node_modules/@emnapi/core/package.json +39 -0
  105. package/node_modules/mdream/node_modules/@emnapi/core/rollup.config.js +60 -0
  106. package/node_modules/mdream/node_modules/@emnapi/runtime/LICENSE +21 -0
  107. package/node_modules/mdream/node_modules/@emnapi/runtime/README.md +1 -0
  108. package/node_modules/mdream/node_modules/@emnapi/runtime/dist/emnapi.d.ts +833 -0
  109. package/node_modules/mdream/node_modules/@emnapi/runtime/dist/emnapi.js +2306 -0
  110. package/node_modules/mdream/node_modules/@emnapi/runtime/dist/emnapi.js.map +1 -0
  111. package/node_modules/mdream/node_modules/@emnapi/runtime/index.cjs +63 -0
  112. package/node_modules/mdream/node_modules/@emnapi/runtime/package.json +39 -0
  113. package/node_modules/mdream/node_modules/@emnapi/runtime/rollup.config.js +25 -0
  114. package/node_modules/mdream/node_modules/@emnapi/wasi-threads/LICENSE +21 -0
  115. package/node_modules/mdream/node_modules/@emnapi/wasi-threads/README.md +203 -0
  116. package/node_modules/mdream/node_modules/@emnapi/wasi-threads/dist/wasi-threads.d.ts +236 -0
  117. package/node_modules/mdream/node_modules/@emnapi/wasi-threads/dist/wasi-threads.js +1086 -0
  118. package/node_modules/mdream/node_modules/@emnapi/wasi-threads/package.json +35 -0
  119. package/node_modules/mdream/node_modules/@emnapi/wasi-threads/rollup.config.js +6 -0
  120. package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/dist/emnapi-plugins.cjs +1472 -0
  121. package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/dist/emnapi-plugins.js +1470 -0
  122. package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/dist/fs-proxy.cjs +237 -0
  123. package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/dist/fs.js +18260 -0
  124. package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/fs-proxy.js +317 -0
  125. package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/package.json +67 -0
  126. package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/runtime.cjs +39 -0
  127. package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/runtime.js +36 -0
  128. package/node_modules/mdream/node_modules/@tybys/wasm-util/LICENSE +21 -0
  129. package/node_modules/mdream/node_modules/@tybys/wasm-util/README.md +193 -0
  130. package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/tsdoc-metadata.json +11 -0
  131. package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.d.ts +423 -0
  132. package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.esm-bundler.js +2932 -0
  133. package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.esm.js +2932 -0
  134. package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.esm.min.js +1 -0
  135. package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.js +2954 -0
  136. package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.min.js +1 -0
  137. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/asyncify.js +158 -0
  138. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/index.js +13 -0
  139. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/jspi.js +46 -0
  140. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/load.js +97 -0
  141. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/memory.js +35 -0
  142. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/error.js +103 -0
  143. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/fd.js +268 -0
  144. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/fs.js +3 -0
  145. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/index.js +192 -0
  146. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/path.js +316 -0
  147. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/preview1.js +1599 -0
  148. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/rights.js +141 -0
  149. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/types.js +220 -0
  150. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/util.js +128 -0
  151. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/webassembly.js +13 -0
  152. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/asyncify.mjs +153 -0
  153. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/index.mjs +9 -0
  154. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/jspi.mjs +39 -0
  155. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/load.mjs +89 -0
  156. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/memory.mjs +28 -0
  157. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/error.mjs +97 -0
  158. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/fd.mjs +256 -0
  159. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/fs.mjs +1 -0
  160. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/index.mjs +186 -0
  161. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/path.mjs +310 -0
  162. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/preview1.mjs +1593 -0
  163. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/rights.mjs +135 -0
  164. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/types.mjs +216 -0
  165. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/util.mjs +113 -0
  166. package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/webassembly.mjs +9 -0
  167. package/node_modules/mdream/node_modules/@tybys/wasm-util/package.json +58 -0
  168. package/node_modules/mdream/node_modules/tslib/CopyrightNotice.txt +15 -0
  169. package/node_modules/mdream/node_modules/tslib/LICENSE.txt +12 -0
  170. package/node_modules/mdream/node_modules/tslib/README.md +164 -0
  171. package/node_modules/mdream/node_modules/tslib/SECURITY.md +41 -0
  172. package/node_modules/mdream/node_modules/tslib/modules/index.d.ts +38 -0
  173. package/node_modules/mdream/node_modules/tslib/modules/index.js +70 -0
  174. package/node_modules/mdream/node_modules/tslib/modules/package.json +3 -0
  175. package/node_modules/mdream/node_modules/tslib/package.json +47 -0
  176. package/node_modules/mdream/node_modules/tslib/tslib.d.ts +460 -0
  177. package/node_modules/mdream/node_modules/tslib/tslib.es6.html +1 -0
  178. package/node_modules/mdream/node_modules/tslib/tslib.es6.js +402 -0
  179. package/node_modules/mdream/node_modules/tslib/tslib.es6.mjs +401 -0
  180. package/node_modules/mdream/node_modules/tslib/tslib.html +1 -0
  181. package/node_modules/mdream/node_modules/tslib/tslib.js +484 -0
  182. package/node_modules/mdream/package.json +110 -0
  183. package/node_modules/mdream/skills/mdream/SKILL.md +124 -0
  184. package/node_modules/mdream/skills/mdream/references/runtimes.md +49 -0
  185. package/node_modules/mdream/wasm/mdream_edge.d.ts +90 -0
  186. package/node_modules/mdream/wasm/mdream_edge.js +517 -0
  187. package/node_modules/mdream/wasm/mdream_edge_bg.wasm +0 -0
  188. package/node_modules/mdream/wasm/mdream_edge_bg.wasm.d.ts +20 -0
  189. package/node_modules/mdream/wasm/package.json +17 -0
  190. package/node_modules/mdream/wasm-bundler/mdream_edge.d.ts +45 -0
  191. package/node_modules/mdream/wasm-bundler/mdream_edge.js +13 -0
  192. package/node_modules/mdream/wasm-bundler/mdream_edge_bg.js +413 -0
  193. package/node_modules/mdream/wasm-bundler/mdream_edge_bg.wasm +0 -0
  194. package/node_modules/mdream/wasm-bundler/mdream_edge_bg.wasm.d.ts +20 -0
  195. package/node_modules/mdream/wasm-bundler/package.json +19 -0
  196. package/node_modules/pathe/LICENSE +70 -0
  197. package/node_modules/pathe/README.md +73 -0
  198. package/node_modules/pathe/dist/index.cjs +39 -0
  199. package/node_modules/pathe/dist/index.d.cts +47 -0
  200. package/node_modules/pathe/dist/index.d.mts +47 -0
  201. package/node_modules/pathe/dist/index.d.ts +47 -0
  202. package/node_modules/pathe/dist/index.mjs +19 -0
  203. package/node_modules/pathe/dist/shared/pathe.BSlhyZSM.cjs +266 -0
  204. package/node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs +249 -0
  205. package/node_modules/pathe/dist/utils.cjs +82 -0
  206. package/node_modules/pathe/dist/utils.d.cts +32 -0
  207. package/node_modules/pathe/dist/utils.d.mts +32 -0
  208. package/node_modules/pathe/dist/utils.d.ts +32 -0
  209. package/node_modules/pathe/dist/utils.mjs +77 -0
  210. package/node_modules/pathe/package.json +61 -0
  211. package/node_modules/pathe/utils.d.ts +1 -0
  212. package/package.json +11 -67
  213. package/skills/nuxt-ai-ready/SKILL.md +123 -0
  214. package/skills/nuxt-ai-ready/references/runtime-indexing.md +75 -0
  215. package/dist/runtime/server/plugins/mcp-data.d.ts +0 -10
  216. package/dist/runtime/server/plugins/mcp-data.js +0 -22
package/README.md CHANGED
@@ -3,6 +3,13 @@
3
3
  [![npm version][npm-version-src]][npm-version-href]
4
4
  [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
5
  [![Nuxt][nuxt-src]][nuxt-href]
6
+ <a href="https://skilld.dev/gh/harlan-zw/nuxt-ai-ready">
7
+ <picture>
8
+ <source media="(prefers-color-scheme: dark)" srcset="https://skilld.dev/b/harlan-zw/nuxt-ai-ready?theme=dark">
9
+ <source media="(prefers-color-scheme: light)" srcset="https://skilld.dev/b/harlan-zw/nuxt-ai-ready?theme=light">
10
+ <img alt="Skill repository on skilld.dev" src="https://skilld.dev/b/harlan-zw/nuxt-ai-ready?theme=light">
11
+ </picture>
12
+ </a>
6
13
 
7
14
  > Best practice AI & LLM discoverability for Nuxt sites. Score 100 on [`npx @vercel/agent-readability audit <URL>`](https://github.com/vercel-labs/agent-readability).
8
15
 
@@ -38,10 +45,7 @@ npx nuxi@latest module add nuxt-ai-ready
38
45
  ```
39
46
 
40
47
  > [!TIP]
41
- > Generate an Agent Skill for this package using [skilld](https://github.com/harlan-zw/skilld):
42
- > ```bash
43
- > npx skilld add nuxt-ai-ready
44
- > ```
48
+ > Using an AI agent? Get the nuxt-ai-ready Skill on [skilld.dev/gh/harlan-zw/nuxt-ai-ready](https://skilld.dev/gh/harlan-zw/nuxt-ai-ready).
45
49
 
46
50
  💡 Made your site AI-ready? Preview how a page converts to LLM-readable markdown with the free [HTML→Markdown tool](https://nuxtseo.com/tools/html-to-markdown), or track how AI engines index, rank and cite your site with [Nuxt SEO Pro](https://nuxtseo.com/pro).
47
51
 
@@ -2,7 +2,7 @@ import { createHash } from 'node:crypto';
2
2
  import { realpath, readFile, readdir } from 'node:fs/promises';
3
3
  import { resolve, isAbsolute, join, relative, sep } from 'node:path';
4
4
  import { parseDocument } from 'yaml';
5
- import { A as AGENT_SKILLS_SCHEMA } from '../shared/nuxt-ai-ready.CxJE2WLA.mjs';
5
+ import { A as AGENT_SKILLS_SCHEMA } from '../shared/nuxt-ai-ready.CLSWou20.mjs';
6
6
  import 'node:module';
7
7
  import '@nuxt/kit';
8
8
  import 'defu';
@@ -5,7 +5,7 @@ import { colorize } from 'consola/utils';
5
5
  import { resolveLocaleFromRoute } from 'nuxtseo-shared/i18n-runtime';
6
6
  import { collectSitemap } from 'sitemapd/parse';
7
7
  import { withLeadingSlash, joinURL, withBase } from 'ufo';
8
- import { l as logger, s as supportsNativeNodeSqlite, M as MARKDOWN_LINK_AVAILABILITY_FILE } from '../shared/nuxt-ai-ready.CxJE2WLA.mjs';
8
+ import { l as logger, s as supportsNativeNodeSqlite, M as MARKDOWN_LINK_AVAILABILITY_FILE } from '../shared/nuxt-ai-ready.CLSWou20.mjs';
9
9
  import { normalizePagePath, toMarkdownPath } from '../../dist/runtime/markdown-path.js';
10
10
  import { toDeployedRoute, toLogicalRoute } from '../../dist/runtime/route-path.js';
11
11
  import { initSchema, computeContentHash, insertPage, queryAllPages, exportDbDump } from '../../dist/runtime/server/db/shared.js';
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "nuxt": ">=4.0.0"
5
5
  },
6
6
  "configKey": "aiReady",
7
- "version": "2.4.1",
7
+ "version": "2.5.1",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.3",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -7,7 +7,7 @@ import 'defu';
7
7
  import 'nuxt-site-config/kit';
8
8
  import 'nuxtseo-shared/kit';
9
9
  import 'pkg-types';
10
- export { m as default } from './shared/nuxt-ai-ready.CxJE2WLA.mjs';
10
+ export { m as default } from './shared/nuxt-ai-ready.CLSWou20.mjs';
11
11
  import '../dist/runtime/markdown-path.js';
12
12
  import '../dist/runtime/server/utils/sitemap-md.js';
13
13
  import '../dist/runtime/server/utils/discovery-response.js';
@@ -1,6 +1,5 @@
1
- import { isPathFile } from "nuxt-site-config/urls";
2
1
  import { defineNuxtPlugin, prerenderRoutes } from "nuxt/app";
3
- import { toMarkdownPath } from "../../markdown-path.js";
2
+ import { markdownAlternatePath } from "../../markdown-path.js";
4
3
  export default defineNuxtPlugin({
5
4
  setup(nuxtApp) {
6
5
  if (!import.meta.prerender) {
@@ -8,10 +7,11 @@ export default defineNuxtPlugin({
8
7
  }
9
8
  nuxtApp.hooks.hook("app:rendered", (ctx) => {
10
9
  const url = ctx.ssrContext?.url || "";
11
- if (isPathFile(url) || ctx.ssrContext?.error || ctx.ssrContext?.noSSR) {
10
+ const markdownPath = markdownAlternatePath(url);
11
+ if (!markdownPath || ctx.ssrContext?.error || ctx.ssrContext?.noSSR) {
12
12
  return;
13
13
  }
14
- prerenderRoutes(toMarkdownPath(url));
14
+ prerenderRoutes(markdownPath);
15
15
  });
16
16
  }
17
17
  });
@@ -4,16 +4,12 @@ import { useRuntimeConfig } from "#nuxtseo/nitro";
4
4
  import { getSiteConfig } from "#site-config/server/composables/getSiteConfig";
5
5
  import { withSiteTrailingSlash, withSiteUrl } from "#site-config/server/composables/utils";
6
6
  import { formatLlmsTxtPageLink, normalizeLlmsTxtConfig } from "./llms-txt-format.js";
7
- import { isReservedPath, toMarkdownPath } from "./markdown-path.js";
7
+ import { hasMarkdownTwin, toMarkdownPath } from "./markdown-path.js";
8
8
  import { normalizePersistedRoute, toDeployedRoute, toLogicalRoute } from "./route-path.js";
9
9
  import { queryPages } from "./server/db/queries.js";
10
10
  import { logger } from "./server/logger.js";
11
11
  import { fetchSitemapUrls } from "./server/utils/sitemap.js";
12
12
  export { normalizeLlmsTxtConfig };
13
- function hasRuntimeMarkdownHandler(pathname) {
14
- const lastSegment = pathname.split("/").pop() || "";
15
- return !isReservedPath(pathname) && !lastSegment.includes(".");
16
- }
17
13
  async function findMarkdownLinkAvailability() {
18
14
  if (!import.meta.prerender) {
19
15
  return {
@@ -205,7 +201,7 @@ Canonical Origin: ${canonicalSiteUrl}`);
205
201
  resolvePageHref = (pathname) => {
206
202
  const deployedPathname = resolvePath(pathname);
207
203
  const markdownPath = resolvePath(toMarkdownPath(pathname));
208
- if (markdownLinkAvailability.paths.has(decodePath(markdownPath)) || markdownLinkAvailability.runtimeMarkdownAvailable && hasRuntimeMarkdownHandler(pathname)) {
204
+ if (markdownLinkAvailability.paths.has(decodePath(markdownPath)) || markdownLinkAvailability.runtimeMarkdownAvailable && hasMarkdownTwin(pathname)) {
209
205
  return markdownPath;
210
206
  }
211
207
  return deployedPathname;
@@ -3,9 +3,13 @@ export declare function isReservedPath(path: string): boolean;
3
3
  export declare function normalizePagePath(path: string): string;
4
4
  export declare function toMarkdownPath(path: string): string;
5
5
  /**
6
- * The `.md` sibling a page may advertise, or null when it has none.
6
+ * True when a path names a page with a `.md` twin: outside the reserved
7
+ * namespaces, and not a file such as `/feed.xml`. A dot alone does not make a
8
+ * file, so `/v1.2` is a page.
7
9
  *
8
- * Advertising and serving read the same predicate here, so a page cannot link
9
- * a representation the markdown handler declines.
10
+ * Prerendering and every advertisement read this one predicate, so a page
11
+ * cannot link a representation the build or the markdown handler lacks.
10
12
  */
13
+ export declare function hasMarkdownTwin(path: string): boolean;
14
+ /** The `.md` sibling a page may advertise, or null when it has none. */
11
15
  export declare function markdownAlternatePath(path: string): string | null;
@@ -1,4 +1,5 @@
1
1
  const RE_TRAILING_SLASHES = /\/+$/;
2
+ const RE_FILE_EXTENSION = /\.[a-z][a-z\d]*$/i;
2
3
  const RE_RESERVED_PATH = /^\/(?:api(?:\/|$)|_|@(?:id|fs|vite|react-refresh)(?:\/|$))/;
3
4
  export function isReservedPath(path) {
4
5
  return RE_RESERVED_PATH.test(path);
@@ -12,11 +13,10 @@ export function toMarkdownPath(path) {
12
13
  return "/index.md";
13
14
  return `${normalizedPath}.md`;
14
15
  }
15
- export function markdownAlternatePath(path) {
16
- if (isReservedPath(path))
17
- return null;
16
+ export function hasMarkdownTwin(path) {
18
17
  const lastSegment = normalizePagePath(path).split("/").pop() || "";
19
- if (lastSegment.includes("."))
20
- return null;
21
- return toMarkdownPath(path);
18
+ return !isReservedPath(path) && !RE_FILE_EXTENSION.test(lastSegment);
19
+ }
20
+ export function markdownAlternatePath(path) {
21
+ return hasMarkdownTwin(path) ? toMarkdownPath(path) : null;
22
22
  }
@@ -1,5 +1,7 @@
1
1
  import { randomUUID } from "uncrypto";
2
2
  import { useEvent, useRuntimeConfig } from "#nuxtseo/nitro";
3
+ import { logger } from "../logger.js";
4
+ import { checkAndHandleStale } from "../utils/checkStale.js";
3
5
  import { parseSitemapCrawlState, serializeSitemapCrawlState } from "../utils/sitemap-crawl-state.js";
4
6
  import { initSchema } from "./drizzle/queries.js";
5
7
  import { useRawDb } from "./drizzle/raw.js";
@@ -15,15 +17,33 @@ function getEventFromContext(providedEvent) {
15
17
  return void 0;
16
18
  }
17
19
  }
18
- let devWarningShown = false;
20
+ let devNoticeShown = false;
19
21
  let schemaInitializationState = { _tag: "Uninitialized" };
22
+ let dumpSyncState = { _tag: "Pending" };
23
+ function syncBuildDump(event) {
24
+ if (dumpSyncState._tag === "Synced")
25
+ return Promise.resolve();
26
+ if (dumpSyncState._tag === "Syncing")
27
+ return dumpSyncState.promise;
28
+ const promise = checkAndHandleStale(event).then(
29
+ () => {
30
+ dumpSyncState = { _tag: "Synced" };
31
+ },
32
+ (error) => {
33
+ dumpSyncState = { _tag: "Pending" };
34
+ throw error;
35
+ }
36
+ );
37
+ dumpSyncState = { _tag: "Syncing", promise };
38
+ return promise;
39
+ }
20
40
  const RE_FTS_CHARS = /[*:^"()]/g;
21
41
  const RE_WHITESPACE = /\s+/;
22
42
  async function getDb(event) {
23
43
  if (import.meta.dev) {
24
- if (!devWarningShown) {
25
- console.warn("[nuxt-ai-ready] Page data unavailable in dev. Run `nuxi generate` for full metadata.");
26
- devWarningShown = true;
44
+ if (!devNoticeShown) {
45
+ logger.info("Page data unavailable in dev. Run `nuxi generate` for full metadata.");
46
+ devNoticeShown = true;
27
47
  }
28
48
  return null;
29
49
  }
@@ -32,7 +52,8 @@ async function getDb(event) {
32
52
  }
33
53
  const resolvedEvent = getEventFromContext(event);
34
54
  const cfg = useRuntimeConfig(resolvedEvent);
35
- if (cfg["nuxt-ai-ready"]?.database?._tag === "Disabled")
55
+ const database = cfg["nuxt-ai-ready"]?.database?._tag;
56
+ if (database === "Disabled")
36
57
  return null;
37
58
  const db = await useRawDb(resolvedEvent);
38
59
  if (schemaInitializationState._tag === "Uninitialized") {
@@ -46,6 +67,8 @@ async function getDb(event) {
46
67
  }
47
68
  if (schemaInitializationState._tag === "Initializing")
48
69
  await schemaInitializationState.promise;
70
+ if (database === "Enabled")
71
+ await syncBuildDump(resolvedEvent);
49
72
  return db;
50
73
  }
51
74
  async function getPrerenderDb() {
@@ -165,7 +165,7 @@ ${contentPage.markdown}`);
165
165
  canonicalUrl,
166
166
  config.mdreamOptions,
167
167
  {
168
- hooks: { route: path, event },
168
+ hooks: { route: path, event, isPrerender: false },
169
169
  additionalFrontmatter
170
170
  }
171
171
  );
@@ -104,6 +104,7 @@ ${contentPage.markdown}`;
104
104
  runtimeConfig.mdreamOptions,
105
105
  {
106
106
  extractUpdatedAt: true,
107
+ hooks: { route: path, event, isPrerender: true },
107
108
  additionalFrontmatter: {
108
109
  canonical_url: canonicalUrl,
109
110
  ...lastUpdated && { last_updated: lastUpdated }
@@ -10,9 +10,17 @@ import {
10
10
  import { decompressFromBase64, importDbDump } from "../db/shared.js";
11
11
  import { logger } from "../logger.js";
12
12
  import { fetchPublicAsset } from "./cloudflare.js";
13
+ function parseBuildMeta(value) {
14
+ if (!value || typeof value !== "object")
15
+ return null;
16
+ const { buildId, pageCount, createdAt } = value;
17
+ if (typeof buildId !== "string" || !buildId || typeof pageCount !== "number")
18
+ return null;
19
+ return { buildId, pageCount, createdAt: typeof createdAt === "string" ? createdAt : "" };
20
+ }
13
21
  async function fetchBuildMeta(event) {
14
22
  logger.debug("[stale-check] Fetching meta...");
15
- return fetchPublicAsset(event, "/__ai-ready/pages.meta.json");
23
+ return parseBuildMeta(await fetchPublicAsset(event, "/__ai-ready/pages.meta.json"));
16
24
  }
17
25
  async function fetchDump(event) {
18
26
  logger.debug("[stale-check] Fetching dump...");
@@ -22,7 +30,10 @@ async function fetchDump(event) {
22
30
  return null;
23
31
  }
24
32
  logger.debug(`[stale-check] Decompressing dump (${(dumpData.length / 1024).toFixed(1)}kb)...`);
25
- return decompressFromBase64(dumpData);
33
+ return decompressFromBase64(dumpData).catch((error) => {
34
+ logger.warn("[stale-check] Build dump is unreadable, skipping restore:", error);
35
+ return null;
36
+ });
26
37
  }
27
38
  async function getStoredBuildId(event) {
28
39
  return getInfoValue(event, "build_id");
@@ -1,3 +1,5 @@
1
+ import { withBase } from "ufo";
2
+ import { useRuntimeConfig } from "#nuxtseo/nitro";
1
3
  const FETCH_TIMEOUT = 5e3;
2
4
  function unavailablePublicAsset(_error) {
3
5
  return null;
@@ -29,7 +31,7 @@ export async function fetchPublicAsset(event, path, options) {
29
31
  }
30
32
  const controller = new AbortController();
31
33
  const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT);
32
- return globalThis.$fetch(path, {
34
+ return globalThis.$fetch(withBase(path, useRuntimeConfig(event).app.baseURL), {
33
35
  baseURL: "/",
34
36
  signal: controller.signal,
35
37
  responseType
@@ -12,4 +12,10 @@ interface FrontmatterFields {
12
12
  }
13
13
  export declare function buildFrontmatter(fields: FrontmatterFields): string;
14
14
  export declare function layerFrontmatter(fields: FrontmatterFields, markdown: string): string;
15
+ /**
16
+ * Move mdream's `meta.description` to a root `description` field, the shape
17
+ * Content source pages and hand-built frontmatter already use. Other `meta`
18
+ * fields stay where mdream put them.
19
+ */
20
+ export declare function hoistMetaDescription(markdown: string): string;
15
21
  export {};
@@ -1,4 +1,4 @@
1
- import { isMap, parseDocument } from "yaml";
1
+ import { isMap, isScalar, parseDocument } from "yaml";
2
2
  function escapeYamlString(value) {
3
3
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
4
4
  }
@@ -43,3 +43,25 @@ ${document.toString({ lineWidth: 0 }).trimEnd()}
43
43
 
44
44
  ${body}`;
45
45
  }
46
+ export function hoistMetaDescription(markdown) {
47
+ const match = markdown.match(FRONTMATTER_RE);
48
+ if (!match)
49
+ return markdown;
50
+ const document = parseDocument(match[1]);
51
+ const root = document.contents;
52
+ const meta = document.get("meta");
53
+ if (document.errors.length || !isMap(root) || !isMap(meta) || !meta.has("description"))
54
+ return markdown;
55
+ const description = meta.get("description", true);
56
+ meta.delete("description");
57
+ if (!meta.items.length)
58
+ document.delete("meta");
59
+ if (!document.has("description")) {
60
+ const titleIndex = root.items.findIndex((pair) => isScalar(pair.key) && pair.key.value === "title");
61
+ root.items.splice(titleIndex + 1, 0, document.createPair("description", description));
62
+ }
63
+ return `---
64
+ ${document.toString({ lineWidth: 0 }).trimEnd()}
65
+ ---
66
+ ${markdown.slice(match[0].length)}`;
67
+ }
@@ -19,7 +19,10 @@ export async function indexPage(route, html, options = {}, event) {
19
19
  const isError = html.includes("__NUXT_ERROR__") || html.includes("nuxt-error-page");
20
20
  const { siteUrl } = createUniversalContext(event);
21
21
  const fullUrl = siteUrl ? `${siteUrl}${route}` : route;
22
- const result = await convertHtmlToMarkdown(html, fullUrl, config.mdreamOptions, { extractUpdatedAt: true });
22
+ const result = await convertHtmlToMarkdown(html, fullUrl, config.mdreamOptions, {
23
+ extractUpdatedAt: true,
24
+ hooks: { route, event, isPrerender: false }
25
+ });
23
26
  const headings = JSON.stringify(result.headings);
24
27
  const keywords = extractKeywords(result.textContent, result.metaKeywords);
25
28
  const contentHash = await computeContentHash(result.markdown);
@@ -1,8 +1,9 @@
1
+ import { hasMarkdownTwin } from "../../markdown-path.js";
1
2
  export function mapSitemapRoutes(urls) {
2
3
  const routeToUrl = /* @__PURE__ */ new Map();
3
4
  for (const url of urls) {
4
5
  const route = url._path?.pathname ?? (url.loc.startsWith("/") ? url.loc.split("?")[0] ?? url.loc : new URL(url.loc).pathname);
5
- if (!route.includes("."))
6
+ if (hasMarkdownTwin(route))
6
7
  routeToUrl.set(route, url);
7
8
  }
8
9
  return routeToUrl;
@@ -4,15 +4,19 @@ export declare function extractLastUpdated(html: string): string | undefined;
4
4
  interface ConvertHtmlOptions {
5
5
  /** Extract updatedAt from meta tags */
6
6
  extractUpdatedAt?: boolean;
7
- /** Call runtime hooks (ai-ready:mdreamConfig, ai-ready:page:markdown) */
8
- hooks?: {
7
+ /**
8
+ * Context for the Nitro hooks (ai-ready:mdreamConfig, ai-ready:page:markdown).
9
+ * Every conversion runs them, so prerender, runtime and indexing agree.
10
+ */
11
+ hooks: {
9
12
  route: string;
10
- event: H3Event;
13
+ event?: H3Event;
14
+ isPrerender: boolean;
11
15
  };
12
16
  /** Extra fields to inject at the root of mdream's emitted YAML frontmatter */
13
17
  additionalFrontmatter?: Record<string, string>;
14
18
  }
15
- export declare function convertHtmlToMarkdown(html: string, url: string, mdreamOptions: ModuleOptions['mdreamOptions'], opts?: ConvertHtmlOptions): Promise<{
19
+ export declare function convertHtmlToMarkdown(html: string, url: string, mdreamOptions: ModuleOptions['mdreamOptions'], opts: ConvertHtmlOptions): Promise<{
16
20
  updatedAt?: string | undefined;
17
21
  markdown: string;
18
22
  title: string;
@@ -1,5 +1,6 @@
1
1
  import { htmlToMarkdown } from "mdream";
2
2
  import { useNitroApp } from "#nuxtseo/nitro";
3
+ import { hoistMetaDescription } from "./utils/frontmatter.js";
3
4
  const RE_NBSP = /\u00A0/g;
4
5
  function normalizeWhitespace(text) {
5
6
  return text.replace(RE_NBSP, " ");
@@ -67,27 +68,22 @@ export function extractLastUpdated(html) {
67
68
  }
68
69
  return void 0;
69
70
  }
70
- export async function convertHtmlToMarkdown(html, url, mdreamOptions, opts = {}) {
71
+ export async function convertHtmlToMarkdown(html, url, mdreamOptions, opts) {
71
72
  const meta = { title: "", description: "", metaKeywords: "", headings: [], textContent: [] };
72
73
  const options = buildMdreamOptions(url, mdreamOptions, meta, opts.extractUpdatedAt ?? false, opts.additionalFrontmatter ?? {});
73
- let markdown;
74
- if (opts.hooks) {
75
- const nitroApp = useNitroApp();
76
- await nitroApp.hooks.callHook("ai-ready:mdreamConfig", options);
77
- const context = {
78
- html,
79
- markdown: htmlToMarkdown(html, options),
80
- route: opts.hooks.route,
81
- title: meta.title,
82
- description: meta.description,
83
- isPrerender: false,
84
- event: opts.hooks.event
85
- };
86
- await nitroApp.hooks.callHook("ai-ready:page:markdown", context);
87
- markdown = context.markdown;
88
- } else {
89
- markdown = htmlToMarkdown(html, options);
90
- }
74
+ const nitroApp = useNitroApp();
75
+ await nitroApp.hooks.callHook("ai-ready:mdreamConfig", options);
76
+ const context = {
77
+ html,
78
+ markdown: hoistMetaDescription(htmlToMarkdown(html, options)),
79
+ route: opts.hooks.route,
80
+ title: meta.title,
81
+ description: meta.description,
82
+ isPrerender: opts.hooks.isPrerender,
83
+ event: opts.hooks.event
84
+ };
85
+ await nitroApp.hooks.callHook("ai-ready:page:markdown", context);
86
+ const markdown = context.markdown;
91
87
  return {
92
88
  markdown: normalizeWhitespace(markdown),
93
89
  title: normalizeWhitespace(meta.title),
@@ -406,8 +406,9 @@ export interface PageDocument {
406
406
  /**
407
407
  * Hook context for markdown processing (Nitro runtime hook)
408
408
  *
409
- * This hook is called during HTML→Markdown conversion in the runtime middleware.
410
- * You can modify the markdown content before it's returned to the client.
409
+ * This hook is called for every HTML→Markdown conversion: runtime `.md`
410
+ * requests, prerendering, and page indexing. Modify the markdown content
411
+ * before the module serves, writes, or stores it.
411
412
  *
412
413
  * @example Modify markdown content
413
414
  * nitroApp.hooks.hook('ai-ready:page:markdown', async (context) => {
@@ -438,8 +439,11 @@ export interface MarkdownContext {
438
439
  description: string;
439
440
  /** Whether this is during prerendering (true) or runtime (false) */
440
441
  isPrerender: boolean;
441
- /** The H3 event object for accessing request/response */
442
- event: H3Event;
442
+ /**
443
+ * The H3 event object for accessing request/response. Undefined when
444
+ * indexing runs outside a request, such as a scheduled task.
445
+ */
446
+ event?: H3Event;
443
447
  }
444
448
  /**
445
449
  * Markdown a site already holds for a route, supplied instead of converting the
@@ -2,13 +2,13 @@ import { createHash, randomBytes } from 'node:crypto';
2
2
  import { readFile, mkdir, writeFile, access } from 'node:fs/promises';
3
3
  import { createRequire } from 'node:module';
4
4
  import { dirname, basename, join } from 'node:path';
5
- import { hasNuxtModule, useNuxt, useLogger, addTypeTemplate, addTemplate, defineNuxtModule, createResolver, addServerImports, addServerPlugin, addServerHandler, extendRouteRules, addPlugin, addImports } from '@nuxt/kit';
5
+ import { hasNuxtModule, useNuxt, useLogger, addTypeTemplate, addTemplate, defineNuxtModule, createResolver, addServerImports, addServerHandler, extendRouteRules, addServerPlugin, addPlugin, addImports } from '@nuxt/kit';
6
6
  import defu$1, { defu } from 'defu';
7
7
  import { installNuxtSiteConfig, useSiteConfig, withSiteUrl } from 'nuxt-site-config/kit';
8
8
  import { resolveNuxtContentVersion, renderNitroTypeAugmentations, setupNitroRuntimeCompatibility } from 'nuxtseo-shared/kit';
9
9
  import { readPackageJSON, resolvePackageJSON } from 'pkg-types';
10
10
  import { fileURLToPath, pathToFileURL } from 'node:url';
11
- import { isReservedPath, normalizePagePath, toMarkdownPath } from '../../dist/runtime/markdown-path.js';
11
+ import { hasMarkdownTwin, normalizePagePath, toMarkdownPath } from '../../dist/runtime/markdown-path.js';
12
12
  import { SITEMAP_MD_ROUTE } from '../../dist/runtime/server/utils/sitemap-md.js';
13
13
  import { publicCacheControl } from '../../dist/runtime/cache-control.js';
14
14
  import { MCP_SERVER_CARD_MEDIA_TYPE, AI_CATALOG_MEDIA_TYPE } from '../../dist/runtime/server/utils/discovery-response.js';
@@ -912,11 +912,7 @@ const RE_MD_EXT = /\.md$/;
912
912
  function isStaticMarkdownSourceRoute(route) {
913
913
  if (route.includes("*") || route.includes(":"))
914
914
  return false;
915
- const path = route.split("?")[0] || route;
916
- if (isReservedPath(path))
917
- return false;
918
- const lastSegment = path.split("/").pop() || "";
919
- return !lastSegment.includes(".");
915
+ return hasMarkdownTwin(route.split("?")[0] || route);
920
916
  }
921
917
  function staticDescribedbyEntry(baseURL) {
922
918
  return `<${encodeURI(toDeployedRoute("/llms.txt", baseURL))}>; rel="describedby"`;
@@ -1467,8 +1463,6 @@ ${details}`);
1467
1463
  updateSeoProFeatures(seoProModules);
1468
1464
  return;
1469
1465
  }
1470
- if (databaseEnabled)
1471
- addServerPlugin(resolve("./runtime/server/plugins/mcp-data"));
1472
1466
  const mcpLink = {
1473
1467
  title: "MCP",
1474
1468
  href: withSiteUrl(finalMcpToolkitState.route, { withBase: true }),
@@ -1610,7 +1604,7 @@ ${details}`);
1610
1604
  if (!runtimeSyncSecret && runtimeSyncEnabled) {
1611
1605
  runtimeSyncSecret = randomBytes(32).toString("hex");
1612
1606
  if (!nuxt.options.dev && !nuxt.options._prepare)
1613
- logger.info(`Generated runtimeSyncSecret (use NUXT_AI_READY_RUNTIME_SYNC_SECRET env to set explicitly)`);
1607
+ logger.info("Generated a new runtimeSyncSecret for this build. If an external scheduler calls /__ai-ready/*, set NUXT_AI_READY_RUNTIME_SYNC_SECRET; the generated secret changes on every build.");
1614
1608
  }
1615
1609
  if (runtimeSyncSecret) {
1616
1610
  const cacheDir = join(nuxt.options.rootDir, "node_modules/.cache/nuxt/ai-ready");
@@ -1624,6 +1618,8 @@ ${details}`);
1624
1618
  nitroConfig.experimental.asyncContext = true;
1625
1619
  const preset = String(nitroConfig.preset || "");
1626
1620
  const isEdgePreset = ["cloudflare", "vercel-edge", "netlify-edge", "deno"].some((p) => preset.startsWith(p));
1621
+ if (isEdgePreset)
1622
+ nitroConfig.experimental.wasm = true;
1627
1623
  if (nitroCompatibility._tag === "nitro-v3") {
1628
1624
  const nitro3Config = nitroConfig;
1629
1625
  const noExternals = Array.isArray(nitro3Config.noExternals) ? nitro3Config.noExternals : [];
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Harlan Wilton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.