@rocket/js 0.0.0 → 0.1.1

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 (340) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +233 -2
  3. package/dist-types/exports/MainMenu.d.ts +2 -0
  4. package/dist-types/exports/MainMenu.d.ts.map +1 -0
  5. package/dist-types/exports/PageData.d.ts +2 -0
  6. package/dist-types/exports/PageData.d.ts.map +1 -0
  7. package/dist-types/exports/RocketCodeBlock.d.ts +2 -0
  8. package/dist-types/exports/RocketCodeBlock.d.ts.map +1 -0
  9. package/dist-types/exports/RocketIcon.d.ts +2 -0
  10. package/dist-types/exports/RocketIcon.d.ts.map +1 -0
  11. package/dist-types/exports/RocketJsDemo.d.ts +2 -0
  12. package/dist-types/exports/RocketJsDemo.d.ts.map +1 -0
  13. package/dist-types/exports/RocketRequestDemo.d.ts +2 -0
  14. package/dist-types/exports/RocketRequestDemo.d.ts.map +1 -0
  15. package/dist-types/exports/SocialPreviewPlayground.d.ts +2 -0
  16. package/dist-types/exports/SocialPreviewPlayground.d.ts.map +1 -0
  17. package/dist-types/exports/adapters/netlify.d.ts +2 -0
  18. package/dist-types/exports/adapters/netlify.d.ts.map +1 -0
  19. package/dist-types/exports/asyncMessage.d.ts +2 -0
  20. package/dist-types/exports/asyncMessage.d.ts.map +1 -0
  21. package/dist-types/exports/component-hydration.d.ts +2 -0
  22. package/dist-types/exports/component-hydration.d.ts.map +1 -0
  23. package/dist-types/exports/components/web-awesome.d.ts +3 -0
  24. package/dist-types/exports/components/web-awesome.d.ts.map +1 -0
  25. package/dist-types/exports/components.d.ts +2 -0
  26. package/dist-types/exports/components.d.ts.map +1 -0
  27. package/dist-types/exports/config.d.ts +2 -0
  28. package/dist-types/exports/config.d.ts.map +1 -0
  29. package/dist-types/exports/debounce.d.ts +2 -0
  30. package/dist-types/exports/debounce.d.ts.map +1 -0
  31. package/dist-types/exports/define/RocketCodeBlock.d.ts +2 -0
  32. package/dist-types/exports/define/RocketCodeBlock.d.ts.map +1 -0
  33. package/dist-types/exports/define/RocketIcon.d.ts +2 -0
  34. package/dist-types/exports/define/RocketIcon.d.ts.map +1 -0
  35. package/dist-types/exports/define/RocketJsDemo.d.ts +2 -0
  36. package/dist-types/exports/define/RocketJsDemo.d.ts.map +1 -0
  37. package/dist-types/exports/define/RocketRequestDemo.d.ts +2 -0
  38. package/dist-types/exports/define/RocketRequestDemo.d.ts.map +1 -0
  39. package/dist-types/exports/define/menus.d.ts +2 -0
  40. package/dist-types/exports/define/menus.d.ts.map +1 -0
  41. package/dist-types/exports/extractCode.d.ts +2 -0
  42. package/dist-types/exports/extractCode.d.ts.map +1 -0
  43. package/dist-types/exports/globalData.d.ts +2 -0
  44. package/dist-types/exports/globalData.d.ts.map +1 -0
  45. package/dist-types/exports/hydration/hydrationLoader.d.ts +2 -0
  46. package/dist-types/exports/hydration/hydrationLoader.d.ts.map +1 -0
  47. package/dist-types/exports/icons.d.ts +2 -0
  48. package/dist-types/exports/icons.d.ts.map +1 -0
  49. package/dist-types/exports/layout-helper.d.ts +2 -0
  50. package/dist-types/exports/layout-helper.d.ts.map +1 -0
  51. package/dist-types/exports/layout.d.ts +2 -0
  52. package/dist-types/exports/layout.d.ts.map +1 -0
  53. package/dist-types/exports/layouts/atlasDoc.d.ts +2 -0
  54. package/dist-types/exports/layouts/atlasDoc.d.ts.map +1 -0
  55. package/dist-types/exports/layouts/atlasHero.d.ts +2 -0
  56. package/dist-types/exports/layouts/atlasHero.d.ts.map +1 -0
  57. package/dist-types/exports/layouts/atlasNotFound.d.ts +2 -0
  58. package/dist-types/exports/layouts/atlasNotFound.d.ts.map +1 -0
  59. package/dist-types/exports/loaded-page-module.d.ts +2 -0
  60. package/dist-types/exports/loaded-page-module.d.ts.map +1 -0
  61. package/dist-types/exports/markdownHook.d.ts +2 -0
  62. package/dist-types/exports/markdownHook.d.ts.map +1 -0
  63. package/dist-types/exports/menu.d.ts +2 -0
  64. package/dist-types/exports/menu.d.ts.map +1 -0
  65. package/dist-types/exports/menus.d.ts +6 -0
  66. package/dist-types/exports/menus.d.ts.map +1 -0
  67. package/dist-types/exports/page-runtime.d.ts +2 -0
  68. package/dist-types/exports/page-runtime.d.ts.map +1 -0
  69. package/dist-types/exports/pages.d.ts +2 -0
  70. package/dist-types/exports/pages.d.ts.map +1 -0
  71. package/dist-types/exports/resolve.d.ts +2 -0
  72. package/dist-types/exports/resolve.d.ts.map +1 -0
  73. package/dist-types/exports/ssr.d.ts +2 -0
  74. package/dist-types/exports/ssr.d.ts.map +1 -0
  75. package/dist-types/exports/standalone-demo-url.d.ts +2 -0
  76. package/dist-types/exports/standalone-demo-url.d.ts.map +1 -0
  77. package/dist-types/exports/transform.d.ts +2 -0
  78. package/dist-types/exports/transform.d.ts.map +1 -0
  79. package/dist-types/exports/types/hydration.d.ts +23 -0
  80. package/dist-types/exports/types/hydration.d.ts.map +1 -0
  81. package/dist-types/exports/types/rocket.d.ts +504 -0
  82. package/dist-types/exports/types/rocket.d.ts.map +1 -0
  83. package/dist-types/exports/types.d.ts +3 -0
  84. package/dist-types/exports/types.d.ts.map +1 -0
  85. package/dist-types/exports/wds-plugin.d.ts +2 -0
  86. package/dist-types/exports/wds-plugin.d.ts.map +1 -0
  87. package/dist-types/src/PageData.d.ts +82 -0
  88. package/dist-types/src/PageData.d.ts.map +1 -0
  89. package/dist-types/src/RocketCodeBlock.d.ts +64 -0
  90. package/dist-types/src/RocketCodeBlock.d.ts.map +1 -0
  91. package/dist-types/src/RocketIcon.d.ts +35 -0
  92. package/dist-types/src/RocketIcon.d.ts.map +1 -0
  93. package/dist-types/src/RocketJsDemo.d.ts +59 -0
  94. package/dist-types/src/RocketJsDemo.d.ts.map +1 -0
  95. package/dist-types/src/RocketJsDemo.test-browser.d.ts +3 -0
  96. package/dist-types/src/RocketJsDemo.test-browser.d.ts.map +1 -0
  97. package/dist-types/src/RocketRequestDemo.d.ts +57 -0
  98. package/dist-types/src/RocketRequestDemo.d.ts.map +1 -0
  99. package/dist-types/src/RocketRequestDemo.test-browser.d.ts +3 -0
  100. package/dist-types/src/RocketRequestDemo.test-browser.d.ts.map +1 -0
  101. package/dist-types/src/SocialPreviewPlayground.d.ts +102 -0
  102. package/dist-types/src/SocialPreviewPlayground.d.ts.map +1 -0
  103. package/dist-types/src/adapters/netlify.d.ts +54 -0
  104. package/dist-types/src/adapters/netlify.d.ts.map +1 -0
  105. package/dist-types/src/asyncMessage.d.ts +14 -0
  106. package/dist-types/src/asyncMessage.d.ts.map +1 -0
  107. package/dist-types/src/cli/RocketBuild.d.ts +78 -0
  108. package/dist-types/src/cli/RocketBuild.d.ts.map +1 -0
  109. package/dist-types/src/cli/RocketCli.d.ts +17 -0
  110. package/dist-types/src/cli/RocketCli.d.ts.map +1 -0
  111. package/dist-types/src/cli/RocketInit.d.ts +22 -0
  112. package/dist-types/src/cli/RocketInit.d.ts.map +1 -0
  113. package/dist-types/src/cli/RocketStart.d.ts +45 -0
  114. package/dist-types/src/cli/RocketStart.d.ts.map +1 -0
  115. package/dist-types/src/cli/cli.d.ts +3 -0
  116. package/dist-types/src/cli/cli.d.ts.map +1 -0
  117. package/dist-types/src/component-hydration.d.ts +26 -0
  118. package/dist-types/src/component-hydration.d.ts.map +1 -0
  119. package/dist-types/src/components/FeatureList.d.ts +15 -0
  120. package/dist-types/src/components/FeatureList.d.ts.map +1 -0
  121. package/dist-types/src/components/Footer.d.ts +17 -0
  122. package/dist-types/src/components/Footer.d.ts.map +1 -0
  123. package/dist-types/src/components/Header.d.ts +6 -0
  124. package/dist-types/src/components/Header.d.ts.map +1 -0
  125. package/dist-types/src/components/RocketDrawer.d.ts +20 -0
  126. package/dist-types/src/components/RocketDrawer.d.ts.map +1 -0
  127. package/dist-types/src/components/RocketSocialLink.d.ts +30 -0
  128. package/dist-types/src/components/RocketSocialLink.d.ts.map +1 -0
  129. package/dist-types/src/components.d.ts +7 -0
  130. package/dist-types/src/components.d.ts.map +1 -0
  131. package/dist-types/src/config.d.ts +6 -0
  132. package/dist-types/src/config.d.ts.map +1 -0
  133. package/dist-types/src/debounce.d.ts +8 -0
  134. package/dist-types/src/debounce.d.ts.map +1 -0
  135. package/dist-types/src/defaultSocialPreviewTemplate.d.ts +31 -0
  136. package/dist-types/src/defaultSocialPreviewTemplate.d.ts.map +1 -0
  137. package/dist-types/src/development-page-module-loader.d.ts +15 -0
  138. package/dist-types/src/development-page-module-loader.d.ts.map +1 -0
  139. package/dist-types/src/extractCode.d.ts +5 -0
  140. package/dist-types/src/extractCode.d.ts.map +1 -0
  141. package/dist-types/src/hydration/evaluate.d.ts +20 -0
  142. package/dist-types/src/hydration/evaluate.d.ts.map +1 -0
  143. package/dist-types/src/hydration/extractStrategies.d.ts +5 -0
  144. package/dist-types/src/hydration/extractStrategies.d.ts.map +1 -0
  145. package/dist-types/src/hydration/hydrationLoader.d.ts +64 -0
  146. package/dist-types/src/hydration/hydrationLoader.d.ts.map +1 -0
  147. package/dist-types/src/icons.d.ts +182 -0
  148. package/dist-types/src/icons.d.ts.map +1 -0
  149. package/dist-types/src/layouts/atlas/atlasDocLayout.d.ts +45 -0
  150. package/dist-types/src/layouts/atlas/atlasDocLayout.d.ts.map +1 -0
  151. package/dist-types/src/layouts/atlas/atlasHeroLayout.d.ts +7 -0
  152. package/dist-types/src/layouts/atlas/atlasHeroLayout.d.ts.map +1 -0
  153. package/dist-types/src/layouts/atlas/atlasNotFoundLayout.d.ts +5 -0
  154. package/dist-types/src/layouts/atlas/atlasNotFoundLayout.d.ts.map +1 -0
  155. package/dist-types/src/layouts/layout-helper.d.ts +16 -0
  156. package/dist-types/src/layouts/layout-helper.d.ts.map +1 -0
  157. package/dist-types/src/layouts/layout.d.ts +7 -0
  158. package/dist-types/src/layouts/layout.d.ts.map +1 -0
  159. package/dist-types/src/loaded-page-module.d.ts +51 -0
  160. package/dist-types/src/loaded-page-module.d.ts.map +1 -0
  161. package/dist-types/src/main.d.ts +2 -0
  162. package/dist-types/src/main.d.ts.map +1 -0
  163. package/dist-types/src/markdownCompiler.d.ts +22 -0
  164. package/dist-types/src/markdownCompiler.d.ts.map +1 -0
  165. package/dist-types/src/markdownHook.d.ts +6 -0
  166. package/dist-types/src/markdownHook.d.ts.map +1 -0
  167. package/dist-types/src/menu.d.ts +22 -0
  168. package/dist-types/src/menu.d.ts.map +1 -0
  169. package/dist-types/src/menus/MainMenu.d.ts +23 -0
  170. package/dist-types/src/menus/MainMenu.d.ts.map +1 -0
  171. package/dist-types/src/menus/RocketMenu.d.ts +23 -0
  172. package/dist-types/src/menus/RocketMenu.d.ts.map +1 -0
  173. package/dist-types/src/menus/RocketNextPage.d.ts +18 -0
  174. package/dist-types/src/menus/RocketNextPage.d.ts.map +1 -0
  175. package/dist-types/src/menus/RocketPreviousPage.d.ts +18 -0
  176. package/dist-types/src/menus/RocketPreviousPage.d.ts.map +1 -0
  177. package/dist-types/src/menus/RocketToc.d.ts +54 -0
  178. package/dist-types/src/menus/RocketToc.d.ts.map +1 -0
  179. package/dist-types/src/menus/pageNavigation.d.ts +41 -0
  180. package/dist-types/src/menus/pageNavigation.d.ts.map +1 -0
  181. package/dist-types/src/page-pagination.d.ts +69 -0
  182. package/dist-types/src/page-pagination.d.ts.map +1 -0
  183. package/dist-types/src/page-runtime.d.ts +110 -0
  184. package/dist-types/src/page-runtime.d.ts.map +1 -0
  185. package/dist-types/src/pages.d.ts +10 -0
  186. package/dist-types/src/pages.d.ts.map +1 -0
  187. package/dist-types/src/publicAssets.d.ts +70 -0
  188. package/dist-types/src/publicAssets.d.ts.map +1 -0
  189. package/dist-types/src/requestDemoMetadata.d.ts +19 -0
  190. package/dist-types/src/requestDemoMetadata.d.ts.map +1 -0
  191. package/dist-types/src/resolve.d.ts +7 -0
  192. package/dist-types/src/resolve.d.ts.map +1 -0
  193. package/dist-types/src/siteDiscoverability.d.ts +33 -0
  194. package/dist-types/src/siteDiscoverability.d.ts.map +1 -0
  195. package/dist-types/src/siteHeadMetadata.d.ts +20 -0
  196. package/dist-types/src/siteHeadMetadata.d.ts.map +1 -0
  197. package/dist-types/src/socialPreviewImages.d.ts +186 -0
  198. package/dist-types/src/socialPreviewImages.d.ts.map +1 -0
  199. package/dist-types/src/socialPreviewTemplatePreview.d.ts +22 -0
  200. package/dist-types/src/socialPreviewTemplatePreview.d.ts.map +1 -0
  201. package/dist-types/src/ssr.d.ts +6 -0
  202. package/dist-types/src/ssr.d.ts.map +1 -0
  203. package/dist-types/src/standalone-demo-url.d.ts +60 -0
  204. package/dist-types/src/standalone-demo-url.d.ts.map +1 -0
  205. package/dist-types/src/static-page-module-loader.d.ts +15 -0
  206. package/dist-types/src/static-page-module-loader.d.ts.map +1 -0
  207. package/dist-types/src/transform.d.ts +10 -0
  208. package/dist-types/src/transform.d.ts.map +1 -0
  209. package/dist-types/src/urlLifecycle.d.ts +23 -0
  210. package/dist-types/src/urlLifecycle.d.ts.map +1 -0
  211. package/dist-types/src/wds-plugin.d.ts +15 -0
  212. package/dist-types/src/wds-plugin.d.ts.map +1 -0
  213. package/docs/assets/home-background.svg +1 -0
  214. package/docs/assets/prism-one-light.css +368 -0
  215. package/docs/assets/rocket-logo-dark-with-text-below.svg +8 -0
  216. package/docs/assets/rocket-logo-dark-with-text.svg +7 -0
  217. package/docs/assets/rocket-logo-dark.svg +7 -0
  218. package/docs/assets/rocket-logo-light-with-text-below.svg +14 -0
  219. package/docs/assets/rocket-logo-light-with-text.svg +13 -0
  220. package/docs/assets/rocket-logo-light.svg +12 -0
  221. package/docs/assets/rocket-text-no-logo.svg +3 -0
  222. package/exports/MainMenu.js +1 -0
  223. package/exports/PageData.js +1 -0
  224. package/exports/RocketCodeBlock.js +1 -0
  225. package/exports/RocketIcon.js +1 -0
  226. package/exports/RocketJsDemo.js +1 -0
  227. package/exports/RocketRequestDemo.js +1 -0
  228. package/exports/SocialPreviewPlayground.js +1 -0
  229. package/exports/adapters/netlify.js +1 -0
  230. package/exports/asyncMessage.js +1 -0
  231. package/exports/component-hydration.js +1 -0
  232. package/exports/components/web-awesome.js +63 -0
  233. package/exports/components.js +1 -0
  234. package/exports/config.js +1 -0
  235. package/exports/debounce.js +1 -0
  236. package/exports/define/RocketCodeBlock.js +2 -0
  237. package/exports/define/RocketIcon.js +3 -0
  238. package/exports/define/RocketJsDemo.js +5 -0
  239. package/exports/define/RocketRequestDemo.js +5 -0
  240. package/exports/define/menus.js +14 -0
  241. package/exports/extractCode.js +1 -0
  242. package/exports/globalData.js +1 -0
  243. package/exports/hydration/hydrationLoader.js +1 -0
  244. package/exports/icons.js +11 -0
  245. package/exports/layout-helper.js +1 -0
  246. package/exports/layout.js +1 -0
  247. package/exports/layouts/_atlas.css +3 -0
  248. package/exports/layouts/atlasDoc.js +5 -0
  249. package/exports/layouts/atlasHero.js +1 -0
  250. package/exports/layouts/atlasNotFound.js +4 -0
  251. package/exports/loaded-page-module.js +5 -0
  252. package/exports/markdownHook.js +4 -0
  253. package/exports/menu.js +4 -0
  254. package/exports/menus.js +5 -0
  255. package/exports/page-runtime.js +5 -0
  256. package/exports/pages.js +1 -0
  257. package/exports/resolve.js +1 -0
  258. package/exports/ssr.js +1 -0
  259. package/exports/standalone-demo-url.js +10 -0
  260. package/exports/transform.js +1 -0
  261. package/exports/types/hydration.ts +26 -0
  262. package/exports/types/rocket.ts +598 -0
  263. package/exports/types.ts +71 -0
  264. package/exports/wds-plugin.js +1 -0
  265. package/package.json +192 -9
  266. package/src/PageData.js +244 -0
  267. package/src/RocketCodeBlock.js +516 -0
  268. package/src/RocketIcon.js +291 -0
  269. package/src/RocketJsDemo.js +397 -0
  270. package/src/RocketJsDemo.test-browser.js +228 -0
  271. package/src/RocketRequestDemo.js +439 -0
  272. package/src/RocketRequestDemo.test-browser.js +301 -0
  273. package/src/SocialPreviewPlayground.js +573 -0
  274. package/src/adapters/netlify.js +814 -0
  275. package/src/asyncMessage.js +21 -0
  276. package/src/cli/RocketBuild.js +581 -0
  277. package/src/cli/RocketCli.js +47 -0
  278. package/src/cli/RocketInit.js +636 -0
  279. package/src/cli/RocketStart.js +145 -0
  280. package/src/cli/cli.js +7 -0
  281. package/src/component-hydration.js +86 -0
  282. package/src/components/FeatureList.js +114 -0
  283. package/src/components/Footer.js +116 -0
  284. package/src/components/Header.js +122 -0
  285. package/src/components/RocketDrawer.js +193 -0
  286. package/src/components/RocketSocialLink.js +128 -0
  287. package/src/components/assets/discord.svg +7 -0
  288. package/src/components/assets/github.svg +4 -0
  289. package/src/components/assets/gitlab.svg +1 -0
  290. package/src/components/assets/info.txt +1 -0
  291. package/src/components/assets/license.svg +3 -0
  292. package/src/components/assets/npm.svg +5 -0
  293. package/src/components/assets/slack.svg +5 -0
  294. package/src/components/assets/telegram.svg +4 -0
  295. package/src/components/assets/twitter.svg +1 -0
  296. package/src/components.js +34 -0
  297. package/src/config.js +319 -0
  298. package/src/debounce.js +21 -0
  299. package/src/defaultSocialPreviewTemplate.js +118 -0
  300. package/src/development-page-module-loader.js +29 -0
  301. package/src/extractCode.js +41 -0
  302. package/src/hydration/evaluate.js +54 -0
  303. package/src/hydration/extractStrategies.js +91 -0
  304. package/src/hydration/hydrationLoader.js +330 -0
  305. package/src/icons.js +898 -0
  306. package/src/layouts/atlas/atlasDoc.css +877 -0
  307. package/src/layouts/atlas/atlasDocLayout.js +275 -0
  308. package/src/layouts/atlas/atlasHero.css +774 -0
  309. package/src/layouts/atlas/atlasHeroLayout.js +337 -0
  310. package/src/layouts/atlas/atlasNotFound.css +365 -0
  311. package/src/layouts/atlas/atlasNotFoundLayout.js +69 -0
  312. package/src/layouts/layout-helper.js +92 -0
  313. package/src/layouts/layout.js +52 -0
  314. package/src/loaded-page-module.js +97 -0
  315. package/src/main.js +72 -0
  316. package/src/markdownCompiler.js +303 -0
  317. package/src/markdownHook.js +148 -0
  318. package/src/menu.js +210 -0
  319. package/src/menus/MainMenu.js +58 -0
  320. package/src/menus/RocketMenu.js +191 -0
  321. package/src/menus/RocketNextPage.js +25 -0
  322. package/src/menus/RocketPreviousPage.js +29 -0
  323. package/src/menus/RocketToc.js +309 -0
  324. package/src/menus/pageNavigation.js +285 -0
  325. package/src/page-pagination.js +241 -0
  326. package/src/page-runtime.js +481 -0
  327. package/src/pages.js +537 -0
  328. package/src/publicAssets.js +336 -0
  329. package/src/requestDemoMetadata.js +97 -0
  330. package/src/resolve.js +15 -0
  331. package/src/siteDiscoverability.js +184 -0
  332. package/src/siteHeadMetadata.js +69 -0
  333. package/src/socialPreviewImages.js +482 -0
  334. package/src/socialPreviewTemplatePreview.js +352 -0
  335. package/src/ssr.js +14 -0
  336. package/src/standalone-demo-url.js +147 -0
  337. package/src/static-page-module-loader.js +29 -0
  338. package/src/transform.js +720 -0
  339. package/src/urlLifecycle.js +57 -0
  340. package/src/wds-plugin.js +307 -0
package/src/pages.js ADDED
@@ -0,0 +1,537 @@
1
+ /** Runs on: server */
2
+ import { glob } from 'node:fs/promises';
3
+ import * as p from 'node:path';
4
+ import { normalizeIconReferencesConfig } from './icons.js';
5
+
6
+ /** @typedef {import('@rocket/js/types.js').PageMetadata} PageMetadata */
7
+ /** @typedef {import('@rocket/js/types.js').PageMetadataConfig} PageMetadataConfig */
8
+ /** @typedef {import('@rocket/js/types.js').PageMetadataCustom} PageMetadataCustom */
9
+
10
+ const ROCKET_OWNED_CUSTOM_ELEMENT_TAGS = new Set(['rocket-icon']);
11
+
12
+ /**
13
+ * @param {string} root
14
+ * @param {string[]} include
15
+ * @param {(string | RegExp)[]} exclude
16
+ */
17
+ export async function getPages(root, include, exclude) {
18
+ /** @type {import('@rocket/js/types.js').PageRegistry} */
19
+ const pages = new Map();
20
+ for await (const file of glob(include, {
21
+ cwd: root,
22
+ exclude: ignoreFn(exclude),
23
+ })) {
24
+ if (file.endsWith('.rocket.md')) {
25
+ const module = await tryImport(`./${p.relative(process.cwd(), file)}`);
26
+ const path = module.config?.path;
27
+ if (!path) {
28
+ throw new Error('No path found in file: ' + file);
29
+ }
30
+ if (pages.has(path)) {
31
+ throw new Error(
32
+ 'Duplicate path found: ' + path + ', used in ' + file + ' and ' + pages.get(path)?.file,
33
+ );
34
+ }
35
+ const normalizedModule = normalizePageModule(file, module);
36
+ validateMarkdownPageComponents(file, normalizedModule);
37
+ const linkText =
38
+ (normalizedModule.config.menu === false
39
+ ? undefined
40
+ : normalizedModule.config.menu?.linkText) || normalizedModule._$menuLinkText$;
41
+ const metadataConfig = normalizePageMetadataConfig(file, normalizedModule.config.metadata);
42
+ const title = metadataConfig.title || module._$title$ || linkText || titleFromPath(path);
43
+ pages.set(path, {
44
+ file,
45
+ module: normalizedModule,
46
+ metadata: pageMetadata(title, linkText, metadataConfig),
47
+ demoNames: normalizedModule._$demoNames$ || [],
48
+ });
49
+ } else if (file.endsWith('.rocket.js')) {
50
+ /** @type {import('@rocket/js/types.js').Module} */
51
+ const module = await import(`./${p.relative(process.cwd(), file)}`, {
52
+ with: { type: 'rocketSetupJsInitial' },
53
+ });
54
+ const path = module.config?.path;
55
+ if (!path) {
56
+ throw new Error('No path found in file: ' + file);
57
+ }
58
+ if (pages.has(path)) {
59
+ throw new Error(
60
+ 'Duplicate path found: ' + path + ', used in ' + file + ' and ' + pages.get(path)?.file,
61
+ );
62
+ }
63
+ const normalizedModule = normalizePageModule(file, module);
64
+ const linkText =
65
+ normalizedModule.config.menu === false ? undefined : normalizedModule.config.menu?.linkText;
66
+ const metadataConfig = normalizePageMetadataConfig(file, normalizedModule.config.metadata);
67
+ const title = metadataConfig.title || linkText || titleFromPath(path);
68
+ pages.set(path, {
69
+ file,
70
+ module: normalizedModule,
71
+ metadata: pageMetadata(title, linkText, metadataConfig),
72
+ });
73
+ }
74
+ }
75
+ return pages;
76
+ }
77
+
78
+ /**
79
+ * @param {string} file
80
+ * @param {import('@rocket/js/types.js').Module} module
81
+ * @returns {import('@rocket/js/types.js').Module}
82
+ */
83
+ function normalizePageModule(file, module) {
84
+ const siteHeadMetadata = normalizePageSiteHeadMetadataConfig(
85
+ file,
86
+ module.config.siteHeadMetadata,
87
+ );
88
+ const hasIconReferences = module.config.iconReferences !== undefined;
89
+ const iconReferences = normalizeIconReferencesConfig(
90
+ module.config.iconReferences,
91
+ `Page Icon References in ${file}: config.iconReferences`,
92
+ );
93
+ if (siteHeadMetadata === undefined && !hasIconReferences) {
94
+ return module;
95
+ }
96
+ return {
97
+ ...module,
98
+ config: {
99
+ ...module.config,
100
+ ...(siteHeadMetadata !== undefined ? { siteHeadMetadata } : {}),
101
+ ...(hasIconReferences ? { iconReferences } : {}),
102
+ },
103
+ };
104
+ }
105
+
106
+ /**
107
+ * @param {string} title
108
+ * @param {string | undefined} linkText
109
+ * @param {PageMetadataConfig} metadataConfig
110
+ * @returns {PageMetadata}
111
+ */
112
+ function pageMetadata(title, linkText, metadataConfig) {
113
+ return {
114
+ title,
115
+ ...(linkText ? { linkText } : {}),
116
+ ...(hasOwn(metadataConfig, 'description') ? { description: metadataConfig.description } : {}),
117
+ ...(hasOwn(metadataConfig, 'date') ? { date: metadataConfig.date } : {}),
118
+ ...(hasOwn(metadataConfig, 'updated') ? { updated: metadataConfig.updated } : {}),
119
+ ...(hasOwn(metadataConfig, 'tags') ? { tags: metadataConfig.tags } : {}),
120
+ ...(hasOwn(metadataConfig, 'authors') ? { authors: metadataConfig.authors } : {}),
121
+ ...(hasOwn(metadataConfig, 'custom') ? { custom: metadataConfig.custom } : {}),
122
+ };
123
+ }
124
+
125
+ const pageMetadataFields = new Set([
126
+ 'title',
127
+ 'description',
128
+ 'date',
129
+ 'updated',
130
+ 'tags',
131
+ 'authors',
132
+ 'custom',
133
+ ]);
134
+ const pageSiteHeadMetadataFields = new Set(['indexing', 'socialPreview']);
135
+ const pageSiteHeadMetadataIndexingValues = new Set(['index', 'noindex']);
136
+ const pageSiteHeadMetadataSocialPreviewFields = new Set(['image']);
137
+
138
+ /**
139
+ * @param {string} file
140
+ * @param {unknown} siteHeadMetadataConfig
141
+ * @returns {import('@rocket/js/types.js').PageSiteHeadMetadataConfig | undefined}
142
+ */
143
+ function normalizePageSiteHeadMetadataConfig(file, siteHeadMetadataConfig) {
144
+ if (siteHeadMetadataConfig === undefined) {
145
+ return undefined;
146
+ }
147
+ if (!isPlainRecord(siteHeadMetadataConfig)) {
148
+ throw invalidPageSiteHeadMetadata(file, 'siteHeadMetadata', 'must be an object');
149
+ }
150
+ const config = /** @type {Record<string, unknown>} */ (siteHeadMetadataConfig);
151
+ for (const field of Object.keys(config)) {
152
+ if (!pageSiteHeadMetadataFields.has(field)) {
153
+ throw invalidPageSiteHeadMetadata(
154
+ file,
155
+ `siteHeadMetadata.${field}`,
156
+ 'is not a known Site Head Metadata Page Option',
157
+ );
158
+ }
159
+ }
160
+
161
+ const normalized = /** @type {import('@rocket/js/types.js').PageSiteHeadMetadataConfig} */ ({});
162
+ if (hasOwn(config, 'indexing')) {
163
+ if (!pageSiteHeadMetadataIndexingValues.has(/** @type {string} */ (config.indexing))) {
164
+ throw invalidPageSiteHeadMetadata(
165
+ file,
166
+ 'siteHeadMetadata.indexing',
167
+ "must be 'index' or 'noindex'",
168
+ );
169
+ }
170
+ normalized.indexing = /** @type {import('@rocket/js/types.js').SiteHeadMetadataIndexing} */ (
171
+ config.indexing
172
+ );
173
+ }
174
+ if (hasOwn(config, 'socialPreview')) {
175
+ normalized.socialPreview = readPageSiteHeadMetadataSocialPreview(file, config.socialPreview);
176
+ }
177
+ return normalized;
178
+ }
179
+
180
+ /**
181
+ * @param {string} file
182
+ * @param {unknown} socialPreview
183
+ * @returns {import('@rocket/js/types.js').PageSiteHeadMetadataSocialPreviewConfig}
184
+ */
185
+ function readPageSiteHeadMetadataSocialPreview(file, socialPreview) {
186
+ if (!isPlainRecord(socialPreview)) {
187
+ throw invalidPageSiteHeadMetadata(file, 'siteHeadMetadata.socialPreview', 'must be an object');
188
+ }
189
+ for (const field of Object.keys(socialPreview)) {
190
+ if (!pageSiteHeadMetadataSocialPreviewFields.has(field)) {
191
+ throw invalidPageSiteHeadMetadata(
192
+ file,
193
+ `siteHeadMetadata.socialPreview.${field}`,
194
+ 'is not a known Social Preview field',
195
+ );
196
+ }
197
+ }
198
+
199
+ const normalized =
200
+ /** @type {import('@rocket/js/types.js').PageSiteHeadMetadataSocialPreviewConfig} */ ({});
201
+ if (hasOwn(socialPreview, 'image')) {
202
+ normalized.image = readPageSiteHeadMetadataSocialPreviewImage(file, socialPreview.image);
203
+ }
204
+ return normalized;
205
+ }
206
+
207
+ /**
208
+ * @param {string} file
209
+ * @param {unknown} image
210
+ * @returns {string}
211
+ */
212
+ function readPageSiteHeadMetadataSocialPreviewImage(file, image) {
213
+ if (typeof image !== 'string') {
214
+ throw invalidPageSiteHeadMetadata(
215
+ file,
216
+ 'siteHeadMetadata.socialPreview.image',
217
+ 'must be a string',
218
+ );
219
+ }
220
+ const normalized = image.trim();
221
+ if (!normalized) {
222
+ throw invalidPageSiteHeadMetadata(
223
+ file,
224
+ 'siteHeadMetadata.socialPreview.image',
225
+ 'must be a non-empty string',
226
+ );
227
+ }
228
+ if (!isSupportedSocialPreviewImageSource(normalized)) {
229
+ throw invalidPageSiteHeadMetadata(
230
+ file,
231
+ 'siteHeadMetadata.socialPreview.image',
232
+ 'must be a Page-relative path, site-root path, or absolute http: or https: URL',
233
+ );
234
+ }
235
+ return normalized;
236
+ }
237
+
238
+ /**
239
+ * @param {string} value
240
+ */
241
+ function isSupportedSocialPreviewImageSource(value) {
242
+ if (value.startsWith('//')) {
243
+ return false;
244
+ }
245
+ if (!/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(value)) {
246
+ return true;
247
+ }
248
+ try {
249
+ const url = new URL(value);
250
+ return url.protocol === 'http:' || url.protocol === 'https:';
251
+ } catch {
252
+ return false;
253
+ }
254
+ }
255
+
256
+ /**
257
+ * @param {string} file
258
+ * @param {unknown} metadataConfig
259
+ * @returns {PageMetadataConfig}
260
+ */
261
+ function normalizePageMetadataConfig(file, metadataConfig) {
262
+ if (metadataConfig === undefined) {
263
+ return {};
264
+ }
265
+ if (!isPlainRecord(metadataConfig)) {
266
+ throw invalidPageMetadata(file, 'metadata', 'must be an object');
267
+ }
268
+ const config = /** @type {Record<string, unknown>} */ (metadataConfig);
269
+ for (const field of Object.keys(config)) {
270
+ if (!pageMetadataFields.has(field)) {
271
+ throw invalidPageMetadata(file, `metadata.${field}`, 'is not a known Page Metadata field');
272
+ }
273
+ }
274
+
275
+ const normalized = /** @type {PageMetadataConfig} */ ({});
276
+ if (hasOwn(config, 'title')) {
277
+ normalized.title = readStringMetadata(file, 'metadata.title', config.title);
278
+ }
279
+ if (hasOwn(config, 'description')) {
280
+ normalized.description = readStringMetadata(file, 'metadata.description', config.description);
281
+ }
282
+ if (hasOwn(config, 'date')) {
283
+ normalized.date = readDateMetadata(file, 'metadata.date', config.date);
284
+ }
285
+ if (hasOwn(config, 'updated')) {
286
+ normalized.updated = readDateMetadata(file, 'metadata.updated', config.updated);
287
+ }
288
+ if (hasOwn(config, 'tags')) {
289
+ normalized.tags = readStringListMetadata(file, 'metadata.tags', config.tags);
290
+ }
291
+ if (hasOwn(config, 'authors')) {
292
+ normalized.authors = readStringListMetadata(file, 'metadata.authors', config.authors);
293
+ }
294
+ if (hasOwn(config, 'custom')) {
295
+ normalized.custom = readCustomMetadata(file, 'metadata.custom', config.custom);
296
+ }
297
+ return normalized;
298
+ }
299
+
300
+ /**
301
+ * @param {string} file
302
+ * @param {string} field
303
+ * @param {unknown} value
304
+ */
305
+ function readStringMetadata(file, field, value) {
306
+ if (typeof value !== 'string') {
307
+ throw invalidPageMetadata(file, field, 'must be a string');
308
+ }
309
+ return value;
310
+ }
311
+
312
+ /**
313
+ * @param {string} file
314
+ * @param {string} field
315
+ * @param {unknown} value
316
+ */
317
+ function readDateMetadata(file, field, value) {
318
+ const dateValue = readStringMetadata(file, field, value);
319
+ if (!isDateOnlyIsoString(dateValue)) {
320
+ throw invalidPageMetadata(file, field, 'must be a date-only ISO string like YYYY-MM-DD');
321
+ }
322
+ return dateValue;
323
+ }
324
+
325
+ /**
326
+ * @param {string} file
327
+ * @param {string} field
328
+ * @param {unknown} value
329
+ */
330
+ function readStringListMetadata(file, field, value) {
331
+ if (!Array.isArray(value)) {
332
+ throw invalidPageMetadata(file, field, 'must be a string array');
333
+ }
334
+ return normalizeStringList(file, field, value);
335
+ }
336
+
337
+ /**
338
+ * @param {string} file
339
+ * @param {string} field
340
+ * @param {unknown} value
341
+ */
342
+ function readCustomMetadata(file, field, value) {
343
+ if (!isPlainRecord(value) || !isStructuredData(value)) {
344
+ throw invalidPageMetadata(file, field, 'must be structured data');
345
+ }
346
+ return /** @type {PageMetadataCustom} */ (value);
347
+ }
348
+
349
+ /**
350
+ * @param {string} file
351
+ * @param {string} field
352
+ * @param {unknown[]} values
353
+ */
354
+ function normalizeStringList(file, field, values) {
355
+ const normalized = [];
356
+ const seen = new Set();
357
+ for (const value of values) {
358
+ if (typeof value !== 'string') {
359
+ throw invalidPageMetadata(file, field, 'must be a string array');
360
+ }
361
+ const trimmed = value.trim();
362
+ if (!seen.has(trimmed)) {
363
+ seen.add(trimmed);
364
+ normalized.push(trimmed);
365
+ }
366
+ }
367
+ return normalized;
368
+ }
369
+
370
+ /**
371
+ * @param {string} value
372
+ */
373
+ function isDateOnlyIsoString(value) {
374
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
375
+ return false;
376
+ }
377
+ const date = new Date(`${value}T00:00:00.000Z`);
378
+ return !Number.isNaN(date.valueOf()) && date.toISOString().slice(0, 10) === value;
379
+ }
380
+
381
+ /**
382
+ * @param {unknown} value
383
+ * @returns {boolean}
384
+ */
385
+ function isStructuredData(value) {
386
+ if (value === null) {
387
+ return true;
388
+ }
389
+ if (['string', 'boolean'].includes(typeof value)) {
390
+ return true;
391
+ }
392
+ if (typeof value === 'number') {
393
+ return Number.isFinite(value);
394
+ }
395
+ if (Array.isArray(value)) {
396
+ return value.every(item => isStructuredData(item));
397
+ }
398
+ if (isPlainRecord(value)) {
399
+ return Object.values(value).every(item => isStructuredData(item));
400
+ }
401
+ return false;
402
+ }
403
+
404
+ /**
405
+ * @param {unknown} value
406
+ * @returns {value is Record<string, unknown>}
407
+ */
408
+ function isPlainRecord(value) {
409
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
410
+ return false;
411
+ }
412
+ const prototype = Object.getPrototypeOf(value);
413
+ return prototype === Object.prototype || prototype === null;
414
+ }
415
+
416
+ /**
417
+ * @param {object} object
418
+ * @param {string} key
419
+ */
420
+ function hasOwn(object, key) {
421
+ return Object.prototype.hasOwnProperty.call(object, key);
422
+ }
423
+
424
+ /**
425
+ * @param {string} file
426
+ * @param {string} field
427
+ * @param {string} message
428
+ */
429
+ function invalidPageMetadata(file, field, message) {
430
+ return new Error(`Invalid Page Metadata in ${file}: config.${field} ${message}`);
431
+ }
432
+
433
+ /**
434
+ * @param {string} file
435
+ * @param {string} field
436
+ * @param {string} message
437
+ */
438
+ function invalidPageSiteHeadMetadata(file, field, message) {
439
+ return new Error(`Invalid Page-level Site Head Metadata in ${file}: config.${field} ${message}`);
440
+ }
441
+
442
+ /**
443
+ * @param {(string | RegExp)[]} exclude
444
+ * @returns {(path: string) => boolean}
445
+ */
446
+ function ignoreFn(exclude) {
447
+ /**
448
+ * @param {string} path
449
+ */
450
+ return function (path) {
451
+ for (const pattern of exclude) {
452
+ if (path.includes('node_modules')) {
453
+ return true;
454
+ } else if (typeof pattern === 'string') {
455
+ if (path.includes(pattern)) return true;
456
+ } else {
457
+ if (pattern.test(path)) return true;
458
+ }
459
+ }
460
+ return false;
461
+ };
462
+ }
463
+
464
+ /**
465
+ * @param {string} path
466
+ * @returns {string}
467
+ */
468
+ function titleFromPath(path) {
469
+ const parts = path.split('/');
470
+ const last = parts.findLast(part => !part.startsWith(':'));
471
+ if (!last) {
472
+ return parts[0] ? capitalize(parts[0].slice(1)) : 'Home';
473
+ }
474
+ return capitalize(last);
475
+ }
476
+
477
+ /**
478
+ * @param {string} string
479
+ */
480
+ function capitalize(string) {
481
+ return string.charAt(0).toUpperCase() + string.slice(1);
482
+ }
483
+
484
+ /**
485
+ * @param {string} path
486
+ * @returns {Promise<import('@rocket/js/types.js').Module>}
487
+ */
488
+ async function tryImport(path) {
489
+ try {
490
+ const module = await import(path, {
491
+ with: { type: 'rocketSetupMdInitial' },
492
+ });
493
+ return module;
494
+ } catch (error) {
495
+ const typedError = /** @type {Error} */ (error);
496
+ typedError.message += ' in file: ' + path;
497
+ throw typedError;
498
+ }
499
+ }
500
+
501
+ /**
502
+ * @param {string} file
503
+ * @param {import('@rocket/js/types.js').Module} module
504
+ */
505
+ function validateMarkdownPageComponents(file, module) {
506
+ const customElementTags = module._$customElementTags$ || [];
507
+ const components = module.components || {};
508
+ const pageLocalCustomElementTags = new Set(module._$pageLocalCustomElementTags$ || []);
509
+ const conflictingTags = customElementTags.filter(
510
+ tag =>
511
+ Object.prototype.hasOwnProperty.call(components, tag) && pageLocalCustomElementTags.has(tag),
512
+ );
513
+ const missingTags = customElementTags.filter(
514
+ tag =>
515
+ !ROCKET_OWNED_CUSTOM_ELEMENT_TAGS.has(tag) &&
516
+ !Object.prototype.hasOwnProperty.call(components, tag) &&
517
+ !pageLocalCustomElementTags.has(tag),
518
+ );
519
+
520
+ if (conflictingTags.length) {
521
+ const tagLabel = conflictingTags.length === 1 ? 'tag' : 'tags';
522
+ throw new Error(
523
+ `Markdown Page ${file} defines custom element ${tagLabel} ${conflictingTags.join(
524
+ ', ',
525
+ )} as both Registered Components and Page-local Custom Elements`,
526
+ );
527
+ }
528
+
529
+ if (missingTags.length) {
530
+ const tagLabel = missingTags.length === 1 ? 'tag' : 'tags';
531
+ throw new Error(
532
+ `Markdown Page ${file} uses unregistered custom element ${tagLabel} ${missingTags.join(
533
+ ', ',
534
+ )}`,
535
+ );
536
+ }
537
+ }