@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.
Files changed (220) hide show
  1. package/README.md +3 -5
  2. package/compiler-assets/nextjs/defaults/app/globals.css +6 -0
  3. package/compiler-assets/nextjs/defaults/group/layout.tsx +23 -0
  4. package/compiler-assets/nextjs/defaults/group/leaf.tsx +48 -0
  5. package/compiler-assets/nextjs/defaults/group/page.tsx +50 -0
  6. package/compiler-assets/nextjs/defaults/project/next.config.mjs +45 -0
  7. package/compiler-assets/nextjs/defaults/project/postcss.config.mjs +5 -0
  8. package/compiler-assets/nextjs/defaults/project/tsconfig.json.template +41 -0
  9. package/compiler-assets/nextjs/defaults/root/css/animation.css +90 -0
  10. package/compiler-assets/nextjs/defaults/root/css/components/dialog.css +21 -0
  11. package/compiler-assets/nextjs/defaults/root/css/components/drawer.css +21 -0
  12. package/compiler-assets/nextjs/defaults/root/css/components/menu.css +23 -0
  13. package/compiler-assets/nextjs/defaults/root/css/components/navigation-menu.css +25 -0
  14. package/compiler-assets/nextjs/defaults/root/css/components/popover.css +17 -0
  15. package/compiler-assets/nextjs/defaults/root/css/components/select.css +23 -0
  16. package/compiler-assets/nextjs/defaults/root/css/components/toast.css +19 -0
  17. package/compiler-assets/nextjs/defaults/root/css/components/tooltip.css +15 -0
  18. package/compiler-assets/nextjs/defaults/root/css/layout.css +22 -0
  19. package/compiler-assets/nextjs/defaults/root/css/media.css +81 -0
  20. package/compiler-assets/nextjs/defaults/root/css/radius.css +49 -0
  21. package/compiler-assets/nextjs/defaults/root/css/scrollbar.css +43 -0
  22. package/compiler-assets/nextjs/defaults/root/css/shadow.css +145 -0
  23. package/compiler-assets/nextjs/defaults/root/css/typography.css +607 -0
  24. package/compiler-assets/nextjs/defaults/root/css/zindex.css +39 -0
  25. package/compiler-assets/nextjs/defaults/root/globals.css +191 -0
  26. package/compiler-assets/nextjs/defaults/root/layout.tsx +19 -0
  27. package/compiler-assets/nextjs/defaults/root/page.tsx +61 -0
  28. package/compiler-assets/nextjs/defaults/root/theme.css +50 -0
  29. package/compiler-assets/nextjs/defaults/source/_internal/logger.ts +21 -0
  30. package/compiler-assets/nextjs/shims/generated-group-layout.tsx +19 -0
  31. package/compiler-assets/nextjs/shims/generated-group-page.tsx +18 -0
  32. package/compiler-assets/nextjs/shims/generated-leaf-page.tsx +21 -0
  33. package/compiler-assets/nextjs/shims/global-layout.tsx +134 -0
  34. package/compiler-assets/nextjs/shims/markdown-route.ts +29 -0
  35. package/compiler-assets/nextjs/shims/og-image-route.ts +18 -0
  36. package/compiler-assets/nextjs/shims/powered-by-footer.tsx +40 -0
  37. package/compiler-assets/nextjs/shims/providers.tsx +13 -0
  38. package/compiler-assets/nextjs/shims/proxy.ts +317 -0
  39. package/compiler-assets/nextjs/shims/publish-os-theme-provider.tsx +77 -0
  40. package/compiler-assets/nextjs/shims/root-page.tsx +13 -0
  41. package/compiler-assets/nextjs/shims/theme-defaults.css +177 -0
  42. package/dist/button-CFdx-ohV.d.ts +20 -0
  43. package/dist/cache/tags.js +6 -14
  44. package/dist/compiler.d.ts +100 -0
  45. package/dist/compiler.js +13379 -0
  46. package/dist/config/createNextConfig.d.ts +2 -1
  47. package/dist/config/createNextConfig.js +16 -12
  48. package/dist/icons.d.ts +1 -0
  49. package/dist/icons.js +2 -0
  50. package/dist/index.d.ts +303 -15
  51. package/dist/index.js +30 -1198
  52. package/dist/kernel/components/blocks/AgentActions.d.ts +9 -3
  53. package/dist/kernel/components/blocks/AgentActions.js +114 -200
  54. package/dist/kernel/components/blocks/animated-icon-swap.js +4 -25
  55. package/dist/kernel/components/blocks/color-palette.js +88 -169
  56. package/dist/kernel/components/blocks/design-system-preview.d.ts +38 -6
  57. package/dist/kernel/components/blocks/design-system-preview.js +44 -52
  58. package/dist/kernel/components/blocks/link-playground.js +23 -71
  59. package/dist/kernel/components/blocks/logo-block.js +18 -47
  60. package/dist/kernel/components/blocks/nav-breadcrumb.d.ts +1 -1
  61. package/dist/kernel/components/blocks/nav-breadcrumb.js +28 -42
  62. package/dist/kernel/components/blocks/navbar.d.ts +1 -1
  63. package/dist/kernel/components/blocks/navbar.js +14 -41
  64. package/dist/kernel/components/blocks/navigation-progress-playground.js +56 -149
  65. package/dist/kernel/components/blocks/navigation-progress.js +53 -157
  66. package/dist/kernel/components/blocks/next-prev.d.ts +1 -1
  67. package/dist/kernel/components/blocks/next-prev.js +16 -42
  68. package/dist/kernel/components/blocks/page-list.d.ts +1 -1
  69. package/dist/kernel/components/blocks/page-list.js +11 -16
  70. package/dist/kernel/components/blocks/search.d.ts +13 -2
  71. package/dist/kernel/components/blocks/search.js +116 -247
  72. package/dist/kernel/components/blocks/sidebar-node.d.ts +2 -2
  73. package/dist/kernel/components/blocks/sidebar-node.js +56 -95
  74. package/dist/kernel/components/blocks/sidebar.d.ts +5 -23
  75. package/dist/kernel/components/blocks/sidebar.js +35 -103
  76. package/dist/kernel/components/blocks/theme-toggle.d.ts +7 -3
  77. package/dist/kernel/components/blocks/theme-toggle.js +2 -2
  78. package/dist/kernel/components/blocks/toc.js +42 -178
  79. package/dist/kernel/components/mdx/components/blockquote.js +3 -24
  80. package/dist/kernel/components/mdx/components/callout.d.ts +1 -1
  81. package/dist/kernel/components/mdx/components/callout.js +15 -47
  82. package/dist/kernel/components/mdx/components/code-block.js +2 -2
  83. package/dist/kernel/components/mdx/components/figure-caption.js +6 -24
  84. package/dist/kernel/components/mdx/components/figure.js +9 -36
  85. package/dist/kernel/components/mdx/components/footnotes.js +3 -24
  86. package/dist/kernel/components/mdx/components/heading-copy-link.js +13 -37
  87. package/dist/kernel/components/mdx/components/heading.d.ts +8 -3
  88. package/dist/kernel/components/mdx/components/heading.js +32 -116
  89. package/dist/kernel/components/mdx/components/hr.d.ts +5 -3
  90. package/dist/kernel/components/mdx/components/hr.js +2 -2
  91. package/dist/kernel/components/mdx/components/image-zoom.js +2 -3
  92. package/dist/kernel/components/mdx/components/image.js +22 -62
  93. package/dist/kernel/components/mdx/components/inline-code.js +3 -24
  94. package/dist/kernel/components/mdx/components/kbd.d.ts +9 -4
  95. package/dist/kernel/components/mdx/components/kbd.js +2 -2
  96. package/dist/kernel/components/mdx/components/link.d.ts +1 -2
  97. package/dist/kernel/components/mdx/components/link.js +2 -2
  98. package/dist/kernel/components/mdx/components/paragraph.js +13 -41
  99. package/dist/kernel/components/mdx/components/pre.js +3 -24
  100. package/dist/kernel/components/mdx/components/strikethrough.js +6 -24
  101. package/dist/kernel/components/mdx/components/table.js +2 -2
  102. package/dist/kernel/components/mdx/components/task-list.js +6 -28
  103. package/dist/kernel/components/mdx/components/video-player.js +53 -88
  104. package/dist/kernel/components/mdx/components/video.js +27 -75
  105. package/dist/kernel/components/mdx/error-boundary.d.ts +1 -1
  106. package/dist/kernel/components/mdx/error-boundary.js +12 -15
  107. package/dist/kernel/components/mdx/error-fallback.js +4 -4
  108. package/dist/kernel/components/mdx/mdx.d.ts +68 -11
  109. package/dist/kernel/components/mdx/mdx.js +29 -29
  110. package/dist/kernel/components/mdx/rehype-heading-ids.js +11 -67
  111. package/dist/kernel/components/mdx/types.d.ts +1 -1
  112. package/dist/kernel/components/ui/accordion.js +3 -26
  113. package/dist/kernel/components/ui/breadcrumb-trail.d.ts +23 -7
  114. package/dist/kernel/components/ui/breadcrumb-trail.js +32 -80
  115. package/dist/kernel/components/ui/breadcrumb.d.ts +1 -1
  116. package/dist/kernel/components/ui/breadcrumb.js +20 -54
  117. package/dist/kernel/components/ui/button-group.d.ts +4 -3
  118. package/dist/kernel/components/ui/button-group.js +7 -30
  119. package/dist/kernel/components/ui/button.js +13 -36
  120. package/dist/kernel/components/ui/card.d.ts +2 -2
  121. package/dist/kernel/components/ui/card.js +2 -23
  122. package/dist/kernel/components/ui/dialog.d.ts +9 -9
  123. package/dist/kernel/components/ui/dialog.js +15 -33
  124. package/dist/kernel/components/ui/drawer.d.ts +10 -10
  125. package/dist/kernel/components/ui/drawer.js +15 -33
  126. package/dist/kernel/components/ui/input.js +6 -30
  127. package/dist/kernel/components/ui/kbd.js +10 -31
  128. package/dist/kernel/components/ui/link.d.ts +1 -1
  129. package/dist/kernel/components/ui/link.js +53 -104
  130. package/dist/kernel/components/ui/menu.d.ts +21 -21
  131. package/dist/kernel/components/ui/menu.js +10 -32
  132. package/dist/kernel/components/ui/meta-key.d.ts +9 -4
  133. package/dist/kernel/components/ui/meta-key.js +2 -2
  134. package/dist/kernel/components/ui/navigation-menu.d.ts +14 -14
  135. package/dist/kernel/components/ui/navigation-menu.js +9 -30
  136. package/dist/kernel/components/ui/popover.d.ts +10 -10
  137. package/dist/kernel/components/ui/popover.js +19 -34
  138. package/dist/kernel/components/ui/progress.js +2 -25
  139. package/dist/kernel/components/ui/scroll-area.js +39 -118
  140. package/dist/kernel/components/ui/select.d.ts +15 -15
  141. package/dist/kernel/components/ui/select.js +19 -35
  142. package/dist/kernel/components/ui/separator.js +2 -25
  143. package/dist/kernel/components/ui/table.js +2 -23
  144. package/dist/kernel/components/ui/tabs.js +39 -99
  145. package/dist/kernel/components/ui/tag.d.ts +2 -2
  146. package/dist/kernel/components/ui/tag.js +4 -25
  147. package/dist/kernel/components/ui/text.d.ts +2 -2
  148. package/dist/kernel/components/ui/text.js +3 -25
  149. package/dist/kernel/components/ui/theme-toggle.d.ts +18 -4
  150. package/dist/kernel/components/ui/theme-toggle.js +18 -44
  151. package/dist/kernel/components/ui/toast.d.ts +10 -10
  152. package/dist/kernel/components/ui/toast.js +13 -35
  153. package/dist/kernel/components/ui/tooltip.d.ts +8 -8
  154. package/dist/kernel/components/ui/tooltip.js +8 -29
  155. package/dist/kernel/defaults.registry.d.ts +1 -1
  156. package/dist/kernel/defaults.registry.js +2 -2
  157. package/dist/kernel/framework-icons.d.ts +1 -0
  158. package/dist/kernel/framework-icons.js +39 -0
  159. package/dist/kernel/routes/agent/markdown.js +36 -65
  160. package/dist/kernel/routes/layouts/group.d.ts +1 -1
  161. package/dist/kernel/routes/layouts/group.js +20 -109
  162. package/dist/kernel/routes/metadata/feed.d.ts +1 -2
  163. package/dist/kernel/routes/metadata/feed.js +46 -127
  164. package/dist/kernel/routes/metadata/llms.d.ts +1 -2
  165. package/dist/kernel/routes/metadata/llms.js +40 -120
  166. package/dist/kernel/routes/metadata/og-image.d.ts +10 -0
  167. package/dist/kernel/routes/metadata/og-image.js +264 -198
  168. package/dist/kernel/routes/metadata/robots.d.ts +1 -2
  169. package/dist/kernel/routes/metadata/robots.js +21 -90
  170. package/dist/kernel/routes/metadata/sitemap.d.ts +1 -2
  171. package/dist/kernel/routes/metadata/sitemap.js +36 -102
  172. package/dist/kernel/routes/pages/group.d.ts +1 -1
  173. package/dist/kernel/routes/pages/group.js +42 -137
  174. package/dist/kernel/routes/pages/leaf.d.ts +1 -1
  175. package/dist/kernel/routes/pages/leaf.js +74 -213
  176. package/dist/kernel/routes/pages/root.d.ts +1 -1
  177. package/dist/kernel/routes/pages/root.js +37 -108
  178. package/dist/keyboard-shortcuts.js +69 -141
  179. package/dist/link-CYaCRDb6.d.ts +35 -0
  180. package/dist/resolvers/manifest-resolver.d.ts +3 -3
  181. package/dist/resolvers/manifest-resolver.js +15 -21
  182. package/dist/route-metadata-og-image-BeKKFHg7.d.ts +58 -0
  183. package/dist/search.d.ts +81 -4
  184. package/dist/search.js +124 -195
  185. package/dist/sidebar-types-Bgchdfd6.d.ts +25 -0
  186. package/dist/theme-scope.d.ts +15 -0
  187. package/dist/theme-scope.js +23 -0
  188. package/dist/types-B_b3C0U6.d.ts +63 -0
  189. package/dist/types-CIwwieNw.d.ts +127 -0
  190. package/dist/types-DHBm7-j6.d.ts +57 -0
  191. package/dist/types-sM2g9nW0.d.ts +12 -0
  192. package/dist/types.d.ts +0 -1
  193. package/dist/types.js +1 -1
  194. package/dist/utils/cn.d.ts +5 -9
  195. package/dist/utils/cn.js +13 -7
  196. package/dist/utils/heading-ids.js +20 -47
  197. package/dist/utils/pretty-date.js +7 -13
  198. package/init/seed/minimal/publish.os/assets/logo/publish-dev-logo.dark.png +0 -0
  199. package/init/seed/minimal/publish.os/assets/logo/publish-dev-logo.png +0 -0
  200. package/init/seed/minimal/publish.os/docs/content/get-started.mdx +54 -0
  201. package/init/seed/minimal/publish.os/docs/content/groups.mdx +31 -0
  202. package/init/seed/minimal/publish.os/docs/content/theme.mdx +64 -0
  203. package/init/seed/minimal/publish.os/publish.os.config.json +21 -0
  204. package/init/seed/minimal/publish.os/theme.css +47 -0
  205. package/init/seed/minimal/seed.json +13 -0
  206. package/package.json +469 -35
  207. package/release/{package.json → app/lucide/package.json} +11 -5
  208. package/release/app/lucide/pnpm-lock.yaml.template +2905 -0
  209. package/release/app/lucide/pnpm-workspace.yaml +11 -0
  210. package/release/app/phosphor/package.json +30 -0
  211. package/release/app/phosphor/pnpm-lock.yaml.template +2908 -0
  212. package/release/app/phosphor/pnpm-workspace.yaml +11 -0
  213. package/release/app/tabler/package.json +30 -0
  214. package/release/app/tabler/pnpm-lock.yaml.template +2911 -0
  215. package/release/app/tabler/pnpm-workspace.yaml +11 -0
  216. package/release/compiler/package.json +20 -0
  217. package/release/compiler/pnpm-lock.yaml.template +2432 -0
  218. package/release/compiler/pnpm-workspace.yaml +11 -0
  219. package/release/release.json +29 -5
  220. package/release/runtime-pnpm-lock.yaml +0 -1316
@@ -1,156 +1,167 @@
1
- // src/kernel/routes/metadata/og-image.tsx
1
+ // src/route-metadata-og-image.tsx
2
2
  import { readFile } from "fs/promises";
3
3
  import { createRequire } from "module";
4
4
  import { ImageResponse } from "next/og";
5
- import { jsx, jsxs } from "react/jsx-runtime";
6
- var ERROR_HEADERS = {
7
- "cache-control": "public, max-age=60, must-revalidate",
8
- "cdn-cache-control": "public, max-age=300",
9
- "vercel-cdn-cache-control": "public, max-age=300",
10
- "x-content-type-options": "nosniff"
11
- };
12
- var SUCCESS_HEADERS = {
13
- "cache-control": "public, max-age=31536000, immutable",
14
- "cdn-cache-control": "public, max-age=31536000, immutable",
15
- "vercel-cdn-cache-control": "public, max-age=31536000, immutable",
16
- "x-content-type-options": "nosniff"
17
- };
18
- var DEVELOPMENT_SUCCESS_HEADERS = {
19
- "cache-control": "no-store",
20
- "cdn-cache-control": "no-store",
21
- "vercel-cdn-cache-control": "no-store",
22
- "x-content-type-options": "nosniff"
5
+
6
+ // src/lib/runtime/logging/logger.ts
7
+ var isDev = process.env.NODE_ENV !== "production", isDebugEnabled = process.env.NEXT_PRIVATE_DEBUG_CACHE === "1", log = {
8
+ debug(...args) {
9
+ isDev && isDebugEnabled && console.debug("[publish.os:debug]", ...args);
10
+ },
11
+ info(...args) {
12
+ console.log("[publish.os]", ...args);
13
+ },
14
+ warn(...args) {
15
+ console.warn("[publish.os:warn]", ...args);
16
+ },
17
+ error(...args) {
18
+ console.error("[publish.os:error]", ...args);
19
+ }
23
20
  };
24
- var KEY_PATTERN = /^[a-f0-9]{16}$/;
25
- var DESCRIPTION_MAX_LENGTH = 260;
26
- var LABEL_MAX_LENGTH = 72;
27
- var SITE_NAME_MAX_LENGTH = 42;
28
- var TITLE_MAX_LENGTH = 220;
29
- var GRID_INSET = 86;
30
- var GRID_BOTTOM = 544;
31
- var CONTENT_X = 122;
32
- var CONTENT_WIDTH = 956;
33
- var TITLE_MAX_FONT_SIZE = 60;
34
- var TITLE_MIN_FONT_SIZE = 40;
35
- var LOGO_MAX_WIDTH = 300;
36
- var LOGO_MAX_HEIGHT = 46;
37
- var MAX_RESPONSE_CACHE_ENTRIES = 128;
38
- var BADGE_RADIUS = 999;
39
- var CONTENT_TYPE_HEADER = { "content-type": "image/png" };
40
- var PLATFORM_FONT_FAMILY = "PublishOS Geist";
41
- var PLATFORM_FONT_WEIGHTS = [
42
- 400,
43
- 500,
44
- 600,
45
- 700,
46
- 800
47
- ];
48
- var fontArrayBufferCache = /* @__PURE__ */ new Map();
49
- var imageResponseFontCache = /* @__PURE__ */ new Map();
50
- var imageResponseCache = /* @__PURE__ */ new Map();
51
- var require2 = createRequire(`${process.cwd()}/package.json`);
52
- var platformFontPath = require2.resolve(
53
- "next/dist/compiled/@vercel/og/Geist-Regular.ttf"
54
- );
55
- var platformFontData;
56
- function isDevelopment() {
57
- return process.env.NODE_ENV === "development";
21
+
22
+ // src/lib/runtime/metadata/og-text.ts
23
+ var segmenter = new Intl.Segmenter("en", { granularity: "grapheme" });
24
+ function ogTextGraphemes(text) {
25
+ return [...segmenter.segment(text)].map(({ segment }) => segment);
58
26
  }
59
- function successHeaders() {
60
- return isDevelopment() ? DEVELOPMENT_SUCCESS_HEADERS : SUCCESS_HEADERS;
27
+ function truncateGraphemes(value, maximum) {
28
+ let result = "";
29
+ for (let segment of ogTextGraphemes(value)) {
30
+ if (result.length + segment.length > maximum) break;
31
+ result += segment;
32
+ }
33
+ return result;
61
34
  }
62
35
  function clampText(value, maxLength) {
63
- if (!value) return void 0;
64
- if (value.length <= maxLength) return value;
65
- return `${value.slice(0, maxLength - 3).trimEnd()}...`;
66
- }
67
- async function routeKey(context) {
68
- const params = await context.params;
69
- return params.key.replace(/\.png$/, "");
36
+ if (value)
37
+ return value.length <= maxLength ? value : `${truncateGraphemes(value, maxLength - 3).trimEnd()}...`;
70
38
  }
71
39
  function ellipsize(value, maxLength) {
72
- if (value.length <= maxLength) return value;
73
- return `${value.slice(0, maxLength - 3).trimEnd()}...`;
40
+ return value.length <= maxLength ? value : `${truncateGraphemes(value, maxLength - 3).trimEnd()}...`;
74
41
  }
75
42
  function wrapText(options) {
76
- const source = clampText(options.text, options.maxLength);
43
+ let source = clampText(options.text, options.maxLength);
77
44
  if (!source) return [];
78
- const maxCharsPerLine = Math.max(
45
+ let maxCharsPerLine = Math.max(
79
46
  12,
80
47
  Math.floor(options.width / (options.fontSize * 0.54))
81
- );
82
- const words = source.split(/\s+/).filter(Boolean);
83
- const lines = [];
84
- let line = "";
85
- for (const word of words) {
86
- const nextLine = line ? `${line} ${word}` : word;
48
+ ), words = source.split(/\s+/).filter(Boolean), lines = [], line = "";
49
+ for (let word of words) {
50
+ let nextLine = line ? `${line} ${word}` : word;
87
51
  if (nextLine.length <= maxCharsPerLine) {
88
52
  line = nextLine;
89
53
  continue;
90
54
  }
91
- if (line) lines.push(line);
92
- line = word.length > maxCharsPerLine ? ellipsize(word, maxCharsPerLine) : word;
93
- if (lines.length === options.maxLines) break;
55
+ if (line && lines.push(line), line = word.length > maxCharsPerLine ? ellipsize(word, maxCharsPerLine) : word, lines.length === options.maxLines) break;
94
56
  }
95
- if (line && lines.length < options.maxLines) lines.push(line);
96
- const consumed = lines.join(" ").replace(/\.\.\.$/, "");
97
- const didOverflow = words.join(" ").length > consumed.length || (lines.at(-1)?.endsWith("...") ?? false);
98
- if (didOverflow && lines.length > 0) {
99
- const lastIndex = lines.length - 1;
57
+ line && lines.length < options.maxLines && lines.push(line);
58
+ let consumed = lines.join(" ").replace(/\.\.\.$/, "");
59
+ if ((words.join(" ").length > consumed.length || (lines.at(-1)?.endsWith("...") ?? !1)) && lines.length > 0) {
60
+ let lastIndex = lines.length - 1;
100
61
  lines[lastIndex] = ellipsize(lines[lastIndex] ?? "", maxCharsPerLine);
101
62
  }
102
63
  return lines;
103
64
  }
104
65
  function singleLineText(options) {
105
- const source = clampText(options.text, options.maxLength);
106
- if (!source) return void 0;
107
- const charWidth = options.fontSize * (options.mono ? 0.62 : 0.54);
108
- const maxChars = Math.max(4, Math.floor(options.width / charWidth));
66
+ let source = clampText(options.text, options.maxLength);
67
+ if (!source) return;
68
+ let charWidth = options.fontSize * (options.mono ? 0.62 : 0.54), maxChars = Math.max(4, Math.floor(options.width / charWidth));
109
69
  return ellipsize(source.replace(/\s+/g, " "), maxChars);
110
70
  }
111
71
  function titleFontSize(title) {
112
- const length = title?.length ?? 0;
113
- if (length > 130) return TITLE_MIN_FONT_SIZE;
114
- if (length > 100) return 44;
115
- if (length > 80) return 48;
116
- if (length > 60) return 52;
117
- if (length > 40) return 56;
118
- return TITLE_MAX_FONT_SIZE;
72
+ let length = title?.length ?? 0;
73
+ return length > 130 ? 40 : length > 100 ? 44 : length > 80 ? 48 : length > 60 ? 52 : length > 40 ? 56 : 60;
119
74
  }
120
75
  function siteUrl(value) {
121
- if (!value) return void 0;
122
- const candidate = value.includes("://") ? value : `https://${value}`;
76
+ if (!value) return;
77
+ let candidate = value.includes("://") ? value : `https://${value}`;
123
78
  try {
124
79
  return new URL(candidate);
125
80
  } catch {
126
- return void 0;
81
+ return;
127
82
  }
128
83
  }
129
84
  function displayUrlParts(entry) {
130
- const url = siteUrl(entry.siteUrl);
131
- const host = url?.hostname ?? entry.siteUrl?.replace(/\/.*$/, "") ?? "";
132
- const basePath = url?.pathname.replace(/\/+$/, "") ?? "";
133
- const routePath = entry.routePath === "/" ? "" : `/${entry.routePath.replace(/^\/+/, "")}`;
134
- const path = `${basePath === "/" ? "" : basePath}${routePath}`;
135
- if (host) return { host, path };
136
- return { host: "", path: path || routePath };
85
+ let url = siteUrl(entry.siteUrl), host = url?.hostname ?? entry.siteUrl?.replace(/\/.*$/, "") ?? "", basePath = url?.pathname.replace(/\/+$/, "") ?? "", routePath = entry.routePath === "/" ? "" : `/${entry.routePath.replace(/^\/+/, "")}`, path = `${basePath === "/" ? "" : basePath}${routePath}`;
86
+ return host ? { host, path } : { host: "", path: path || routePath };
87
+ }
88
+ function getOgImageText(entry) {
89
+ let titleSize = titleFontSize(entry.title), titleLines = wrapText({
90
+ fontSize: titleSize,
91
+ maxLength: 220,
92
+ maxLines: 2,
93
+ text: entry.title,
94
+ width: 900
95
+ }), descriptionLines = wrapText({
96
+ fontSize: 30,
97
+ maxLength: 260,
98
+ maxLines: 2,
99
+ text: entry.description,
100
+ width: 870
101
+ }), label = singleLineText({
102
+ fontSize: 22,
103
+ maxLength: 72,
104
+ mono: !0,
105
+ text: entry.label,
106
+ width: 520
107
+ }), displayUrl = displayUrlParts(entry), siteName = clampText(entry.siteName ?? entry.alt, 42);
108
+ return {
109
+ titleSize,
110
+ titleLines,
111
+ descriptionLines,
112
+ label,
113
+ displayUrl,
114
+ siteName
115
+ };
116
+ }
117
+
118
+ // src/route-metadata-og-image.tsx
119
+ import { jsx, jsxs } from "react/jsx-runtime";
120
+ var ERROR_HEADERS = {
121
+ "cache-control": "public, max-age=60, must-revalidate",
122
+ "cdn-cache-control": "public, max-age=300",
123
+ "vercel-cdn-cache-control": "public, max-age=300",
124
+ "x-content-type-options": "nosniff"
125
+ }, SUCCESS_HEADERS = {
126
+ "cache-control": "public, max-age=31536000, immutable",
127
+ "cdn-cache-control": "public, max-age=31536000, immutable",
128
+ "vercel-cdn-cache-control": "public, max-age=31536000, immutable",
129
+ "x-content-type-options": "nosniff"
130
+ }, DEVELOPMENT_SUCCESS_HEADERS = {
131
+ "cache-control": "no-store",
132
+ "cdn-cache-control": "no-store",
133
+ "vercel-cdn-cache-control": "no-store",
134
+ "x-content-type-options": "nosniff"
135
+ }, KEY_PATTERN = /^[a-f0-9]{16}$/, GRID_INSET = 86, GRID_BOTTOM = 544, CONTENT_X = 122, CONTENT_WIDTH = 956, LOGO_MAX_WIDTH = 300, LOGO_MAX_HEIGHT = 46, MAX_RESPONSE_CACHE_ENTRIES = 128, BADGE_RADIUS = 999, CONTENT_TYPE_HEADER = { "content-type": "image/png" }, PLATFORM_FONT_FAMILY = "PublishOS Geist", PLATFORM_FONT_WEIGHTS = [
136
+ 400,
137
+ 500,
138
+ 600,
139
+ 700,
140
+ 800
141
+ ], fontArrayBufferCache = /* @__PURE__ */ new Map(), imageResponseFontCache = /* @__PURE__ */ new Map(), imageResponseFontSupportCache = /* @__PURE__ */ new WeakMap(), warnedImageResponseFonts = /* @__PURE__ */ new WeakSet(), imageResponseCache = /* @__PURE__ */ new Map(), require2 = createRequire(`${process.cwd()}/package.json`), platformFontPath = require2.resolve(
142
+ "next/dist/compiled/@vercel/og/Geist-Regular.ttf"
143
+ ), platformFontData;
144
+ function isDevelopment() {
145
+ return process.env.NODE_ENV === "development";
146
+ }
147
+ function successHeaders() {
148
+ return isDevelopment() ? DEVELOPMENT_SUCCESS_HEADERS : SUCCESS_HEADERS;
149
+ }
150
+ async function routeKey(context) {
151
+ return (await context.params).key.replace(/\.png$/, "");
137
152
  }
138
153
  function dataUrlToArrayBuffer(value) {
139
- const cached = fontArrayBufferCache.get(value);
154
+ let cached = fontArrayBufferCache.get(value);
140
155
  if (cached) return cached;
141
- const binary = atob(value);
142
- const bytes = new Uint8Array(binary.length);
143
- for (let index = 0; index < binary.length; index += 1) {
156
+ let binary = atob(value), bytes = new Uint8Array(binary.length);
157
+ for (let index = 0; index < binary.length; index += 1)
144
158
  bytes[index] = binary.charCodeAt(index);
145
- }
146
- fontArrayBufferCache.set(value, bytes.buffer);
147
- return bytes.buffer;
159
+ return fontArrayBufferCache.set(value, bytes.buffer), bytes.buffer;
148
160
  }
149
161
  function platformFonts() {
150
- platformFontData ??= readFile(platformFontPath).then(
162
+ return platformFontData ??= readFile(platformFontPath).then(
151
163
  (data) => data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength)
152
- );
153
- return platformFontData.then(
164
+ ), platformFontData.then(
154
165
  (data) => PLATFORM_FONT_WEIGHTS.map((weight) => ({
155
166
  data: data.slice(0),
156
167
  name: PLATFORM_FONT_FAMILY,
@@ -159,29 +170,72 @@ function platformFonts() {
159
170
  }))
160
171
  );
161
172
  }
173
+ function imageResponseFontIsUsable(font, probe) {
174
+ let results = imageResponseFontSupportCache.get(font.data) ?? /* @__PURE__ */ new Map(), cached = results.get(probe);
175
+ if (cached) return cached;
176
+ let result = platformFonts().then(
177
+ (fallback) => new ImageResponse(
178
+ /* @__PURE__ */ jsx(
179
+ "div",
180
+ {
181
+ style: {
182
+ display: "flex",
183
+ fontFamily: `${JSON.stringify(font.name)}, ${JSON.stringify(PLATFORM_FONT_FAMILY)}`,
184
+ fontStyle: font.style,
185
+ fontWeight: font.weight
186
+ },
187
+ children: probe
188
+ }
189
+ ),
190
+ { fonts: [font, ...fallback], height: 32, width: 64 }
191
+ ).arrayBuffer().then(
192
+ () => !0,
193
+ () => !1
194
+ )
195
+ );
196
+ return results.set(probe, result), imageResponseFontSupportCache.set(font.data, results), result;
197
+ }
162
198
  async function imageResponseFonts(entry) {
163
- const cached = imageResponseFontCache.get(entry.key);
199
+ let cached = imageResponseFontCache.get(entry.key);
164
200
  if (cached) return cached;
165
- const manifestFonts = ["main", "mono"].flatMap((role) => {
166
- const font = entry.fonts?.[role];
167
- return font?.files?.map((file) => ({
168
- data: dataUrlToArrayBuffer(file.data),
201
+ let selection = (async () => {
202
+ let usableRoles = /* @__PURE__ */ new Set(), manifestFonts = (await Promise.all(
203
+ ["main", "mono"].flatMap((role) => {
204
+ let font = entry.fonts?.[role];
205
+ return font?.files?.map(async (file) => {
206
+ let candidate = {
207
+ data: dataUrlToArrayBuffer(file.data),
208
+ name: font.family,
209
+ style: file.style,
210
+ weight: file.weight
211
+ };
212
+ if (!file.probe || await imageResponseFontIsUsable(candidate, file.probe))
213
+ return usableRoles.add(role), candidate;
214
+ warnedImageResponseFonts.has(candidate.data) || (warnedImageResponseFonts.add(candidate.data), log.warn(
215
+ `Open Graph image font ${JSON.stringify(file.path ?? font.family)} is not compatible with ImageResponse. PublishOS uses its bundled static font for this Open Graph role. Browser text still uses ${JSON.stringify(font.family)}.`
216
+ ));
217
+ }) ?? [];
218
+ })
219
+ )).filter((font) => !!font), fallbackFonts = (entry.fallbackFonts ?? []).map((font) => ({
169
220
  name: font.family,
170
- style: file.style,
171
- weight: file.weight
172
- })) ?? [];
173
- });
174
- const fonts = manifestFonts.length > 0 ? [...manifestFonts, ...await platformFonts()] : await platformFonts();
175
- imageResponseFontCache.set(entry.key, fonts);
176
- return fonts;
221
+ data: dataUrlToArrayBuffer(font.data),
222
+ style: font.style,
223
+ weight: font.weight
224
+ }));
225
+ return {
226
+ fonts: [...manifestFonts, ...await platformFonts(), ...fallbackFonts],
227
+ usableRoles
228
+ };
229
+ })();
230
+ return imageResponseFontCache.set(entry.key, selection), selection;
177
231
  }
178
232
  function fontFamily(font, fallback) {
179
- const fallbackStack = fallback === "mono" ? `"${PLATFORM_FONT_FAMILY}", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace` : `"${PLATFORM_FONT_FAMILY}", Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`;
233
+ let fallbackStack = fallback === "mono" ? `"${PLATFORM_FONT_FAMILY}", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace` : `"${PLATFORM_FONT_FAMILY}", Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`;
180
234
  return font?.family ? `${JSON.stringify(font.family)}, ${fallbackStack}` : fallbackStack;
181
235
  }
182
236
  function fittedLogoDimensions(logo) {
183
- if (!logo?.width || !logo.height) return void 0;
184
- const scale = Math.min(
237
+ if (!logo?.width || !logo.height) return;
238
+ let scale = Math.min(
185
239
  LOGO_MAX_WIDTH / logo.width,
186
240
  LOGO_MAX_HEIGHT / logo.height,
187
241
  1
@@ -193,16 +247,14 @@ function fittedLogoDimensions(logo) {
193
247
  }
194
248
  function cacheImageResponse(key, render) {
195
249
  if (isDevelopment()) return render();
196
- const cached = imageResponseCache.get(key);
250
+ let cached = imageResponseCache.get(key);
197
251
  if (cached) return cached;
198
- const promise = render().catch((error) => {
199
- imageResponseCache.delete(key);
200
- throw error;
252
+ let promise = render().catch((error) => {
253
+ throw imageResponseCache.delete(key), error;
201
254
  });
202
- imageResponseCache.set(key, promise);
203
- if (imageResponseCache.size > MAX_RESPONSE_CACHE_ENTRIES) {
204
- const oldest = imageResponseCache.keys().next().value;
205
- if (oldest) imageResponseCache.delete(oldest);
255
+ if (imageResponseCache.set(key, promise), imageResponseCache.size > MAX_RESPONSE_CACHE_ENTRIES) {
256
+ let oldest = imageResponseCache.keys().next().value;
257
+ oldest && imageResponseCache.delete(oldest);
206
258
  }
207
259
  return promise;
208
260
  }
@@ -213,77 +265,91 @@ function responseFromCachedImage(cached) {
213
265
  });
214
266
  }
215
267
  async function cachedImageResponse(response) {
216
- const headersToApply = successHeaders();
217
- const headers = new Headers(response.headers);
218
- headers.set("cache-control", headersToApply["cache-control"]);
219
- headers.set("cdn-cache-control", headersToApply["cdn-cache-control"]);
220
- headers.set(
268
+ let headersToApply = successHeaders(), headers = new Headers(response.headers);
269
+ return headers.set("cache-control", headersToApply["cache-control"]), headers.set("cdn-cache-control", headersToApply["cdn-cache-control"]), headers.set(
221
270
  "vercel-cdn-cache-control",
222
271
  headersToApply["vercel-cdn-cache-control"]
223
- );
224
- headers.set(
272
+ ), headers.set(
225
273
  "x-content-type-options",
226
274
  headersToApply["x-content-type-options"]
227
- );
228
- if (!headers.has("content-type")) {
229
- headers.set("content-type", CONTENT_TYPE_HEADER["content-type"]);
230
- }
231
- return {
275
+ ), headers.has("content-type") || headers.set("content-type", CONTENT_TYPE_HEADER["content-type"]), {
232
276
  body: await response.arrayBuffer(),
233
277
  headers,
234
278
  status: response.status
235
279
  };
236
280
  }
237
281
  function createOgImageRoute({ manifest }) {
238
- return async function GET(_request, context) {
239
- const key = await routeKey(context);
240
- if (!KEY_PATTERN.test(key)) {
282
+ return async function(_request, context) {
283
+ let key = await routeKey(context);
284
+ if (!KEY_PATTERN.test(key))
241
285
  return new Response("Bad request", {
242
286
  headers: ERROR_HEADERS,
243
287
  status: 400
244
288
  });
245
- }
246
- const entry = manifest.generated[key];
247
- if (!entry || entry.source !== "generated") {
289
+ let entry = manifest.generated[key];
290
+ if (!entry || entry.source !== "generated")
248
291
  return new Response("Not found", {
249
292
  headers: ERROR_HEADERS,
250
293
  status: 404
251
294
  });
252
- }
253
- const titleSize = titleFontSize(entry.title);
254
- const titleLines = wrapText({
255
- fontSize: titleSize,
256
- maxLength: TITLE_MAX_LENGTH,
257
- maxLines: 2,
258
- text: entry.title,
259
- width: 900
260
- });
261
- const descriptionLines = wrapText({
262
- fontSize: 30,
263
- maxLength: DESCRIPTION_MAX_LENGTH,
264
- maxLines: 2,
265
- text: entry.description,
266
- width: 870
267
- });
268
- const label = singleLineText({
269
- fontSize: 22,
270
- maxLength: LABEL_MAX_LENGTH,
271
- mono: true,
272
- text: entry.label,
273
- width: 520
274
- });
275
- const displayUrl = displayUrlParts(entry);
276
- const siteName = clampText(
277
- entry.siteName ?? entry.alt,
278
- SITE_NAME_MAX_LENGTH
279
- );
280
- const background = entry.background ?? "#ffffff";
281
- const textPrimary = entry.textPrimary ?? "#111111";
282
- const textSecondary = entry.textSecondary ?? "#525252";
283
- const accent = entry.accent ?? "#2563eb";
284
- const stroke = entry.stroke ?? "#e5e7eb";
285
- const logoSrc = entry.logo?.dataUri;
286
- const logoDimensions = fittedLogoDimensions(entry.logo);
295
+ let {
296
+ titleSize,
297
+ titleLines,
298
+ descriptionLines,
299
+ label,
300
+ displayUrl,
301
+ siteName
302
+ } = getOgImageText(entry), background = entry.background ?? "#ffffff", textPrimary = entry.textPrimary ?? "#111111", textSecondary = entry.textSecondary ?? "#525252", accent = entry.accent ?? "#2563eb", stroke = entry.stroke ?? "#e5e7eb", logoSrc = entry.logo?.dataUri, logoDimensions = fittedLogoDimensions(entry.logo), fontSelection = await imageResponseFonts(entry), mainFont = fontSelection.usableRoles.has("main") ? entry.fonts?.main : void 0, monoFont = fontSelection.usableRoles.has("mono") ? entry.fonts?.mono : void 0, renderText = (text, fontSize, role) => {
303
+ if (!text || !entry.emoji && !entry.fallbackGlyphs) return text;
304
+ let glyphs = entry.fallbackGlyphs?.[role], segments = ogTextGraphemes(text);
305
+ if (!segments.some((segment) => entry.emoji?.[segment] || glyphs?.[segment]))
306
+ return text;
307
+ let parts = [], remaining = "", remainingFamily, flush = () => {
308
+ remaining && (parts.push(
309
+ remainingFamily ? /* @__PURE__ */ jsx(
310
+ "span",
311
+ {
312
+ style: {
313
+ fontFamily: JSON.stringify(remainingFamily),
314
+ whiteSpace: role === "mono" ? "pre" : "pre-wrap"
315
+ },
316
+ children: remaining
317
+ },
318
+ parts.length
319
+ ) : /* @__PURE__ */ jsx(
320
+ "span",
321
+ {
322
+ style: { whiteSpace: role === "mono" ? "pre" : "pre-wrap" },
323
+ children: remaining
324
+ },
325
+ parts.length
326
+ )
327
+ ), remaining = "");
328
+ };
329
+ for (let segment of segments) {
330
+ let image = entry.emoji?.[segment];
331
+ if (!image) {
332
+ let family = glyphs?.[segment] ?? (/^\s+$/u.test(segment) ? remainingFamily : void 0);
333
+ family !== remainingFamily && flush(), remainingFamily = family, remaining += segment;
334
+ continue;
335
+ }
336
+ flush(), parts.push(
337
+ // biome-ignore lint/performance/noImgElement: ImageResponse uses prepared inline SVG artwork, not next/image.
338
+ /* @__PURE__ */ jsx(
339
+ "img",
340
+ {
341
+ alt: "",
342
+ src: image,
343
+ width: fontSize,
344
+ height: fontSize,
345
+ style: { flexShrink: 0 }
346
+ },
347
+ parts.length
348
+ )
349
+ );
350
+ }
351
+ return flush(), parts;
352
+ };
287
353
  return responseFromCachedImage(
288
354
  await cacheImageResponse(
289
355
  entry.key,
@@ -296,7 +362,7 @@ function createOgImageRoute({ manifest }) {
296
362
  background,
297
363
  color: textPrimary,
298
364
  display: "flex",
299
- fontFamily: fontFamily(entry.fonts?.main, "sans"),
365
+ fontFamily: fontFamily(mainFont, "sans"),
300
366
  height: "100%",
301
367
  position: "relative",
302
368
  width: "100%"
@@ -365,7 +431,7 @@ function createOgImageRoute({ manifest }) {
365
431
  alignItems: "center",
366
432
  color: accent,
367
433
  display: "flex",
368
- fontFamily: fontFamily(entry.fonts?.main, "sans"),
434
+ fontFamily: fontFamily(mainFont, "sans"),
369
435
  fontSize: 22,
370
436
  fontWeight: 700,
371
437
  height: GRID_INSET,
@@ -394,7 +460,7 @@ function createOgImageRoute({ manifest }) {
394
460
  }
395
461
  }
396
462
  )
397
- ) : siteName
463
+ ) : renderText(siteName, 22, "main")
398
464
  }
399
465
  ),
400
466
  label ? /* @__PURE__ */ jsx(
@@ -403,7 +469,7 @@ function createOgImageRoute({ manifest }) {
403
469
  style: {
404
470
  alignItems: "center",
405
471
  display: "flex",
406
- fontFamily: fontFamily(entry.fonts?.mono, "mono"),
472
+ fontFamily: fontFamily(monoFont, "mono"),
407
473
  height: GRID_INSET,
408
474
  justifyContent: "flex-end",
409
475
  overflow: "hidden",
@@ -466,7 +532,7 @@ function createOgImageRoute({ manifest }) {
466
532
  }
467
533
  }
468
534
  ),
469
- /* @__PURE__ */ jsx("div", { style: { display: "flex", position: "relative" }, children: label })
535
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", position: "relative" }, children: renderText(label, 20, "mono") })
470
536
  ]
471
537
  }
472
538
  )
@@ -497,7 +563,7 @@ function createOgImageRoute({ manifest }) {
497
563
  lineHeight: 1.08,
498
564
  width: 900
499
565
  },
500
- children: titleLines.map((line) => /* @__PURE__ */ jsx("div", { style: { display: "flex" }, children: line }, line))
566
+ children: titleLines.map((line) => /* @__PURE__ */ jsx("div", { style: { display: "flex" }, children: renderText(line, titleSize, "main") }, line))
501
567
  }
502
568
  ),
503
569
  descriptionLines.length > 0 ? /* @__PURE__ */ jsx(
@@ -511,7 +577,7 @@ function createOgImageRoute({ manifest }) {
511
577
  lineHeight: 1.25,
512
578
  width: 870
513
579
  },
514
- children: descriptionLines.map((line) => /* @__PURE__ */ jsx("div", { style: { display: "flex" }, children: line }, line))
580
+ children: descriptionLines.map((line) => /* @__PURE__ */ jsx("div", { style: { display: "flex" }, children: renderText(line, 30, "main") }, line))
515
581
  }
516
582
  ) : null
517
583
  ]
@@ -523,7 +589,7 @@ function createOgImageRoute({ manifest }) {
523
589
  style: {
524
590
  alignItems: "center",
525
591
  display: "flex",
526
- fontFamily: fontFamily(entry.fonts?.mono, "mono"),
592
+ fontFamily: fontFamily(monoFont, "mono"),
527
593
  fontSize: 22,
528
594
  height: GRID_INSET,
529
595
  justifyContent: "flex-start",
@@ -555,7 +621,7 @@ function createOgImageRoute({ manifest }) {
555
621
  flexShrink: 0,
556
622
  whiteSpace: "nowrap"
557
623
  },
558
- children: displayUrl.host
624
+ children: renderText(displayUrl.host, 22, "mono")
559
625
  }
560
626
  ) : null,
561
627
  displayUrl.path ? /* @__PURE__ */ jsx(
@@ -569,7 +635,7 @@ function createOgImageRoute({ manifest }) {
569
635
  textOverflow: "ellipsis",
570
636
  whiteSpace: "nowrap"
571
637
  },
572
- children: displayUrl.path
638
+ children: renderText(displayUrl.path, 22, "mono")
573
639
  }
574
640
  ) : null
575
641
  ]
@@ -581,7 +647,7 @@ function createOgImageRoute({ manifest }) {
581
647
  }
582
648
  ),
583
649
  {
584
- fonts: await imageResponseFonts(entry),
650
+ fonts: fontSelection.fonts,
585
651
  headers: {
586
652
  ...CONTENT_TYPE_HEADER,
587
653
  ...successHeaders()
@@ -1,5 +1,4 @@
1
- import { ManifestLike } from '../../../types.js';
2
- import 'react';
1
+ import { M as ManifestLike } from '../../../types-CIwwieNw.js';
3
2
 
4
3
  declare function createRobotsTxtRoute(manifest: ManifestLike): () => Promise<Response>;
5
4