@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
@@ -0,0 +1,69 @@
1
+ import { html } from 'lit';
2
+ import { document } from '../layout-helper.js';
3
+ import { resolve } from '../../resolve.js';
4
+
5
+ /** @type {import('@rocket/js/types.js').Components} */
6
+ export const atlasNotFoundComponents = {};
7
+
8
+ /**
9
+ * Renders the header logo.
10
+ * @param {Array<string>} logo
11
+ */
12
+ function renderHeaderLogo(logo) {
13
+ if (logo.length === 1) {
14
+ return html`<img src=${logo[0]} alt="Logo" width="130" />`;
15
+ } else if (logo.length === 2) {
16
+ return html`
17
+ <img src=${logo[0]} alt="Logo" width="36" />
18
+ <img src=${logo[1]} alt="Logo Text" width="88" />
19
+ `;
20
+ }
21
+ return html`<b>Header logo should only contain one or two images.</b>`;
22
+ }
23
+
24
+ /**
25
+ * @param {Array<{url: string, name: string, label?: string}>} socials
26
+ */
27
+ function renderSocialLinks(socials) {
28
+ return socials.map(social => html`<a href=${social.url}>${social.label ?? social.name}</a>`);
29
+ }
30
+
31
+ /** @type {import('@rocket/js/types.js').Layout<import('@rocket/js/types.js').DocData>} */
32
+ export const atlasNotFoundLayout = (pageData, data) => {
33
+ const homeLink = data.headerData.homeLink || '/';
34
+ const rocketLogo = data.headerData.logo[0];
35
+
36
+ return document(
37
+ pageData,
38
+ html`
39
+ <div class="atlas-not-found">
40
+ <header class="atlas-not-found-header">
41
+ <a href=${homeLink} class="atlas-not-found-logo">
42
+ ${renderHeaderLogo(data.headerData.logo)}
43
+ </a>
44
+ <nav class="atlas-not-found-links" aria-label="Project links">
45
+ ${renderSocialLinks(data.headerData.socials)}
46
+ </nav>
47
+ </header>
48
+
49
+ <main class="atlas-not-found-main">
50
+ <div class="atlas-not-found-copy">${pageData.content}</div>
51
+
52
+ <div class="atlas-not-found-scene" aria-hidden="true">
53
+ <div class="atlas-not-found-stars"></div>
54
+ <div class="atlas-not-found-orbit"></div>
55
+ <p class="atlas-not-found-code">404</p>
56
+ <img class="atlas-not-found-rocket" src=${rocketLogo} alt="" />
57
+ </div>
58
+ </main>
59
+ </div>
60
+ `,
61
+ {
62
+ menu: false,
63
+ headerContent: html`<link
64
+ rel="stylesheet"
65
+ href="${resolve('@rocket/js/layouts/atlasNotFound.css', import.meta)}"
66
+ />`,
67
+ },
68
+ );
69
+ };
@@ -0,0 +1,92 @@
1
+ /** Runs on: imported-md-string */
2
+ import { html } from '@lit-labs/ssr';
3
+ import { ifDefined } from 'lit/directives/if-defined.js';
4
+ import { defaultHtmlMenu } from '../menu.js';
5
+
6
+ /** @typedef {import('lit/directive.js').DirectiveResult | import('lit').TemplateResult} LitHTML */
7
+
8
+ /**
9
+ * @param {import("../../exports/PageData.js").PageData} data
10
+ * @param {LitHTML} content
11
+ * @param {Object} [options]
12
+ * @param {LitHTML} [options.title]
13
+ * @param {'html' | false} [options.menu] render a default menu. set to false if you want your own
14
+ * @param {LitHTML} [options.headerContent]
15
+ */
16
+ export function document(
17
+ data,
18
+ content,
19
+ {
20
+ title = data.siteHeadMetadata?.title ?? data.title,
21
+ menu = 'html',
22
+ headerContent = undefined,
23
+ } = {},
24
+ ) {
25
+ const siteHeadMetadata = data.siteHeadMetadata;
26
+ return html`<!DOCTYPE html>
27
+ <html lang=${ifDefined(siteHeadMetadata?.language)}>
28
+ <head>
29
+ <meta charset="utf-8" />
30
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
31
+ <title>${title}</title>
32
+ ${siteHeadMetadataTemplate(siteHeadMetadata)}
33
+ ${menu
34
+ ? html`<style>
35
+ body {
36
+ display: flex;
37
+ }
38
+ #menu {
39
+ margin-right: 1em;
40
+ }
41
+ </style>`
42
+ : ''}
43
+ ${data.clientCode} ${headerContent}
44
+ </head>
45
+ <body>
46
+ ${menu
47
+ ? html`<div id="menu">${defaultHtmlMenu(data.pageTree)}</div>
48
+ <div id="content">${content}</div>`
49
+ : content}
50
+ </body>
51
+ </html>`;
52
+ }
53
+
54
+ /**
55
+ * @param {import('@rocket/js/types.js').SiteHeadMetadata | undefined} metadata
56
+ */
57
+ function siteHeadMetadataTemplate(metadata) {
58
+ if (!metadata) {
59
+ return '';
60
+ }
61
+ return html`
62
+ <meta name="description" content=${metadata.description} />
63
+ ${metadata.indexing === 'noindex' ? html`<meta name="robots" content="noindex" />` : ''}
64
+ <link rel="canonical" href=${metadata.canonicalUrl} />
65
+ ${metadata.icons?.ico ? html`<link rel="icon" href=${metadata.icons.ico} sizes="any" />` : ''}
66
+ ${metadata.icons?.svg
67
+ ? html`<link rel="icon" href=${metadata.icons.svg} type="image/svg+xml" />`
68
+ : ''}
69
+ ${metadata.icons?.appleTouchIcon
70
+ ? html`<link rel="apple-touch-icon" href=${metadata.icons.appleTouchIcon} />`
71
+ : ''}
72
+ ${metadata.themeColor ? html`<meta name="theme-color" content=${metadata.themeColor} />` : ''}
73
+ <meta property="og:site_name" content=${metadata.siteName} />
74
+ <meta property="og:title" content=${metadata.title} />
75
+ <meta property="og:description" content=${metadata.description} />
76
+ <meta property="og:url" content=${metadata.canonicalUrl} />
77
+ <meta property="og:type" content="website" />
78
+ ${metadata.socialPreview?.image
79
+ ? html`<meta property="og:image" content=${metadata.socialPreview.image} />`
80
+ : ''}
81
+ <meta
82
+ name="twitter:card"
83
+ content=${metadata.socialPreview?.image ? 'summary_large_image' : 'summary'}
84
+ />
85
+ <meta name="twitter:title" content=${metadata.title} />
86
+ <meta name="twitter:description" content=${metadata.description} />
87
+ <meta name="twitter:url" content=${metadata.canonicalUrl} />
88
+ ${metadata.socialPreview?.image
89
+ ? html`<meta name="twitter:image" content=${metadata.socialPreview.image} />`
90
+ : ''}
91
+ `;
92
+ }
@@ -0,0 +1,52 @@
1
+ /** Runs on: imported-md-string */
2
+ import { html } from 'lit';
3
+ import { document } from './layout-helper.js';
4
+ import { resolve } from '../resolve.js';
5
+ import { addBootstrapIconLibrary } from '../icons.js';
6
+
7
+ /** @type {import('@rocket/js/types.js').Layout<null>} */
8
+ export const layout = data => {
9
+ addBootstrapIconLibrary(data);
10
+ return document(data, data.content, {
11
+ menu: 'html',
12
+ headerContent: html`
13
+ <link
14
+ rel="stylesheet"
15
+ href="${resolve('@rocket/js/docs/assets/prism-one-light.css', import.meta)}"
16
+ />
17
+ <link
18
+ rel="stylesheet"
19
+ href="${resolve('@awesome.me/webawesome/dist/styles/webawesome.css', import.meta)}"
20
+ />
21
+ `,
22
+ });
23
+ };
24
+
25
+ /** @type {import('@rocket/js/types.js').Layout<null>} */
26
+ export const singleDemoLayout = data => {
27
+ addBootstrapIconLibrary(data);
28
+ return document(data, data.content, {
29
+ menu: false,
30
+ headerContent: html`
31
+ <link
32
+ rel="stylesheet"
33
+ href="${resolve('@awesome.me/webawesome/dist/styles/webawesome.css', import.meta)}"
34
+ />
35
+ <link
36
+ rel="stylesheet"
37
+ href="${resolve('@rocket/js/docs/assets/prism-one-light.css', import.meta)}"
38
+ />
39
+ <style>
40
+ body {
41
+ line-height: 24px;
42
+ font-family: Arial, Helvetica, sans-serif;
43
+ -webkit-font-smoothing: antialiased;
44
+ -moz-osx-font-smoothing: grayscale;
45
+ width: clamp(70%, 80em, 98%);
46
+ }
47
+ </style>
48
+ `,
49
+ });
50
+ };
51
+
52
+ export { addBootstrapIconLibrary };
@@ -0,0 +1,97 @@
1
+ /** @typedef {'markdown' | 'javascript'} LoadedPageModuleKind */
2
+ /** @typedef {import('@rocket/js/types.js').Components} Components */
3
+ /** @typedef {import('@rocket/js/types.js').JavaScriptPageResult} JavaScriptPageResult */
4
+ /** @typedef {import('@rocket/js/types.js').JsPage} JsPage */
5
+ /** @typedef {import('@rocket/js/types.js').JsPageContext} JsPageContext */
6
+ /** @typedef {(components: Components) => string | Promise<string>} ParseComponents */
7
+
8
+ /**
9
+ * @param {{
10
+ * kind: LoadedPageModuleKind;
11
+ * module: unknown;
12
+ * parseComponents?: ParseComponents;
13
+ * }} options
14
+ */
15
+ export function normalizeLoadedPageModule({ kind, module, parseComponents }) {
16
+ if (kind === 'markdown') {
17
+ return normalizeMarkdownPageModule(module, { parseComponents });
18
+ }
19
+ if (kind === 'javascript') {
20
+ return normalizeJavaScriptPageModule(module, { parseComponents });
21
+ }
22
+ throw new Error(`Unsupported Loaded Page Module kind: ${kind}`);
23
+ }
24
+
25
+ /**
26
+ * @param {unknown} module
27
+ * @param {{ parseComponents?: ParseComponents }} [options]
28
+ */
29
+ export function normalizeMarkdownPageModule(module, { parseComponents } = {}) {
30
+ const rawModule =
31
+ /** @type {{ contentFn?: unknown; components?: Components } | null | undefined} */ (module);
32
+ return {
33
+ kind: /** @type {'markdown'} */ ('markdown'),
34
+ contentFn: normalizeMarkdownPageContent(rawModule, { parseComponents }),
35
+ };
36
+ }
37
+
38
+ /**
39
+ * @param {unknown} module
40
+ * @param {{ parseComponents?: ParseComponents }} [options]
41
+ */
42
+ export function normalizeJavaScriptPageModule(module, { parseComponents } = {}) {
43
+ return {
44
+ kind: /** @type {'javascript'} */ ('javascript'),
45
+ body: normalizeJavaScriptPageBody(module, { parseComponents }),
46
+ };
47
+ }
48
+
49
+ /**
50
+ * @param {unknown} module
51
+ * @param {{ parseComponents?: ParseComponents }} options
52
+ */
53
+ function normalizeJavaScriptPageBody(module, { parseComponents }) {
54
+ const rawModule =
55
+ /** @type {{ default?: unknown; content?: unknown; components?: Components }} */ (module);
56
+ const body = rawModule?.default || rawModule?.content;
57
+ const components = rawModule?.components;
58
+ if (!parseComponents || typeof body !== 'function' || !components) {
59
+ return body;
60
+ }
61
+ const pageBody = /** @type {JsPage} */ (body);
62
+ /** @type {(request: Request, context: JsPageContext) => Promise<JavaScriptPageResult>} */
63
+ const renderHydratedJavaScriptPage = async (request, { params, pageData, adapterContext }) => {
64
+ pageData._hasBrowserLoadedComponents = hasBrowserLoadedComponents(components);
65
+ pageData._hydrationScript = await parseComponents(components);
66
+ return pageBody(request, { params, pageData, adapterContext });
67
+ };
68
+ return renderHydratedJavaScriptPage;
69
+ }
70
+
71
+ /**
72
+ * @param {{ contentFn?: unknown; components?: Components } | null | undefined} rawModule
73
+ * @param {{ parseComponents?: ParseComponents }} options
74
+ */
75
+ function normalizeMarkdownPageContent(rawModule, { parseComponents }) {
76
+ const contentFn = rawModule?.contentFn;
77
+ const components = rawModule?.components;
78
+ if (!parseComponents || typeof contentFn !== 'function' || !components) {
79
+ return contentFn;
80
+ }
81
+ /** @type {(pageData: { _hydrationScript?: string; _hasBrowserLoadedComponents?: boolean }, layout: unknown) => Promise<unknown>} */
82
+ const renderMarkdownPage = async (pageData, layout) => {
83
+ pageData._hasBrowserLoadedComponents = hasBrowserLoadedComponents(components);
84
+ pageData._hydrationScript = await parseComponents(components);
85
+ return contentFn(pageData, layout);
86
+ };
87
+ return renderMarkdownPage;
88
+ }
89
+
90
+ /**
91
+ * @param {Components} components
92
+ */
93
+ function hasBrowserLoadedComponents(components) {
94
+ return Object.values(components).some(
95
+ component => component.loading === 'client' || component.loading.startsWith('hydrate:'),
96
+ );
97
+ }
package/src/main.js ADDED
@@ -0,0 +1,72 @@
1
+ /** Runs on: server */
2
+ import { register } from 'node:module';
3
+ import { startDevServer } from '@web/dev-server';
4
+ import customRocketPlugin from './wds-plugin.js';
5
+ import { MessageChannel } from 'node:worker_threads';
6
+ import { customElements } from '@lit-labs/ssr-dom-shim';
7
+ import { readConfig } from './config.js';
8
+
9
+ const configFilePath = process.argv[2] || undefined;
10
+ const startOptions = readStartOptions(process.argv[3]);
11
+
12
+ customElements.define = (name, ctor) => {
13
+ customElements.__definitions.set(name, {
14
+ ctor,
15
+ // @ts-ignore
16
+ observedAttributes: ctor.observedAttributes ?? [],
17
+ });
18
+ };
19
+
20
+ const config = await readConfig(configFilePath);
21
+
22
+ const { port1, port2 } = new MessageChannel();
23
+
24
+ // register must be AFTER the config is read
25
+ register('./markdownHook.js', {
26
+ parentURL: import.meta.url,
27
+ data: { port: port1 },
28
+ transferList: [port1],
29
+ });
30
+
31
+ /** @type {import("@web/dev-server").DevServerConfig} */
32
+ let devServerConfig = {
33
+ plugins: [
34
+ customRocketPlugin(config.includeGlobs, config.excludeRegex, port2, {
35
+ siteHeadMetadata: config.siteHeadMetadata,
36
+ siteOrigin: config.siteOrigin,
37
+ siteDiscoverability: config.siteDiscoverability,
38
+ urlLifecycle: config.urlLifecycle,
39
+ iconLibraries: config.iconLibraries,
40
+ defaultIconLibrary: config.defaultIconLibrary,
41
+ watch: startOptions.watch,
42
+ }),
43
+ ],
44
+ open: startOptions.open ?? true,
45
+ nodeResolve: { exportConditions: ['browser'] },
46
+ watch: startOptions.watch ?? true,
47
+ port: startOptions.port ?? 8888,
48
+ };
49
+
50
+ devServerConfig = config.adjustDevServerConfig(devServerConfig);
51
+
52
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
53
+ const server = await startDevServer({
54
+ config: devServerConfig,
55
+ readCliArgs: false,
56
+ readFileConfig: false,
57
+ });
58
+
59
+ /**
60
+ * @param {string | undefined} value
61
+ * @returns {{ port?: number; open?: boolean; watch?: boolean }}
62
+ */
63
+ function readStartOptions(value) {
64
+ if (!value) {
65
+ return {};
66
+ }
67
+ const parsed = JSON.parse(value);
68
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
69
+ return {};
70
+ }
71
+ return /** @type {{ port?: number; open?: boolean; watch?: boolean }} */ (parsed);
72
+ }
@@ -0,0 +1,303 @@
1
+ /** Runs on: import-hook and build */
2
+ import markdown from 'remark-parse';
3
+ import remarkRehype from 'remark-rehype';
4
+ import rehypeRaw from 'rehype-raw';
5
+ import { unified } from 'unified';
6
+ import { visit } from 'unist-util-visit';
7
+ import { extractMdCode } from './extractCode.js';
8
+ import { mdToJs, mdToJsSingleDemo } from './transform.js';
9
+ import { init, parse as parseExports } from 'es-module-lexer';
10
+ import ts from 'typescript';
11
+ import { parseRequestDemoMetadata } from './requestDemoMetadata.js';
12
+
13
+ /**
14
+ * @param {string} source
15
+ * @returns {Promise<string>}
16
+ */
17
+ export async function compileMarkdownSetup(source) {
18
+ const result = await unified()
19
+ .use(markdown)
20
+ .use(extractMdCode('server'))
21
+ .use(extractPageLocalCustomElementTags)
22
+ .use(extractDemoNames)
23
+ .use(validateRequestDemos)
24
+ .use(remarkRehype, { allowDangerousHtml: true })
25
+ .use(rehypeRaw)
26
+ .use(extractCustomElementTags)
27
+ .use(getTitle)
28
+ .use(compileToServerCode)
29
+ .process(source);
30
+ const code = /** @type {{server: string}} */ (result.data.code);
31
+ return code.server;
32
+ }
33
+
34
+ /**
35
+ * @param {string} source
36
+ * @param {{singleDemo?: string}} [options]
37
+ * @returns {Promise<string>}
38
+ */
39
+ export async function compileMarkdownLoad(source, { singleDemo } = {}) {
40
+ if (singleDemo) {
41
+ return mdToJsSingleDemo(source, singleDemo);
42
+ }
43
+ return mdToJs(source);
44
+ }
45
+
46
+ /**
47
+ * @returns {import('vite').Plugin}
48
+ */
49
+ export function rocketMarkdownPlugin() {
50
+ return {
51
+ name: 'rocket-markdown',
52
+ async transform(source, id) {
53
+ const importOptions = markdownImportOptions(id);
54
+ if (!importOptions) {
55
+ return;
56
+ }
57
+ return {
58
+ code: await compileMarkdownLoad(source, { singleDemo: importOptions.singleDemo }),
59
+ map: null,
60
+ };
61
+ },
62
+ };
63
+ }
64
+
65
+ /**
66
+ * @param {string} id
67
+ * @returns {{ singleDemo?: string } | null}
68
+ */
69
+ function markdownImportOptions(id) {
70
+ const queryIndex = id.indexOf('?');
71
+ const file = queryIndex === -1 ? id : id.slice(0, queryIndex);
72
+ if (!file.endsWith('.rocket.md')) {
73
+ return null;
74
+ }
75
+ const query = queryIndex === -1 ? '' : id.slice(queryIndex + 1);
76
+ return {
77
+ singleDemo: new URLSearchParams(query).get('rocketSingleDemo') || undefined,
78
+ };
79
+ }
80
+
81
+ /**
82
+ * Only output server code
83
+ * @typedef {import('unist').Node} Node
84
+ * @this {import('unified').Processor}
85
+ * @type {import('unified').Plugin<[import("unist-util-remove").Options?]|Array<void>, Node, string>}
86
+ */
87
+ function compileToServerCode() {
88
+ Object.assign(this, { Compiler: compiler });
89
+
90
+ /**
91
+ * @type {import('unified').Compiler}
92
+ */
93
+ function compiler(_, file) {
94
+ const code = /** @type {{server: string}} */ (file.data.code);
95
+ return code.server;
96
+ }
97
+ }
98
+
99
+ function getTitle() {
100
+ /** @type {string | undefined} */
101
+ let h1Text,
102
+ /** @type {string | undefined} */
103
+ h1LinkText = undefined;
104
+ /** @type {import('unist-util-visit').Visitor} */
105
+ const visitor = _node => {
106
+ const node = /** @type {import('hast').Element} */ (_node);
107
+ if (typeof node.properties['link-text'] === 'string') {
108
+ h1LinkText = node.properties['link-text'];
109
+ }
110
+ let text = '';
111
+ visit(node, 'text', node => {
112
+ text += node.value;
113
+ });
114
+ if (h1Text !== undefined) {
115
+ throw new Error('Multiple h1 elements found:\n - ' + h1Text + '\n - ' + text);
116
+ }
117
+ h1Text = text;
118
+ };
119
+
120
+ /**
121
+ * @param {import('unist').Node} tree
122
+ * @param {import('vfile').VFile} file
123
+ */
124
+ return function (tree, file) {
125
+ visit(tree, { type: 'element', tagName: 'h1' }, visitor);
126
+ const code = /** @type {{server: string}} */ (file.data.code);
127
+ const demoNames = /** @type {string[] | undefined} */ (file.data.demoNames) || [];
128
+ const customElementTags =
129
+ /** @type {string[] | undefined} */ (file.data.customElementTags) || [];
130
+ const pageLocalCustomElementTags =
131
+ /** @type {string[] | undefined} */ (file.data.pageLocalCustomElementTags) || [];
132
+ code.server += `;
133
+ export const _$title$ = ${JSON.stringify(h1Text)};
134
+ export const _$menuLinkText$ = ${JSON.stringify(h1LinkText)};
135
+ export const _$demoNames$ = ${JSON.stringify(demoNames)};
136
+ export const _$customElementTags$ = ${JSON.stringify(customElementTags)};
137
+ export const _$pageLocalCustomElementTags$ = ${JSON.stringify(pageLocalCustomElementTags)};
138
+ `;
139
+ return tree;
140
+ };
141
+ }
142
+
143
+ function extractPageLocalCustomElementTags() {
144
+ /** @type {Set<string>} */
145
+ const pageLocalCustomElementTags = new Set();
146
+
147
+ /** @type {import('unist-util-visit').Visitor} */
148
+ const visitor = _node => {
149
+ const node = /** @type {import('mdast').Code} */ (_node);
150
+ if (node.lang === 'js' && node.meta === 'client' && typeof node.value === 'string') {
151
+ for (const tag of parseCustomElementDefineTags(node.value)) {
152
+ pageLocalCustomElementTags.add(tag);
153
+ }
154
+ }
155
+ };
156
+
157
+ /**
158
+ * @param {import('unist').Node} tree
159
+ * @param {import('vfile').VFile} file
160
+ */
161
+ return function (tree, file) {
162
+ visit(tree, 'code', visitor);
163
+ file.data.pageLocalCustomElementTags = [...pageLocalCustomElementTags].sort();
164
+ return tree;
165
+ };
166
+ }
167
+
168
+ /**
169
+ * @param {string} code
170
+ * @returns {string[]}
171
+ */
172
+ function parseCustomElementDefineTags(code) {
173
+ const sourceFile = ts.createSourceFile(
174
+ 'page-client.js',
175
+ code,
176
+ ts.ScriptTarget.Latest,
177
+ true,
178
+ ts.ScriptKind.JS,
179
+ );
180
+ /** @type {Set<string>} */
181
+ const tags = new Set();
182
+
183
+ /**
184
+ * @param {import('typescript').Node} node
185
+ */
186
+ function visitNode(node) {
187
+ const tag = readCustomElementDefineTag(node);
188
+ if (tag) {
189
+ tags.add(tag);
190
+ }
191
+ ts.forEachChild(node, visitNode);
192
+ }
193
+
194
+ visitNode(sourceFile);
195
+ return [...tags].sort();
196
+ }
197
+
198
+ /**
199
+ * @param {import('typescript').Node} node
200
+ * @returns {string | undefined}
201
+ */
202
+ function readCustomElementDefineTag(node) {
203
+ if (!ts.isCallExpression(node)) {
204
+ return;
205
+ }
206
+ const callTarget = node.expression;
207
+ if (!ts.isPropertyAccessExpression(callTarget) || callTarget.name.text !== 'define') {
208
+ return;
209
+ }
210
+ const receiver = callTarget.expression;
211
+ if (!ts.isIdentifier(receiver) || receiver.text !== 'customElements') {
212
+ return;
213
+ }
214
+ const [tagArgument] = node.arguments;
215
+ if (!isLiteralTagName(tagArgument)) {
216
+ return;
217
+ }
218
+ return tagArgument.text.includes('-') ? tagArgument.text : undefined;
219
+ }
220
+
221
+ /**
222
+ * @param {import('typescript').Node | undefined} node
223
+ * @returns {node is import('typescript').StringLiteral | import('typescript').NoSubstitutionTemplateLiteral}
224
+ */
225
+ function isLiteralTagName(node) {
226
+ return (
227
+ node !== undefined && (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node))
228
+ );
229
+ }
230
+
231
+ function extractDemoNames() {
232
+ /** @type {string[]} */
233
+ const demoNames = [];
234
+
235
+ /** @type {import('unist-util-visit').Visitor} */
236
+ const visitor = _node => {
237
+ const node = /** @type {import('mdast').Code} */ (_node);
238
+ if (node.lang === 'js' && node.meta === 'demo' && typeof node.value === 'string') {
239
+ for (const exported of parseExports(node.value)[1]) {
240
+ demoNames.push(exported.ln || exported.n);
241
+ }
242
+ }
243
+ };
244
+
245
+ /**
246
+ * @param {import('unist').Node} tree
247
+ * @param {import('vfile').VFile} file
248
+ */
249
+ return async function (tree, file) {
250
+ await init;
251
+ visit(tree, 'code', visitor);
252
+ file.data.demoNames = demoNames;
253
+ return tree;
254
+ };
255
+ }
256
+
257
+ function validateRequestDemos() {
258
+ /** @type {import('unist-util-visit').Visitor} */
259
+ const visitor = _node => {
260
+ const node = /** @type {import('mdast').Code} */ (_node);
261
+ if (isRequestDemoCodeNode(node)) {
262
+ parseRequestDemoMetadata(node.meta);
263
+ }
264
+ };
265
+
266
+ /**
267
+ * @param {import('unist').Node} tree
268
+ */
269
+ return function (tree) {
270
+ visit(tree, 'code', visitor);
271
+ return tree;
272
+ };
273
+ }
274
+
275
+ /**
276
+ * @param {import('mdast').Code} node
277
+ */
278
+ function isRequestDemoCodeNode(node) {
279
+ return node.lang === 'js' && /^request-demo(?:\s|$)/.test(node.meta || '');
280
+ }
281
+
282
+ function extractCustomElementTags() {
283
+ /** @type {Set<string>} */
284
+ const customElementTags = new Set();
285
+
286
+ /** @type {import('unist-util-visit').Visitor} */
287
+ const visitor = _node => {
288
+ const node = /** @type {import('hast').Element} */ (_node);
289
+ if (node.tagName.includes('-')) {
290
+ customElementTags.add(node.tagName);
291
+ }
292
+ };
293
+
294
+ /**
295
+ * @param {import('unist').Node} tree
296
+ * @param {import('vfile').VFile} file
297
+ */
298
+ return function (tree, file) {
299
+ visit(tree, 'element', visitor);
300
+ file.data.customElementTags = [...customElementTags].sort();
301
+ return tree;
302
+ };
303
+ }