@publish.os/nextjs 0.0.1-alpha.90 → 0.0.1-alpha.91

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 (223) hide show
  1. package/compiler-assets/nextjs/defaults/group/layout.tsx +1 -5
  2. package/compiler-assets/nextjs/defaults/group/page.tsx +31 -22
  3. package/compiler-assets/nextjs/defaults/project/next.config.mjs +19 -10
  4. package/compiler-assets/nextjs/defaults/project/tsconfig.json.template +10 -0
  5. package/compiler-assets/nextjs/defaults/root/css/components/code-block.css +18 -0
  6. package/compiler-assets/nextjs/shims/document.tsx +38 -0
  7. package/compiler-assets/nextjs/shims/generated-leaf-page.tsx +2 -0
  8. package/compiler-assets/nextjs/shims/global-layout.tsx +8 -42
  9. package/compiler-assets/nextjs/shims/global-not-found.tsx +69 -0
  10. package/compiler-assets/nextjs/shims/markdown-route.ts +2 -0
  11. package/compiler-assets/nextjs/shims/metadata-icons.tsx +39 -0
  12. package/compiler-assets/nextjs/shims/not-found-content.tsx +53 -0
  13. package/compiler-assets/nextjs/shims/not-found-navigation.tsx +60 -0
  14. package/compiler-assets/nextjs/shims/proxy.ts +126 -60
  15. package/compiler-assets/nextjs/shims/site-fenced-code-block.tsx +2 -6
  16. package/compiler-assets/nextjs/shims/site-mdx-components.tsx +28 -16
  17. package/compiler-assets/nextjs/shims/site-mdx.tsx +6 -1
  18. package/dist/{build-operation-2JAYBSKF.js → build-operation-5QMLXF7N.js} +29 -23
  19. package/dist/{button-c3WGnxIj.d.ts → button-BdCScEKi.d.ts} +3 -3
  20. package/dist/capture-local-source-WGGDIUU2.js +258 -0
  21. package/dist/chunk-22RSSUNV.js +13 -0
  22. package/dist/{chunk-WKTEO6RS.js → chunk-4BC2L2KA.js} +46 -12
  23. package/dist/{chunk-WDY4IK6Z.js → chunk-5J3YUNRY.js} +3 -10
  24. package/dist/chunk-5KAD7W53.js +248 -0
  25. package/dist/{chunk-DWA3ZRGW.js → chunk-6C65KV7O.js} +2 -2
  26. package/dist/{chunk-GGKFQ3MA.js → chunk-6D2E6UMD.js} +144 -70
  27. package/dist/{chunk-7OGTPSKI.js → chunk-7NY22B5U.js} +8 -3
  28. package/dist/chunk-EFO6AWXN.js +19 -0
  29. package/dist/{chunk-726GV2NF.js → chunk-F3AGNDF4.js} +100 -67
  30. package/dist/chunk-GBPLER5H.js +426 -0
  31. package/dist/chunk-IL4RJOKI.js +186 -0
  32. package/dist/{chunk-DLDFHU7Y.js → chunk-NNBJZPFM.js} +4 -2
  33. package/dist/{chunk-VO2I7MTM.js → chunk-ORIUWJBQ.js} +8 -6
  34. package/dist/{chunk-H6XILMZX.js → chunk-OXOFRXEI.js} +1806 -831
  35. package/dist/chunk-UYGCOWRF.js +1709 -0
  36. package/dist/{chunk-YLTOLYWM.js → chunk-WL75GQ5M.js} +6 -18
  37. package/dist/compiler.d.ts +15 -2
  38. package/dist/compiler.js +90 -21
  39. package/dist/components/blocks/agent-actions.d.ts +81 -0
  40. package/dist/components/blocks/agent-actions.js +594 -0
  41. package/dist/components/blocks/toc.d.ts +43 -0
  42. package/dist/components/blocks/toc.js +136 -0
  43. package/dist/components/ui/button.d.ts +5 -0
  44. package/dist/components/ui/button.js +94 -0
  45. package/dist/compose-CVBJRAF6.js +16 -0
  46. package/dist/config/createNextConfig.js +17 -3
  47. package/dist/{dev-operation-TZDVJCN7.js → dev-operation-OSHHWRWK.js} +121 -81
  48. package/dist/{framework-selection-X4U6Y6QC.js → framework-selection-ZVO323PK.js} +3 -2
  49. package/dist/ide-support-CU6Z5PVR.js +16 -0
  50. package/dist/index.d.ts +40 -1
  51. package/dist/jsx-dev-runtime.d.ts +6 -0
  52. package/dist/jsx-dev-runtime.js +100 -0
  53. package/dist/jsx-runtime.d.ts +7 -0
  54. package/dist/jsx-runtime.js +97 -0
  55. package/dist/kernel/components/blocks/AgentActions.d.ts +35 -6
  56. package/dist/kernel/components/blocks/AgentActions.js +383 -142
  57. package/dist/kernel/components/blocks/agent-actions.d.ts +5 -0
  58. package/dist/kernel/components/blocks/agent-actions.js +594 -0
  59. package/dist/kernel/components/blocks/animated-icon-swap.js +1 -1
  60. package/dist/kernel/components/blocks/color-palette.js +4 -4
  61. package/dist/kernel/components/blocks/logo-block.js +1 -1
  62. package/dist/kernel/components/blocks/nav-breadcrumb.js +2 -2
  63. package/dist/kernel/components/blocks/navbar.js +17 -17
  64. package/dist/kernel/components/blocks/navigation-progress.js +2 -2
  65. package/dist/kernel/components/blocks/next-prev.js +1 -1
  66. package/dist/kernel/components/blocks/page-list.js +2 -2
  67. package/dist/kernel/components/blocks/search.d.ts +1 -1
  68. package/dist/kernel/components/blocks/search.js +16 -17
  69. package/dist/kernel/components/blocks/sidebar-node.js +1 -1
  70. package/dist/kernel/components/blocks/sidebar.js +7 -4
  71. package/dist/kernel/components/blocks/theme-toggle.d.ts +1 -1
  72. package/dist/kernel/components/blocks/theme-toggle.js +5 -5
  73. package/dist/kernel/components/blocks/toc-client.d.ts +40 -0
  74. package/dist/kernel/components/blocks/toc-client.js +495 -0
  75. package/dist/kernel/components/blocks/toc.d.ts +19 -1
  76. package/dist/kernel/components/blocks/toc.js +121 -179
  77. package/dist/kernel/components/mdx/components/blockquote.js +1 -1
  78. package/dist/kernel/components/mdx/components/callout.js +1 -1
  79. package/dist/kernel/components/mdx/components/code-block.js +2 -2
  80. package/dist/kernel/components/mdx/components/copy-code-button.js +5 -4
  81. package/dist/kernel/components/mdx/components/figure-caption.d.ts +1 -1
  82. package/dist/kernel/components/mdx/components/figure-caption.js +3 -2
  83. package/dist/kernel/components/mdx/components/figure.d.ts +6 -2
  84. package/dist/kernel/components/mdx/components/figure.js +23 -13
  85. package/dist/kernel/components/mdx/components/footnotes.js +1 -1
  86. package/dist/kernel/components/mdx/components/heading-copy-link.js +1 -1
  87. package/dist/kernel/components/mdx/components/heading.js +6 -3
  88. package/dist/kernel/components/mdx/components/hr.js +2 -2
  89. package/dist/kernel/components/mdx/components/image-zoom.js +1 -1
  90. package/dist/kernel/components/mdx/components/image.d.ts +1 -1
  91. package/dist/kernel/components/mdx/components/image.js +21 -16
  92. package/dist/kernel/components/mdx/components/inline-code.js +1 -1
  93. package/dist/kernel/components/mdx/components/kbd.js +2 -2
  94. package/dist/kernel/components/mdx/components/link.d.ts +3 -3
  95. package/dist/kernel/components/mdx/components/link.js +2 -2
  96. package/dist/kernel/components/mdx/components/paragraph.js +1 -1
  97. package/dist/kernel/components/mdx/components/strikethrough.js +1 -1
  98. package/dist/kernel/components/mdx/components/table.js +2 -2
  99. package/dist/kernel/components/mdx/components/task-list.js +1 -1
  100. package/dist/kernel/components/mdx/components/video-player.d.ts +6 -2
  101. package/dist/kernel/components/mdx/components/video-player.js +6 -2
  102. package/dist/kernel/components/mdx/components/video.d.ts +5 -3
  103. package/dist/kernel/components/mdx/components/video.js +7 -5
  104. package/dist/kernel/components/mdx/error-boundary.d.ts +1 -1
  105. package/dist/kernel/components/mdx/error-boundary.js +2 -2
  106. package/dist/kernel/components/mdx/error-fallback.js +1 -1
  107. package/dist/kernel/components/mdx/mdx.d.ts +20 -10
  108. package/dist/kernel/components/mdx/mdx.js +231 -34
  109. package/dist/kernel/components/mdx/rehype-heading-ids.d.ts +1 -0
  110. package/dist/kernel/components/mdx/rehype-heading-ids.js +5 -3
  111. package/dist/kernel/components/mdx/types.d.ts +1 -1
  112. package/dist/kernel/components/next-image.d.ts +12 -0
  113. package/dist/kernel/components/next-image.js +61 -0
  114. package/dist/kernel/components/ui/accordion.js +1 -1
  115. package/dist/kernel/components/ui/breadcrumb-trail.d.ts +2 -2
  116. package/dist/kernel/components/ui/breadcrumb-trail.js +2 -2
  117. package/dist/kernel/components/ui/breadcrumb.d.ts +1 -1
  118. package/dist/kernel/components/ui/breadcrumb.js +4 -4
  119. package/dist/kernel/components/ui/button-group.d.ts +1 -1
  120. package/dist/kernel/components/ui/button-group.js +3 -3
  121. package/dist/kernel/components/ui/button.d.ts +56 -4
  122. package/dist/kernel/components/ui/button.js +43 -39
  123. package/dist/kernel/components/ui/card.js +1 -1
  124. package/dist/kernel/components/ui/dialog.js +1 -1
  125. package/dist/kernel/components/ui/drawer.js +1 -1
  126. package/dist/kernel/components/ui/input.d.ts +2 -2
  127. package/dist/kernel/components/ui/input.js +1 -1
  128. package/dist/kernel/components/ui/kbd.d.ts +1 -1
  129. package/dist/kernel/components/ui/kbd.js +1 -1
  130. package/dist/kernel/components/ui/link.d.ts +8 -2
  131. package/dist/kernel/components/ui/link.js +2 -2
  132. package/dist/kernel/components/ui/menu.js +1 -1
  133. package/dist/kernel/components/ui/mod-key.js +2 -2
  134. package/dist/kernel/components/ui/navigation-menu.js +1 -1
  135. package/dist/kernel/components/ui/popover.js +1 -1
  136. package/dist/kernel/components/ui/progress.js +1 -1
  137. package/dist/kernel/components/ui/scroll-area.d.ts +8 -8
  138. package/dist/kernel/components/ui/scroll-area.js +1 -1
  139. package/dist/kernel/components/ui/select.js +1 -1
  140. package/dist/kernel/components/ui/separator.js +1 -1
  141. package/dist/kernel/components/ui/table.js +1 -1
  142. package/dist/kernel/components/ui/tabs.js +1 -1
  143. package/dist/kernel/components/ui/tag.js +1 -1
  144. package/dist/kernel/components/ui/text.d.ts +1 -1
  145. package/dist/kernel/components/ui/text.js +1 -1
  146. package/dist/kernel/components/ui/toast.js +1 -1
  147. package/dist/kernel/components/ui/tooltip.js +1 -1
  148. package/dist/kernel/defaults.registry.d.ts +2 -15
  149. package/dist/kernel/defaults.registry.js +2 -17
  150. package/dist/kernel/routes/agent/markdown.d.ts +3 -0
  151. package/dist/kernel/routes/agent/markdown.js +219 -48
  152. package/dist/kernel/routes/layouts/group.d.ts +1 -1
  153. package/dist/kernel/routes/layouts/group.js +5 -7
  154. package/dist/kernel/routes/metadata/feed.d.ts +1 -1
  155. package/dist/kernel/routes/metadata/feed.js +109 -83
  156. package/dist/kernel/routes/metadata/llms.d.ts +11 -3
  157. package/dist/kernel/routes/metadata/llms.js +154 -57
  158. package/dist/kernel/routes/metadata/og-image.js +1 -1
  159. package/dist/kernel/routes/metadata/robots.d.ts +1 -1
  160. package/dist/kernel/routes/metadata/sitemap.d.ts +22 -3
  161. package/dist/kernel/routes/metadata/sitemap.js +183 -43
  162. package/dist/kernel/routes/not-found.d.ts +34 -0
  163. package/dist/kernel/routes/not-found.js +213 -0
  164. package/dist/kernel/routes/pages/group.d.ts +2 -2
  165. package/dist/kernel/routes/pages/group.js +1 -1
  166. package/dist/kernel/routes/pages/leaf.d.ts +30 -3
  167. package/dist/kernel/routes/pages/leaf.js +5 -4
  168. package/dist/kernel/routes/pages/root.d.ts +2 -2
  169. package/dist/kernel/routes/pages/root.js +1 -1
  170. package/dist/keyboard-shortcuts.js +1 -1
  171. package/dist/route-metadata-og-image-BeKKFHg7.d.ts +58 -0
  172. package/dist/search.js +7 -9
  173. package/dist/theme-scope.js +1 -1
  174. package/dist/{types-BzkZty3r.d.ts → types-J2w_puPF.d.ts} +1 -20
  175. package/dist/types-sM2g9nW0.d.ts +12 -0
  176. package/dist/types.d.ts +1 -0
  177. package/dist/utils/heading-ids.js +30 -11
  178. package/dist/utils/toc-selection.d.ts +7 -0
  179. package/dist/utils/toc-selection.js +14 -0
  180. package/dist/validate-local-source-SV44DBQT.js +16 -0
  181. package/dist/validate-publish-os-source-NZJF3TB2.js +14 -0
  182. package/init/seed/minimal/publish.os/assets/blog/hello-world.svg +13 -0
  183. package/init/seed/minimal/publish.os/assets/favicon.dark.svg +13 -0
  184. package/init/seed/minimal/publish.os/assets/favicon.svg +13 -0
  185. package/init/seed/minimal/publish.os/blog/content/hello-world.mdx +48 -0
  186. package/init/seed/minimal/publish.os/blog/content/series-a.mdx +11 -0
  187. package/init/seed/minimal/publish.os/blog/index.tsx +82 -0
  188. package/init/seed/minimal/publish.os/blog/layout.tsx +13 -0
  189. package/init/seed/minimal/publish.os/blog/page.tsx +76 -0
  190. package/init/seed/minimal/publish.os/components/blog/copy-link.tsx +64 -0
  191. package/init/seed/minimal/publish.os/docs/content/get-started.mdx +2 -3
  192. package/init/seed/minimal/publish.os/docs/content/groups.mdx +5 -6
  193. package/init/seed/minimal/publish.os/publish.os.config.json +6 -2
  194. package/init/seed/minimal/publish.os/theme.css +3 -3
  195. package/init/seed/minimal/seed.json +11 -4
  196. package/init/seed/scratch/publish.os/docs/content/get-started.mdx +1 -1
  197. package/init/seed/scratch/publish.os/publish.os.config.json +1 -1
  198. package/package.json +45 -20
  199. package/release/app/phosphor/package.json +3 -3
  200. package/release/app/phosphor/pnpm-lock.yaml.template +88 -75
  201. package/release/compiler/package.json +5 -3
  202. package/release/compiler/pnpm-lock.yaml.template +118 -74
  203. package/release/release.json +6 -6
  204. package/dist/button-CtzUJB8u.d.ts +0 -11
  205. package/dist/chunk-535TM4A5.js +0 -1455
  206. package/dist/chunk-B2V22WRT.js +0 -297
  207. package/dist/chunk-NECL5IBJ.js +0 -318
  208. package/dist/chunk-SVYGXXYR.js +0 -36
  209. package/dist/chunk-UF6ATARM.js +0 -1100
  210. package/dist/compose-NN23UJGC.js +0 -13
  211. package/dist/ide-support-ZNW7ODFY.js +0 -15
  212. package/dist/kernel/components/blocks/design-system-preview.d.ts +0 -61
  213. package/dist/kernel/components/blocks/design-system-preview.js +0 -667
  214. package/dist/kernel/components/blocks/link-playground.d.ts +0 -5
  215. package/dist/kernel/components/blocks/link-playground.js +0 -744
  216. package/dist/kernel/components/blocks/navigation-progress-playground.d.ts +0 -5
  217. package/dist/kernel/components/blocks/navigation-progress-playground.js +0 -629
  218. package/dist/kernel/components/ui/theme-toggle.d.ts +0 -24
  219. package/dist/kernel/components/ui/theme-toggle.js +0 -53
  220. package/dist/validate-local-source-XRL2Y7XE.js +0 -14
  221. package/dist/validate-publish-os-source-DAPZ4QGE.js +0 -12
  222. package/init/seed/minimal/publish.os/assets/favicon/favicon.dark.png +0 -0
  223. package/init/seed/minimal/publish.os/assets/favicon/favicon.png +0 -0
@@ -0,0 +1,1709 @@
1
+ import {
2
+ SOURCE_ASSET_PREFIX
3
+ } from "./chunk-EFO6AWXN.js";
4
+ import {
5
+ MAX_MEDIA_SVG_BYTES,
6
+ ignoredMediaDocumentWarning,
7
+ ignoredMediaPathWarning,
8
+ mediaFileByteLimit,
9
+ mediaFileTooLarge,
10
+ readBoundedMediaFile
11
+ } from "./chunk-5KAD7W53.js";
12
+ import {
13
+ isExcludedSourcePath,
14
+ isSameOrDescendant
15
+ } from "./chunk-WL75GQ5M.js";
16
+ import {
17
+ AppError
18
+ } from "./chunk-22RSSUNV.js";
19
+
20
+ // src/lib/compiler/source/mdx-component-contract.ts
21
+ import ts from "typescript";
22
+ var groupedMdxExports = {
23
+ figure: { FigureCaption: "figcaption" },
24
+ table: {
25
+ TableHeadGroup: "thead",
26
+ TableBodyGroup: "tbody",
27
+ TableRowGroup: "tr",
28
+ TableHeaderCell: "th",
29
+ TableDataCell: "td"
30
+ }
31
+ }, replacedMdxSourceFiles = {
32
+ a: "link",
33
+ "figure-caption": "figure",
34
+ h1: "heading",
35
+ h2: "heading",
36
+ h3: "heading",
37
+ h4: "heading",
38
+ h5: "heading",
39
+ h6: "heading",
40
+ img: "image",
41
+ pre: "code-block",
42
+ "table-body-group": "table",
43
+ "table-data-cell": "table",
44
+ "table-header-cell": "table",
45
+ "table-head-group": "table",
46
+ "table-row-group": "table"
47
+ };
48
+ function mdxComponentExportName(stem) {
49
+ return stem.split("-").map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("");
50
+ }
51
+ function collectBindingNames(name) {
52
+ return ts.isIdentifier(name) ? [name.text] : name.elements.flatMap(
53
+ (element) => ts.isOmittedExpression(element) ? [] : collectBindingNames(element.name)
54
+ );
55
+ }
56
+ function namedValueExports(sourceFile) {
57
+ let names = /* @__PURE__ */ new Set();
58
+ for (let statement of sourceFile.statements) {
59
+ if (ts.isExportDeclaration(statement) && !statement.isTypeOnly && statement.exportClause && ts.isNamedExports(statement.exportClause)) {
60
+ for (let element of statement.exportClause.elements)
61
+ element.isTypeOnly || names.add(element.name.text);
62
+ continue;
63
+ }
64
+ if (!ts.canHaveModifiers(statement)) continue;
65
+ let modifiers = ts.getModifiers(statement);
66
+ if (!(!modifiers?.some(
67
+ (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword
68
+ ) || modifiers.some(
69
+ (modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword
70
+ ))) {
71
+ if ((ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name)
72
+ names.add(statement.name.text);
73
+ else if (ts.isVariableStatement(statement))
74
+ for (let declaration of statement.declarationList.declarations)
75
+ for (let name of collectBindingNames(declaration.name))
76
+ names.add(name);
77
+ }
78
+ }
79
+ return names;
80
+ }
81
+
82
+ // src/lib/compiler/source/mdx-icon-imports.ts
83
+ import { readFile } from "fs/promises";
84
+ import { createRequire } from "module";
85
+ import { dirname, resolve } from "path";
86
+ import remarkMdx from "remark-mdx";
87
+ import remarkParse from "remark-parse";
88
+ import ts2 from "typescript";
89
+ import { unified } from "unified";
90
+
91
+ // src/lib/compiler/source/frontmatter.ts
92
+ import matter from "gray-matter";
93
+ var DATA_LANGUAGES = /* @__PURE__ */ new Set(["json", "yaml", "yml"]), FRONTMATTER_DELIMITER = "---", UnsupportedFrontmatterLanguageError = class extends Error {
94
+ constructor(language) {
95
+ super(`Unsupported frontmatter language "${language}". Use YAML or JSON.`);
96
+ this.language = language;
97
+ this.name = "UnsupportedFrontmatterLanguageError";
98
+ }
99
+ language;
100
+ };
101
+ function frontmatterLanguage(source) {
102
+ if (!matter.test(source) || source[FRONTMATTER_DELIMITER.length] === FRONTMATTER_DELIMITER.at(-1))
103
+ return;
104
+ let lineEnd = source.indexOf(`
105
+ `, FRONTMATTER_DELIMITER.length), headerEnd = lineEnd === -1 ? source.length : lineEnd;
106
+ return source.slice(FRONTMATTER_DELIMITER.length, headerEnd).replace(/\r$/, "").trim();
107
+ }
108
+ function parseSourceFrontmatter(source) {
109
+ let inspected = source.charCodeAt(0) === 65279 ? source.slice(1) : source, marker = frontmatterLanguage(inspected), language = marker?.toLowerCase();
110
+ if (marker && language && (!DATA_LANGUAGES.has(language) || language === "json" && marker !== "json"))
111
+ throw new UnsupportedFrontmatterLanguageError(marker);
112
+ return matter(source, { language: "yaml" });
113
+ }
114
+
115
+ // src/lib/compiler/source/mdx-icon-imports.ts
116
+ var mdxIconPackage = "@phosphor-icons/react/ssr", parser = unified().use(remarkParse).use(remarkMdx), MdxIconImportError = class extends Error {
117
+ constructor(message, line, column, code = "FRAMEWORK_MDX_IMPORT_REJECTED") {
118
+ super(message);
119
+ this.line = line;
120
+ this.column = column;
121
+ this.code = code;
122
+ }
123
+ line;
124
+ column;
125
+ code;
126
+ };
127
+ function mdxIconImportsFromTree(tree, lineOffset = 0) {
128
+ let imports = [];
129
+ for (let node of tree.children)
130
+ if (node.type === "mdxjsEsm")
131
+ for (let statement of node.data?.estree?.body ?? []) {
132
+ let line = (statement.loc?.start.line ?? node.position?.start.line ?? 1) + lineOffset, column = (statement.loc?.start.column ?? 0) + 1;
133
+ if (statement.type !== "ImportDeclaration" || statement.source.value !== mdxIconPackage || statement.specifiers.length === 0 || statement.specifiers.some(
134
+ (specifier) => specifier.type !== "ImportSpecifier"
135
+ ))
136
+ throw new MdxIconImportError(
137
+ `MDX supports named icon imports from "${mdxIconPackage}". Use import { ArrowRightIcon } from "${mdxIconPackage}". Other MDX imports and exports are unsupported.`,
138
+ line,
139
+ column
140
+ );
141
+ for (let specifier of statement.specifiers) {
142
+ if (specifier.type !== "ImportSpecifier") continue;
143
+ if (specifier.imported.type !== "Identifier")
144
+ throw new MdxIconImportError(
145
+ "Import an icon by its exact identifier, such as ArrowRightIcon.",
146
+ line,
147
+ column
148
+ );
149
+ let imported = specifier.imported.name;
150
+ imports.push({ imported, local: specifier.local.name, line, column });
151
+ }
152
+ }
153
+ return imports;
154
+ }
155
+ function readMdxIconImports(source, lineOffset = 0) {
156
+ return /^\s*(?:import|export)\s/m.test(source) ? mdxIconImportsFromTree(parser.parse(source), lineOffset) : [];
157
+ }
158
+ var exportedIcons;
159
+ async function validateMdxIconImports(source) {
160
+ if (!/^\s*(?:import|export)\s/m.test(source)) return [];
161
+ let body = parseSourceFrontmatter(source).content, lineOffset = source.slice(0, source.length - body.length).split(`
162
+ `).length - 1, imports = readMdxIconImports(body, lineOffset);
163
+ if (imports.length === 0) return imports;
164
+ exportedIcons ??= (async () => {
165
+ let require2 = createRequire(import.meta.url), entry = resolve(
166
+ dirname(require2.resolve("@phosphor-icons/react/package.json")),
167
+ "dist/ssr/index.es.js"
168
+ );
169
+ return namedValueExports(
170
+ ts2.createSourceFile(
171
+ entry,
172
+ await readFile(entry, "utf8"),
173
+ ts2.ScriptTarget.Latest,
174
+ !0
175
+ )
176
+ );
177
+ })();
178
+ let exports = await exportedIcons;
179
+ for (let binding of imports)
180
+ if (!exports.has(binding.imported))
181
+ throw new MdxIconImportError(
182
+ `"${binding.imported}" is not exported by "${mdxIconPackage}". Import an exact icon export such as ArrowRightIcon.`,
183
+ binding.line,
184
+ binding.column,
185
+ "FRAMEWORK_MDX_IMPORT_EXPORT_MISSING"
186
+ );
187
+ return imports;
188
+ }
189
+
190
+ // src/lib/compiler/source/config/root-content-group.ts
191
+ var ROOT_CONTENT_GROUP_KEY = "__root", ROOT_CONTENT_GROUP_TITLE = "Root";
192
+
193
+ // src/lib/compiler/source/assert-source-dependency.ts
194
+ import { lstat } from "fs/promises";
195
+ import { isAbsolute, relative, resolve as resolve2, sep } from "path";
196
+ async function assertSourceDependency({
197
+ publishOsDir,
198
+ path,
199
+ sourceFile
200
+ }) {
201
+ let root = resolve2(publishOsDir), target = resolve2(path), targetRelativePath = relative(root, target), details = {
202
+ file: (isAbsolute(sourceFile) ? relative(root, sourceFile) : sourceFile).split(sep).join("/"),
203
+ target: targetRelativePath.split(sep).join("/")
204
+ };
205
+ if (!isSameOrDescendant(root, target))
206
+ throw new AppError({
207
+ code: "FRAMEWORK_SOURCE_DEPENDENCY_ESCAPE",
208
+ message: "Source dependencies must stay inside publish.os.",
209
+ details
210
+ });
211
+ if (isExcludedSourcePath(details.target))
212
+ throw new AppError({
213
+ code: "FRAMEWORK_SOURCE_DEPENDENCY_EXCLUDED",
214
+ message: "Source dependencies cannot use nested sites, generated output, or root IDE metadata.",
215
+ details
216
+ });
217
+ let segments = targetRelativePath ? targetRelativePath.split(sep) : [], current = root;
218
+ for (let segment of ["", ...segments]) {
219
+ current = resolve2(current, segment);
220
+ let entry = await lstat(current).catch((error) => {
221
+ throw error.code !== "ENOENT" && error.code !== "ENOTDIR" ? error : new AppError({
222
+ code: "FRAMEWORK_SOURCE_DEPENDENCY_MISSING",
223
+ message: "A source dependency does not exist.",
224
+ details
225
+ });
226
+ });
227
+ if (entry.isSymbolicLink())
228
+ throw new AppError({
229
+ code: "FRAMEWORK_SOURCE_DEPENDENCY_SYMLINK",
230
+ message: "Source dependencies cannot use symbolic links.",
231
+ details
232
+ });
233
+ if (current === target ? !entry.isFile() : !entry.isDirectory())
234
+ throw new AppError({
235
+ code: "FRAMEWORK_SOURCE_DEPENDENCY_NOT_FILE",
236
+ message: "A source dependency must resolve to a regular file.",
237
+ details
238
+ });
239
+ }
240
+ }
241
+
242
+ // src/lib/compiler/packages/nextjs-runtime-surface.json
243
+ var nextjs_runtime_surface_default = {
244
+ packageExports: [
245
+ ".",
246
+ "./jsx-runtime",
247
+ "./jsx-dev-runtime",
248
+ "./resolvers/manifest-resolver",
249
+ "./mdx/error-boundary",
250
+ "./mdx/error-fallback",
251
+ "./mdx/mdx",
252
+ "./mdx/rehype-heading-ids",
253
+ "./mdx/types",
254
+ "./mdx/components/blockquote",
255
+ "./mdx/components/callout",
256
+ "./mdx/components/code-block",
257
+ "./mdx/components/figure-caption",
258
+ "./mdx/components/figure",
259
+ "./mdx/components/footnotes",
260
+ "./mdx/components/heading-copy-link",
261
+ "./mdx/components/heading",
262
+ "./mdx/components/hr",
263
+ "./mdx/components/image-zoom",
264
+ "./mdx/components/image",
265
+ "./mdx/components/inline-code",
266
+ "./mdx/components/kbd",
267
+ "./mdx/components/link",
268
+ "./mdx/components/paragraph",
269
+ "./mdx/components/strikethrough",
270
+ "./mdx/components/table",
271
+ "./mdx/components/task-list",
272
+ "./mdx/components/video",
273
+ "./mdx",
274
+ "./cache/tags",
275
+ "./keyboard-shortcuts",
276
+ "./search",
277
+ "./theme-scope",
278
+ "./types",
279
+ "./kernel/defaults.registry",
280
+ "./kernel/routes/agent/markdown",
281
+ "./kernel/routes/not-found",
282
+ "./kernel/routes/layouts/group",
283
+ "./kernel/routes/metadata/feed",
284
+ "./kernel/routes/metadata/llms",
285
+ "./kernel/routes/metadata/og-image",
286
+ "./kernel/routes/metadata/robots",
287
+ "./kernel/routes/metadata/sitemap",
288
+ "./kernel/routes/pages/group",
289
+ "./kernel/routes/pages/leaf",
290
+ "./kernel/routes/pages/root",
291
+ "./kernel/components/blocks/AgentActions",
292
+ "./kernel/components/blocks/agent-actions",
293
+ "./kernel/components/blocks/animated-icon-swap",
294
+ "./kernel/components/blocks/color-palette",
295
+ "./kernel/components/blocks/logo-block",
296
+ "./kernel/components/blocks/nav-breadcrumb",
297
+ "./kernel/components/blocks/navbar",
298
+ "./kernel/components/blocks/navigation-progress",
299
+ "./kernel/components/blocks/next-prev",
300
+ "./kernel/components/blocks/page-list",
301
+ "./kernel/components/blocks/search",
302
+ "./kernel/components/blocks/sidebar-node",
303
+ "./kernel/components/blocks/sidebar",
304
+ "./kernel/components/blocks/theme-toggle",
305
+ "./kernel/components/blocks/toc",
306
+ "./kernel/components/blocks/toc-client",
307
+ "./kernel/components/next-image",
308
+ "./kernel/components/mdx/error-boundary",
309
+ "./kernel/components/mdx/error-fallback",
310
+ "./kernel/components/mdx/mdx",
311
+ "./kernel/components/mdx/rehype-heading-ids",
312
+ "./kernel/components/mdx/types",
313
+ "./kernel/components/mdx/components/blockquote",
314
+ "./kernel/components/mdx/components/callout",
315
+ "./kernel/components/mdx/components/code-block",
316
+ "./kernel/components/mdx/components/copy-code-button",
317
+ "./kernel/components/mdx/components/figure-caption",
318
+ "./kernel/components/mdx/components/figure",
319
+ "./kernel/components/mdx/components/footnotes",
320
+ "./kernel/components/mdx/components/heading-copy-link",
321
+ "./kernel/components/mdx/components/heading",
322
+ "./kernel/components/mdx/components/hr",
323
+ "./kernel/components/mdx/components/image-zoom",
324
+ "./kernel/components/mdx/components/image",
325
+ "./kernel/components/mdx/components/inline-code",
326
+ "./kernel/components/mdx/components/kbd",
327
+ "./kernel/components/mdx/components/link",
328
+ "./kernel/components/mdx/components/paragraph",
329
+ "./kernel/components/mdx/components/strikethrough",
330
+ "./kernel/components/mdx/components/table",
331
+ "./kernel/components/mdx/components/task-list",
332
+ "./kernel/components/mdx/components/video-player",
333
+ "./kernel/components/mdx/components/video",
334
+ "./kernel/components/ui/accordion",
335
+ "./kernel/components/ui/breadcrumb-trail",
336
+ "./kernel/components/ui/breadcrumb",
337
+ "./kernel/components/ui/button-group",
338
+ "./kernel/components/ui/button",
339
+ "./components/ui/button",
340
+ "./components/blocks/toc",
341
+ "./components/blocks/agent-actions",
342
+ "./kernel/components/ui/card",
343
+ "./kernel/components/ui/dialog",
344
+ "./kernel/components/ui/drawer",
345
+ "./kernel/components/ui/input",
346
+ "./kernel/components/ui/kbd",
347
+ "./kernel/components/ui/link",
348
+ "./kernel/components/ui/menu",
349
+ "./kernel/components/ui/mod-key",
350
+ "./kernel/components/ui/navigation-menu",
351
+ "./kernel/components/ui/popover",
352
+ "./kernel/components/ui/progress",
353
+ "./kernel/components/ui/scroll-area",
354
+ "./kernel/components/ui/select",
355
+ "./kernel/components/ui/separator",
356
+ "./kernel/components/ui/table",
357
+ "./kernel/components/ui/tabs",
358
+ "./kernel/components/ui/tag",
359
+ "./kernel/components/ui/text",
360
+ "./kernel/components/ui/toast",
361
+ "./kernel/components/ui/tooltip",
362
+ "./utils/pretty-date",
363
+ "./utils/cn",
364
+ "./utils/heading-ids",
365
+ "./utils/toc-selection",
366
+ "./config/createNextConfig"
367
+ ],
368
+ allowedSourceImports: [
369
+ "@publish.os/nextjs",
370
+ "@publish.os/nextjs/jsx-runtime",
371
+ "@publish.os/nextjs/jsx-dev-runtime",
372
+ "@publish.os/nextjs/cache/tags",
373
+ "@publish.os/nextjs/config/createNextConfig",
374
+ "@publish.os/nextjs/kernel/components/blocks/navigation-progress",
375
+ "@publish.os/nextjs/components/ui/button",
376
+ "@publish.os/nextjs/components/blocks/toc",
377
+ "@publish.os/nextjs/components/blocks/agent-actions",
378
+ "@publish.os/nextjs/kernel/components/blocks/toc-client",
379
+ "@publish.os/nextjs/kernel/routes/layouts/group",
380
+ "@publish.os/nextjs/kernel/routes/metadata/feed",
381
+ "@publish.os/nextjs/kernel/routes/metadata/llms",
382
+ "@publish.os/nextjs/kernel/routes/metadata/og-image",
383
+ "@publish.os/nextjs/kernel/routes/metadata/robots",
384
+ "@publish.os/nextjs/kernel/routes/metadata/sitemap",
385
+ "@publish.os/nextjs/kernel/routes/pages/group",
386
+ "@publish.os/nextjs/kernel/routes/pages/leaf",
387
+ "@publish.os/nextjs/kernel/routes/pages/root",
388
+ "@publish.os/nextjs/keyboard-shortcuts",
389
+ "@publish.os/nextjs/mdx",
390
+ "@publish.os/nextjs/mdx/error-boundary",
391
+ "@publish.os/nextjs/mdx/error-fallback",
392
+ "@publish.os/nextjs/mdx/mdx",
393
+ "@publish.os/nextjs/resolvers/manifest-resolver",
394
+ "@publish.os/nextjs/search",
395
+ "@publish.os/nextjs/theme-scope",
396
+ "@publish.os/nextjs/types",
397
+ "@publish.os/nextjs/utils/cn",
398
+ "@publish.os/nextjs/utils/heading-ids",
399
+ "@publish.os/nextjs/utils/toc-selection",
400
+ "@publish.os/nextjs/utils/pretty-date"
401
+ ],
402
+ allowedSourceDependencyImports: [
403
+ "@phosphor-icons/react/ssr",
404
+ "react",
405
+ "react-dom",
406
+ "class-variance-authority",
407
+ "next/link",
408
+ "next/image",
409
+ "next/navigation",
410
+ "@base-ui/react/accordion",
411
+ "@base-ui/react/button",
412
+ "@base-ui/react/checkbox",
413
+ "@base-ui/react/dialog",
414
+ "@base-ui/react/drawer",
415
+ "@base-ui/react/input",
416
+ "@base-ui/react/menu",
417
+ "@base-ui/react/popover",
418
+ "@base-ui/react/progress",
419
+ "@base-ui/react/scroll-area",
420
+ "@base-ui/react/select",
421
+ "@base-ui/react/separator",
422
+ "@base-ui/react/switch",
423
+ "@base-ui/react/tabs",
424
+ "@base-ui/react/tooltip",
425
+ "@base-ui/react/toast"
426
+ ],
427
+ entries: {
428
+ index: "src/index.ts",
429
+ "jsx-runtime": "src/jsx-runtime.ts",
430
+ "jsx-dev-runtime": "src/jsx-dev-runtime.ts",
431
+ "cache/tags": "src/cache-tags.ts",
432
+ "config/createNextConfig": "src/create-next-config.ts",
433
+ "keyboard-shortcuts": "src/lib/keyboard/keyboard-shortcuts.tsx",
434
+ search: "src/modules/search/search.tsx",
435
+ "theme-scope": "src/lib/theme/theme-scope.tsx",
436
+ "kernel/defaults.registry": "src/defaults-registry.ts",
437
+ "kernel/components/blocks/AgentActions": "src/modules/agent-actions/agent-actions.tsx",
438
+ "kernel/components/blocks/agent-actions": "src/modules/agent-actions/agent-actions.tsx",
439
+ "kernel/components/blocks/animated-icon-swap": "src/components/ui/animated-icon-swap.tsx",
440
+ "kernel/components/blocks/color-palette": "src/modules/design-system/color-palette.tsx",
441
+ "kernel/components/blocks/logo-block": "src/components/block/logo-block.tsx",
442
+ "kernel/components/blocks/nav-breadcrumb": "src/components/block/navbar/nav-breadcrumb.tsx",
443
+ "kernel/components/blocks/navbar": "src/components/block/navbar/navbar.tsx",
444
+ "kernel/components/blocks/navigation-progress": "src/components/block/navigation-progress.tsx",
445
+ "kernel/components/blocks/next-prev": "src/components/block/page-navigation/next-prev.tsx",
446
+ "kernel/components/blocks/page-list": "src/components/block/page-navigation/page-list.tsx",
447
+ "kernel/components/blocks/search": "src/modules/search/search-block.tsx",
448
+ "kernel/components/blocks/sidebar-node": "src/components/block/sidebar/sidebar-node.tsx",
449
+ "kernel/components/blocks/sidebar": "src/components/block/sidebar/sidebar.tsx",
450
+ "kernel/components/blocks/theme-toggle": "src/components/block/theme-toggle.tsx",
451
+ "kernel/components/blocks/toc": "src/components/block/toc/toc.tsx",
452
+ "kernel/components/blocks/toc-client": "src/components/block/toc/toc-client.tsx",
453
+ "kernel/components/next-image": "src/components/next-image.tsx",
454
+ "kernel/components/mdx/error-boundary": "src/components/mdx/error-boundary.tsx",
455
+ "kernel/components/mdx/error-fallback": "src/components/mdx/error-fallback.tsx",
456
+ "kernel/components/mdx/mdx": "src/components/mdx/mdx.tsx",
457
+ "kernel/components/mdx/rehype-heading-ids": "src/components/mdx/plugins/rehype-heading-ids.ts",
458
+ "kernel/components/mdx/types": "src/components/mdx/types.ts",
459
+ "kernel/routes/layouts/group": "src/route-layout-group.tsx",
460
+ "kernel/routes/agent/markdown": "src/route-agent-markdown.ts",
461
+ "kernel/routes/not-found": "src/route-not-found.ts",
462
+ "kernel/routes/metadata/feed": "src/route-metadata-feed.ts",
463
+ "kernel/routes/metadata/llms": "src/route-metadata-llms.ts",
464
+ "kernel/routes/metadata/og-image": "src/route-metadata-og-image.tsx",
465
+ "kernel/routes/metadata/robots": "src/route-metadata-robots.ts",
466
+ "kernel/routes/metadata/sitemap": "src/route-metadata-sitemap.ts",
467
+ "kernel/routes/pages/group": "src/route-page-group.tsx",
468
+ "kernel/routes/pages/leaf": "src/route-page-leaf.tsx",
469
+ "kernel/routes/pages/root": "src/route-page-root.tsx",
470
+ "resolvers/manifest-resolver": "src/manifest-resolver.ts",
471
+ types: "src/types.ts",
472
+ "utils/cn": "src/components/utils/cn.ts",
473
+ "utils/heading-ids": "src/components/mdx/heading-ids.ts",
474
+ "utils/toc-selection": "src/components/block/toc/selection.ts",
475
+ "utils/pretty-date": "src/components/utils/pretty-date.ts",
476
+ "kernel/components/mdx/components/blockquote": "src/components/mdx/blockquote.tsx",
477
+ "kernel/components/mdx/components/callout": "src/components/mdx/callout.tsx",
478
+ "kernel/components/mdx/components/code-block": "src/components/mdx/code-block/code-block.tsx",
479
+ "kernel/components/mdx/components/copy-code-button": "src/components/mdx/code-block/copy-code-button.tsx",
480
+ "kernel/components/mdx/components/figure-caption": "src/components/mdx/figure/figure-caption.tsx",
481
+ "kernel/components/mdx/components/figure": "src/components/mdx/figure/figure.tsx",
482
+ "kernel/components/mdx/components/footnotes": "src/components/mdx/footnotes.tsx",
483
+ "kernel/components/mdx/components/heading-copy-link": "src/components/mdx/heading-copy-link.tsx",
484
+ "kernel/components/mdx/components/heading": "src/components/mdx/heading.tsx",
485
+ "kernel/components/mdx/components/hr": "src/components/mdx/hr.tsx",
486
+ "kernel/components/mdx/components/image-zoom": "src/components/mdx/image/image-zoom.tsx",
487
+ "kernel/components/mdx/components/image": "src/components/mdx/image/image.tsx",
488
+ "kernel/components/mdx/components/inline-code": "src/components/mdx/inline-code.tsx",
489
+ "kernel/components/mdx/components/kbd": "src/components/mdx/kbd.tsx",
490
+ "kernel/components/mdx/components/link": "src/components/mdx/link.tsx",
491
+ "kernel/components/mdx/components/paragraph": "src/components/mdx/paragraph.tsx",
492
+ "kernel/components/mdx/components/strikethrough": "src/components/mdx/strikethrough.tsx",
493
+ "kernel/components/mdx/components/table": "src/components/mdx/table.tsx",
494
+ "kernel/components/mdx/components/task-list": "src/components/mdx/task-list.tsx",
495
+ "kernel/components/mdx/components/video-player": "src/components/mdx/video/video-player.tsx",
496
+ "kernel/components/mdx/components/video": "src/components/mdx/video/video.tsx",
497
+ "kernel/components/ui/accordion": "src/components/ui/accordion.tsx",
498
+ "kernel/components/ui/breadcrumb-trail": "src/components/ui/breadcrumb-trail.tsx",
499
+ "kernel/components/ui/breadcrumb": "src/components/ui/breadcrumb.tsx",
500
+ "kernel/components/ui/button-group": "src/components/ui/button-group.tsx",
501
+ "kernel/components/ui/button": "src/components/ui/button.tsx",
502
+ "components/ui/button": "src/components/ui/button.tsx",
503
+ "components/blocks/toc": "src/components/block/toc/toc.tsx",
504
+ "components/blocks/agent-actions": "src/modules/agent-actions/agent-actions.tsx",
505
+ "kernel/components/ui/card": "src/components/ui/card.tsx",
506
+ "kernel/components/ui/dialog": "src/components/ui/dialog.tsx",
507
+ "kernel/components/ui/drawer": "src/components/ui/drawer.tsx",
508
+ "kernel/components/ui/input": "src/components/ui/input.tsx",
509
+ "kernel/components/ui/kbd": "src/components/ui/kbd.tsx",
510
+ "kernel/components/ui/link": "src/components/ui/link.tsx",
511
+ "kernel/components/ui/menu": "src/components/ui/menu.tsx",
512
+ "kernel/components/ui/mod-key": "src/components/ui/mod-key.tsx",
513
+ "kernel/components/ui/navigation-menu": "src/components/ui/navigation-menu.tsx",
514
+ "kernel/components/ui/popover": "src/components/ui/popover.tsx",
515
+ "kernel/components/ui/progress": "src/components/ui/progress.tsx",
516
+ "kernel/components/ui/scroll-area": "src/components/ui/scroll-area.tsx",
517
+ "kernel/components/ui/select": "src/components/ui/select.tsx",
518
+ "kernel/components/ui/separator": "src/components/ui/separator.tsx",
519
+ "kernel/components/ui/table": "src/components/ui/table.tsx",
520
+ "kernel/components/ui/tabs": "src/components/ui/tabs.tsx",
521
+ "kernel/components/ui/tag": "src/components/ui/tag.tsx",
522
+ "kernel/components/ui/text": "src/components/ui/text.tsx",
523
+ "kernel/components/ui/toast": "src/components/ui/toast.tsx",
524
+ "kernel/components/ui/tooltip": "src/components/ui/tooltip.tsx"
525
+ },
526
+ entryAliases: {},
527
+ browserEntries: [
528
+ "src/lib/keyboard/keyboard-shortcuts.tsx",
529
+ "src/modules/search/search.tsx",
530
+ "src/lib/theme/theme-scope.tsx",
531
+ "src/modules/agent-actions/agent-actions.tsx",
532
+ "src/modules/design-system/color-palette.tsx",
533
+ "src/components/block/navbar/navbar.tsx",
534
+ "src/components/block/navigation-progress.tsx",
535
+ "src/modules/search/search-block.tsx",
536
+ "src/components/block/sidebar/sidebar.tsx",
537
+ "src/components/block/toc/toc-client.tsx",
538
+ "src/components/mdx/error-boundary.tsx",
539
+ "src/components/mdx/types.ts",
540
+ "src/types.ts",
541
+ "src/components/utils/cn.ts",
542
+ "src/components/mdx/heading-ids.ts",
543
+ "src/components/utils/pretty-date.ts",
544
+ "src/components/mdx/heading-copy-link.tsx",
545
+ "src/components/mdx/image/image-zoom.tsx",
546
+ "src/components/mdx/video/video-player.tsx",
547
+ "src/components/ui/accordion.tsx",
548
+ "src/components/ui/breadcrumb-trail.tsx",
549
+ "src/components/ui/dialog.tsx",
550
+ "src/components/ui/drawer.tsx",
551
+ "src/components/ui/menu.tsx",
552
+ "src/components/ui/navigation-menu.tsx",
553
+ "src/components/ui/popover.tsx",
554
+ "src/components/ui/progress.tsx",
555
+ "src/components/ui/scroll-area.tsx",
556
+ "src/components/ui/tabs.tsx",
557
+ "src/components/ui/toast.tsx",
558
+ "src/components/ui/tooltip.tsx"
559
+ ]
560
+ };
561
+
562
+ // src/lib/compiler/packages/nextjs-runtime-surface.ts
563
+ var surface = nextjs_runtime_surface_default, allowedNextjsSourceImports = [...surface.allowedSourceImports], allowedNextjsSourceDependencyImports = [
564
+ ...surface.allowedSourceDependencyImports
565
+ ];
566
+ function supportedNextjsSourceImports() {
567
+ return [
568
+ ...allowedNextjsSourceImports,
569
+ ...allowedNextjsSourceDependencyImports
570
+ ];
571
+ }
572
+ function supportedRuntimeComponentAliases() {
573
+ return Object.keys(surface.entries).filter((name) => name.startsWith("kernel/components/")).map((name) => `@components/${name.slice(18)}`);
574
+ }
575
+ function originalDefaultComponentSourcePath(specifier) {
576
+ let prefix = "@publish.os/nextjs/";
577
+ if (!specifier.startsWith(prefix)) return;
578
+ let subpath = specifier.slice(prefix.length);
579
+ if (!surface.packageExports.includes(`./${subpath}`) || !surface.entries[subpath])
580
+ return;
581
+ let componentPrefix = "kernel/components/";
582
+ if (!subpath.startsWith(componentPrefix)) return;
583
+ let sourcePath = subpath.slice(componentPrefix.length);
584
+ if (sourcePath.startsWith("mdx/components/") && (sourcePath = `mdx/${sourcePath.slice(15)}`), !!/^(?:ui|blocks|mdx)\//.test(sourcePath))
585
+ return `components/${sourcePath}`;
586
+ }
587
+
588
+ // src/lib/compiler/source/assets/favicons-and-logos.ts
589
+ import { extname } from "path";
590
+ var MAX_FAVICON_BYTES = 1 * 1024 * 1024, MAX_LOGO_BYTES = 2 * 1024 * 1024, FAVICON_FORMATS = ["svg", "png", "jpg", "jpeg", "ico"], LOGO_FORMATS = ["svg", "png", "jpg", "jpeg", "webp", "avif"], FORMAT_RANK = {
591
+ svg: 0,
592
+ png: 1,
593
+ jpg: 2,
594
+ jpeg: 2,
595
+ ico: 3
596
+ }, LOGO_FORMAT_RANK = {
597
+ svg: 0,
598
+ png: 1,
599
+ jpg: 2,
600
+ jpeg: 2,
601
+ webp: 3,
602
+ avif: 4
603
+ };
604
+ function formatOf(path) {
605
+ return extname(path).slice(1).toLowerCase();
606
+ }
607
+ function normalizedToken(value) {
608
+ return value.toLowerCase().split(/[._-]+/).filter(Boolean);
609
+ }
610
+ function classifyPath(path) {
611
+ let segments = path.split("/"), file = segments.at(-1) ?? "", format = formatOf(file), stem = file.slice(0, -(format.length + 1)), tokens = normalizedToken(stem), inLogoFolder = segments[0] === "assets" && segments[1]?.toLowerCase() === "logo", inFaviconFolder = segments[0] === "assets" && segments[1]?.toLowerCase() === "favicon", inIdentityFolder = inLogoFolder || inFaviconFolder, explicitRoles = /* @__PURE__ */ new Set();
612
+ if (tokens.includes("logo") && explicitRoles.add("logo"), tokens.includes("mark") && explicitRoles.add("mark"), tokens.includes("wordmark") && explicitRoles.add("wordmark"), tokens.includes("favicon") && explicitRoles.add("favicon"), tokens.includes("apple") && tokens.includes("icon") && explicitRoles.add("apple-icon"), explicitRoles.size > 1)
613
+ throw conflict("FRAMEWORK_IDENTITY_ROLE_CONFLICT", [path]);
614
+ let explicitRole = [...explicitRoles][0];
615
+ if (inLogoFolder && inFaviconFolder)
616
+ throw conflict("FRAMEWORK_IDENTITY_FOLDER_CONFLICT", [path]);
617
+ if (inLogoFolder && ["favicon", "apple-icon"].includes(explicitRole ?? "") || inFaviconFolder && ["logo", "mark", "wordmark"].includes(explicitRole ?? ""))
618
+ throw conflict("FRAMEWORK_IDENTITY_FOLDER_ROLE_CONFLICT", [path]);
619
+ let role = explicitRole;
620
+ !role && inLogoFolder && (role = "logo"), !role && inFaviconFolder && (role = "favicon");
621
+ let hasModeLight = tokens.includes("light"), hasModeDark = tokens.includes("dark");
622
+ if (hasModeLight && hasModeDark)
623
+ throw conflict("FRAMEWORK_IDENTITY_MODE_CONFLICT", [path]);
624
+ let mode = hasModeLight ? "light" : hasModeDark ? "dark" : "default";
625
+ if (!role && !inIdentityFolder && (hasModeLight || hasModeDark) && (role = "logo"), !role) return;
626
+ let roleTokens = tokens.filter(
627
+ (token) => token !== "light" && token !== "dark"
628
+ ), priority = role === "apple-icon" && roleTokens.length === 2 && roleTokens[0] === "apple" && roleTokens[1] === "icon" || role !== "apple-icon" && roleTokens.length === 1 && roleTokens[0] === role ? 1 : explicitRole ? 2 : format === "svg" ? 3 : inIdentityFolder ? 4 : 5;
629
+ if (role === "apple-icon" && (inLogoFolder || format === "svg"))
630
+ throw conflict("FRAMEWORK_IDENTITY_FORMAT_REJECTED", [path]);
631
+ if (role === "favicon" && !FAVICON_FORMATS.includes(format))
632
+ throw conflict("FRAMEWORK_IDENTITY_FORMAT_REJECTED", [path]);
633
+ if (role === "apple-icon" && !["png", "jpg", "jpeg"].includes(format))
634
+ throw conflict("FRAMEWORK_IDENTITY_FORMAT_REJECTED", [path]);
635
+ if (["logo", "mark", "wordmark"].includes(role) && !LOGO_FORMATS.includes(format))
636
+ throw conflict("FRAMEWORK_IDENTITY_FORMAT_REJECTED", [path]);
637
+ if (role === "apple-icon" && mode !== "default")
638
+ throw conflict("FRAMEWORK_IDENTITY_MODE_CONFLICT", [path]);
639
+ return { path, role, mode, format, priority };
640
+ }
641
+ function conflict(code, paths) {
642
+ let candidates = [...paths].sort();
643
+ return new AppError({
644
+ code,
645
+ message: `Identity asset conflict: ${candidates.join(", ")}`,
646
+ details: { candidates }
647
+ });
648
+ }
649
+ function duplicateWarning(role, mode, candidates) {
650
+ let paths = candidates.map((candidate) => candidate.path).sort(), selected = paths[0] ?? "", ignored = paths.slice(1);
651
+ return {
652
+ code: "FRAMEWORK_IDENTITY_DUPLICATE",
653
+ level: "warning",
654
+ message: `Duplicate ${role} identity assets for ${mode} mode; using ${selected} and ignoring ${ignored.join(", ")}.`,
655
+ details: { role, mode, selected, candidates: paths }
656
+ };
657
+ }
658
+ function deduplicateCandidates(candidates, role) {
659
+ let groups = /* @__PURE__ */ new Map();
660
+ for (let candidate of candidates) {
661
+ let format = ["jpg", "jpeg"].includes(candidate.format) ? "jpeg" : candidate.format, key = role === "favicon" ? `${candidate.mode}:${format}:${candidate.size ?? ""}` : role === "apple-icon" ? `${format}:${candidate.size ?? ""}` : `${candidate.mode}:${format}`, group = groups.get(key) ?? [];
662
+ group.push(candidate), groups.set(key, group);
663
+ }
664
+ let selected = [], warnings = [];
665
+ for (let key of [...groups.keys()].sort()) {
666
+ let group = (groups.get(key) ?? []).sort(
667
+ (left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0
668
+ ), winner = group[0];
669
+ winner && selected.push(winner), group.length > 1 && winner && warnings.push(duplicateWarning(role, winner.mode, group));
670
+ }
671
+ return { candidates: selected, warnings };
672
+ }
673
+ function chooseCandidates(candidates, role) {
674
+ let roleCandidates = candidates.filter(
675
+ (candidate) => candidate.role === role
676
+ );
677
+ if (roleCandidates.length === 0) return { selected: [], warnings: [] };
678
+ if (role === "apple-icon") {
679
+ let byFormatAndSize = /* @__PURE__ */ new Map();
680
+ for (let candidate of roleCandidates) {
681
+ let key = `${["jpg", "jpeg"].includes(candidate.format) ? "jpeg" : candidate.format}:${candidate.size ?? ""}`, group = byFormatAndSize.get(key) ?? [];
682
+ group.push(candidate), byFormatAndSize.set(key, group);
683
+ }
684
+ let selected2 = [], warnings = [];
685
+ for (let key of [...byFormatAndSize.keys()].sort()) {
686
+ let group = byFormatAndSize.get(key) ?? [], priority2 = Math.min(
687
+ ...group.map((candidate) => candidate.priority)
688
+ ), deduplicated = deduplicateCandidates(
689
+ group.filter((candidate) => candidate.priority === priority2),
690
+ role
691
+ );
692
+ selected2.push(...deduplicated.candidates), warnings.push(...deduplicated.warnings);
693
+ }
694
+ return { selected: selected2, warnings };
695
+ }
696
+ let priority = Math.min(
697
+ ...roleCandidates.map((candidate) => candidate.priority)
698
+ ), winning = deduplicateCandidates(
699
+ roleCandidates.filter((candidate) => candidate.priority === priority),
700
+ role
701
+ ), selected = [];
702
+ for (let requestedMode of ["light", "dark"]) {
703
+ let modeCandidates = winning.candidates.filter((candidate) => candidate.mode === requestedMode).length > 0 ? winning.candidates.filter(
704
+ (candidate) => candidate.mode === requestedMode
705
+ ) : winning.candidates.filter((candidate) => candidate.mode === "default").length > 0 ? winning.candidates.filter(
706
+ (candidate) => candidate.mode === "default"
707
+ ) : winning.candidates.filter(
708
+ (candidate) => candidate.mode !== requestedMode
709
+ );
710
+ if (role === "favicon") {
711
+ if (modeCandidates.length === 0) continue;
712
+ let formatRank = Math.min(
713
+ ...modeCandidates.map(
714
+ (candidate) => FORMAT_RANK[candidate.format] ?? 99
715
+ )
716
+ );
717
+ selected.push(
718
+ ...modeCandidates.filter(
719
+ (candidate) => (FORMAT_RANK[candidate.format] ?? 99) === formatRank
720
+ )
721
+ );
722
+ } else {
723
+ let formatRank = Math.min(
724
+ ...modeCandidates.map(
725
+ (candidate) => LOGO_FORMAT_RANK[candidate.format] ?? 99
726
+ )
727
+ ), preferred = modeCandidates.filter(
728
+ (candidate) => (LOGO_FORMAT_RANK[candidate.format] ?? 99) === formatRank
729
+ ).sort(
730
+ (left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0
731
+ );
732
+ preferred[0] && selected.push(preferred[0]);
733
+ }
734
+ }
735
+ let unique = /* @__PURE__ */ new Map();
736
+ for (let item of selected) unique.set(item.path, item);
737
+ return {
738
+ selected: [...unique.values()],
739
+ warnings: winning.warnings
740
+ };
741
+ }
742
+ function icoSizes(contents) {
743
+ if (contents.length < 6) return;
744
+ let count = contents.readUInt16LE(4), sizes = /* @__PURE__ */ new Set();
745
+ for (let index = 0; index < count; index += 1) {
746
+ let offset = 6 + index * 16;
747
+ if (offset + 16 > contents.length) break;
748
+ let width = contents[offset] || 256, height = contents[offset + 1] || 256;
749
+ sizes.add(`${width}x${height}`);
750
+ }
751
+ return [...sizes].sort().join(", ") || void 0;
752
+ }
753
+ function assetSizes(asset) {
754
+ return asset.sizes ? asset.sizes : asset.width && asset.height ? `${asset.width}x${asset.height}` : asset.mimeType === "image/svg+xml" ? "any" : void 0;
755
+ }
756
+ function buildFaviconsAndLogos(options) {
757
+ let mediaImages = /* @__PURE__ */ new Map();
758
+ for (let output of options.media.outputs)
759
+ mediaImages.set(output.outputPath, output.contents);
760
+ let candidates = [];
761
+ for (let [sourceUrl, media] of Object.entries(
762
+ options.media.manifest.assets
763
+ )) {
764
+ if (media.mediaType !== "image") continue;
765
+ let path = sourceUrl.slice(1), candidate = classifyPath(path);
766
+ if (!candidate) continue;
767
+ let bytes = mediaImages.get(media.outputPath);
768
+ if (!bytes) continue;
769
+ let limit = ["logo", "mark", "wordmark"].includes(candidate.role) ? MAX_LOGO_BYTES : MAX_FAVICON_BYTES;
770
+ if (media.byteSize > limit)
771
+ throw new AppError({
772
+ code: "FRAMEWORK_IDENTITY_FILE_TOO_LARGE",
773
+ message: `${path} exceeds the ${limit} byte identity image limit`,
774
+ details: { path, bytes: media.byteSize, limit }
775
+ });
776
+ if ((candidate.role === "favicon" || candidate.role === "apple-icon") && (candidate.format === "ico" && (icoSizes(bytes)?.split(", ").some((size) => {
777
+ let [width, height] = size.split("x").map(Number);
778
+ return width !== height;
779
+ }) ?? !1) || media.width && media.height && media.width !== media.height))
780
+ throw conflict("FRAMEWORK_IDENTITY_NOT_SQUARE", [path]);
781
+ candidates.push({
782
+ ...candidate,
783
+ size: candidate.format === "ico" ? icoSizes(bytes) : media.width && media.height ? `${media.width}x${media.height}` : candidate.format === "svg" ? "any" : void 0
784
+ });
785
+ }
786
+ let choices = [
787
+ chooseCandidates(candidates, "favicon"),
788
+ chooseCandidates(candidates, "apple-icon"),
789
+ chooseCandidates(candidates, "logo"),
790
+ chooseCandidates(candidates, "mark"),
791
+ chooseCandidates(candidates, "wordmark")
792
+ ], selected = choices.flatMap((choice) => choice.selected), warnings = choices.flatMap((choice) => choice.warnings), assets = [];
793
+ for (let candidate of selected) {
794
+ let mediaEntry = options.media.manifest.assets[`/${candidate.path}`];
795
+ if (!mediaEntry) continue;
796
+ let contents = mediaImages.get(mediaEntry.outputPath);
797
+ if (!contents) continue;
798
+ let sizes = candidate.format === "ico" ? icoSizes(contents) : void 0, asset = {
799
+ kind: `${candidate.role}-${candidate.mode}`,
800
+ sourcePath: mediaEntry.sourcePath,
801
+ outputPath: mediaEntry.outputPath,
802
+ contentHash: mediaEntry.contentHash,
803
+ mimeType: mediaEntry.mimeType,
804
+ byteSize: mediaEntry.byteSize,
805
+ width: mediaEntry.width,
806
+ height: mediaEntry.height,
807
+ sizes
808
+ };
809
+ assets.push(asset);
810
+ }
811
+ let by = (role, mode) => assets.find((asset) => asset.kind === `${role}-${mode}`), all = (role, mode) => assets.filter((asset) => asset.kind === `${role}-${mode}`), favicon = {
812
+ fallback: all("favicon", "default"),
813
+ light: all("favicon", "light").length ? all("favicon", "light") : all("favicon", "default").length ? all("favicon", "default") : all("favicon", "dark"),
814
+ dark: all("favicon", "dark").length ? all("favicon", "dark") : all("favicon", "default").length ? all("favicon", "default") : all("favicon", "light"),
815
+ apple: all("apple-icon", "default")
816
+ }, logo = {
817
+ light: by("logo", "light") ?? by("logo", "default") ?? by("logo", "dark"),
818
+ dark: by("logo", "dark") ?? by("logo", "default") ?? by("logo", "light"),
819
+ markLight: by("mark", "light") ?? by("mark", "default") ?? by("mark", "dark"),
820
+ markDark: by("mark", "dark") ?? by("mark", "default") ?? by("mark", "light"),
821
+ wordmarkLight: by("wordmark", "light") ?? by("wordmark", "default") ?? by("wordmark", "dark"),
822
+ wordmarkDark: by("wordmark", "dark") ?? by("wordmark", "default") ?? by("wordmark", "light")
823
+ }, icon = [];
824
+ for (let [mode, entries] of [
825
+ ["light", favicon.light],
826
+ ["dark", favicon.dark]
827
+ ])
828
+ for (let entry of entries ?? []) {
829
+ let existing = icon.find((item) => item.url === entry.outputPath);
830
+ existing ? delete existing.media : icon.push({
831
+ url: entry.outputPath,
832
+ type: entry.mimeType,
833
+ sizes: assetSizes(entry),
834
+ media: `(prefers-color-scheme: ${mode})`
835
+ });
836
+ }
837
+ let apple = favicon.apple?.map((entry) => ({
838
+ url: entry.outputPath,
839
+ type: entry.mimeType,
840
+ sizes: assetSizes(entry)
841
+ }));
842
+ return {
843
+ manifest: {
844
+ assets,
845
+ favicon,
846
+ logo,
847
+ metadataIcons: {
848
+ ...icon.length ? { icon } : {},
849
+ ...apple?.length ? { apple } : {}
850
+ }
851
+ },
852
+ warnings
853
+ };
854
+ }
855
+ function faviconsAndLogosManifestModule(manifest) {
856
+ return `export const faviconsAndLogos = ${JSON.stringify(manifest, null, 2)} as const;
857
+
858
+ export type FaviconsAndLogosManifest = typeof faviconsAndLogos;
859
+ export type FaviconAndLogoAssetManifestEntry = FaviconsAndLogosManifest["assets"][number];
860
+ `;
861
+ }
862
+
863
+ // src/lib/compiler/source/assets/media-assets.ts
864
+ import { createHash } from "crypto";
865
+ import { lstat as lstat2, mkdir, readdir, rm, writeFile } from "fs/promises";
866
+ import { dirname as dirname2, join, relative as relative2, resolve as resolve3, sep as sep2 } from "path";
867
+
868
+ // src/lib/compiler/source/assets/image-admission.ts
869
+ import { inflateSync } from "zlib";
870
+ import valueParser from "postcss-value-parser";
871
+ import { SaxesParser } from "saxes";
872
+ import sharp from "sharp";
873
+ var PNG_SIGNATURE = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
874
+ function pngCrc32(contents) {
875
+ let crc = 4294967295;
876
+ for (let byte of contents) {
877
+ crc ^= byte;
878
+ for (let bit = 0; bit < 8; bit += 1)
879
+ crc = crc >>> 1 ^ (crc & 1 ? 3988292384 : 0);
880
+ }
881
+ return (crc ^ 4294967295) >>> 0;
882
+ }
883
+ function isValidIcoPng(options) {
884
+ let { payload, width, height, directoryBitDepth } = options;
885
+ if (payload.length < 45 || !payload.subarray(0, 8).equals(PNG_SIGNATURE))
886
+ return !1;
887
+ let offset = 8, imageDataSeen = !1, paletteSeen = !1, imageDataEnded = !1, headerSeen = !1, ended = !1, bitDepth = 0, colorType = -1, interlace = -1, imageData = [];
888
+ for (; offset + 12 <= payload.length; ) {
889
+ let length = payload.readUInt32BE(offset), end = offset + 12 + length;
890
+ if (end > payload.length) return !1;
891
+ let type = payload.toString("ascii", offset + 4, offset + 8), data = payload.subarray(offset + 8, offset + 8 + length), checkData = payload.subarray(offset + 4, offset + 8 + length);
892
+ if (pngCrc32(checkData) !== payload.readUInt32BE(offset + 8 + length))
893
+ return !1;
894
+ if (type === "IHDR") {
895
+ if (offset !== 8 || length !== 13 || headerSeen || (headerSeen = !0, data.readUInt32BE(0) !== width || data.readUInt32BE(4) !== height) || (bitDepth = data[8] ?? 0, colorType = data[9] ?? -1, interlace = data[12] ?? -1, !{
896
+ 0: [1, 2, 4, 8, 16],
897
+ 2: [8, 16],
898
+ 3: [1, 2, 4, 8],
899
+ 4: [8, 16],
900
+ 6: [8, 16]
901
+ }[colorType]?.includes(bitDepth) || data[10] !== 0 || data[11] !== 0 || interlace !== 0 && interlace !== 1))
902
+ return !1;
903
+ } else if (type === "PLTE") {
904
+ if (imageDataSeen || length === 0 || length % 3 !== 0 || length > 768)
905
+ return !1;
906
+ paletteSeen = !0;
907
+ } else if (type === "IDAT") {
908
+ if (imageDataEnded || colorType === 3 && !paletteSeen) return !1;
909
+ imageDataSeen = !0, imageData.push(data);
910
+ } else if (type === "IEND") {
911
+ if (length !== 0 || !imageDataSeen || end !== payload.length)
912
+ return !1;
913
+ ended = !0;
914
+ break;
915
+ } else {
916
+ imageDataSeen && (imageDataEnded = !0);
917
+ let ancillary = (type.charCodeAt(0) ?? 0) >= 97;
918
+ if (type === "tRNS" ? imageDataSeen : !ancillary) return !1;
919
+ }
920
+ offset = end;
921
+ }
922
+ if (!headerSeen || !ended || imageData.length === 0) return !1;
923
+ let bitsPerPixel = bitDepth * ({
924
+ 0: 1,
925
+ 2: 3,
926
+ 3: 1,
927
+ 4: 2,
928
+ 6: 4
929
+ }[colorType] ?? 0), expectedDirectoryDepth = colorType === 3 ? bitDepth : bitsPerPixel, passRows = (interlace === 0 ? [[0, 0, 1, 1]] : [
930
+ [0, 0, 8, 8],
931
+ [4, 0, 8, 8],
932
+ [0, 4, 4, 8],
933
+ [2, 0, 4, 4],
934
+ [0, 2, 2, 4],
935
+ [1, 0, 2, 2],
936
+ [0, 1, 1, 2]
937
+ ]).flatMap(([xStart, yStart, xStep, yStep]) => {
938
+ let passWidth = width > xStart ? Math.ceil((width - xStart) / xStep) : 0, passHeight = height > yStart ? Math.ceil((height - yStart) / yStep) : 0;
939
+ if (passWidth === 0 || passHeight === 0) return [];
940
+ let rowBytes = Math.ceil(passWidth * bitsPerPixel / 8);
941
+ return Array.from({ length: passHeight }, () => rowBytes);
942
+ }), expectedInflatedBytes = passRows.reduce(
943
+ (total, rowBytes) => total + rowBytes + 1,
944
+ 0
945
+ );
946
+ try {
947
+ let decoded = inflateSync(Buffer.concat(imageData), {
948
+ maxOutputLength: expectedInflatedBytes
949
+ });
950
+ if (decoded.length !== expectedInflatedBytes) return !1;
951
+ let decodedOffset = 0;
952
+ for (let rowBytes of passRows) {
953
+ if ((decoded[decodedOffset] ?? 255) > 4) return !1;
954
+ decodedOffset += rowBytes + 1;
955
+ }
956
+ return expectedDirectoryDepth === directoryBitDepth;
957
+ } catch {
958
+ return !1;
959
+ }
960
+ }
961
+ function isValidIcoDib(options) {
962
+ let { payload, width, height, directoryBitDepth } = options;
963
+ if (payload.length < 40) return !1;
964
+ let headerSize = payload.readUInt32LE(0), dibWidth = payload.readInt32LE(4), dibHeight = payload.readInt32LE(8), planes = payload.readUInt16LE(12), bitDepth = payload.readUInt16LE(14), compression = payload.readUInt32LE(16), colorsUsed = payload.readUInt32LE(32);
965
+ if (headerSize < 40 || headerSize > payload.length || dibWidth !== width || Math.abs(dibHeight) !== height * 2 || planes !== 1 || directoryBitDepth !== bitDepth || ![1, 4, 8, 24, 32].includes(bitDepth) || compression !== 0)
966
+ return !1;
967
+ let paletteBytes = (bitDepth <= 8 ? colorsUsed || 1 << bitDepth : 0) * 4, xorBytes = Math.ceil(width * bitDepth / 32) * 4 * height, maskBytes = Math.ceil(width / 32) * 4 * height;
968
+ return headerSize + paletteBytes + xorBytes + maskBytes <= payload.length;
969
+ }
970
+ function hasImageSignature(options) {
971
+ let { contents, format } = options;
972
+ if (format === "png")
973
+ return contents.length >= 8 && contents.readUInt32BE(0) === 2303741511;
974
+ if (format === "jpeg")
975
+ return contents.length >= 2 && contents[0] === 255 && contents[1] === 216;
976
+ if (format === "gif") {
977
+ let header = contents.subarray(0, 6).toString("ascii");
978
+ return header === "GIF87a" || header === "GIF89a";
979
+ }
980
+ if (format === "webp")
981
+ return contents.subarray(0, 4).toString("ascii") === "RIFF" && contents.subarray(8, 12).toString("ascii") === "WEBP";
982
+ if (format === "avif")
983
+ return contents.subarray(4, 12).toString("ascii").includes("ftyp");
984
+ if (contents.length < 22 || contents[0] !== 0 || contents[1] !== 0 || contents[2] !== 1 || contents[3] !== 0)
985
+ return !1;
986
+ let count = contents.readUInt16LE(4), tableEnd = 6 + count * 16;
987
+ if (count === 0 || tableEnd > contents.length) return !1;
988
+ let images = [], totalPixels = 0;
989
+ for (let index = 0; index < count; index += 1) {
990
+ let entry = 6 + index * 16, width = contents[entry] || 256, height = contents[entry + 1] || 256, planes = contents.readUInt16LE(entry + 4), bitDepth = contents.readUInt16LE(entry + 6), bytes = contents.readUInt32LE(entry + 8), offset = contents.readUInt32LE(entry + 12);
991
+ if (bytes === 0 || ![0, 1].includes(planes) || ![1, 4, 8, 24, 32].includes(bitDepth) || offset < tableEnd || offset + bytes > contents.length || (totalPixels += width * height, totalPixels > 4e7)) return !1;
992
+ images.push({ offset, bytes, width, height, bitDepth });
993
+ }
994
+ images.sort((left, right) => left.offset - right.offset);
995
+ let previousEnd = tableEnd;
996
+ for (let { offset, bytes, width, height, bitDepth } of images) {
997
+ if (offset < previousEnd) return !1;
998
+ previousEnd = offset + bytes;
999
+ let payload = contents.subarray(offset, offset + bytes);
1000
+ if (payload.subarray(0, 8).equals(PNG_SIGNATURE)) {
1001
+ if (!isValidIcoPng({ payload, width, height, directoryBitDepth: bitDepth }))
1002
+ return !1;
1003
+ continue;
1004
+ }
1005
+ if (!isValidIcoDib({
1006
+ payload,
1007
+ width,
1008
+ height,
1009
+ directoryBitDepth: bitDepth
1010
+ }))
1011
+ return !1;
1012
+ }
1013
+ return !0;
1014
+ }
1015
+ async function readRasterMetadata(options) {
1016
+ let metadata;
1017
+ try {
1018
+ metadata = await sharp(options.contents, { animated: !0 }).metadata();
1019
+ } catch (error) {
1020
+ throw new AppError({
1021
+ code: `${options.errorPrefix}_DIMENSIONS_UNREADABLE`,
1022
+ message: `${options.path} has image metadata that could not be read`,
1023
+ details: {
1024
+ path: options.path,
1025
+ cause: error instanceof Error ? error.message : String(error)
1026
+ }
1027
+ });
1028
+ }
1029
+ let rawWidth = metadata.width, rawHeight = metadata.pageHeight ?? metadata.height;
1030
+ if (!rawWidth || !rawHeight)
1031
+ throw new AppError({
1032
+ code: `${options.errorPrefix}_DIMENSIONS_UNREADABLE`,
1033
+ message: `${options.path} is missing readable raster image dimensions`,
1034
+ details: { path: options.path }
1035
+ });
1036
+ let orientation = metadata.orientation ?? 1, rotated = orientation >= 5 && orientation <= 8, width = rotated ? rawHeight : rawWidth, height = rotated ? rawWidth : rawHeight, { maxRasterMegapixels, maxRasterSidePixels } = options.policy;
1037
+ if (width > maxRasterSidePixels || height > maxRasterSidePixels || width * height > maxRasterMegapixels * 1e6)
1038
+ throw new AppError({
1039
+ code: `${options.errorPrefix}_DIMENSIONS_TOO_LARGE`,
1040
+ message: `${options.path} is ${width}x${height}. Raster images must be no larger than ${maxRasterSidePixels}px on either side and ${maxRasterMegapixels} megapixels.`,
1041
+ details: {
1042
+ path: options.path,
1043
+ width,
1044
+ height,
1045
+ maxSidePixels: maxRasterSidePixels,
1046
+ maxMegapixels: maxRasterMegapixels
1047
+ }
1048
+ });
1049
+ return {
1050
+ width,
1051
+ height,
1052
+ animated: (metadata.pages ?? 1) > 1
1053
+ };
1054
+ }
1055
+ function validateSvg(options) {
1056
+ if (options.contents.byteLength > options.policy.maxSvgBytes)
1057
+ throw new AppError({
1058
+ code: `${options.errorPrefix}_SVG_TOO_LARGE`,
1059
+ message: `${options.path} is larger than the ${Math.round(options.policy.maxSvgBytes / 1024)} KB SVG limit`,
1060
+ details: { path: options.path, bytes: options.contents.byteLength }
1061
+ });
1062
+ let source = options.contents.toString("utf-8");
1063
+ if (!source.toLowerCase().includes("<svg"))
1064
+ throw new AppError({
1065
+ code: `${options.errorPrefix}_SVG_INVALID`,
1066
+ message: `${options.path} is not a valid SVG document`,
1067
+ details: { path: options.path }
1068
+ });
1069
+ let unsafe = () => {
1070
+ throw new AppError({
1071
+ code: `${options.errorPrefix}_SVG_UNSAFE`,
1072
+ message: `${options.path} contains unsafe SVG content`,
1073
+ details: { path: options.path }
1074
+ });
1075
+ }, forbiddenElements = /* @__PURE__ */ new Set([
1076
+ "script",
1077
+ "foreignobject",
1078
+ "iframe",
1079
+ "object",
1080
+ "embed",
1081
+ "audio",
1082
+ "video",
1083
+ "animate",
1084
+ "animatemotion",
1085
+ "animatetransform",
1086
+ "set"
1087
+ ]), decodeCssEscapes = (value) => value.replace(/\\([\da-f]{1,6})\s?|\\(.)/giu, (_match, hex, char) => {
1088
+ if (!hex) return char ?? "";
1089
+ let codePoint = Number.parseInt(hex, 16);
1090
+ return codePoint === 0 || codePoint > 1114111 || codePoint >= 55296 && codePoint <= 57343 ? "\uFFFD" : String.fromCodePoint(codePoint);
1091
+ }), hasExternalCssUrl = (value) => {
1092
+ let decoded = decodeCssEscapes(value), external = !1;
1093
+ return valueParser(decoded).walk((node) => {
1094
+ if (node.type !== "function") return;
1095
+ let functionName = node.value.toLowerCase();
1096
+ if (["image-set", "-webkit-image-set", "image"].includes(functionName) && node.nodes.some(
1097
+ (child) => child.type === "string" && child.value.trim() !== "" && !child.value.trim().startsWith("#")
1098
+ ) && (external = !0), functionName !== "url") return;
1099
+ let target = valueParser.stringify(node.nodes).trim().replace(/^(["'])(.*)\1$/su, "$2");
1100
+ target && !target.startsWith("#") && (external = !0);
1101
+ }), external;
1102
+ }, hasExternalCssImport = (value) => {
1103
+ let decoded = decodeCssEscapes(value).replace(/\/\*[\s\S]*?\*\//gu, " ");
1104
+ return /@import(?=\s|["'(])\s*(?:url\(\s*)?(?:"([^"#][^"]*)"|'([^'#][^']*)'|([^\s;)'"#][^\s;)]*))/iu.test(
1105
+ decoded
1106
+ );
1107
+ }, isExternalReference = (value) => {
1108
+ let target = value.trim();
1109
+ return target.length > 0 && !target.startsWith("#");
1110
+ }, rootSeen = !1, styleContents = [], parseFailure, parser2 = new SaxesParser({ xmlns: !0 });
1111
+ parser2.on("doctype", () => unsafe()), parser2.on("processinginstruction", () => unsafe()), parser2.on("error", (error) => {
1112
+ parseFailure ??= error;
1113
+ }), parser2.on("opentag", (tag) => {
1114
+ let localName = tag.local.toLowerCase();
1115
+ styleContents.length > 0 && unsafe(), rootSeen || (rootSeen = !0, localName !== "svg" && unsafe()), forbiddenElements.has(localName) && unsafe(), localName === "style" && styleContents.push("");
1116
+ for (let attribute of Object.values(tag.attributes)) {
1117
+ let name = attribute.local.toLowerCase(), value = attribute.value;
1118
+ name === "base" && attribute.uri === "http://www.w3.org/XML/1998/namespace" && value.trim() !== "" && unsafe(), name.startsWith("on") && unsafe(), (name === "href" || name === "src") && isExternalReference(value) && unsafe(), hasExternalCssUrl(value) && unsafe();
1119
+ }
1120
+ }), parser2.on("closetag", (tag) => {
1121
+ if (tag.local.toLowerCase() === "style") {
1122
+ let contents = styleContents.pop();
1123
+ contents && (hasExternalCssUrl(contents) || hasExternalCssImport(contents)) && unsafe();
1124
+ }
1125
+ });
1126
+ let appendStyleText = (value) => {
1127
+ let last = styleContents.length - 1;
1128
+ last >= 0 && (styleContents[last] = `${styleContents[last]}${value}`);
1129
+ };
1130
+ return parser2.on("text", appendStyleText), parser2.on("cdata", appendStyleText), parser2.write(source).close(), (parseFailure || !rootSeen) && unsafe(), options.contents;
1131
+ }
1132
+
1133
+ // src/lib/compiler/source/assets/media-assets.ts
1134
+ var DEFAULT_MAX_TOTAL_BYTES = 100 * 1024 * 1024, DEFAULT_MAX_FILE_COUNT = 500, MEDIA_IMAGE_ADMISSION_POLICY = {
1135
+ maxRasterMegapixels: 40,
1136
+ maxRasterSidePixels: 8192,
1137
+ maxSvgBytes: MAX_MEDIA_SVG_BYTES
1138
+ }, MEDIA_PUBLIC_PREFIX = SOURCE_ASSET_PREFIX;
1139
+ function mediaAssetBudgets() {
1140
+ return {
1141
+ maxTotalBytes: DEFAULT_MAX_TOTAL_BYTES,
1142
+ maxFileCount: DEFAULT_MAX_FILE_COUNT
1143
+ };
1144
+ }
1145
+ function toPosixPath(path) {
1146
+ return path.split(sep2).join("/");
1147
+ }
1148
+ function hasUnsafeControlCharacters(value) {
1149
+ for (let character of value) {
1150
+ let code = character.codePointAt(0) ?? 0;
1151
+ if (code <= 31 || code >= 127 && code <= 159) return !0;
1152
+ }
1153
+ return !1;
1154
+ }
1155
+ function encodeAssetPath(relativePath) {
1156
+ let segments = relativePath.split("/");
1157
+ if (segments.some(
1158
+ (segment) => segment === "" || segment === "." || segment === ".." || segment.startsWith(".") || segment.includes("\\") || hasUnsafeControlCharacters(segment)
1159
+ ))
1160
+ throw new AppError({
1161
+ code: "FRAMEWORK_MEDIA_PATH_REJECTED",
1162
+ message: `Media asset path "${relativePath}" is not allowed`,
1163
+ details: { path: relativePath }
1164
+ });
1165
+ let encoded;
1166
+ try {
1167
+ encoded = segments.map((segment) => encodeURIComponent(segment)).join("/");
1168
+ } catch {
1169
+ throw new AppError({
1170
+ code: "FRAMEWORK_MEDIA_PATH_REJECTED",
1171
+ message: `Media asset path "${relativePath}" does not produce a safe URL path`,
1172
+ details: { path: relativePath }
1173
+ });
1174
+ }
1175
+ if (encoded.length > 512 || segments.some((segment) => segment.length > 100))
1176
+ throw new AppError({
1177
+ code: "FRAMEWORK_MEDIA_PATH_REJECTED",
1178
+ message: `Media asset path "${relativePath}" exceeds the supported URL length`,
1179
+ details: { path: relativePath }
1180
+ });
1181
+ return encoded;
1182
+ }
1183
+ async function walkAssetFiles(dir, state, root = dir) {
1184
+ let entries = await readdir(dir, { withFileTypes: !0 }).catch((error) => {
1185
+ if (error.code === "ENOENT") return [];
1186
+ throw error;
1187
+ });
1188
+ entries.sort((a, b) => a.name.localeCompare(b.name));
1189
+ for (let entry of entries) {
1190
+ let absolutePath = join(dir, entry.name), relativePath = toPosixPath(relative2(root, absolutePath));
1191
+ if (isExcludedSourcePath(`assets/${relativePath}`)) continue;
1192
+ if (entry.name.startsWith(".")) {
1193
+ state.warnings.push(ignoredMediaPathWarning(`assets/${relativePath}`));
1194
+ continue;
1195
+ }
1196
+ let info = await lstat2(absolutePath);
1197
+ if (info.isSymbolicLink())
1198
+ throw new AppError({
1199
+ code: "FRAMEWORK_MEDIA_SYMLINK_REJECTED",
1200
+ message: `Media asset "${relativePath}" is a symlink. Symlinks are not supported in publish.os/assets.`,
1201
+ details: { path: absolutePath }
1202
+ });
1203
+ if (info.isDirectory()) {
1204
+ await walkAssetFiles(absolutePath, state, root);
1205
+ continue;
1206
+ }
1207
+ if (info.isFile()) {
1208
+ let ignoredDocument = ignoredMediaDocumentWarning(
1209
+ `assets/${relativePath}`
1210
+ );
1211
+ if (ignoredDocument) {
1212
+ encodeAssetPath(relativePath), state.warnings.push(ignoredDocument);
1213
+ continue;
1214
+ }
1215
+ if (state.files.push(relativePath), state.files.length > state.maxFileCount)
1216
+ throw new AppError({
1217
+ code: "FRAMEWORK_MEDIA_FILE_COUNT_EXCEEDED",
1218
+ message: `publish.os/assets contains more than ${state.maxFileCount} files, exceeding the limit of ${state.maxFileCount}`,
1219
+ details: { count: state.files.length, limit: state.maxFileCount }
1220
+ });
1221
+ }
1222
+ }
1223
+ }
1224
+ function hash(contents) {
1225
+ return `sha256-${createHash("sha256").update(contents).digest("hex").slice(0, 16)}`;
1226
+ }
1227
+ async function classifyAsset(relativePath, contents) {
1228
+ let ext = relativePath.split(".").at(-1)?.toLowerCase() ?? "";
1229
+ if (ext === "png" && hasImageSignature({ contents, format: "png" })) {
1230
+ let metadata = await readRasterMetadata({
1231
+ contents,
1232
+ errorPrefix: "FRAMEWORK_MEDIA",
1233
+ path: relativePath,
1234
+ policy: MEDIA_IMAGE_ADMISSION_POLICY
1235
+ });
1236
+ return {
1237
+ contents,
1238
+ mediaType: "image",
1239
+ mimeType: "image/png",
1240
+ outputContents: contents,
1241
+ ...metadata
1242
+ };
1243
+ }
1244
+ if (ext === "ico" && hasImageSignature({ contents, format: "ico" }))
1245
+ return {
1246
+ contents,
1247
+ mediaType: "image",
1248
+ mimeType: "image/x-icon",
1249
+ outputContents: contents
1250
+ };
1251
+ if (ext === "ico")
1252
+ throw new AppError({
1253
+ code: "FRAMEWORK_MEDIA_ICO_INVALID",
1254
+ message: `${relativePath} is not a valid ICO image`,
1255
+ details: { path: relativePath }
1256
+ });
1257
+ if ((ext === "jpg" || ext === "jpeg") && hasImageSignature({ contents, format: "jpeg" })) {
1258
+ let metadata = await readRasterMetadata({
1259
+ contents,
1260
+ errorPrefix: "FRAMEWORK_MEDIA",
1261
+ path: relativePath,
1262
+ policy: MEDIA_IMAGE_ADMISSION_POLICY
1263
+ });
1264
+ return {
1265
+ contents,
1266
+ mediaType: "image",
1267
+ mimeType: "image/jpeg",
1268
+ outputContents: contents,
1269
+ ...metadata
1270
+ };
1271
+ }
1272
+ if (ext === "gif" && hasImageSignature({ contents, format: "gif" })) {
1273
+ let metadata = await readRasterMetadata({
1274
+ contents,
1275
+ errorPrefix: "FRAMEWORK_MEDIA",
1276
+ path: relativePath,
1277
+ policy: MEDIA_IMAGE_ADMISSION_POLICY
1278
+ });
1279
+ return {
1280
+ contents,
1281
+ mediaType: "image",
1282
+ mimeType: "image/gif",
1283
+ outputContents: contents,
1284
+ ...metadata
1285
+ };
1286
+ }
1287
+ if (ext === "webp" && hasImageSignature({ contents, format: "webp" })) {
1288
+ let metadata = await readRasterMetadata({
1289
+ contents,
1290
+ errorPrefix: "FRAMEWORK_MEDIA",
1291
+ path: relativePath,
1292
+ policy: MEDIA_IMAGE_ADMISSION_POLICY
1293
+ });
1294
+ return {
1295
+ contents,
1296
+ mediaType: "image",
1297
+ mimeType: "image/webp",
1298
+ outputContents: contents,
1299
+ ...metadata
1300
+ };
1301
+ }
1302
+ if (ext === "avif" && hasImageSignature({ contents, format: "avif" })) {
1303
+ let metadata = await readRasterMetadata({
1304
+ contents,
1305
+ errorPrefix: "FRAMEWORK_MEDIA",
1306
+ path: relativePath,
1307
+ policy: MEDIA_IMAGE_ADMISSION_POLICY
1308
+ });
1309
+ return {
1310
+ contents,
1311
+ mediaType: "image",
1312
+ mimeType: "image/avif",
1313
+ outputContents: contents,
1314
+ ...metadata
1315
+ };
1316
+ }
1317
+ if (ext === "svg") {
1318
+ let outputContents = validateSvg({
1319
+ contents,
1320
+ errorPrefix: "FRAMEWORK_MEDIA",
1321
+ path: relativePath,
1322
+ policy: MEDIA_IMAGE_ADMISSION_POLICY
1323
+ });
1324
+ return {
1325
+ contents,
1326
+ mediaType: "image",
1327
+ mimeType: "image/svg+xml",
1328
+ outputContents
1329
+ };
1330
+ }
1331
+ if (ext === "mp4" && contents.subarray(4, 8).toString("ascii") === "ftyp")
1332
+ return {
1333
+ contents,
1334
+ mediaType: "video",
1335
+ mimeType: "video/mp4",
1336
+ outputContents: contents
1337
+ };
1338
+ if (ext === "webm" && contents[0] === 26 && contents[1] === 69 && contents[2] === 223 && contents[3] === 163)
1339
+ return {
1340
+ contents,
1341
+ mediaType: "video",
1342
+ mimeType: "video/webm",
1343
+ outputContents: contents
1344
+ };
1345
+ if (ext === "json")
1346
+ return JSON.parse(contents.toString("utf-8")), {
1347
+ contents,
1348
+ mediaType: "file",
1349
+ mimeType: "application/json",
1350
+ outputContents: contents
1351
+ };
1352
+ throw new AppError({
1353
+ code: "FRAMEWORK_MEDIA_TYPE_REJECTED",
1354
+ message: `${relativePath} is not an allowed media type`,
1355
+ details: { path: relativePath }
1356
+ });
1357
+ }
1358
+ async function admitThemeImageResource(options) {
1359
+ let asset = await classifyAsset(options.relativePath, options.contents);
1360
+ if (asset.mediaType !== "image")
1361
+ throw new AppError({
1362
+ code: "FRAMEWORK_MEDIA_TYPE_REJECTED",
1363
+ message: `${options.relativePath} is not an allowed image type`,
1364
+ details: { path: options.relativePath }
1365
+ });
1366
+ return {
1367
+ contents: asset.outputContents,
1368
+ mimeType: asset.mimeType,
1369
+ width: asset.width,
1370
+ height: asset.height
1371
+ };
1372
+ }
1373
+ function assertAssetSize(options) {
1374
+ if (options.asset.contents.byteLength > options.limit)
1375
+ throw mediaFileTooLarge({
1376
+ relativePath: options.relativePath,
1377
+ bytes: options.asset.contents.byteLength,
1378
+ limit: options.limit
1379
+ });
1380
+ }
1381
+ function isOptimizableLocalImage(asset) {
1382
+ return asset.mediaType === "image" && !!(asset.width && asset.height) && !asset.animated && asset.mimeType !== "image/svg+xml" && asset.mimeType !== "image/gif";
1383
+ }
1384
+ async function buildMediaAssets(options) {
1385
+ let assetsDir = resolve3(options.publishOsDir, "assets"), { maxFileCount, maxTotalBytes } = mediaAssetBudgets(), walkState = { files: [], warnings: [], maxFileCount };
1386
+ await walkAssetFiles(assetsDir, walkState);
1387
+ let files = walkState.files.sort(), warnings = walkState.warnings, manifest = {
1388
+ assets: {},
1389
+ totals: {
1390
+ bytes: 0,
1391
+ count: 0,
1392
+ images: 0,
1393
+ videos: 0,
1394
+ documents: 0,
1395
+ files: 0
1396
+ }
1397
+ }, outputs = [], seenPublicPaths = /* @__PURE__ */ new Map();
1398
+ for (let file of files) {
1399
+ let sourcePath = resolve3(assetsDir, file);
1400
+ if (!isSameOrDescendant(assetsDir, sourcePath))
1401
+ throw new AppError({
1402
+ code: "FRAMEWORK_MEDIA_PATH_REJECTED",
1403
+ message: `${file} escapes publish.os/assets`,
1404
+ details: { path: file }
1405
+ });
1406
+ let normalized = encodeAssetPath(file), sourcePublicPath = `/assets/${normalized}`, publicPath = `${MEDIA_PUBLIC_PREFIX}/${normalized}`, existing = seenPublicPaths.get(publicPath);
1407
+ if (existing)
1408
+ throw new AppError({
1409
+ code: "FRAMEWORK_MEDIA_PATH_COLLISION",
1410
+ message: `${file} and ${existing} both resolve to ${publicPath}`,
1411
+ details: { path: file, existing, publicPath }
1412
+ });
1413
+ seenPublicPaths.set(publicPath, file);
1414
+ let byteLimit = mediaFileByteLimit(file), contents = await readBoundedMediaFile({
1415
+ path: sourcePath,
1416
+ relativePath: file,
1417
+ limit: byteLimit
1418
+ }), asset = await classifyAsset(file, contents);
1419
+ assertAssetSize({ asset, relativePath: file, limit: byteLimit });
1420
+ let totalBytes = manifest.totals.bytes + asset.outputContents.byteLength;
1421
+ if (totalBytes > maxTotalBytes)
1422
+ throw new AppError({
1423
+ code: "FRAMEWORK_MEDIA_TOTAL_TOO_LARGE",
1424
+ message: `publish.os/assets is ${totalBytes} bytes, exceeding the limit of ${maxTotalBytes}`,
1425
+ details: { bytes: totalBytes, limit: maxTotalBytes }
1426
+ });
1427
+ let contentHash = hash(asset.outputContents), outputPath = publicPath, optimized = isOptimizableLocalImage(asset), aspect = asset.width && asset.height ? asset.width / asset.height : void 0;
1428
+ manifest.assets[sourcePublicPath] = {
1429
+ sourcePath: `publish.os/assets/${file}`,
1430
+ outputPath,
1431
+ contentHash,
1432
+ mediaType: asset.mediaType,
1433
+ mimeType: asset.mimeType,
1434
+ byteSize: asset.outputContents.byteLength,
1435
+ intrinsicWidth: asset.width,
1436
+ intrinsicHeight: asset.height,
1437
+ width: asset.width,
1438
+ height: asset.height,
1439
+ aspect,
1440
+ animated: asset.animated,
1441
+ optimized,
1442
+ optimizationReason: optimized ? void 0 : asset.mediaType === "image" ? asset.mimeType === "image/svg+xml" ? "svg" : asset.animated ? "animated" : asset.mimeType === "image/gif" ? "gif" : "dimensions-unavailable" : void 0
1443
+ }, manifest.totals.bytes += asset.outputContents.byteLength, manifest.totals.count += 1, asset.mediaType === "image" ? manifest.totals.images += 1 : asset.mediaType === "video" ? manifest.totals.videos += 1 : asset.mediaType === "document" ? manifest.totals.documents += 1 : manifest.totals.files += 1, outputs.push({ contents: asset.outputContents, outputPath: publicPath });
1444
+ }
1445
+ return { manifest, outputs, warnings };
1446
+ }
1447
+ async function writeMediaOutputs(options) {
1448
+ await rm(resolve3(options.outputDir, "public", "_publishos", "assets"), {
1449
+ force: !0,
1450
+ recursive: !0
1451
+ }), await rm(resolve3(options.outputDir, "public", "_publishos", "media"), {
1452
+ force: !0,
1453
+ recursive: !0
1454
+ }), await rm(resolve3(options.outputDir, "public", "assets"), {
1455
+ force: !0,
1456
+ recursive: !0
1457
+ });
1458
+ for (let output of options.media.outputs) {
1459
+ let segments = output.outputPath.replace(/^\/+/, "").split("/").map(decodeURIComponent);
1460
+ if (segments.some(
1461
+ (segment) => !segment || segment === "." || segment === ".." || segment.includes("/") || segment.includes("\\") || hasUnsafeControlCharacters(segment)
1462
+ ))
1463
+ throw new AppError({
1464
+ code: "FRAMEWORK_MEDIA_PATH_REJECTED",
1465
+ message: `Media output path "${output.outputPath}" is not safe`,
1466
+ details: { path: output.outputPath }
1467
+ });
1468
+ let relativeOutput = segments.join(sep2), dest = resolve3(options.outputDir, "public", relativeOutput);
1469
+ await mkdir(dirname2(dest), { recursive: !0 }), await writeFile(dest, output.contents);
1470
+ }
1471
+ }
1472
+ function mediaManifestModule(manifest) {
1473
+ return `export const mediaManifest = ${JSON.stringify(manifest, null, 2)} as const;
1474
+
1475
+ export type MediaManifest = typeof mediaManifest;
1476
+ export type MediaAssetManifestEntry = MediaManifest["assets"][keyof MediaManifest["assets"]];
1477
+ `;
1478
+ }
1479
+
1480
+ // src/lib/compiler/source/routing/slug-path.ts
1481
+ var SLUG_SEGMENT_RE = /^[a-z0-9]+(?:[.-][a-z0-9]+)*$/;
1482
+ function issue(code, message, details) {
1483
+ return details ? { code, message, details } : { code, message };
1484
+ }
1485
+ function isLowerAlpha(code) {
1486
+ return code >= 97 && code <= 122;
1487
+ }
1488
+ function isUpperAlpha(code) {
1489
+ return code >= 65 && code <= 90;
1490
+ }
1491
+ function isDigit(code) {
1492
+ return code >= 48 && code <= 57;
1493
+ }
1494
+ function isAsciiAlphaNumeric(code) {
1495
+ return isLowerAlpha(code) || isUpperAlpha(code) || isDigit(code);
1496
+ }
1497
+ function isWhitespace(code) {
1498
+ return code === 32 || code === 9 || code === 10 || code === 11 || code === 12 || code === 13 || code === 160;
1499
+ }
1500
+ function isUnsafeInvisible(code) {
1501
+ return code <= 31 || code >= 127 && code <= 159 || code >= 8203 && code <= 8207 || code >= 8232 && code <= 8239 || code >= 8288 && code <= 8303 || code === 65279;
1502
+ }
1503
+ function isCombiningMark(code) {
1504
+ return code >= 768 && code <= 879 || code >= 6832 && code <= 6911 || code >= 7616 && code <= 7679 || code >= 8400 && code <= 8447 || code >= 65056 && code <= 65071;
1505
+ }
1506
+ function hasPercentEscape(value) {
1507
+ return /%[0-9a-fA-F]{2}/.test(value);
1508
+ }
1509
+ function appendNormalizedChar(output, char, pendingSeparator) {
1510
+ pendingSeparator && output.length > 0 && output.push(pendingSeparator), output.push(char);
1511
+ }
1512
+ function queueSeparator(current, next) {
1513
+ return current === "." || next === "." ? "." : "-";
1514
+ }
1515
+ function normalizeSegmentValue(input) {
1516
+ let output = [], pendingSeparator, sanitized = !1;
1517
+ for (let char of input.normalize("NFKD")) {
1518
+ let code = char.codePointAt(0) ?? 0;
1519
+ if (isCombiningMark(code)) {
1520
+ sanitized = !0;
1521
+ continue;
1522
+ }
1523
+ if (isAsciiAlphaNumeric(code)) {
1524
+ let lower = isUpperAlpha(code) ? char.toLowerCase() : char;
1525
+ pendingSeparator = appendNormalizedChar(output, lower, pendingSeparator), sanitized = sanitized || lower !== char;
1526
+ continue;
1527
+ }
1528
+ if (char === "." || char === "-") {
1529
+ pendingSeparator = queueSeparator(pendingSeparator, char);
1530
+ continue;
1531
+ }
1532
+ if (isWhitespace(code) || char === "_" || isUnsafeInvisible(code)) {
1533
+ pendingSeparator = queueSeparator(pendingSeparator, "-"), sanitized = !0;
1534
+ continue;
1535
+ }
1536
+ pendingSeparator = queueSeparator(pendingSeparator, "-"), sanitized = !0;
1537
+ }
1538
+ return { value: output.join(""), sanitized };
1539
+ }
1540
+ function validateSegment(slug, options) {
1541
+ return slug ? slug.length > options.maxSegmentLength ? {
1542
+ code: "SLUG_SEGMENT_TOO_LONG",
1543
+ error: `URL path must be ${options.maxSegmentLength} characters or less`,
1544
+ isValid: !1
1545
+ } : slug !== slug.toLowerCase() ? {
1546
+ code: "SLUG_UPPERCASE_INVALID",
1547
+ error: "URL path must be lowercase",
1548
+ isValid: !1
1549
+ } : SLUG_SEGMENT_RE.test(slug) ? { isValid: !0 } : {
1550
+ code: "SLUG_PATTERN_INVALID",
1551
+ error: 'URL path can only include lowercase letters, numbers, and single "." or "-" separators',
1552
+ isValid: !1
1553
+ } : {
1554
+ code: "SLUG_EMPTY",
1555
+ error: "URL path is required",
1556
+ isValid: !1
1557
+ };
1558
+ }
1559
+ function normalizeSlugSegmentInternal(input, options = {}) {
1560
+ let maxSegmentLength = options.maxSegmentLength ?? 100, warnings = [], errors = [], trimmed = input.normalize("NFKC").trim(), rawLower = trimmed.toLowerCase();
1561
+ hasPercentEscape(trimmed) && errors.push(
1562
+ issue(
1563
+ "PATH_PERCENT_ESCAPE_INVALID",
1564
+ "Path input must not contain percent escapes",
1565
+ {
1566
+ value: input
1567
+ }
1568
+ )
1569
+ ), (rawLower === "." || rawLower === "..") && errors.push(
1570
+ issue(
1571
+ "PATH_DOT_SEGMENT_INVALID",
1572
+ "Path segments must not be dot traversal segments",
1573
+ {
1574
+ segment: input
1575
+ }
1576
+ )
1577
+ );
1578
+ let normalized = normalizeSegmentValue(trimmed), value = normalized.value;
1579
+ value.length > maxSegmentLength && (errors.push(
1580
+ issue(
1581
+ "SLUG_SEGMENT_TOO_LONG",
1582
+ `Path segments must be ${maxSegmentLength} characters or less`,
1583
+ {
1584
+ max: maxSegmentLength,
1585
+ segment: input
1586
+ }
1587
+ )
1588
+ ), value = value.slice(0, maxSegmentLength)), (normalized.sanitized || value !== trimmed) && warnings.push(
1589
+ issue("PATH_SEGMENT_NORMALIZED", "Path segment was normalized", {
1590
+ from: input,
1591
+ to: value
1592
+ })
1593
+ ), !value && options.allowEmpty !== !0 && errors.push(
1594
+ issue("PATH_SEGMENT_EMPTY", "Path segment normalized to an empty value", {
1595
+ segment: input
1596
+ })
1597
+ );
1598
+ let validation = value ? validateSegment(value, {
1599
+ maxSegmentLength
1600
+ }) : { isValid: !0 };
1601
+ return validation.isValid || errors.push(issue(validation.code, validation.error, { segment: input })), {
1602
+ changed: value !== input,
1603
+ errors,
1604
+ value,
1605
+ warnings
1606
+ };
1607
+ }
1608
+ function normalizePathParts(input, options = {}) {
1609
+ let warnings = [], errors = [], maxPathLength = options.maxPathLength ?? 512, trimmed = input.normalize("NFKC").trim();
1610
+ (/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(trimmed) || /^\/\/[^/]/.test(trimmed)) && errors.push(
1611
+ issue(
1612
+ "PATH_PROTOCOL_INVALID",
1613
+ "Path input must not be a URL or protocol reference",
1614
+ {
1615
+ value: input
1616
+ }
1617
+ )
1618
+ ), /[?#]/.test(trimmed) && errors.push(
1619
+ issue(
1620
+ "PATH_QUERY_HASH_INVALID",
1621
+ "Path input must not include a query string or hash",
1622
+ {
1623
+ value: input
1624
+ }
1625
+ )
1626
+ ), trimmed.includes("\\") && warnings.push(
1627
+ issue(
1628
+ "PATH_BACKSLASH_NORMALIZED",
1629
+ "Backslashes were normalized to slashes",
1630
+ {
1631
+ value: input
1632
+ }
1633
+ )
1634
+ );
1635
+ let rawSegments = trimmed.replace(/\\/g, "/").split("/"), segments = [];
1636
+ for (let rawSegment of rawSegments) {
1637
+ if (!rawSegment) continue;
1638
+ let segment = normalizeSlugSegmentInternal(rawSegment, options);
1639
+ warnings.push(...segment.warnings), errors.push(...segment.errors), segment.value && segments.push(segment.value);
1640
+ }
1641
+ segments.length === 0 && options.allowEmpty !== !0 && errors.push(
1642
+ issue("PATH_EMPTY", "Path input normalized to an empty value", {
1643
+ value: input
1644
+ })
1645
+ );
1646
+ let value = segments.join("/");
1647
+ return value.length > maxPathLength && errors.push(
1648
+ issue(
1649
+ "SLUG_PATH_TOO_LONG",
1650
+ `Path must be ${maxPathLength} characters or less`,
1651
+ {
1652
+ max: maxPathLength,
1653
+ value: input
1654
+ }
1655
+ )
1656
+ ), { errors, value, warnings };
1657
+ }
1658
+ function normalizeSlugPath(input, options = {}) {
1659
+ let normalized = normalizePathParts(input, options);
1660
+ return {
1661
+ ...normalized,
1662
+ changed: normalized.value !== input
1663
+ };
1664
+ }
1665
+ function normalizeUrlPath(input, options = {}) {
1666
+ let normalized = normalizePathParts(input, options), value = normalized.value ? `/${normalized.value}` : "/";
1667
+ return {
1668
+ ...normalized,
1669
+ value,
1670
+ changed: value !== input
1671
+ };
1672
+ }
1673
+ function joinUrlPath(parentPath, childPath) {
1674
+ if (childPath.startsWith("/"))
1675
+ return normalizeUrlPath(childPath).value;
1676
+ let parent = parentPath === "/" ? "" : parentPath.replace(/\/+$/, "");
1677
+ return normalizeUrlPath(`${parent}/${childPath}`).value;
1678
+ }
1679
+
1680
+ export {
1681
+ UnsupportedFrontmatterLanguageError,
1682
+ parseSourceFrontmatter,
1683
+ groupedMdxExports,
1684
+ replacedMdxSourceFiles,
1685
+ mdxComponentExportName,
1686
+ collectBindingNames,
1687
+ namedValueExports,
1688
+ mdxIconPackage,
1689
+ MdxIconImportError,
1690
+ readMdxIconImports,
1691
+ validateMdxIconImports,
1692
+ ROOT_CONTENT_GROUP_KEY,
1693
+ ROOT_CONTENT_GROUP_TITLE,
1694
+ assertSourceDependency,
1695
+ nextjs_runtime_surface_default,
1696
+ supportedNextjsSourceImports,
1697
+ supportedRuntimeComponentAliases,
1698
+ originalDefaultComponentSourcePath,
1699
+ buildFaviconsAndLogos,
1700
+ faviconsAndLogosManifestModule,
1701
+ mediaAssetBudgets,
1702
+ admitThemeImageResource,
1703
+ buildMediaAssets,
1704
+ writeMediaOutputs,
1705
+ mediaManifestModule,
1706
+ normalizeSlugPath,
1707
+ normalizeUrlPath,
1708
+ joinUrlPath
1709
+ };