nuxt-ai-ready 1.2.0 β 1.3.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 +2 -0
- package/dist/devtools/200.html +1 -1
- package/dist/devtools/404.html +1 -1
- package/dist/devtools/_nuxt/builds/latest.json +1 -1
- package/dist/devtools/_nuxt/builds/meta/cfed7300-fd87-4d26-98a1-6e1d8a608160.json +1 -0
- package/dist/devtools/debug/index.html +1 -1
- package/dist/devtools/docs/index.html +1 -1
- package/dist/devtools/index.html +1 -1
- package/dist/devtools/llms-txt/index.html +1 -1
- package/dist/devtools/pages/index.html +1 -1
- package/dist/module.d.mts +11 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +118 -12
- package/dist/runtime/llms-txt-utils.js +37 -4
- package/dist/runtime/server/db/drizzle/queries.d.ts +3 -1
- package/dist/runtime/server/db/drizzle/queries.js +71 -11
- package/dist/runtime/server/db/queries.d.ts +7 -1
- package/dist/runtime/server/db/queries.js +33 -14
- package/dist/runtime/server/db/schema/postgres.d.ts +34 -0
- package/dist/runtime/server/db/schema/postgres.js +4 -2
- package/dist/runtime/server/db/schema/sqlite.d.ts +38 -0
- package/dist/runtime/server/db/schema/sqlite.js +4 -2
- package/dist/runtime/server/db/schema-sql.d.ts +18 -2
- package/dist/runtime/server/db/schema-sql.js +100 -85
- package/dist/runtime/server/db/shared.d.ts +13 -3
- package/dist/runtime/server/db/shared.js +31 -14
- package/dist/runtime/server/middleware/markdown.d.ts +1 -1
- package/dist/runtime/server/middleware/markdown.js +64 -28
- package/dist/runtime/server/middleware/markdown.prerender.js +37 -1
- package/dist/runtime/server/utils/content.d.ts +8 -0
- package/dist/runtime/server/utils/content.js +4 -0
- package/dist/runtime/server/utils/frontmatter.d.ts +6 -0
- package/dist/runtime/server/utils/frontmatter.js +7 -0
- package/dist/runtime/server/utils/i18n.d.ts +32 -0
- package/dist/runtime/server/utils/i18n.js +33 -0
- package/dist/runtime/server/utils.d.ts +1 -0
- package/dist/runtime/server/utils.js +5 -0
- package/dist/runtime/types.d.ts +13 -0
- package/package.json +1 -1
- package/dist/devtools/_nuxt/builds/meta/feeb28d1-669d-4cde-b5e6-08a29aab779a.json +0 -1
package/README.md
CHANGED
|
@@ -18,11 +18,13 @@ Nuxt AI Ready implements both. It converts your pages to markdown, generates llm
|
|
|
18
18
|
|
|
19
19
|
- π **llms.txt Generation**: Auto-generate `llms.txt` and `llms-full.txt` with page metadata and full markdown content
|
|
20
20
|
- π **On-Demand Markdown**: Any route available as `.md` (e.g., `/about` β `/about.md`), automatically served to AI crawlers
|
|
21
|
+
- π **[Nuxt Content](https://content.nuxt.com) Integration**: Routes backed by a page collection serve source markdown directly, skipping HTMLβmarkdown conversion
|
|
21
22
|
- π‘ **Content Signals**: Configure AI training/search/input permissions via [Nuxt Robots](https://nuxtseo.com/robots)
|
|
22
23
|
- π **Sitemap Integration**: Index AI-allowed pages via [Nuxt Sitemap](https://nuxtseo.com/sitemap)
|
|
23
24
|
- β‘ **MCP Server**: `list_pages` and `search_pages` tools with FTS5 full-text search
|
|
24
25
|
- ποΈ **Runtime Indexing**: Index pages on-demand without prerendering, with SQLite/D1/LibSQL support
|
|
25
26
|
- π **[IndexNow](https://nuxtseo.com/ai-ready/guides/indexnow)**: Instantly notify Bing, Yandex, and other search engines when pages change
|
|
27
|
+
- π **[i18n Aware](https://nuxtseo.com/ai-ready/guides/i18n)**: Auto-detects [`@nuxtjs/i18n`](https://i18n.nuxtjs.org/) for hreflang `Link` headers, locale-tagged frontmatter, and an Available Languages section in `llms.txt`
|
|
26
28
|
- π§ **[RAG Ready](https://nuxtseo.com/ai-ready/advanced/rag-example)**: Markdown output optimized for vectorizing and semantic search
|
|
27
29
|
|
|
28
30
|
## Installation
|
package/dist/devtools/200.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"cfed7300-fd87-4d26-98a1-6e1d8a608160",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1777105835626,false]</script></body></html>
|
package/dist/devtools/404.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"cfed7300-fd87-4d26-98a1-6e1d8a608160",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1777105835626,false]</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"
|
|
1
|
+
{"id":"cfed7300-fd87-4d26-98a1-6e1d8a608160","timestamp":1777105827246}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"id":"cfed7300-fd87-4d26-98a1-6e1d8a608160","timestamp":1777105827246,"prerendered":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"cfed7300-fd87-4d26-98a1-6e1d8a608160",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1777105835625,false]</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"cfed7300-fd87-4d26-98a1-6e1d8a608160",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1777105835626,false]</script></body></html>
|
package/dist/devtools/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"cfed7300-fd87-4d26-98a1-6e1d8a608160",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1777105835627,false]</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"cfed7300-fd87-4d26-98a1-6e1d8a608160",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1777105835626,false]</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt-ai-ready/_nuxt/entry.BLpi4vfB.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js"><script type="module" src="/__nuxt-ai-ready/_nuxt/B3Ds4CMX.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-ai-ready",buildId:"cfed7300-fd87-4d26-98a1-6e1d8a608160",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1777105835626,false]</script></body></html>
|
package/dist/module.d.mts
CHANGED
|
@@ -55,6 +55,17 @@ interface ModulePublicRuntimeConfig {
|
|
|
55
55
|
runtimeSyncSecret?: string;
|
|
56
56
|
indexNow?: string;
|
|
57
57
|
sitemapPrerendered: boolean;
|
|
58
|
+
i18n?: {
|
|
59
|
+
defaultLocale: string;
|
|
60
|
+
strategy: 'no_prefix' | 'prefix_except_default' | 'prefix' | 'prefix_and_default';
|
|
61
|
+
locales: Array<{
|
|
62
|
+
code: string;
|
|
63
|
+
hreflang: string;
|
|
64
|
+
name?: string;
|
|
65
|
+
nativeName?: string;
|
|
66
|
+
}>;
|
|
67
|
+
} | null;
|
|
68
|
+
ftsTokenizer?: string;
|
|
58
69
|
}
|
|
59
70
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
60
71
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { useLogger, useNuxt, addTypeTemplate, addTemplate, defineNuxtModule, cre
|
|
|
5
5
|
import defu from 'defu';
|
|
6
6
|
import { installNuxtSiteConfig, useSiteConfig, withSiteUrl } from 'nuxt-site-config/kit';
|
|
7
7
|
import { setupDevToolsUI } from 'nuxtseo-shared/devtools';
|
|
8
|
+
import { resolveNuxtContentVersion } from 'nuxtseo-shared/kit';
|
|
8
9
|
import { readPackageJSON } from 'pkg-types';
|
|
9
10
|
import { parseSitemapXml } from '@nuxtjs/sitemap/utils';
|
|
10
11
|
import { colorize } from 'consola/utils';
|
|
@@ -13,6 +14,7 @@ import { initSchema, computeContentHash, insertPage, queryAllPages, exportDbDump
|
|
|
13
14
|
import { comparePageHashes, submitToIndexNowShared } from '../dist/runtime/server/utils/indexnow-shared.js';
|
|
14
15
|
import { buildLlmsFullTxtHeader, formatPageForLlmsFullTxt } from '../dist/runtime/server/utils/llms-full.js';
|
|
15
16
|
import { isAbsolute, join as join$1 } from 'pathe';
|
|
17
|
+
import { resolveI18nConfig } from 'nuxtseo-shared/i18n';
|
|
16
18
|
|
|
17
19
|
const logger = useLogger("nuxt-ai-ready");
|
|
18
20
|
|
|
@@ -59,7 +61,7 @@ async function submitIndexNow(changedRoutes, addedRoutes, siteUrl, indexNow) {
|
|
|
59
61
|
logger.warn(`[indexnow] Failed to submit: ${result.error}`);
|
|
60
62
|
}
|
|
61
63
|
}
|
|
62
|
-
function createCrawlerState(dbPath, llmsFullTxtPath, siteInfo, llmsTxtConfig, indexNow, concurrency = 10) {
|
|
64
|
+
function createCrawlerState(dbPath, llmsFullTxtPath, siteInfo, llmsTxtConfig, indexNow, concurrency = 10, ftsTokenizer, i18n) {
|
|
63
65
|
return {
|
|
64
66
|
prerenderedRoutes: /* @__PURE__ */ new Set(),
|
|
65
67
|
errorRoutes: /* @__PURE__ */ new Set(),
|
|
@@ -70,7 +72,9 @@ function createCrawlerState(dbPath, llmsFullTxtPath, siteInfo, llmsTxtConfig, in
|
|
|
70
72
|
siteInfo,
|
|
71
73
|
llmsTxtConfig,
|
|
72
74
|
indexNow,
|
|
73
|
-
concurrency
|
|
75
|
+
concurrency,
|
|
76
|
+
ftsTokenizer,
|
|
77
|
+
i18n
|
|
74
78
|
};
|
|
75
79
|
}
|
|
76
80
|
async function initCrawler(state) {
|
|
@@ -92,8 +96,8 @@ async function initCrawler(state) {
|
|
|
92
96
|
}
|
|
93
97
|
};
|
|
94
98
|
state.db = db;
|
|
95
|
-
await initSchema(db);
|
|
96
|
-
logger.debug(`Crawler initialized with SQLite at ${state.dbPath}`);
|
|
99
|
+
await initSchema(db, { ftsTokenizer: state.ftsTokenizer });
|
|
100
|
+
logger.debug(`Crawler initialized with SQLite at ${state.dbPath} (tokenizer: ${state.ftsTokenizer || "default"})`);
|
|
97
101
|
}
|
|
98
102
|
if (state.llmsFullTxtPath) {
|
|
99
103
|
logger.debug(`Creating directory for llms-full.txt: ${dirname(state.llmsFullTxtPath)}`);
|
|
@@ -108,6 +112,16 @@ async function initCrawler(state) {
|
|
|
108
112
|
function flattenHeadings(headings) {
|
|
109
113
|
return (headings || []).map((h) => Object.entries(h).map(([tag, text]) => `${tag}:${text}`).join("")).join("|");
|
|
110
114
|
}
|
|
115
|
+
function resolveRouteLocale(route, i18n) {
|
|
116
|
+
if (!i18n)
|
|
117
|
+
return "";
|
|
118
|
+
if (i18n.strategy === "no_prefix")
|
|
119
|
+
return i18n.defaultLocale;
|
|
120
|
+
const segments = route.split("/").filter(Boolean);
|
|
121
|
+
const first = segments[0];
|
|
122
|
+
const matched = first ? i18n.locales.find((l) => l.code === first) : void 0;
|
|
123
|
+
return matched ? matched.code : i18n.defaultLocale;
|
|
124
|
+
}
|
|
111
125
|
async function processMarkdownRoute(state, nuxt, route, parsed, lastmod, options) {
|
|
112
126
|
const { markdown, title, description, headings, keywords, updatedAt: metaUpdatedAt } = parsed;
|
|
113
127
|
let updatedAt = (lastmod instanceof Date ? lastmod.toISOString() : lastmod) || (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -127,7 +141,8 @@ async function processMarkdownRoute(state, nuxt, route, parsed, lastmod, options
|
|
|
127
141
|
headings: flattenHeadings(headings),
|
|
128
142
|
keywords: keywords || [],
|
|
129
143
|
contentHash,
|
|
130
|
-
updatedAt
|
|
144
|
+
updatedAt,
|
|
145
|
+
locale: resolveRouteLocale(route, state.i18n)
|
|
131
146
|
});
|
|
132
147
|
}
|
|
133
148
|
if (state.llmsFullTxtPath && !options?.skipLlmsFullTxt) {
|
|
@@ -247,11 +262,20 @@ async function prerenderRoute(nitro, route) {
|
|
|
247
262
|
nitro._prerenderedRoutes.push(_route);
|
|
248
263
|
return stat(filePath);
|
|
249
264
|
}
|
|
250
|
-
function setupPrerenderHandler(options, dbPath, siteInfo, llmsTxtConfig, indexNow) {
|
|
265
|
+
function setupPrerenderHandler(options, dbPath, siteInfo, llmsTxtConfig, indexNow, extras = {}) {
|
|
251
266
|
const nuxt = useNuxt();
|
|
252
267
|
nuxt.hooks.hook("nitro:init", async (nitro) => {
|
|
253
268
|
const llmsFullTxtPath = join(nitro.options.output.publicDir, "llms-full.txt");
|
|
254
|
-
const state = createCrawlerState(
|
|
269
|
+
const state = createCrawlerState(
|
|
270
|
+
dbPath,
|
|
271
|
+
llmsFullTxtPath,
|
|
272
|
+
siteInfo,
|
|
273
|
+
llmsTxtConfig,
|
|
274
|
+
indexNow,
|
|
275
|
+
options.prerender?.concurrency,
|
|
276
|
+
extras.ftsTokenizer,
|
|
277
|
+
extras.i18n
|
|
278
|
+
);
|
|
255
279
|
let initPromise = null;
|
|
256
280
|
nitro.hooks.hook("prerender:generate", async (route) => {
|
|
257
281
|
if (route.error) {
|
|
@@ -285,7 +309,8 @@ function setupPrerenderHandler(options, dbPath, siteInfo, llmsTxtConfig, indexNo
|
|
|
285
309
|
headings: "",
|
|
286
310
|
keywords: [],
|
|
287
311
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
288
|
-
isError: true
|
|
312
|
+
isError: true,
|
|
313
|
+
locale: resolveRouteLocale(route, state.i18n)
|
|
289
314
|
});
|
|
290
315
|
}
|
|
291
316
|
logger.debug(`Wrote ${state.errorRoutes.size} error routes to database`);
|
|
@@ -454,6 +479,16 @@ declare module '#ai-ready-virtual/db-provider.mjs' {
|
|
|
454
479
|
declare module '#ai-ready-virtual/db-schema.mjs' {
|
|
455
480
|
export * from '#ai-ready/server/db/schema/sqlite'
|
|
456
481
|
}
|
|
482
|
+
|
|
483
|
+
declare module '#ai-ready-virtual/content-lookup.mjs' {
|
|
484
|
+
import type { H3Event } from 'h3'
|
|
485
|
+
export function lookupContentPage(event: H3Event, path: string): Promise<{
|
|
486
|
+
markdown: string
|
|
487
|
+
title?: string
|
|
488
|
+
description?: string
|
|
489
|
+
updatedAt?: string
|
|
490
|
+
} | null>
|
|
491
|
+
}
|
|
457
492
|
`
|
|
458
493
|
});
|
|
459
494
|
}
|
|
@@ -487,6 +522,39 @@ function refineDatabaseConfig(config, rootDir) {
|
|
|
487
522
|
};
|
|
488
523
|
}
|
|
489
524
|
|
|
525
|
+
const CJK_PREFIXES = ["zh", "ja", "ko"];
|
|
526
|
+
function hasCjkLocale(i18n) {
|
|
527
|
+
return i18n.locales.some((l) => CJK_PREFIXES.some((p) => l.code.startsWith(p) || l.hreflang.startsWith(p)));
|
|
528
|
+
}
|
|
529
|
+
function toRuntimeI18nConfig(auto) {
|
|
530
|
+
return {
|
|
531
|
+
defaultLocale: auto.defaultLocale,
|
|
532
|
+
strategy: auto.strategy,
|
|
533
|
+
locales: auto.locales.map((l) => {
|
|
534
|
+
const raw = l;
|
|
535
|
+
return {
|
|
536
|
+
code: l.code,
|
|
537
|
+
hreflang: l._hreflang || raw.language || l.code,
|
|
538
|
+
name: raw.name,
|
|
539
|
+
nativeName: raw.nativeName ?? raw.name
|
|
540
|
+
};
|
|
541
|
+
})
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
async function detectI18n(opts = {}) {
|
|
545
|
+
if (opts.autoI18n === false)
|
|
546
|
+
return null;
|
|
547
|
+
const auto = await resolveI18nConfig({ warn: (msg) => logger.warn(msg) });
|
|
548
|
+
if (!auto)
|
|
549
|
+
return null;
|
|
550
|
+
if (!auto.locales?.length) {
|
|
551
|
+
logger.warn("[ai-ready] @nuxtjs/i18n detected but no locales configured. i18n integration disabled.");
|
|
552
|
+
return null;
|
|
553
|
+
}
|
|
554
|
+
logger.debug(`[ai-ready] i18n detected: ${auto.locales.length} locales, strategy=${auto.strategy}, default=${auto.defaultLocale}`);
|
|
555
|
+
return toRuntimeI18nConfig(auto);
|
|
556
|
+
}
|
|
557
|
+
|
|
490
558
|
const module$1 = defineNuxtModule({
|
|
491
559
|
meta: {
|
|
492
560
|
name: "nuxt-ai-ready",
|
|
@@ -547,6 +615,11 @@ const module$1 = defineNuxtModule({
|
|
|
547
615
|
logger.warn("`mdreamOptions.preset` is deprecated. Use `mdreamOptions: { minimal: true }` instead. See https://github.com/harlan-zw/nuxt-ai-ready/releases/tag/v1.0.0");
|
|
548
616
|
}
|
|
549
617
|
await installNuxtSiteConfig();
|
|
618
|
+
const i18nConfig = await detectI18n({ autoI18n: config.autoI18n });
|
|
619
|
+
if (i18nConfig) {
|
|
620
|
+
logger.info(`i18n detected: ${i18nConfig.locales.length} locales (default: ${i18nConfig.defaultLocale}, strategy: ${i18nConfig.strategy})`);
|
|
621
|
+
}
|
|
622
|
+
const ftsTokenizer = i18nConfig && hasCjkLocale(i18nConfig) ? "trigram" : "unicode61 remove_diacritics 2";
|
|
550
623
|
nuxt.options.nitro.alias = nuxt.options.nitro.alias || {};
|
|
551
624
|
nuxt.options.alias["#ai-ready"] = resolve("./runtime");
|
|
552
625
|
const preset = String(nuxt.options.nitro.preset || "");
|
|
@@ -581,6 +654,8 @@ const module$1 = defineNuxtModule({
|
|
|
581
654
|
nuxt.options.nitro.scanDirs.push(
|
|
582
655
|
resolve("./runtime/server/utils")
|
|
583
656
|
);
|
|
657
|
+
const contentVersion = await resolveNuxtContentVersion();
|
|
658
|
+
const hasNuxtContentV3 = !!(contentVersion && contentVersion.version === 3);
|
|
584
659
|
if (typeof config.contentSignal === "object") {
|
|
585
660
|
const robotsOpts = nuxt.options.robots !== false ? nuxt.options.robots : {};
|
|
586
661
|
nuxt.options.robots = robotsOpts;
|
|
@@ -743,13 +818,13 @@ export async function readPageDataFromFilesystem() {
|
|
|
743
818
|
if (nodeVersion >= 22) {
|
|
744
819
|
const { DatabaseSync } = await import('node' + ':sqlite')
|
|
745
820
|
const db = new DatabaseSync(dbPath, { open: true })
|
|
746
|
-
rows = db.prepare('SELECT route, title, description, markdown, headings, keywords, updated_at, is_error FROM ai_ready_pages').all()
|
|
821
|
+
rows = db.prepare('SELECT route, title, description, markdown, headings, keywords, updated_at, is_error, locale FROM ai_ready_pages').all()
|
|
747
822
|
db.close()
|
|
748
823
|
}
|
|
749
824
|
else {
|
|
750
825
|
const Database = (await import('better-sqlite3')).default
|
|
751
826
|
const db = new Database(dbPath, { readonly: true })
|
|
752
|
-
rows = db.prepare('SELECT route, title, description, markdown, headings, keywords, updated_at, is_error FROM ai_ready_pages').all()
|
|
827
|
+
rows = db.prepare('SELECT route, title, description, markdown, headings, keywords, updated_at, is_error, locale FROM ai_ready_pages').all()
|
|
753
828
|
db.close()
|
|
754
829
|
}
|
|
755
830
|
|
|
@@ -761,6 +836,7 @@ export async function readPageDataFromFilesystem() {
|
|
|
761
836
|
headings: r.headings,
|
|
762
837
|
keywords: JSON.parse(r.keywords || '[]'),
|
|
763
838
|
updatedAt: r.updated_at,
|
|
839
|
+
locale: r.locale || '',
|
|
764
840
|
}))
|
|
765
841
|
const errorRoutes = rows.filter(r => r.is_error).map(r => r.route)
|
|
766
842
|
|
|
@@ -792,6 +868,34 @@ export const logger = createConsola({
|
|
|
792
868
|
mcp: { enabled: hasMCP, tools: hasMCP && config.mcp?.tools !== false, resources: hasMCP && config.mcp?.resources !== false },
|
|
793
869
|
cron: !!config.cron
|
|
794
870
|
})}`;
|
|
871
|
+
nitroConfig.virtual["#ai-ready-virtual/content-lookup.mjs"] = hasNuxtContentV3 ? `
|
|
872
|
+
import { queryCollection } from '@nuxt/content/server'
|
|
873
|
+
import manifest from '#content/manifest'
|
|
874
|
+
import { stringify } from 'minimark/stringify'
|
|
875
|
+
|
|
876
|
+
const pageCollections = Object.entries(manifest)
|
|
877
|
+
.filter(([, info]) => info.type === 'page')
|
|
878
|
+
.map(([name]) => name)
|
|
879
|
+
|
|
880
|
+
export async function lookupContentPage(event, path) {
|
|
881
|
+
if (!pageCollections.length) return null
|
|
882
|
+
const candidates = path === '/' ? ['/'] : [path, path.replace(/\\/$/, '')]
|
|
883
|
+
for (const collection of pageCollections) {
|
|
884
|
+
for (const candidate of candidates) {
|
|
885
|
+
const page = await queryCollection(event, collection).path(candidate).first().catch(() => null)
|
|
886
|
+
if (!page) continue
|
|
887
|
+
const markdown = stringify({ ...page.body, type: 'minimark' }, { format: 'markdown/html' })
|
|
888
|
+
return {
|
|
889
|
+
markdown,
|
|
890
|
+
title: page.title,
|
|
891
|
+
description: page.description,
|
|
892
|
+
updatedAt: page.seo?.articleModifiedTime || page.updatedAt,
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
return null
|
|
897
|
+
}
|
|
898
|
+
` : `export async function lookupContentPage() { return null }`;
|
|
795
899
|
});
|
|
796
900
|
const database = refineDatabaseConfig(config.database || {}, nuxt.options.rootDir);
|
|
797
901
|
nuxt.options.runtimeConfig["nuxt-ai-ready"] = {
|
|
@@ -815,7 +919,9 @@ export const logger = createConsola({
|
|
|
815
919
|
},
|
|
816
920
|
runtimeSyncSecret,
|
|
817
921
|
indexNow,
|
|
818
|
-
sitemapPrerendered
|
|
922
|
+
sitemapPrerendered,
|
|
923
|
+
i18n: i18nConfig,
|
|
924
|
+
ftsTokenizer
|
|
819
925
|
};
|
|
820
926
|
addServerHandler({
|
|
821
927
|
middleware: true,
|
|
@@ -875,7 +981,7 @@ export const logger = createConsola({
|
|
|
875
981
|
name: siteConfig.name,
|
|
876
982
|
url: siteConfig.url,
|
|
877
983
|
description: siteConfig.description
|
|
878
|
-
}, mergedLlmsTxt, indexNow);
|
|
984
|
+
}, mergedLlmsTxt, indexNow, { ftsTokenizer, i18n: i18nConfig });
|
|
879
985
|
}
|
|
880
986
|
addServerPlugin(resolve("./runtime/server/plugins/db-lifecycle"));
|
|
881
987
|
setupDevToolsUI({
|
|
@@ -2,8 +2,21 @@ import { useRuntimeConfig } from "nitropack/runtime";
|
|
|
2
2
|
import { getSiteConfig } from "#site-config/server/composables/getSiteConfig";
|
|
3
3
|
import { normalizeLlmsTxtConfig } from "./llms-txt-format.js";
|
|
4
4
|
import { queryPages } from "./server/db/queries.js";
|
|
5
|
+
import { localePath, resolveLocaleFromRoute } from "./server/utils/i18n.js";
|
|
5
6
|
import { fetchSitemapUrls } from "./server/utils/sitemap.js";
|
|
6
7
|
export { normalizeLlmsTxtConfig };
|
|
8
|
+
function formatAvailableLanguagesSection(i18n, pageCounts) {
|
|
9
|
+
const lines = ["## Available Languages on Website", ""];
|
|
10
|
+
for (const locale of i18n.locales) {
|
|
11
|
+
const isDefault = locale.code === i18n.defaultLocale;
|
|
12
|
+
const prefix = localePath("/", locale.code, i18n);
|
|
13
|
+
const count = pageCounts.get(locale.code) ?? 0;
|
|
14
|
+
const display = locale.nativeName ? `${locale.nativeName} (${locale.code})` : locale.name ? `${locale.name} (${locale.code})` : locale.code;
|
|
15
|
+
const suffix = isDefault ? "Content included below" : "Visit website for content";
|
|
16
|
+
lines.push(`- ${display} - ${count} pages - ${prefix} - ${suffix}`);
|
|
17
|
+
}
|
|
18
|
+
return lines;
|
|
19
|
+
}
|
|
7
20
|
function getGroupPrefix(url, depth) {
|
|
8
21
|
const segments = url.split("/").filter(Boolean);
|
|
9
22
|
if (segments.length === 0)
|
|
@@ -101,6 +114,7 @@ export async function buildLlmsTxt(event) {
|
|
|
101
114
|
const sitemapConfig = runtimeConfig.sitemap;
|
|
102
115
|
const siteConfig = getSiteConfig(event);
|
|
103
116
|
const llmsTxtConfig = aiReadyConfig.llmsTxt;
|
|
117
|
+
const i18n = aiReadyConfig.i18n;
|
|
104
118
|
const parts = [];
|
|
105
119
|
parts.push(`# ${siteConfig.name || siteConfig.url}`);
|
|
106
120
|
if (siteConfig.description) {
|
|
@@ -137,19 +151,38 @@ Canonical Origin: ${siteConfig.url}`);
|
|
|
137
151
|
const prerendered = [];
|
|
138
152
|
for (const page of pages) {
|
|
139
153
|
seenPaths.add(page.route);
|
|
140
|
-
prerendered.push({ pathname: page.route, title: page.title, description: page.description });
|
|
154
|
+
prerendered.push({ pathname: page.route, title: page.title, description: page.description, locale: page.locale });
|
|
141
155
|
}
|
|
142
156
|
const devModeHint = import.meta.dev && prerendered.length === 0 ? " (dev mode - run `nuxi generate` for page titles)" : "";
|
|
143
157
|
const other = [];
|
|
144
158
|
for (const url of urls) {
|
|
145
159
|
const pathname = url.loc.startsWith("/") ? url.loc : new URL(url.loc).pathname;
|
|
146
160
|
if (!seenPaths.has(pathname) && !errorSet.has(pathname)) {
|
|
147
|
-
|
|
161
|
+
const locale = i18n ? resolveLocaleFromRoute(pathname, i18n).locale : void 0;
|
|
162
|
+
other.push({ pathname, locale });
|
|
148
163
|
seenPaths.add(pathname);
|
|
149
164
|
}
|
|
150
165
|
}
|
|
151
|
-
|
|
152
|
-
|
|
166
|
+
if (i18n) {
|
|
167
|
+
const pageCounts = /* @__PURE__ */ new Map();
|
|
168
|
+
for (const locale of i18n.locales) pageCounts.set(locale.code, 0);
|
|
169
|
+
for (const p of [...prerendered, ...other]) {
|
|
170
|
+
const code = p.locale || resolveLocaleFromRoute(p.pathname, i18n).locale;
|
|
171
|
+
pageCounts.set(code, (pageCounts.get(code) ?? 0) + 1);
|
|
172
|
+
}
|
|
173
|
+
parts.push(...formatAvailableLanguagesSection(i18n, pageCounts));
|
|
174
|
+
parts.push("");
|
|
175
|
+
}
|
|
176
|
+
const isDefaultLocale = (item) => {
|
|
177
|
+
if (!i18n)
|
|
178
|
+
return true;
|
|
179
|
+
const code = item.locale || resolveLocaleFromRoute(item.pathname, i18n).locale;
|
|
180
|
+
return code === i18n.defaultLocale;
|
|
181
|
+
};
|
|
182
|
+
const filteredPrerendered = i18n ? prerendered.filter(isDefaultLocale) : prerendered;
|
|
183
|
+
const filteredOther = i18n ? other.filter(isDefaultLocale) : other;
|
|
184
|
+
const sortedPrerendered = sortPagesByPath(filteredPrerendered);
|
|
185
|
+
const sortedOther = sortPagesByPath(filteredOther);
|
|
153
186
|
if (sortedPrerendered.length > 0 && sortedOther.length > 0) {
|
|
154
187
|
parts.push(`## Prerendered Pages${devModeHint}
|
|
155
188
|
`);
|
|
@@ -99,7 +99,9 @@ export declare function setInfoValue(event: H3Event | undefined, key: string, va
|
|
|
99
99
|
*/
|
|
100
100
|
export declare function deleteInfoValue(event: H3Event | undefined, key: string): Promise<void>;
|
|
101
101
|
/**
|
|
102
|
-
* Initialize database schema
|
|
102
|
+
* Initialize database schema. Rebuilds on SCHEMA_VERSION change or when the
|
|
103
|
+
* SQLite FTS5 tokenizer differs from the one baked into the existing virtual
|
|
104
|
+
* table (Postgres has no FTS5; tokenizer comparison is SQLite-only).
|
|
103
105
|
*/
|
|
104
106
|
export declare function initSchema(event?: H3Event): Promise<void>;
|
|
105
107
|
/**
|