nuxt-ai-ready 1.7.11 → 1.7.12
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/dist/chunks/agent-skills.mjs +1 -1
- package/dist/chunks/prerender.mjs +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/server/middleware/markdown.js +21 -4
- package/dist/runtime/server/plugins/link-header.d.ts +4 -0
- package/dist/runtime/server/plugins/link-header.js +40 -0
- package/dist/shared/{nuxt-ai-ready.jeGqwuW1.mjs → nuxt-ai-ready.Cp2hOQih.mjs} +6 -0
- package/package.json +10 -10
|
@@ -2,7 +2,7 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
import { realpath, readFile } from 'node:fs/promises';
|
|
3
3
|
import { resolve, isAbsolute, relative, sep } from 'node:path';
|
|
4
4
|
import { parseDocument } from 'yaml';
|
|
5
|
-
import { A as AGENT_SKILLS_SCHEMA } from '../shared/nuxt-ai-ready.
|
|
5
|
+
import { A as AGENT_SKILLS_SCHEMA } from '../shared/nuxt-ai-ready.Cp2hOQih.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, withBase, joinURL } from 'ufo';
|
|
8
|
-
import { l as logger, M as MARKDOWN_LINK_AVAILABILITY_FILE } from '../shared/nuxt-ai-ready.
|
|
8
|
+
import { l as logger, M as MARKDOWN_LINK_AVAILABILITY_FILE } from '../shared/nuxt-ai-ready.Cp2hOQih.mjs';
|
|
9
9
|
import { normalizePagePath, toMarkdownPath } from '../../dist/runtime/markdown-path.js';
|
|
10
10
|
import { toLogicalRoute, toDeployedRoute } 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
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.
|
|
10
|
+
export { m as default } from './shared/nuxt-ai-ready.Cp2hOQih.mjs';
|
|
11
11
|
import '../dist/runtime/server/utils/discovery-response.js';
|
|
12
12
|
import 'node:url';
|
|
13
13
|
import 'pathe';
|
|
@@ -5,14 +5,31 @@ import { withSiteUrl } from "#site-config/server/composables/utils";
|
|
|
5
5
|
import { toMarkdownPath } from "../../markdown-path.js";
|
|
6
6
|
import { toDeployedRoute } from "../../route-path.js";
|
|
7
7
|
import { logger } from "../logger.js";
|
|
8
|
+
import { setStatusAwareLinkHeader } from "../plugins/link-header.js";
|
|
8
9
|
import { CONTENT_NEGOTIATION_VARY, resolveContentNegotiation } from "../utils/content-negotiation.js";
|
|
9
10
|
import { computeLocaleAlternates, resolveLocaleAlternateUrl, resolveLocaleFromRoute } from "../utils/i18n.js";
|
|
10
11
|
import { buildLinkHeader } from "../utils/link-header.js";
|
|
11
12
|
import { getMarkdownRenderInfo } from "../utils/markdown-request.js";
|
|
12
13
|
const INTERNAL_HEADER = "x-ai-ready-internal";
|
|
14
|
+
function setLinkHeader(event, path, variant, config, resolveUrl, routeContext) {
|
|
15
|
+
setHeader(event, "link", buildLinkHeader(path, variant, config, resolveUrl, routeContext));
|
|
16
|
+
}
|
|
17
|
+
function setStatusAwareHeader(event, path, variant, config, resolveUrl, routeContext) {
|
|
18
|
+
const successHeader = buildLinkHeader(path, variant, config, resolveUrl, routeContext);
|
|
19
|
+
if (!config.i18n) {
|
|
20
|
+
setHeader(event, "link", successHeader);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const safeHeader = buildLinkHeader(path, variant, { ...config, i18n: null }, resolveUrl, routeContext);
|
|
24
|
+
setStatusAwareLinkHeader(event, safeHeader, successHeader);
|
|
25
|
+
}
|
|
13
26
|
function setNegotiationHeaders(event, path, config, resolveUrl, routeContext) {
|
|
14
27
|
appendHeader(event, "vary", CONTENT_NEGOTIATION_VARY);
|
|
15
|
-
|
|
28
|
+
setLinkHeader(event, path, "html", config, resolveUrl, routeContext);
|
|
29
|
+
}
|
|
30
|
+
function setStatusAwareNegotiationHeaders(event, path, config, resolveUrl, routeContext) {
|
|
31
|
+
appendHeader(event, "vary", CONTENT_NEGOTIATION_VARY);
|
|
32
|
+
setStatusAwareHeader(event, path, "html", config, resolveUrl, routeContext);
|
|
16
33
|
}
|
|
17
34
|
function setUncacheableHeaders(event) {
|
|
18
35
|
setHeader(event, "cache-control", "private, no-store");
|
|
@@ -29,7 +46,7 @@ function setUncacheableHeaders(event) {
|
|
|
29
46
|
}
|
|
30
47
|
function setMarkdownHeaders(event, path, config, resolveUrl, routeContext) {
|
|
31
48
|
setHeader(event, "content-type", "text/markdown; charset=utf-8");
|
|
32
|
-
|
|
49
|
+
setLinkHeader(event, path, "markdown", config, resolveUrl, routeContext);
|
|
33
50
|
if (config.markdownCacheHeaders) {
|
|
34
51
|
const { maxAge, swr } = config.markdownCacheHeaders;
|
|
35
52
|
const cacheControl = swr ? `public, max-age=${maxAge}, stale-while-revalidate=${maxAge}` : `public, max-age=${maxAge}`;
|
|
@@ -100,9 +117,9 @@ export default defineEventHandler(async (event) => {
|
|
|
100
117
|
const canonicalUrl = resolveUrl(path);
|
|
101
118
|
if (negotiation === "html") {
|
|
102
119
|
if (contentNegotiation._tag === "enabled")
|
|
103
|
-
|
|
120
|
+
setStatusAwareNegotiationHeaders(event, path, config, resolveUrl, routeContext);
|
|
104
121
|
else
|
|
105
|
-
|
|
122
|
+
setStatusAwareHeader(event, path, "html", config, resolveUrl, routeContext);
|
|
106
123
|
return;
|
|
107
124
|
}
|
|
108
125
|
if (!isExplicit) {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { getHeader, getResponseStatus, setHeader } from "#nuxtseo/h3";
|
|
2
|
+
import { defineNitroPlugin } from "#nuxtseo/nitro";
|
|
3
|
+
const STATUS_AWARE_LINK_HEADER = "nuxt-ai-ready:status-aware-link-header";
|
|
4
|
+
const ERROR_LINK_HEADER = "x-nuxt-ai-ready-error-link";
|
|
5
|
+
export function setStatusAwareLinkHeader(event, safeHeader, successHeader) {
|
|
6
|
+
event.context[STATUS_AWARE_LINK_HEADER] = {
|
|
7
|
+
error: safeHeader,
|
|
8
|
+
success: successHeader ?? safeHeader
|
|
9
|
+
};
|
|
10
|
+
setHeader(event, "link", safeHeader);
|
|
11
|
+
}
|
|
12
|
+
export default defineNitroPlugin((nitro) => {
|
|
13
|
+
nitro.hooks.hook("error", (_error, { event }) => {
|
|
14
|
+
if (!event)
|
|
15
|
+
return;
|
|
16
|
+
const header = event.context[STATUS_AWARE_LINK_HEADER];
|
|
17
|
+
if (header)
|
|
18
|
+
event.node.req.headers[ERROR_LINK_HEADER] = header.error;
|
|
19
|
+
});
|
|
20
|
+
nitro.hooks.hook("beforeResponse", (event) => {
|
|
21
|
+
const header = event.context[STATUS_AWARE_LINK_HEADER];
|
|
22
|
+
if (!header)
|
|
23
|
+
return;
|
|
24
|
+
setHeader(event, "link", getResponseStatus(event) >= 400 ? header.error : header.success);
|
|
25
|
+
});
|
|
26
|
+
nitro.hooks.hook("render:response", (response, { event }) => {
|
|
27
|
+
const header = event.context[STATUS_AWARE_LINK_HEADER];
|
|
28
|
+
const errorHeader = event.path.startsWith("/__nuxt_error") && getHeader(event, "x-nuxt-error") === "true" ? getHeader(event, ERROR_LINK_HEADER) : void 0;
|
|
29
|
+
if (errorHeader) {
|
|
30
|
+
response.headers ||= {};
|
|
31
|
+
response.headers.link = errorHeader;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!header)
|
|
35
|
+
return;
|
|
36
|
+
response.headers ||= {};
|
|
37
|
+
const statusCode = response.statusCode ?? getResponseStatus(event);
|
|
38
|
+
response.headers.link = statusCode >= 400 ? header.error : header.success;
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -480,11 +480,16 @@ function collectPagePaths(routes, parentPath = "") {
|
|
|
480
480
|
return paths;
|
|
481
481
|
}, /* @__PURE__ */ new Map());
|
|
482
482
|
}
|
|
483
|
+
function isUnlocalizedLocalePage(page) {
|
|
484
|
+
return page?._tag === "unlocalized" && typeof page.path === "string";
|
|
485
|
+
}
|
|
483
486
|
function materializeI18nPages(i18n, routes) {
|
|
484
487
|
if (!i18n.pages)
|
|
485
488
|
return void 0;
|
|
486
489
|
const pagePaths = collectPagePaths(routes);
|
|
487
490
|
return Object.fromEntries(Object.entries(i18n.pages).map(([pageName, pageLocales]) => {
|
|
491
|
+
if (isUnlocalizedLocalePage(pageLocales))
|
|
492
|
+
return [pageName, pageLocales];
|
|
488
493
|
const defaultPath = pageLocales?.[i18n.defaultLocale];
|
|
489
494
|
const fallbackPath = typeof defaultPath === "string" ? defaultPath : pagePaths.get(pageName);
|
|
490
495
|
const locales = Object.fromEntries(i18n.locales.flatMap((locale) => {
|
|
@@ -1471,6 +1476,7 @@ export async function lookupContentPage(event, path) {
|
|
|
1471
1476
|
middleware: true,
|
|
1472
1477
|
handler: resolve("./runtime/server/middleware/markdown")
|
|
1473
1478
|
});
|
|
1479
|
+
addServerPlugin(resolve("./runtime/server/plugins/link-header"));
|
|
1474
1480
|
addPlugin({
|
|
1475
1481
|
mode: "server",
|
|
1476
1482
|
src: resolve("./runtime/app/plugins/md-alternate.server")
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-ai-ready",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.7.
|
|
4
|
+
"version": "1.7.12",
|
|
5
5
|
"description": "Best practice AI & LLM discoverability for Nuxt sites.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -62,18 +62,18 @@
|
|
|
62
62
|
}
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@mdream/js": "^1.
|
|
65
|
+
"@mdream/js": "^1.6.2",
|
|
66
66
|
"@nuxt/kit": "^4.5.2",
|
|
67
67
|
"citty": "^0.2.2",
|
|
68
68
|
"consola": "^3.4.2",
|
|
69
69
|
"defu": "^6.1.7",
|
|
70
70
|
"drizzle-orm": "^0.45.2",
|
|
71
|
-
"mdream": "^1.
|
|
72
|
-
"nuxt-site-config": "^4.2.
|
|
73
|
-
"nuxtseo-shared": "^5.3.
|
|
71
|
+
"mdream": "^1.6.2",
|
|
72
|
+
"nuxt-site-config": "^4.2.2",
|
|
73
|
+
"nuxtseo-shared": "^5.3.12",
|
|
74
74
|
"pathe": "^2.0.3",
|
|
75
75
|
"pkg-types": "^2.3.1",
|
|
76
|
-
"site-config-stack": "^4.2.
|
|
76
|
+
"site-config-stack": "^4.2.2",
|
|
77
77
|
"sitemapd": "^0.2.2",
|
|
78
78
|
"ufo": "^1.6.4",
|
|
79
79
|
"uncrypto": "^0.1.3",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"@nuxtjs/eslint-config-typescript": "^12.1.0",
|
|
90
90
|
"@nuxtjs/mcp-toolkit": "^0.18.1",
|
|
91
91
|
"@nuxtjs/robots": "^6.1.4",
|
|
92
|
-
"@nuxtjs/sitemap": "^8.3.
|
|
92
|
+
"@nuxtjs/sitemap": "^8.3.4",
|
|
93
93
|
"@types/better-sqlite3": "^9.6.0",
|
|
94
94
|
"@vitest/coverage-v8": "^4.1.10",
|
|
95
95
|
"@vue/test-utils": "^2.4.11",
|
|
@@ -103,8 +103,8 @@
|
|
|
103
103
|
"happy-dom": "^20.11.2",
|
|
104
104
|
"nitropack": "^2.13.4",
|
|
105
105
|
"nuxt": "^4.5.2",
|
|
106
|
-
"nuxt-site-config": "^4.2.
|
|
107
|
-
"nuxtseo-layer-devtools": "^5.3.
|
|
106
|
+
"nuxt-site-config": "^4.2.2",
|
|
107
|
+
"nuxtseo-layer-devtools": "^5.3.12",
|
|
108
108
|
"playwright": "^1.62.1",
|
|
109
109
|
"playwright-core": "^1.62.1",
|
|
110
110
|
"tinyglobby": "^0.2.17",
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
"vue": "^3.5.41",
|
|
115
115
|
"vue-router": "^5.2.0",
|
|
116
116
|
"vue-tsc": "^3.3.9",
|
|
117
|
-
"wrangler": "^4.
|
|
117
|
+
"wrangler": "^4.121.0",
|
|
118
118
|
"zod": "^4.4.3"
|
|
119
119
|
},
|
|
120
120
|
"scripts": {
|