@farming-labs/docs 0.2.120 → 0.2.121

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 (188) hide show
  1. package/README.md +8 -0
  2. package/dist/access.d.mts +13 -0
  3. package/dist/access.mjs +56 -0
  4. package/dist/agent-conformance.d.mts +60 -0
  5. package/dist/agent-conformance.mjs +538 -0
  6. package/dist/agent-contract.d.mts +47 -0
  7. package/dist/agent-contract.mjs +645 -0
  8. package/dist/agent-detection.d.mts +6 -0
  9. package/dist/agent-detection.mjs +83 -0
  10. package/dist/agent-evals.d.mts +224 -0
  11. package/dist/{agent-evals-BLNLvXbG.mjs → agent-evals.mjs} +7 -565
  12. package/dist/agent-feedback-evaluations-node.mjs +38 -0
  13. package/dist/agent-feedback-evaluations.d.mts +91 -0
  14. package/dist/{agent-feedback-evaluations-CcMGlgsO.mjs → agent-feedback-evaluations.mjs} +2 -2
  15. package/dist/agent-feedback-loop.d.mts +45 -0
  16. package/dist/{agent-feedback-loop-CcZL_sb1.mjs → agent-feedback-loop.mjs} +1 -1
  17. package/dist/agent-maintenance.d.mts +71 -0
  18. package/dist/{agent-maintenance-CuZ7iAKq.mjs → agent-maintenance.mjs} +1 -1
  19. package/dist/agent-provenance.d.mts +23 -0
  20. package/dist/agent-provenance.mjs +77 -0
  21. package/dist/agent-scope.mjs +321 -0
  22. package/dist/agent-skills-archive.mjs +86 -0
  23. package/dist/agent-skills-bundle.d.mts +1 -1
  24. package/dist/{agent-skills-progressive-disclosure-PjPtTYL-.mjs → agent-skills-progressive-disclosure.mjs} +2 -2
  25. package/dist/{agent-skills-server-D5IuvwM7.d.mts → agent-skills-server.d.mts} +3 -3
  26. package/dist/{agent-skills-server-BC7md56k.mjs → agent-skills-server.mjs} +2 -2
  27. package/dist/agent-skills-vite.d.mts +3 -3
  28. package/dist/agent-skills-vite.mjs +1 -2
  29. package/dist/agent-surface-drift.mjs +236 -0
  30. package/dist/{golden-evaluations-CLUViycJ.mjs → agent-usefulness.mjs} +5 -290
  31. package/dist/{content-change-hydration-wqXIZHp6.d.mts → agent.d.mts} +10 -411
  32. package/dist/agent.mjs +2729 -0
  33. package/dist/{analytics-w3FDOksr.d.mts → analytics.d.mts} +2 -2
  34. package/dist/{analytics-p8Vhhu2P.mjs → analytics.mjs} +2 -2
  35. package/dist/{sitemap-server-BUdPBcGs.d.mts → api-reference.d.mts} +2 -6
  36. package/dist/api-reference.mjs +1481 -0
  37. package/dist/{audience-exposure-DBrFWULA.d.mts → audience-exposure.d.mts} +1 -1
  38. package/dist/audience-exposure.mjs +8 -0
  39. package/dist/audience.d.mts +44 -0
  40. package/dist/audience.mjs +1654 -0
  41. package/dist/authoring-mcp.d.mts +44 -0
  42. package/dist/{authoring-mcp-CiCUQe3o.mjs → authoring-mcp.mjs} +3 -3
  43. package/dist/browser.d.mts +6 -4
  44. package/dist/browser.mjs +6 -7
  45. package/dist/build.d.mts +8 -0
  46. package/dist/build.mjs +8 -0
  47. package/dist/changelog.d.mts +20 -0
  48. package/dist/changelog.mjs +39 -0
  49. package/dist/{agent-export-CA6IUQ7T.mjs → cli/agent-export.mjs} +19 -45
  50. package/dist/{agent-CYk2DxY7.mjs → cli/agent.mjs} +6 -35
  51. package/dist/{agents-BUiVmj8i.mjs → cli/agents.mjs} +5 -18
  52. package/dist/cli/api-doctor.mjs +206 -0
  53. package/dist/{authoring-C2ymvYWl.mjs → cli/authoring.mjs} +2 -8
  54. package/dist/{cloud-6eKrlmKd.mjs → cli/cloud.mjs} +3 -3
  55. package/dist/{codeblocks-CHpgAwY-.mjs → cli/codeblocks.mjs} +2 -2
  56. package/dist/cli/config.d.mts +11 -0
  57. package/dist/{config-BZnKAj_Y.mjs → cli/config.mjs} +1 -1
  58. package/dist/cli/dev-banner.mjs +58 -0
  59. package/dist/{dev-Bnn-NUNa.mjs → cli/dev.mjs} +3 -57
  60. package/dist/{doctor-Bfkrkzad.mjs → cli/doctor.mjs} +41 -226
  61. package/dist/{downgrade-CHMta85e.mjs → cli/downgrade.mjs} +2 -2
  62. package/dist/cli/errors.d.mts +4 -0
  63. package/dist/{errors-BtnVLhNF.mjs → cli/errors.mjs} +1 -1
  64. package/dist/{feedback-evals-DMilg9pY.mjs → cli/feedback-evals.mjs} +3 -36
  65. package/dist/{feedback-DL4T5oIO.mjs → cli/feedback.mjs} +1 -1
  66. package/dist/cli/git-dates.mjs +35 -0
  67. package/dist/cli/golden-evaluations.mjs +52 -0
  68. package/dist/cli/index.d.mts +2 -3
  69. package/dist/cli/index.mjs +38 -38
  70. package/dist/{init-K0LmXDZ5.mjs → cli/init.mjs} +3 -3
  71. package/dist/{mcp-iLCmnPJI.mjs → cli/mcp.mjs} +7 -19
  72. package/dist/{openapi-diff-HcpUNjA-.mjs → cli/openapi-diff.mjs} +2 -7
  73. package/dist/{openapi-sdk-BQKC6H-_.mjs → cli/openapi-sdk.mjs} +2 -7
  74. package/dist/{openapi-source-DK6ts_Bk.mjs → cli/openapi-source.mjs} +2 -2
  75. package/dist/{package-version-HJhYeq4M.mjs → cli/package-version.mjs} +2 -2
  76. package/dist/{propose-JmUv_BTt.mjs → cli/propose.mjs} +1 -1
  77. package/dist/{review-C6EmbV0l.mjs → cli/review.mjs} +16 -15
  78. package/dist/{robots-DteZB8vl.mjs → cli/robots.mjs} +3 -7
  79. package/dist/{search-Bhuv_YsL.mjs → cli/search.mjs} +7 -20
  80. package/dist/{sitemap-DW5LDKDa.mjs → cli/sitemap.mjs} +7 -42
  81. package/dist/{skills-BAPQLSCm.mjs → cli/skills.mjs} +5 -19
  82. package/dist/{templates-BuQ8YsGv.mjs → cli/templates.mjs} +1 -1
  83. package/dist/{upgrade-DlQMOFV1.mjs → cli/upgrade.mjs} +2 -2
  84. package/dist/{utils-C7KDrPpA.mjs → cli/utils.mjs} +1 -1
  85. package/dist/client/react.d.mts +2 -18
  86. package/dist/client/react.mjs +1 -157
  87. package/dist/{cloud-analytics-D14HplI7.mjs → cloud-analytics.mjs} +1 -1
  88. package/dist/{cloud-ask-ai-BrsTXQf6.d.mts → cloud-ask-ai.d.mts} +2 -2
  89. package/dist/{cloud-ask-ai-BqKhjpS5.mjs → cloud-ask-ai.mjs} +3 -3
  90. package/dist/code-blocks.d.mts +51 -0
  91. package/dist/{code-blocks-GYdvS3BH.mjs → code-blocks.mjs} +2 -2
  92. package/dist/code-group-mdx.d.mts +11 -0
  93. package/dist/code-group-mdx.mjs +57 -0
  94. package/dist/content-change-hydration.d.mts +87 -0
  95. package/dist/{openapi-mcp-BIOTLiA7.mjs → content-change-hydration.mjs} +5 -210
  96. package/dist/content-changes.d.mts +47 -0
  97. package/dist/content-changes.mjs +216 -0
  98. package/dist/create-theme.d.mts +48 -0
  99. package/dist/create-theme.mjs +57 -0
  100. package/dist/date.d.mts +5 -0
  101. package/dist/date.mjs +17 -0
  102. package/dist/define-docs.d.mts +9 -0
  103. package/dist/define-docs.mjs +46 -0
  104. package/dist/docs-cloud-client.d.mts +18 -0
  105. package/dist/docs-cloud-client.mjs +161 -0
  106. package/dist/docs-cloud-server.d.mts +2 -2
  107. package/dist/docs-cloud-server.mjs +2 -3
  108. package/dist/heading-toc.d.mts +10 -0
  109. package/dist/heading-toc.mjs +23 -0
  110. package/dist/http-body.d.mts +14 -0
  111. package/dist/{http-body-DkAPk6D5.mjs → http-body.mjs} +1 -1
  112. package/dist/http-cache.d.mts +25 -0
  113. package/dist/http-cache.mjs +140 -0
  114. package/dist/http-link.mjs +81 -0
  115. package/dist/i18n.d.mts +18 -0
  116. package/dist/{i18n-B1gJ9EW0.mjs → i18n.mjs} +1 -1
  117. package/dist/index.d.mts +42 -674
  118. package/dist/index.mjs +40 -14
  119. package/dist/markdown-rendering.mjs +1 -1
  120. package/dist/markdown-section-cache.mjs +49 -0
  121. package/dist/markdown-sections.d.mts +47 -0
  122. package/dist/{markdown-sections-9Oxr33b-.mjs → markdown-sections.mjs} +29 -703
  123. package/dist/mcp-auth.d.mts +14 -0
  124. package/dist/mcp-auth.mjs +99 -0
  125. package/dist/mcp.d.mts +5 -3
  126. package/dist/mcp.mjs +21 -9
  127. package/dist/mdx.d.mts +6 -0
  128. package/dist/mdx.mjs +7 -0
  129. package/dist/metadata.d.mts +60 -0
  130. package/dist/{metadata-BOHn0Y5K.mjs → metadata.mjs} +2 -2
  131. package/dist/native-api-reference.mjs +968 -0
  132. package/dist/okf.d.mts +42 -0
  133. package/dist/okf.mjs +145 -0
  134. package/dist/openapi-contract.mjs +154 -0
  135. package/dist/{openapi-mcp-node-C4jUpZG6.mjs → openapi-mcp-node.mjs} +1 -1
  136. package/dist/openapi-mcp.d.mts +26 -0
  137. package/dist/openapi-mcp.mjs +132 -0
  138. package/dist/openapi-operations.d.mts +71 -0
  139. package/dist/{openapi-operations-DFpaqOqA.mjs → openapi-operations.mjs} +1 -1
  140. package/dist/openapi-overlays.mjs +221 -0
  141. package/dist/openapi-references.mjs +233 -0
  142. package/dist/pagination.d.mts +7 -0
  143. package/dist/pagination.mjs +100 -0
  144. package/dist/prompt-references.d.mts +12 -0
  145. package/dist/prompt-references.mjs +132 -0
  146. package/dist/prompt-utils.d.mts +36 -0
  147. package/dist/{prompt-utils-B5g-bv7o.mjs → prompt-utils.mjs} +1 -57
  148. package/dist/reading-time.d.mts +23 -0
  149. package/dist/reading-time.mjs +58 -0
  150. package/dist/related.d.mts +7 -0
  151. package/dist/related.mjs +50 -0
  152. package/dist/retrieval-digest.d.mts +16 -0
  153. package/dist/{retrieval-digest-CT-eIEcp.mjs → retrieval-digest.mjs} +1 -1
  154. package/dist/review.d.mts +69 -0
  155. package/dist/review.mjs +562 -0
  156. package/dist/robots.d.mts +54 -0
  157. package/dist/{robots-BYJAVeI6.mjs → robots.mjs} +5 -3
  158. package/dist/runtime.d.mts +3 -3
  159. package/dist/runtime.mjs +3 -9
  160. package/dist/search.d.mts +210 -0
  161. package/dist/search.mjs +3401 -0
  162. package/dist/server.d.mts +22 -198
  163. package/dist/server.mjs +21 -19
  164. package/dist/sidebar.d.mts +15 -0
  165. package/dist/sidebar.mjs +73 -0
  166. package/dist/sitemap-server.d.mts +7 -0
  167. package/dist/{sitemap-server-Lg3YhUx4.mjs → sitemap-server.mjs} +2 -2
  168. package/dist/{sitemap-Cl8vrixd.d.mts → sitemap.d.mts} +3 -3
  169. package/dist/sitemap.mjs +254 -0
  170. package/dist/{standards-discovery-BHPc7YIX.d.mts → standards-discovery.d.mts} +2 -2
  171. package/dist/{standards-discovery-sSEojU80.mjs → standards-discovery.mjs} +3 -139
  172. package/dist/telemetry-runtime.d.mts +42 -0
  173. package/dist/telemetry-runtime.mjs +238 -0
  174. package/dist/telemetry.d.mts +15 -0
  175. package/dist/telemetry.mjs +117 -0
  176. package/dist/{types-BJFeMXWZ.d.mts → types.d.mts} +3 -2
  177. package/dist/urls.d.mts +7 -0
  178. package/dist/urls.mjs +21 -0
  179. package/dist/utils.d.mts +8 -0
  180. package/dist/utils.mjs +22 -0
  181. package/package.json +21 -3
  182. package/dist/agent-DkAidqtV.mjs +0 -9026
  183. package/dist/api-reference-BYee4zMo.mjs +0 -3046
  184. package/dist/prompt-references-DMgbu_dz.mjs +0 -1082
  185. package/dist/retrieval-digest-AOx2-LbC.d.mts +0 -367
  186. package/dist/sidebar-CFHBj29f.mjs +0 -421
  187. package/dist/sidebar-CMPbVfGP.d.mts +0 -63
  188. /package/dist/{openapi-CfCzX_a1.mjs → cli/openapi.mjs} +0 -0
@@ -0,0 +1,23 @@
1
+ //#region src/heading-toc.ts
2
+ /**
3
+ * Encode heading fragments emitted by a renderer's nested table of contents.
4
+ *
5
+ * Fumadocs stores fragment URLs as raw DOM ids. Encoding the fragment after its
6
+ * heading visitor runs keeps links valid without changing path prefixes.
7
+ */
8
+ function encodeDocsHeadingTocUrls(value) {
9
+ if (Array.isArray(value)) {
10
+ for (const item of value) encodeDocsHeadingTocUrls(item);
11
+ return;
12
+ }
13
+ if (!value || typeof value !== "object") return;
14
+ const item = value;
15
+ if (typeof item.url === "string") {
16
+ const hashIndex = item.url.indexOf("#");
17
+ if (hashIndex >= 0) item.url = `${item.url.slice(0, hashIndex)}#${encodeURIComponent(item.url.slice(hashIndex + 1))}`;
18
+ }
19
+ encodeDocsHeadingTocUrls(item.children);
20
+ }
21
+
22
+ //#endregion
23
+ export { encodeDocsHeadingTocUrls };
@@ -0,0 +1,14 @@
1
+ //#region src/http-body.d.ts
2
+ declare const DEFAULT_DOCS_JSON_BODY_MAX_BYTES: number;
3
+ type DocsJsonBodyResult = {
4
+ ok: true;
5
+ value: unknown;
6
+ } | {
7
+ ok: false;
8
+ reason: "invalid_json" | "request_too_large";
9
+ maxBodyBytes: number;
10
+ };
11
+ /** Read and parse JSON without buffering an unbounded request body. */
12
+ declare function readDocsJsonBody(request: Request, maxBodyBytes?: number): Promise<DocsJsonBodyResult>;
13
+ //#endregion
14
+ export { DEFAULT_DOCS_JSON_BODY_MAX_BYTES, DocsJsonBodyResult, readDocsJsonBody };
@@ -61,4 +61,4 @@ async function readDocsJsonBody(request, maxBodyBytes = DEFAULT_DOCS_JSON_BODY_M
61
61
  }
62
62
 
63
63
  //#endregion
64
- export { readDocsJsonBody as n, DEFAULT_DOCS_JSON_BODY_MAX_BYTES as t };
64
+ export { DEFAULT_DOCS_JSON_BODY_MAX_BYTES, readDocsJsonBody };
@@ -0,0 +1,25 @@
1
+ //#region src/http-cache.d.ts
2
+ interface DocsCacheableResponseOptions {
3
+ request: Request;
4
+ content: string | Uint8Array;
5
+ status?: number;
6
+ headers?: HeadersInit;
7
+ /** Stable SHA-256 hex digest when the caller already hashed the exact response bytes. */
8
+ sha256?: string;
9
+ /** Exact representation modification time. Invalid values are omitted. */
10
+ lastModified?: string | Date | null;
11
+ }
12
+ /** Format an RFC 9530 Content-Digest field from a SHA-256 hex digest. */
13
+ declare function formatDocsContentDigest(sha256: string): string;
14
+ /** Normalize an exact source timestamp for Last-Modified. */
15
+ declare function resolveDocsHttpDate(value?: string | Date | null): string | undefined;
16
+ /** Match strong or weak If-None-Match validators for a GET/HEAD representation. */
17
+ declare function requestMatchesDocsEtag(request: Request, etag: string): boolean;
18
+ /** Apply If-Modified-Since only when the stronger If-None-Match validator is absent. */
19
+ declare function requestHasFreshDocsDate(request: Request, lastModified?: string): boolean;
20
+ /**
21
+ * Build a byte-stable GET/HEAD response with HTTP validators and RFC 9530 integrity metadata.
22
+ */
23
+ declare function createDocsCacheableResponse(options: DocsCacheableResponseOptions): Response;
24
+ //#endregion
25
+ export { DocsCacheableResponseOptions, createDocsCacheableResponse, formatDocsContentDigest, requestHasFreshDocsDate, requestMatchesDocsEtag, resolveDocsHttpDate };
@@ -0,0 +1,140 @@
1
+ import { sha256DocsContent } from "./retrieval-digest.mjs";
2
+
3
+ //#region src/http-cache.ts
4
+ const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5
+ const MAX_CACHED_TEXT_REPRESENTATIONS = 64;
6
+ const MAX_CACHED_TEXT_CHARACTERS = 8 * 1024 * 1024;
7
+ const textValidatorCache = /* @__PURE__ */ new Map();
8
+ let cachedTextCharacters = 0;
9
+ function encodeBase64(bytes) {
10
+ let encoded = "";
11
+ for (let offset = 0; offset < bytes.length; offset += 3) {
12
+ const first = bytes[offset];
13
+ const second = bytes[offset + 1];
14
+ const third = bytes[offset + 2];
15
+ const value = first << 16 | (second ?? 0) << 8 | (third ?? 0);
16
+ encoded += BASE64_ALPHABET[value >>> 18 & 63];
17
+ encoded += BASE64_ALPHABET[value >>> 12 & 63];
18
+ encoded += second === void 0 ? "=" : BASE64_ALPHABET[value >>> 6 & 63];
19
+ encoded += third === void 0 ? "=" : BASE64_ALPHABET[value & 63];
20
+ }
21
+ return encoded;
22
+ }
23
+ function sha256HexBytes(sha256) {
24
+ if (!/^[a-f\d]{64}$/iu.test(sha256)) throw new Error("A SHA-256 digest must contain exactly 64 hexadecimal characters.");
25
+ const bytes = new Uint8Array(32);
26
+ for (let index = 0; index < bytes.length; index += 1) bytes[index] = Number.parseInt(sha256.slice(index * 2, index * 2 + 2), 16);
27
+ return bytes;
28
+ }
29
+ /** Format an RFC 9530 Content-Digest field from a SHA-256 hex digest. */
30
+ function formatDocsContentDigest(sha256) {
31
+ return `sha-256=:${encodeBase64(sha256HexBytes(sha256))}:`;
32
+ }
33
+ function resolveDocsContentValidators(content, suppliedSha256) {
34
+ if (suppliedSha256) return {
35
+ sha256: suppliedSha256,
36
+ contentDigest: formatDocsContentDigest(suppliedSha256)
37
+ };
38
+ const cached = typeof content === "string" ? textValidatorCache.get(content) : void 0;
39
+ if (cached) {
40
+ if (typeof content === "string") {
41
+ textValidatorCache.delete(content);
42
+ textValidatorCache.set(content, cached);
43
+ }
44
+ return cached;
45
+ }
46
+ const sha256 = sha256DocsContent(content);
47
+ const validators = {
48
+ sha256,
49
+ contentDigest: formatDocsContentDigest(sha256)
50
+ };
51
+ if (typeof content !== "string") return validators;
52
+ if (content.length <= MAX_CACHED_TEXT_CHARACTERS) {
53
+ textValidatorCache.set(content, validators);
54
+ cachedTextCharacters += content.length;
55
+ while (textValidatorCache.size > MAX_CACHED_TEXT_REPRESENTATIONS || cachedTextCharacters > MAX_CACHED_TEXT_CHARACTERS) {
56
+ const oldest = textValidatorCache.keys().next().value;
57
+ if (oldest === void 0) break;
58
+ textValidatorCache.delete(oldest);
59
+ cachedTextCharacters -= oldest.length;
60
+ }
61
+ }
62
+ return validators;
63
+ }
64
+ /** Normalize an exact source timestamp for Last-Modified. */
65
+ function resolveDocsHttpDate(value) {
66
+ if (!value) return void 0;
67
+ if (typeof value === "string" && !/(?:T|\s)\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?/.test(value.trim())) return;
68
+ const date = value instanceof Date ? value : new Date(value);
69
+ if (Number.isNaN(date.getTime())) return void 0;
70
+ return date.toUTCString();
71
+ }
72
+ function normalizeEtag(value) {
73
+ return value.trim().replace(/^W\//iu, "");
74
+ }
75
+ /** Match strong or weak If-None-Match validators for a GET/HEAD representation. */
76
+ function requestMatchesDocsEtag(request, etag) {
77
+ const header = request.headers.get("if-none-match");
78
+ if (!header) return false;
79
+ if (header.trim() === "*") return true;
80
+ const expected = normalizeEtag(etag);
81
+ return header.split(",").some((candidate) => normalizeEtag(candidate) === expected);
82
+ }
83
+ /** Apply If-Modified-Since only when the stronger If-None-Match validator is absent. */
84
+ function requestHasFreshDocsDate(request, lastModified) {
85
+ const method = request.method.toUpperCase();
86
+ if (method !== "GET" && method !== "HEAD") return false;
87
+ if (!lastModified || request.headers.has("if-none-match")) return false;
88
+ const ifModifiedSince = request.headers.get("if-modified-since");
89
+ if (!ifModifiedSince) return false;
90
+ const resourceTime = Date.parse(lastModified);
91
+ const requestTime = Date.parse(ifModifiedSince);
92
+ return Number.isFinite(resourceTime) && Number.isFinite(requestTime) && Math.floor(resourceTime / 1e3) <= Math.floor(requestTime / 1e3);
93
+ }
94
+ function exposeValidatorHeaders(headers) {
95
+ if (!headers.has("Access-Control-Allow-Origin")) return;
96
+ const exposed = new Set((headers.get("Access-Control-Expose-Headers") ?? "").split(",").map((value) => value.trim()).filter(Boolean));
97
+ exposed.add("Content-Digest");
98
+ exposed.add("ETag");
99
+ if (headers.has("Last-Modified")) exposed.add("Last-Modified");
100
+ headers.set("Access-Control-Expose-Headers", [...exposed].join(", "));
101
+ }
102
+ /**
103
+ * Build a byte-stable GET/HEAD response with HTTP validators and RFC 9530 integrity metadata.
104
+ */
105
+ function createDocsCacheableResponse(options) {
106
+ const method = options.request.method.toUpperCase();
107
+ const isSafeRetrieval = method === "GET" || method === "HEAD";
108
+ const status = options.status ?? 200;
109
+ const canApplyConditionalRequest = status === 200;
110
+ const { sha256, contentDigest } = resolveDocsContentValidators(options.content, options.sha256);
111
+ const etag = `"${sha256}"`;
112
+ const lastModified = resolveDocsHttpDate(options.lastModified);
113
+ const headers = new Headers(options.headers);
114
+ headers.set("Content-Digest", contentDigest);
115
+ headers.set("ETag", etag);
116
+ if (lastModified) headers.set("Last-Modified", lastModified);
117
+ exposeValidatorHeaders(headers);
118
+ if (canApplyConditionalRequest && requestMatchesDocsEtag(options.request, etag)) {
119
+ headers.delete("Content-Type");
120
+ return new Response(null, {
121
+ status: isSafeRetrieval ? 304 : 412,
122
+ headers
123
+ });
124
+ }
125
+ if (canApplyConditionalRequest && isSafeRetrieval && requestHasFreshDocsDate(options.request, lastModified)) {
126
+ headers.delete("Content-Type");
127
+ return new Response(null, {
128
+ status: 304,
129
+ headers
130
+ });
131
+ }
132
+ const body = method === "HEAD" ? null : typeof options.content === "string" ? options.content : options.content;
133
+ return new Response(body, {
134
+ status,
135
+ headers
136
+ });
137
+ }
138
+
139
+ //#endregion
140
+ export { createDocsCacheableResponse, formatDocsContentDigest, requestHasFreshDocsDate, requestMatchesDocsEtag, resolveDocsHttpDate };
@@ -0,0 +1,81 @@
1
+ //#region src/http-link.ts
2
+ /** Split an HTTP list without treating delimiters inside quotes or URI references as separators. */
3
+ function splitHttpList(value, delimiter) {
4
+ const parts = [];
5
+ let start = 0;
6
+ let quoted = false;
7
+ let escaped = false;
8
+ let angleDepth = 0;
9
+ for (let index = 0; index < value.length; index += 1) {
10
+ const character = value[index];
11
+ if (escaped) {
12
+ escaped = false;
13
+ continue;
14
+ }
15
+ if (quoted && character === "\\") {
16
+ escaped = true;
17
+ continue;
18
+ }
19
+ if (character === "\"") {
20
+ quoted = !quoted;
21
+ continue;
22
+ }
23
+ if (!quoted && character === "<") angleDepth += 1;
24
+ if (!quoted && character === ">" && angleDepth > 0) angleDepth -= 1;
25
+ if (!quoted && angleDepth === 0 && character === delimiter) {
26
+ parts.push(value.slice(start, index).trim());
27
+ start = index + 1;
28
+ }
29
+ }
30
+ parts.push(value.slice(start).trim());
31
+ return parts.filter(Boolean);
32
+ }
33
+ function unquoteHttpValue(value) {
34
+ const trimmed = value.trim();
35
+ if (!trimmed.startsWith("\"") || !trimmed.endsWith("\"")) return trimmed;
36
+ return trimmed.slice(1, -1).replace(/\\(.)/g, "$1");
37
+ }
38
+ /** Parse Link header values while preserving the target/relation association. */
39
+ function parseHttpLinkHeader(header) {
40
+ if (!header) return [];
41
+ const links = [];
42
+ for (const value of splitHttpList(header, ",")) {
43
+ const target = value.match(/^\s*<([^>]*)>/);
44
+ if (!target) continue;
45
+ const relations = [];
46
+ for (const rawParameter of splitHttpList(value.slice(target[0].length), ";")) {
47
+ const separator = rawParameter.indexOf("=");
48
+ if (separator < 0 || rawParameter.slice(0, separator).trim().toLowerCase() !== "rel") continue;
49
+ relations.push(...unquoteHttpValue(rawParameter.slice(separator + 1)).toLowerCase().split(/\s+/));
50
+ }
51
+ links.push({
52
+ href: target[1],
53
+ relations: relations.filter(Boolean)
54
+ });
55
+ }
56
+ return links;
57
+ }
58
+ function httpLinkMatchesExpectation(links, expectation, responseUrl) {
59
+ let expectedUrl;
60
+ try {
61
+ expectedUrl = new URL(expectation.href, responseUrl).toString();
62
+ } catch {
63
+ return false;
64
+ }
65
+ return links.some((link) => {
66
+ try {
67
+ return new URL(link.href, responseUrl).toString() === expectedUrl && link.relations.includes(expectation.rel.toLowerCase());
68
+ } catch {
69
+ return false;
70
+ }
71
+ });
72
+ }
73
+ function httpLinkHeaderHasTargetRelation(header, href, rel, responseUrl) {
74
+ return httpLinkMatchesExpectation(parseHttpLinkHeader(header), {
75
+ href,
76
+ rel
77
+ }, responseUrl);
78
+ }
79
+
80
+ //#endregion
81
+ export { httpLinkHeaderHasTargetRelation, httpLinkMatchesExpectation, parseHttpLinkHeader, splitHttpList, unquoteHttpValue };
@@ -0,0 +1,18 @@
1
+ import { DocsI18nConfig } from "./types.mjs";
2
+
3
+ //#region src/i18n.d.ts
4
+ interface ResolvedDocsI18n {
5
+ locales: string[];
6
+ defaultLocale: string;
7
+ }
8
+ interface DocsPathMatch {
9
+ /** Slug path relative to the docs root (no leading slash). */
10
+ slug: string;
11
+ /** Entry path used for URLs (no locale segment). */
12
+ entryPath: string;
13
+ }
14
+ declare function resolveDocsI18n(config?: DocsI18nConfig | null): ResolvedDocsI18n | null;
15
+ declare function resolveDocsLocale(searchParams: URLSearchParams, i18n?: ResolvedDocsI18n | null): string | undefined;
16
+ declare function resolveDocsPath(pathname: string, entry: string): DocsPathMatch;
17
+ //#endregion
18
+ export { DocsPathMatch, ResolvedDocsI18n, resolveDocsI18n, resolveDocsLocale, resolveDocsPath };
@@ -37,4 +37,4 @@ function resolveDocsPath(pathname, entry) {
37
37
  }
38
38
 
39
39
  //#endregion
40
- export { resolveDocsLocale as n, resolveDocsPath as r, resolveDocsI18n as t };
40
+ export { resolveDocsI18n, resolveDocsLocale, resolveDocsPath };