@publish.os/nextjs 0.0.1-alpha.6 → 0.0.1-alpha.7
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 +3 -5
- package/compiler-assets/nextjs/defaults/app/globals.css +6 -0
- package/compiler-assets/nextjs/defaults/group/layout.tsx +23 -0
- package/compiler-assets/nextjs/defaults/group/leaf.tsx +48 -0
- package/compiler-assets/nextjs/defaults/group/page.tsx +50 -0
- package/compiler-assets/nextjs/defaults/project/next.config.mjs +45 -0
- package/compiler-assets/nextjs/defaults/project/postcss.config.mjs +5 -0
- package/compiler-assets/nextjs/defaults/project/tsconfig.json.template +41 -0
- package/compiler-assets/nextjs/defaults/root/css/animation.css +90 -0
- package/compiler-assets/nextjs/defaults/root/css/components/dialog.css +21 -0
- package/compiler-assets/nextjs/defaults/root/css/components/drawer.css +21 -0
- package/compiler-assets/nextjs/defaults/root/css/components/menu.css +23 -0
- package/compiler-assets/nextjs/defaults/root/css/components/navigation-menu.css +25 -0
- package/compiler-assets/nextjs/defaults/root/css/components/popover.css +17 -0
- package/compiler-assets/nextjs/defaults/root/css/components/select.css +23 -0
- package/compiler-assets/nextjs/defaults/root/css/components/toast.css +19 -0
- package/compiler-assets/nextjs/defaults/root/css/components/tooltip.css +15 -0
- package/compiler-assets/nextjs/defaults/root/css/layout.css +22 -0
- package/compiler-assets/nextjs/defaults/root/css/media.css +81 -0
- package/compiler-assets/nextjs/defaults/root/css/radius.css +49 -0
- package/compiler-assets/nextjs/defaults/root/css/scrollbar.css +43 -0
- package/compiler-assets/nextjs/defaults/root/css/shadow.css +145 -0
- package/compiler-assets/nextjs/defaults/root/css/typography.css +607 -0
- package/compiler-assets/nextjs/defaults/root/css/zindex.css +39 -0
- package/compiler-assets/nextjs/defaults/root/globals.css +191 -0
- package/compiler-assets/nextjs/defaults/root/layout.tsx +19 -0
- package/compiler-assets/nextjs/defaults/root/page.tsx +61 -0
- package/compiler-assets/nextjs/defaults/root/theme.css +50 -0
- package/compiler-assets/nextjs/defaults/source/_internal/logger.ts +21 -0
- package/compiler-assets/nextjs/shims/generated-group-layout.tsx +19 -0
- package/compiler-assets/nextjs/shims/generated-group-page.tsx +18 -0
- package/compiler-assets/nextjs/shims/generated-leaf-page.tsx +21 -0
- package/compiler-assets/nextjs/shims/global-layout.tsx +134 -0
- package/compiler-assets/nextjs/shims/markdown-route.ts +29 -0
- package/compiler-assets/nextjs/shims/og-image-route.ts +18 -0
- package/compiler-assets/nextjs/shims/powered-by-footer.tsx +40 -0
- package/compiler-assets/nextjs/shims/providers.tsx +13 -0
- package/compiler-assets/nextjs/shims/proxy.ts +317 -0
- package/compiler-assets/nextjs/shims/publish-os-theme-provider.tsx +77 -0
- package/compiler-assets/nextjs/shims/root-page.tsx +13 -0
- package/compiler-assets/nextjs/shims/theme-defaults.css +177 -0
- package/dist/button-CFdx-ohV.d.ts +20 -0
- package/dist/cache/tags.js +6 -14
- package/dist/compiler.d.ts +100 -0
- package/dist/compiler.js +13379 -0
- package/dist/config/createNextConfig.d.ts +2 -1
- package/dist/config/createNextConfig.js +16 -12
- package/dist/icons.d.ts +1 -0
- package/dist/icons.js +2 -0
- package/dist/index.d.ts +303 -15
- package/dist/index.js +30 -1198
- package/dist/kernel/components/blocks/AgentActions.d.ts +9 -3
- package/dist/kernel/components/blocks/AgentActions.js +114 -200
- package/dist/kernel/components/blocks/animated-icon-swap.js +4 -25
- package/dist/kernel/components/blocks/color-palette.js +88 -169
- package/dist/kernel/components/blocks/design-system-preview.d.ts +38 -6
- package/dist/kernel/components/blocks/design-system-preview.js +44 -52
- package/dist/kernel/components/blocks/link-playground.js +23 -71
- package/dist/kernel/components/blocks/logo-block.js +18 -47
- package/dist/kernel/components/blocks/nav-breadcrumb.d.ts +1 -1
- package/dist/kernel/components/blocks/nav-breadcrumb.js +28 -42
- package/dist/kernel/components/blocks/navbar.d.ts +1 -1
- package/dist/kernel/components/blocks/navbar.js +14 -41
- package/dist/kernel/components/blocks/navigation-progress-playground.js +56 -149
- package/dist/kernel/components/blocks/navigation-progress.js +53 -157
- package/dist/kernel/components/blocks/next-prev.d.ts +1 -1
- package/dist/kernel/components/blocks/next-prev.js +16 -42
- package/dist/kernel/components/blocks/page-list.d.ts +1 -1
- package/dist/kernel/components/blocks/page-list.js +11 -16
- package/dist/kernel/components/blocks/search.d.ts +13 -2
- package/dist/kernel/components/blocks/search.js +116 -247
- package/dist/kernel/components/blocks/sidebar-node.d.ts +2 -2
- package/dist/kernel/components/blocks/sidebar-node.js +56 -95
- package/dist/kernel/components/blocks/sidebar.d.ts +5 -23
- package/dist/kernel/components/blocks/sidebar.js +35 -103
- package/dist/kernel/components/blocks/theme-toggle.d.ts +7 -3
- package/dist/kernel/components/blocks/theme-toggle.js +2 -2
- package/dist/kernel/components/blocks/toc.js +42 -178
- package/dist/kernel/components/mdx/components/blockquote.js +3 -24
- package/dist/kernel/components/mdx/components/callout.d.ts +1 -1
- package/dist/kernel/components/mdx/components/callout.js +15 -47
- package/dist/kernel/components/mdx/components/code-block.js +2 -2
- package/dist/kernel/components/mdx/components/figure-caption.js +6 -24
- package/dist/kernel/components/mdx/components/figure.js +9 -36
- package/dist/kernel/components/mdx/components/footnotes.js +3 -24
- package/dist/kernel/components/mdx/components/heading-copy-link.js +13 -37
- package/dist/kernel/components/mdx/components/heading.d.ts +8 -3
- package/dist/kernel/components/mdx/components/heading.js +32 -116
- package/dist/kernel/components/mdx/components/hr.d.ts +5 -3
- package/dist/kernel/components/mdx/components/hr.js +2 -2
- package/dist/kernel/components/mdx/components/image-zoom.js +2 -3
- package/dist/kernel/components/mdx/components/image.js +22 -62
- package/dist/kernel/components/mdx/components/inline-code.js +3 -24
- package/dist/kernel/components/mdx/components/kbd.d.ts +9 -4
- package/dist/kernel/components/mdx/components/kbd.js +2 -2
- package/dist/kernel/components/mdx/components/link.d.ts +1 -2
- package/dist/kernel/components/mdx/components/link.js +2 -2
- package/dist/kernel/components/mdx/components/paragraph.js +13 -41
- package/dist/kernel/components/mdx/components/pre.js +3 -24
- package/dist/kernel/components/mdx/components/strikethrough.js +6 -24
- package/dist/kernel/components/mdx/components/table.js +2 -2
- package/dist/kernel/components/mdx/components/task-list.js +6 -28
- package/dist/kernel/components/mdx/components/video-player.js +53 -88
- package/dist/kernel/components/mdx/components/video.js +27 -75
- package/dist/kernel/components/mdx/error-boundary.d.ts +1 -1
- package/dist/kernel/components/mdx/error-boundary.js +12 -15
- package/dist/kernel/components/mdx/error-fallback.js +4 -4
- package/dist/kernel/components/mdx/mdx.d.ts +68 -11
- package/dist/kernel/components/mdx/mdx.js +29 -29
- package/dist/kernel/components/mdx/rehype-heading-ids.js +11 -67
- package/dist/kernel/components/mdx/types.d.ts +1 -1
- package/dist/kernel/components/ui/accordion.js +3 -26
- package/dist/kernel/components/ui/breadcrumb-trail.d.ts +23 -7
- package/dist/kernel/components/ui/breadcrumb-trail.js +32 -80
- package/dist/kernel/components/ui/breadcrumb.d.ts +1 -1
- package/dist/kernel/components/ui/breadcrumb.js +20 -54
- package/dist/kernel/components/ui/button-group.d.ts +4 -3
- package/dist/kernel/components/ui/button-group.js +7 -30
- package/dist/kernel/components/ui/button.js +13 -36
- package/dist/kernel/components/ui/card.d.ts +2 -2
- package/dist/kernel/components/ui/card.js +2 -23
- package/dist/kernel/components/ui/dialog.d.ts +9 -9
- package/dist/kernel/components/ui/dialog.js +15 -33
- package/dist/kernel/components/ui/drawer.d.ts +10 -10
- package/dist/kernel/components/ui/drawer.js +15 -33
- package/dist/kernel/components/ui/input.js +6 -30
- package/dist/kernel/components/ui/kbd.js +10 -31
- package/dist/kernel/components/ui/link.d.ts +1 -1
- package/dist/kernel/components/ui/link.js +53 -104
- package/dist/kernel/components/ui/menu.d.ts +21 -21
- package/dist/kernel/components/ui/menu.js +10 -32
- package/dist/kernel/components/ui/meta-key.d.ts +9 -4
- package/dist/kernel/components/ui/meta-key.js +2 -2
- package/dist/kernel/components/ui/navigation-menu.d.ts +14 -14
- package/dist/kernel/components/ui/navigation-menu.js +9 -30
- package/dist/kernel/components/ui/popover.d.ts +10 -10
- package/dist/kernel/components/ui/popover.js +19 -34
- package/dist/kernel/components/ui/progress.js +2 -25
- package/dist/kernel/components/ui/scroll-area.js +39 -118
- package/dist/kernel/components/ui/select.d.ts +15 -15
- package/dist/kernel/components/ui/select.js +19 -35
- package/dist/kernel/components/ui/separator.js +2 -25
- package/dist/kernel/components/ui/table.js +2 -23
- package/dist/kernel/components/ui/tabs.js +39 -99
- package/dist/kernel/components/ui/tag.d.ts +2 -2
- package/dist/kernel/components/ui/tag.js +4 -25
- package/dist/kernel/components/ui/text.d.ts +2 -2
- package/dist/kernel/components/ui/text.js +3 -25
- package/dist/kernel/components/ui/theme-toggle.d.ts +18 -4
- package/dist/kernel/components/ui/theme-toggle.js +18 -44
- package/dist/kernel/components/ui/toast.d.ts +10 -10
- package/dist/kernel/components/ui/toast.js +13 -35
- package/dist/kernel/components/ui/tooltip.d.ts +8 -8
- package/dist/kernel/components/ui/tooltip.js +8 -29
- package/dist/kernel/defaults.registry.d.ts +1 -1
- package/dist/kernel/defaults.registry.js +2 -2
- package/dist/kernel/framework-icons.d.ts +1 -0
- package/dist/kernel/framework-icons.js +39 -0
- package/dist/kernel/routes/agent/markdown.js +36 -65
- package/dist/kernel/routes/layouts/group.d.ts +1 -1
- package/dist/kernel/routes/layouts/group.js +20 -109
- package/dist/kernel/routes/metadata/feed.d.ts +1 -2
- package/dist/kernel/routes/metadata/feed.js +46 -127
- package/dist/kernel/routes/metadata/llms.d.ts +1 -2
- package/dist/kernel/routes/metadata/llms.js +40 -120
- package/dist/kernel/routes/metadata/og-image.d.ts +10 -0
- package/dist/kernel/routes/metadata/og-image.js +264 -198
- package/dist/kernel/routes/metadata/robots.d.ts +1 -2
- package/dist/kernel/routes/metadata/robots.js +21 -90
- package/dist/kernel/routes/metadata/sitemap.d.ts +1 -2
- package/dist/kernel/routes/metadata/sitemap.js +36 -102
- package/dist/kernel/routes/pages/group.d.ts +1 -1
- package/dist/kernel/routes/pages/group.js +42 -137
- package/dist/kernel/routes/pages/leaf.d.ts +1 -1
- package/dist/kernel/routes/pages/leaf.js +74 -213
- package/dist/kernel/routes/pages/root.d.ts +1 -1
- package/dist/kernel/routes/pages/root.js +37 -108
- package/dist/keyboard-shortcuts.js +69 -141
- package/dist/link-CYaCRDb6.d.ts +35 -0
- package/dist/resolvers/manifest-resolver.d.ts +3 -3
- package/dist/resolvers/manifest-resolver.js +15 -21
- package/dist/route-metadata-og-image-BeKKFHg7.d.ts +58 -0
- package/dist/search.d.ts +81 -4
- package/dist/search.js +124 -195
- package/dist/sidebar-types-Bgchdfd6.d.ts +25 -0
- package/dist/theme-scope.d.ts +15 -0
- package/dist/theme-scope.js +23 -0
- package/dist/types-B_b3C0U6.d.ts +63 -0
- package/dist/types-CIwwieNw.d.ts +127 -0
- package/dist/types-DHBm7-j6.d.ts +57 -0
- package/dist/types-sM2g9nW0.d.ts +12 -0
- package/dist/types.d.ts +0 -1
- package/dist/types.js +1 -1
- package/dist/utils/cn.d.ts +5 -9
- package/dist/utils/cn.js +13 -7
- package/dist/utils/heading-ids.js +20 -47
- package/dist/utils/pretty-date.js +7 -13
- package/init/seed/minimal/publish.os/assets/logo/publish-dev-logo.dark.png +0 -0
- package/init/seed/minimal/publish.os/assets/logo/publish-dev-logo.png +0 -0
- package/init/seed/minimal/publish.os/docs/content/get-started.mdx +54 -0
- package/init/seed/minimal/publish.os/docs/content/groups.mdx +31 -0
- package/init/seed/minimal/publish.os/docs/content/theme.mdx +64 -0
- package/init/seed/minimal/publish.os/publish.os.config.json +21 -0
- package/init/seed/minimal/publish.os/theme.css +47 -0
- package/init/seed/minimal/seed.json +13 -0
- package/package.json +469 -35
- package/release/{package.json → app/lucide/package.json} +11 -5
- package/release/app/lucide/pnpm-lock.yaml.template +2905 -0
- package/release/app/lucide/pnpm-workspace.yaml +11 -0
- package/release/app/phosphor/package.json +30 -0
- package/release/app/phosphor/pnpm-lock.yaml.template +2908 -0
- package/release/app/phosphor/pnpm-workspace.yaml +11 -0
- package/release/app/tabler/package.json +30 -0
- package/release/app/tabler/pnpm-lock.yaml.template +2911 -0
- package/release/app/tabler/pnpm-workspace.yaml +11 -0
- package/release/compiler/package.json +20 -0
- package/release/compiler/pnpm-lock.yaml.template +2432 -0
- package/release/compiler/pnpm-workspace.yaml +11 -0
- package/release/release.json +29 -5
- package/release/runtime-pnpm-lock.yaml +0 -1316
|
@@ -1,148 +1,74 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/route-metadata-feed.ts
|
|
2
|
+
import { tags } from "@publish.os/nextjs/cache/tags";
|
|
2
3
|
import { cacheLife, cacheTag } from "next/cache";
|
|
3
4
|
|
|
4
|
-
// src/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
function safeSegment(value) {
|
|
13
|
-
const raw = value.trim().toLowerCase() || "root";
|
|
14
|
-
const normalized = raw.replace(/\\/g, "/").replace(/\/+/g, "/").replace(/^\//, "").replace(/\/$/, "").replace(/[^a-z0-9:_./-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
15
|
-
const segment = normalized || "root";
|
|
16
|
-
if (segment.length <= MAX_SEGMENT_LEN) return segment;
|
|
17
|
-
return `${segment.slice(0, 48)}.${sha256(segment)}`;
|
|
18
|
-
}
|
|
19
|
-
function assertTag(tag) {
|
|
20
|
-
if (tag.length > MAX_TAG_LEN || !TAG_PATTERN.test(tag)) {
|
|
21
|
-
return `tag:${sha256(tag)}`;
|
|
5
|
+
// src/lib/runtime/metadata/canonical-url.ts
|
|
6
|
+
function canonicalUrl(manifest, path) {
|
|
7
|
+
let origin = manifest.site.url?.replace(/\/+$/, "");
|
|
8
|
+
if (!origin) return path;
|
|
9
|
+
try {
|
|
10
|
+
return new URL(path, `${origin}/`).toString();
|
|
11
|
+
} catch {
|
|
12
|
+
return path;
|
|
22
13
|
}
|
|
23
|
-
return tag;
|
|
24
14
|
}
|
|
25
|
-
var tags = {
|
|
26
|
-
site() {
|
|
27
|
-
return "site";
|
|
28
|
-
},
|
|
29
|
-
pages() {
|
|
30
|
-
return "pages";
|
|
31
|
-
},
|
|
32
|
-
group(group) {
|
|
33
|
-
return assertTag(`group:${safeSegment(group)}`);
|
|
34
|
-
},
|
|
35
|
-
page(group, slug) {
|
|
36
|
-
const path = Array.isArray(slug) ? slug.join("/") : slug;
|
|
37
|
-
return assertTag(`page:${safeSegment(group)}:${safeSegment(path)}`);
|
|
38
|
-
},
|
|
39
|
-
manifest(contentHash) {
|
|
40
|
-
return assertTag(`manifest:${safeSegment(contentHash)}`);
|
|
41
|
-
},
|
|
42
|
-
sitemap() {
|
|
43
|
-
return "sitemap";
|
|
44
|
-
},
|
|
45
|
-
robots() {
|
|
46
|
-
return "robots";
|
|
47
|
-
},
|
|
48
|
-
llms(scope = "root") {
|
|
49
|
-
return assertTag(`llms:${safeSegment(scope)}`);
|
|
50
|
-
},
|
|
51
|
-
feed(format, scope = "site") {
|
|
52
|
-
return assertTag(`feed:${safeSegment(format)}:${safeSegment(scope)}`);
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
15
|
|
|
56
|
-
// src/
|
|
57
|
-
var CACHE_CONTROL = "public, max-age=300, s-maxage=3600, stale-while-revalidate=3600, must-revalidate";
|
|
58
|
-
var CDN_CACHE_CONTROL = "public, max-age=3600, stale-while-revalidate=3600, must-revalidate";
|
|
59
|
-
var SHORT_CACHE_CONTROL = "public, max-age=60, s-maxage=600, stale-while-revalidate=300, must-revalidate";
|
|
60
|
-
var SHORT_CDN_CACHE_CONTROL = "public, max-age=300, stale-while-revalidate=3600";
|
|
16
|
+
// src/lib/runtime/response/cached-text-response.ts
|
|
17
|
+
var CACHE_CONTROL = "public, max-age=300, s-maxage=3600, stale-while-revalidate=3600, must-revalidate", CDN_CACHE_CONTROL = "public, max-age=3600, stale-while-revalidate=3600, must-revalidate", SHORT_CACHE_CONTROL = "public, max-age=60, s-maxage=600, stale-while-revalidate=300, must-revalidate", SHORT_CDN_CACHE_CONTROL = "public, max-age=300, stale-while-revalidate=3600";
|
|
61
18
|
function cacheControl(policy) {
|
|
62
|
-
|
|
63
|
-
if (policy === "short") return SHORT_CACHE_CONTROL;
|
|
64
|
-
return policy;
|
|
19
|
+
return !policy || policy === "default" ? CACHE_CONTROL : policy === "short" ? SHORT_CACHE_CONTROL : policy;
|
|
65
20
|
}
|
|
66
21
|
function cdnCacheControl(policy) {
|
|
67
|
-
|
|
68
|
-
if (policy === "short") return SHORT_CDN_CACHE_CONTROL;
|
|
69
|
-
return policy;
|
|
22
|
+
return !policy || policy === "default" ? CDN_CACHE_CONTROL : policy === "short" ? SHORT_CDN_CACHE_CONTROL : policy;
|
|
70
23
|
}
|
|
71
24
|
function cachedTextHeaders(contentType, options = {}) {
|
|
72
|
-
|
|
73
|
-
headers.set("cache-control", cacheControl(options.cachePolicy));
|
|
74
|
-
headers.set("cdn-cache-control", cdnCacheControl(options.cachePolicy));
|
|
75
|
-
headers.set("vercel-cdn-cache-control", cdnCacheControl(options.cachePolicy));
|
|
76
|
-
headers.set("content-type", contentType);
|
|
77
|
-
headers.set("x-content-type-options", "nosniff");
|
|
78
|
-
if (options.noindex) headers.set("x-robots-tag", "noindex");
|
|
79
|
-
return headers;
|
|
25
|
+
let headers = new Headers(options.headers);
|
|
26
|
+
return headers.set("cache-control", cacheControl(options.cachePolicy)), headers.set("cdn-cache-control", cdnCacheControl(options.cachePolicy)), headers.set("vercel-cdn-cache-control", cdnCacheControl(options.cachePolicy)), headers.set("content-type", contentType), headers.set("x-content-type-options", "nosniff"), options.noindex && headers.set("x-robots-tag", "noindex"), headers;
|
|
80
27
|
}
|
|
81
28
|
function createCachedTextResponse(options) {
|
|
82
|
-
|
|
83
|
-
const method = options.method ?? "GET";
|
|
84
|
-
const headers = cachedTextHeaders(options.contentType, options);
|
|
29
|
+
let status = options.status ?? 200, method = options.method ?? "GET", headers = cachedTextHeaders(options.contentType, options);
|
|
85
30
|
return new Response(method === "HEAD" ? null : options.body, {
|
|
86
31
|
headers,
|
|
87
32
|
status
|
|
88
33
|
});
|
|
89
34
|
}
|
|
90
35
|
|
|
91
|
-
// src/
|
|
92
|
-
function canonicalUrl(manifest, path) {
|
|
93
|
-
const origin = manifest.site.url?.replace(/\/+$/, "");
|
|
94
|
-
if (!origin) return path;
|
|
95
|
-
try {
|
|
96
|
-
return new URL(path, `${origin}/`).toString();
|
|
97
|
-
} catch {
|
|
98
|
-
return path;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// src/kernel/routes/metadata/feed.ts
|
|
36
|
+
// src/route-metadata-feed.ts
|
|
103
37
|
function xmlEscape(value) {
|
|
104
38
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
105
39
|
}
|
|
106
40
|
function pageTimestamp(page) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
41
|
+
let value = pageDate(page);
|
|
42
|
+
return value ? Date.parse(value) : -1 / 0;
|
|
43
|
+
}
|
|
44
|
+
function validDate(value) {
|
|
45
|
+
return value && !Number.isNaN(Date.parse(value)) ? value : void 0;
|
|
111
46
|
}
|
|
112
47
|
function pageInScope(page, options) {
|
|
113
|
-
|
|
114
|
-
if (options.scope === "self") return page.group === options.group;
|
|
115
|
-
return page.group === options.group || page.group.startsWith(`${options.group}/`);
|
|
48
|
+
return options.scope === "site" || !options.group ? !0 : options.scope === "self" ? page.group === options.group : page.group === options.group || page.group.startsWith(`${options.group}/`);
|
|
116
49
|
}
|
|
117
50
|
function feedPages(manifest, options) {
|
|
118
|
-
|
|
119
|
-
const pages = manifest.pages.filter((page) => statuses.includes(page.status)).filter((page) => pageInScope(page, options)).sort((a, b) => pageTimestamp(b) - pageTimestamp(a));
|
|
51
|
+
let statuses = options.status ?? ["published"], pages = manifest.pages.filter((page) => statuses.includes(page.status)).filter((page) => pageInScope(page, options)).sort((a, b) => pageTimestamp(b) - pageTimestamp(a));
|
|
120
52
|
return options.limit ? pages.slice(0, options.limit) : pages;
|
|
121
53
|
}
|
|
122
54
|
async function rssXml(manifest, options = {}) {
|
|
123
55
|
"use cache";
|
|
124
|
-
cacheLife("page")
|
|
125
|
-
cacheTag(
|
|
56
|
+
cacheLife("page"), cacheTag(
|
|
126
57
|
tags.site(),
|
|
127
58
|
tags.feed("rss", options.group ?? options.scope ?? "site"),
|
|
128
59
|
tags.manifest(manifest.contentHash)
|
|
129
60
|
);
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const homeUrl = canonicalUrl(manifest, "/");
|
|
134
|
-
const items = pages.map((page) => {
|
|
135
|
-
const pageUrl = canonicalUrl(manifest, page.path);
|
|
136
|
-
const pubDate = page.publishedAt ? `
|
|
137
|
-
<pubDate>${xmlEscape(new Date(page.publishedAt).toUTCString())}</pubDate>` : "";
|
|
138
|
-
const description2 = page.description ? `
|
|
61
|
+
let title = manifest.site.name, description = manifest.site.description ?? title, pages = feedPages(manifest, options), homeUrl = canonicalUrl(manifest, "/"), items = pages.map((page) => {
|
|
62
|
+
let pageUrl = canonicalUrl(manifest, page.path), publishedAt = validDate(page.publishedAt), pubDate = publishedAt ? `
|
|
63
|
+
<pubDate>${xmlEscape(new Date(publishedAt).toUTCString())}</pubDate>` : "", description2 = page.description ? `
|
|
139
64
|
<description>${xmlEscape(page.description)}</description>` : "";
|
|
140
65
|
return ` <item>
|
|
141
66
|
<title>${xmlEscape(page.title)}</title>
|
|
142
67
|
<link>${xmlEscape(pageUrl)}</link>
|
|
143
68
|
<guid>${xmlEscape(pageUrl)}</guid>${pubDate}${description2}
|
|
144
69
|
</item>`;
|
|
145
|
-
}).join(
|
|
70
|
+
}).join(`
|
|
71
|
+
`);
|
|
146
72
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
147
73
|
<rss version="2.0">
|
|
148
74
|
<channel>
|
|
@@ -155,28 +81,21 @@ ${items}
|
|
|
155
81
|
`;
|
|
156
82
|
}
|
|
157
83
|
function pageDate(page) {
|
|
158
|
-
return page.publishedAt ?? page.updatedAt;
|
|
84
|
+
return validDate(page.publishedAt) ?? validDate(page.updatedAt);
|
|
159
85
|
}
|
|
160
86
|
function latestFeedDate(pages) {
|
|
161
|
-
|
|
87
|
+
let timestamp = Math.max(0, ...pages.map((page) => pageTimestamp(page)));
|
|
162
88
|
return new Date(timestamp).toISOString();
|
|
163
89
|
}
|
|
164
90
|
async function atomXml(manifest, options = {}) {
|
|
165
91
|
"use cache";
|
|
166
|
-
cacheLife("page")
|
|
167
|
-
cacheTag(
|
|
92
|
+
cacheLife("page"), cacheTag(
|
|
168
93
|
tags.site(),
|
|
169
94
|
tags.feed("atom", options.group ?? options.scope ?? "site"),
|
|
170
95
|
tags.manifest(manifest.contentHash)
|
|
171
96
|
);
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const homeUrl = canonicalUrl(manifest, "/");
|
|
175
|
-
const entries = pages.map((page) => {
|
|
176
|
-
const date = pageDate(page);
|
|
177
|
-
const updated = date ? new Date(date).toISOString() : latestFeedDate([]);
|
|
178
|
-
const pageUrl = canonicalUrl(manifest, page.path);
|
|
179
|
-
const summary = page.description ? `
|
|
97
|
+
let title = manifest.site.name, pages = feedPages(manifest, options), homeUrl = canonicalUrl(manifest, "/"), entries = pages.map((page) => {
|
|
98
|
+
let date = pageDate(page), updated = date ? new Date(date).toISOString() : latestFeedDate([]), pageUrl = canonicalUrl(manifest, page.path), summary = page.description ? `
|
|
180
99
|
<summary>${xmlEscape(page.description)}</summary>` : "";
|
|
181
100
|
return ` <entry>
|
|
182
101
|
<title>${xmlEscape(page.title)}</title>
|
|
@@ -184,7 +103,8 @@ async function atomXml(manifest, options = {}) {
|
|
|
184
103
|
<link href="${xmlEscape(pageUrl)}" />
|
|
185
104
|
<updated>${xmlEscape(updated)}</updated>${summary}
|
|
186
105
|
</entry>`;
|
|
187
|
-
}).join(
|
|
106
|
+
}).join(`
|
|
107
|
+
`);
|
|
188
108
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
189
109
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
|
190
110
|
<title>${xmlEscape(title)}</title>
|
|
@@ -196,13 +116,12 @@ ${entries}
|
|
|
196
116
|
}
|
|
197
117
|
async function jsonFeed(manifest, options = {}) {
|
|
198
118
|
"use cache";
|
|
199
|
-
cacheLife("page")
|
|
200
|
-
cacheTag(
|
|
119
|
+
cacheLife("page"), cacheTag(
|
|
201
120
|
tags.site(),
|
|
202
121
|
tags.feed("json", options.group ?? options.scope ?? "site"),
|
|
203
122
|
tags.manifest(manifest.contentHash)
|
|
204
123
|
);
|
|
205
|
-
|
|
124
|
+
let pages = feedPages(manifest, options);
|
|
206
125
|
return `${JSON.stringify(
|
|
207
126
|
{
|
|
208
127
|
version: "https://jsonfeed.org/version/1.1",
|
|
@@ -215,8 +134,8 @@ async function jsonFeed(manifest, options = {}) {
|
|
|
215
134
|
title: page.title,
|
|
216
135
|
summary: page.description,
|
|
217
136
|
content_text: page.body,
|
|
218
|
-
date_published: page.publishedAt,
|
|
219
|
-
date_modified: page.updatedAt,
|
|
137
|
+
date_published: validDate(page.publishedAt),
|
|
138
|
+
date_modified: validDate(page.updatedAt),
|
|
220
139
|
tags: page.tags
|
|
221
140
|
}))
|
|
222
141
|
},
|
|
@@ -226,7 +145,7 @@ async function jsonFeed(manifest, options = {}) {
|
|
|
226
145
|
`;
|
|
227
146
|
}
|
|
228
147
|
function createRssFeedRoute(manifest, options = {}) {
|
|
229
|
-
return async function
|
|
148
|
+
return async function() {
|
|
230
149
|
return createCachedTextResponse({
|
|
231
150
|
body: await rssXml(manifest, options),
|
|
232
151
|
contentType: "application/rss+xml; charset=utf-8"
|
|
@@ -234,7 +153,7 @@ function createRssFeedRoute(manifest, options = {}) {
|
|
|
234
153
|
};
|
|
235
154
|
}
|
|
236
155
|
function createAtomFeedRoute(manifest, options = {}) {
|
|
237
|
-
return async function
|
|
156
|
+
return async function() {
|
|
238
157
|
return createCachedTextResponse({
|
|
239
158
|
body: await atomXml(manifest, options),
|
|
240
159
|
contentType: "application/atom+xml; charset=utf-8"
|
|
@@ -242,7 +161,7 @@ function createAtomFeedRoute(manifest, options = {}) {
|
|
|
242
161
|
};
|
|
243
162
|
}
|
|
244
163
|
function createJsonFeedRoute(manifest, options = {}) {
|
|
245
|
-
return async function
|
|
164
|
+
return async function() {
|
|
246
165
|
return createCachedTextResponse({
|
|
247
166
|
body: await jsonFeed(manifest, options),
|
|
248
167
|
contentType: "application/feed+json; charset=utf-8"
|
|
@@ -250,7 +169,7 @@ function createJsonFeedRoute(manifest, options = {}) {
|
|
|
250
169
|
};
|
|
251
170
|
}
|
|
252
171
|
function createPrecomputedFeedRoute(output) {
|
|
253
|
-
return function
|
|
172
|
+
return function() {
|
|
254
173
|
return createCachedTextResponse({
|
|
255
174
|
body: output.body,
|
|
256
175
|
contentType: output.contentType
|
|
@@ -1,151 +1,79 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/route-metadata-llms.ts
|
|
2
|
+
import { tags } from "@publish.os/nextjs/cache/tags";
|
|
2
3
|
import { cacheLife, cacheTag } from "next/cache";
|
|
3
4
|
|
|
4
|
-
// src/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
function safeSegment(value) {
|
|
13
|
-
const raw = value.trim().toLowerCase() || "root";
|
|
14
|
-
const normalized = raw.replace(/\\/g, "/").replace(/\/+/g, "/").replace(/^\//, "").replace(/\/$/, "").replace(/[^a-z0-9:_./-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
15
|
-
const segment = normalized || "root";
|
|
16
|
-
if (segment.length <= MAX_SEGMENT_LEN) return segment;
|
|
17
|
-
return `${segment.slice(0, 48)}.${sha256(segment)}`;
|
|
18
|
-
}
|
|
19
|
-
function assertTag(tag) {
|
|
20
|
-
if (tag.length > MAX_TAG_LEN || !TAG_PATTERN.test(tag)) {
|
|
21
|
-
return `tag:${sha256(tag)}`;
|
|
5
|
+
// src/lib/runtime/metadata/canonical-url.ts
|
|
6
|
+
function canonicalUrl(manifest, path) {
|
|
7
|
+
let origin = manifest.site.url?.replace(/\/+$/, "");
|
|
8
|
+
if (!origin) return path;
|
|
9
|
+
try {
|
|
10
|
+
return new URL(path, `${origin}/`).toString();
|
|
11
|
+
} catch {
|
|
12
|
+
return path;
|
|
22
13
|
}
|
|
23
|
-
return tag;
|
|
24
14
|
}
|
|
25
|
-
var tags = {
|
|
26
|
-
site() {
|
|
27
|
-
return "site";
|
|
28
|
-
},
|
|
29
|
-
pages() {
|
|
30
|
-
return "pages";
|
|
31
|
-
},
|
|
32
|
-
group(group) {
|
|
33
|
-
return assertTag(`group:${safeSegment(group)}`);
|
|
34
|
-
},
|
|
35
|
-
page(group, slug) {
|
|
36
|
-
const path = Array.isArray(slug) ? slug.join("/") : slug;
|
|
37
|
-
return assertTag(`page:${safeSegment(group)}:${safeSegment(path)}`);
|
|
38
|
-
},
|
|
39
|
-
manifest(contentHash) {
|
|
40
|
-
return assertTag(`manifest:${safeSegment(contentHash)}`);
|
|
41
|
-
},
|
|
42
|
-
sitemap() {
|
|
43
|
-
return "sitemap";
|
|
44
|
-
},
|
|
45
|
-
robots() {
|
|
46
|
-
return "robots";
|
|
47
|
-
},
|
|
48
|
-
llms(scope = "root") {
|
|
49
|
-
return assertTag(`llms:${safeSegment(scope)}`);
|
|
50
|
-
},
|
|
51
|
-
feed(format, scope = "site") {
|
|
52
|
-
return assertTag(`feed:${safeSegment(format)}:${safeSegment(scope)}`);
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
15
|
|
|
56
|
-
// src/
|
|
57
|
-
var CACHE_CONTROL = "public, max-age=300, s-maxage=3600, stale-while-revalidate=3600, must-revalidate";
|
|
58
|
-
var CDN_CACHE_CONTROL = "public, max-age=3600, stale-while-revalidate=3600, must-revalidate";
|
|
59
|
-
var SHORT_CACHE_CONTROL = "public, max-age=60, s-maxage=600, stale-while-revalidate=300, must-revalidate";
|
|
60
|
-
var SHORT_CDN_CACHE_CONTROL = "public, max-age=300, stale-while-revalidate=3600";
|
|
16
|
+
// src/lib/runtime/response/cached-text-response.ts
|
|
17
|
+
var CACHE_CONTROL = "public, max-age=300, s-maxage=3600, stale-while-revalidate=3600, must-revalidate", CDN_CACHE_CONTROL = "public, max-age=3600, stale-while-revalidate=3600, must-revalidate", SHORT_CACHE_CONTROL = "public, max-age=60, s-maxage=600, stale-while-revalidate=300, must-revalidate", SHORT_CDN_CACHE_CONTROL = "public, max-age=300, stale-while-revalidate=3600";
|
|
61
18
|
function cacheControl(policy) {
|
|
62
|
-
|
|
63
|
-
if (policy === "short") return SHORT_CACHE_CONTROL;
|
|
64
|
-
return policy;
|
|
19
|
+
return !policy || policy === "default" ? CACHE_CONTROL : policy === "short" ? SHORT_CACHE_CONTROL : policy;
|
|
65
20
|
}
|
|
66
21
|
function cdnCacheControl(policy) {
|
|
67
|
-
|
|
68
|
-
if (policy === "short") return SHORT_CDN_CACHE_CONTROL;
|
|
69
|
-
return policy;
|
|
22
|
+
return !policy || policy === "default" ? CDN_CACHE_CONTROL : policy === "short" ? SHORT_CDN_CACHE_CONTROL : policy;
|
|
70
23
|
}
|
|
71
24
|
function cachedTextHeaders(contentType, options = {}) {
|
|
72
|
-
|
|
73
|
-
headers.set("cache-control", cacheControl(options.cachePolicy));
|
|
74
|
-
headers.set("cdn-cache-control", cdnCacheControl(options.cachePolicy));
|
|
75
|
-
headers.set("vercel-cdn-cache-control", cdnCacheControl(options.cachePolicy));
|
|
76
|
-
headers.set("content-type", contentType);
|
|
77
|
-
headers.set("x-content-type-options", "nosniff");
|
|
78
|
-
if (options.noindex) headers.set("x-robots-tag", "noindex");
|
|
79
|
-
return headers;
|
|
25
|
+
let headers = new Headers(options.headers);
|
|
26
|
+
return headers.set("cache-control", cacheControl(options.cachePolicy)), headers.set("cdn-cache-control", cdnCacheControl(options.cachePolicy)), headers.set("vercel-cdn-cache-control", cdnCacheControl(options.cachePolicy)), headers.set("content-type", contentType), headers.set("x-content-type-options", "nosniff"), options.noindex && headers.set("x-robots-tag", "noindex"), headers;
|
|
80
27
|
}
|
|
81
28
|
function createCachedTextResponse(options) {
|
|
82
|
-
|
|
83
|
-
const method = options.method ?? "GET";
|
|
84
|
-
const headers = cachedTextHeaders(options.contentType, options);
|
|
29
|
+
let status = options.status ?? 200, method = options.method ?? "GET", headers = cachedTextHeaders(options.contentType, options);
|
|
85
30
|
return new Response(method === "HEAD" ? null : options.body, {
|
|
86
31
|
headers,
|
|
87
32
|
status
|
|
88
33
|
});
|
|
89
34
|
}
|
|
90
35
|
|
|
91
|
-
// src/
|
|
92
|
-
|
|
93
|
-
const origin = manifest.site.url?.replace(/\/+$/, "");
|
|
94
|
-
if (!origin) return path;
|
|
95
|
-
try {
|
|
96
|
-
return new URL(path, `${origin}/`).toString();
|
|
97
|
-
} catch {
|
|
98
|
-
return path;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// src/kernel/routes/metadata/llms.ts
|
|
103
|
-
var DEFAULT_LLMS_FULL_MAX_BYTES = 1e6;
|
|
104
|
-
var TEXT_ENCODER = new TextEncoder();
|
|
36
|
+
// src/route-metadata-llms.ts
|
|
37
|
+
var DEFAULT_LLMS_FULL_MAX_BYTES = 1e6, TEXT_ENCODER = new TextEncoder();
|
|
105
38
|
function byteLength(value) {
|
|
106
39
|
return TEXT_ENCODER.encode(value).byteLength;
|
|
107
40
|
}
|
|
108
41
|
function pageInScope(page, options) {
|
|
109
|
-
|
|
110
|
-
if (options.scope === "self") return page.group === options.group;
|
|
111
|
-
return page.group === options.group || page.group.startsWith(`${options.group}/`);
|
|
42
|
+
return options.scope === "site" || !options.group ? !0 : options.scope === "self" ? page.group === options.group : page.group === options.group || page.group.startsWith(`${options.group}/`);
|
|
112
43
|
}
|
|
113
44
|
function llmsSummary(manifest) {
|
|
114
45
|
return manifest.site.description ? `> ${manifest.site.description}` : `> Agent-readable index for ${manifest.site.name}.`;
|
|
115
46
|
}
|
|
116
47
|
async function llmsTxt(manifest, options = {}) {
|
|
117
48
|
"use cache";
|
|
118
|
-
cacheLife("page")
|
|
119
|
-
cacheTag(
|
|
49
|
+
cacheLife("page"), cacheTag(
|
|
120
50
|
tags.site(),
|
|
121
51
|
tags.llms(options.group ?? options.scope ?? "root"),
|
|
122
52
|
tags.manifest(manifest.contentHash)
|
|
123
53
|
);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const lines = visiblePages.map((page) => {
|
|
127
|
-
const description = options.includeDescriptions && page.description ? ` - ${page.description}` : "";
|
|
54
|
+
let pages = manifest.pages.filter((page) => page.status === "published").filter((page) => pageInScope(page, options)), lines = (options.limit ? pages.slice(0, options.limit) : pages).map((page) => {
|
|
55
|
+
let description = options.includeDescriptions && page.description ? ` - ${page.description}` : "";
|
|
128
56
|
return `- [${page.title}](${canonicalUrl(manifest, page.path)})${description}`;
|
|
129
|
-
})
|
|
130
|
-
const linkLines = (options.links ?? []).map(
|
|
57
|
+
}), linkLines = (options.links ?? []).map(
|
|
131
58
|
(link) => `- [${link.title}](${canonicalUrl(manifest, link.path)})`
|
|
132
|
-
)
|
|
133
|
-
const linkSection = linkLines.length ? `
|
|
59
|
+
), linkSection = linkLines.length ? `
|
|
134
60
|
|
|
135
61
|
## Group LLM indexes
|
|
136
62
|
|
|
137
|
-
${linkLines.join(
|
|
63
|
+
${linkLines.join(`
|
|
64
|
+
`)}` : "";
|
|
138
65
|
return `# ${manifest.site.name}
|
|
139
66
|
|
|
140
67
|
${llmsSummary(manifest)}
|
|
141
68
|
|
|
142
69
|
## Pages
|
|
143
70
|
|
|
144
|
-
${lines.join(
|
|
71
|
+
${lines.join(`
|
|
72
|
+
`)}${linkSection}
|
|
145
73
|
`;
|
|
146
74
|
}
|
|
147
75
|
function createLlmsTxtRoute(manifest, options = {}) {
|
|
148
|
-
return async function
|
|
76
|
+
return async function() {
|
|
149
77
|
return createCachedTextResponse({
|
|
150
78
|
body: await llmsTxt(manifest, options),
|
|
151
79
|
contentType: "text/plain; charset=utf-8"
|
|
@@ -153,7 +81,7 @@ function createLlmsTxtRoute(manifest, options = {}) {
|
|
|
153
81
|
};
|
|
154
82
|
}
|
|
155
83
|
function createPrecomputedLlmsTxtRoute(output) {
|
|
156
|
-
return function
|
|
84
|
+
return function() {
|
|
157
85
|
return createCachedTextResponse({
|
|
158
86
|
body: output.body,
|
|
159
87
|
contentType: "text/plain; charset=utf-8"
|
|
@@ -161,35 +89,27 @@ function createPrecomputedLlmsTxtRoute(output) {
|
|
|
161
89
|
};
|
|
162
90
|
}
|
|
163
91
|
async function llmsFullTxt(manifest, artifacts, options = {}) {
|
|
164
|
-
|
|
165
|
-
const header = `# ${manifest.site.name} Full Content
|
|
92
|
+
let maxBytes = options.maxBytes ?? DEFAULT_LLMS_FULL_MAX_BYTES, header = `# ${manifest.site.name} Full Content
|
|
166
93
|
|
|
167
94
|
> LLMS index: ${canonicalUrl(manifest, "/llms.txt")}
|
|
168
95
|
> Sitemap: ${canonicalUrl(manifest, "/sitemap.md")}
|
|
169
96
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
let totalBytes = byteLength(header);
|
|
173
|
-
let included = 0;
|
|
174
|
-
let truncated = false;
|
|
175
|
-
for (const artifact of Object.values(artifacts).sort(
|
|
97
|
+
`, sections = [], totalBytes = byteLength(header), included = 0, truncated = !1;
|
|
98
|
+
for (let artifact of Object.values(artifacts).sort(
|
|
176
99
|
(a, b) => a.markdownPath.localeCompare(b.markdownPath)
|
|
177
100
|
)) {
|
|
178
|
-
|
|
101
|
+
let section = `---
|
|
179
102
|
|
|
180
103
|
${artifact.body.trim()}
|
|
181
104
|
|
|
182
|
-
|
|
183
|
-
const sectionBytes = byteLength(section);
|
|
105
|
+
`, sectionBytes = byteLength(section);
|
|
184
106
|
if (totalBytes + sectionBytes > maxBytes) {
|
|
185
|
-
truncated =
|
|
107
|
+
truncated = !0;
|
|
186
108
|
break;
|
|
187
109
|
}
|
|
188
|
-
sections.push(section);
|
|
189
|
-
totalBytes += sectionBytes;
|
|
190
|
-
included += 1;
|
|
110
|
+
sections.push(section), totalBytes += sectionBytes, included += 1;
|
|
191
111
|
}
|
|
192
|
-
|
|
112
|
+
let footer = truncated ? `
|
|
193
113
|
> Truncated at ${included} of ${Object.keys(artifacts).length} Markdown pages to stay under ${maxBytes} bytes.
|
|
194
114
|
` : "";
|
|
195
115
|
return `${header}${sections.join("")}${footer}`;
|
|
@@ -201,7 +121,7 @@ async function llmsFullTxtResponse(manifest, artifacts, options = {}) {
|
|
|
201
121
|
});
|
|
202
122
|
}
|
|
203
123
|
function createLlmsFullTxtRoute(manifest, artifacts, options = {}) {
|
|
204
|
-
return async function
|
|
124
|
+
return async function() {
|
|
205
125
|
return llmsFullTxtResponse(manifest, artifacts, options);
|
|
206
126
|
};
|
|
207
127
|
}
|
|
@@ -29,6 +29,14 @@ type OgImageEntryLike = {
|
|
|
29
29
|
main: OgFontRoleLike;
|
|
30
30
|
mono: OgFontRoleLike;
|
|
31
31
|
};
|
|
32
|
+
emoji?: Readonly<Record<string, string>>;
|
|
33
|
+
fallbackGlyphs?: Partial<Record<"main" | "mono", Readonly<Record<string, string>>>>;
|
|
34
|
+
fallbackFonts?: ReadonlyArray<{
|
|
35
|
+
family: string;
|
|
36
|
+
data: string;
|
|
37
|
+
style: "normal" | "italic";
|
|
38
|
+
weight: number;
|
|
39
|
+
}>;
|
|
32
40
|
};
|
|
33
41
|
type OgManifestLike = {
|
|
34
42
|
width: number;
|
|
@@ -49,6 +57,8 @@ type OgFontRoleLike = {
|
|
|
49
57
|
family: string;
|
|
50
58
|
files?: ReadonlyArray<{
|
|
51
59
|
data: string;
|
|
60
|
+
path?: string;
|
|
61
|
+
probe?: string;
|
|
52
62
|
style: "normal" | "italic";
|
|
53
63
|
weight: number;
|
|
54
64
|
}>;
|