@omega.js/web 0.1.0

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 (1162) hide show
  1. package/LICENSE +98 -0
  2. package/README.md +640 -0
  3. package/bin/omega +2 -0
  4. package/bin/omega-web +2 -0
  5. package/bin/omg +2 -0
  6. package/core/_includes/admin/sections/sidebar.json +100 -0
  7. package/core/_includes/admin/sections/topbar.json +11 -0
  8. package/core/_includes/backend/sections/sidebar.json +39 -0
  9. package/core/_includes/backend/sections/topbar.json +16 -0
  10. package/core/_includes/core/body.html +102 -0
  11. package/core/_includes/core/foot.html +536 -0
  12. package/core/_includes/core/head.html +423 -0
  13. package/core/_includes/core/pricing/price-per-unit.html +33 -0
  14. package/core/_includes/core/showcase/entry-body.html +94 -0
  15. package/core/_includes/core/showcase/index-body.html +43 -0
  16. package/core/_includes/core/showcase/nav.html +60 -0
  17. package/core/_includes/frontend/sections/footer.json +74 -0
  18. package/core/_includes/frontend/sections/nav.json +70 -0
  19. package/core/_includes/global/sections/account.json +31 -0
  20. package/core/_includes/modules/engagement/giscus.html +26 -0
  21. package/core/_layouts/blueprint/404.html +10 -0
  22. package/core/_layouts/blueprint/about.html +10 -0
  23. package/core/_layouts/blueprint/account/index.html +11 -0
  24. package/core/_layouts/blueprint/admin/calendar/index.html +590 -0
  25. package/core/_layouts/blueprint/admin/dashboard/index.html +301 -0
  26. package/core/_layouts/blueprint/admin/firebase/index.html +214 -0
  27. package/core/_layouts/blueprint/admin/posts/editor.html +157 -0
  28. package/core/_layouts/blueprint/admin/posts/index.html +126 -0
  29. package/core/_layouts/blueprint/admin/stackblitz/index.html +30 -0
  30. package/core/_layouts/blueprint/admin/studio/index.html +85 -0
  31. package/core/_layouts/blueprint/admin/users/index.html +272 -0
  32. package/core/_layouts/blueprint/admin/users/new.html +82 -0
  33. package/core/_layouts/blueprint/admin/verts/index.html +204 -0
  34. package/core/_layouts/blueprint/alternatives/alternative.html +15 -0
  35. package/core/_layouts/blueprint/alternatives/index.html +10 -0
  36. package/core/_layouts/blueprint/app.html +10 -0
  37. package/core/_layouts/blueprint/auth/reset.html +19 -0
  38. package/core/_layouts/blueprint/auth/signin.html +19 -0
  39. package/core/_layouts/blueprint/auth/signup.html +19 -0
  40. package/core/_layouts/blueprint/auth/token.html +19 -0
  41. package/core/_layouts/blueprint/blog/categories/category.html +8 -0
  42. package/core/_layouts/blueprint/blog/categories/index.html +11 -0
  43. package/core/_layouts/blueprint/blog/index.html +10 -0
  44. package/core/_layouts/blueprint/blog/post.html +5 -0
  45. package/core/_layouts/blueprint/blog/tags/index.html +11 -0
  46. package/core/_layouts/blueprint/blog/tags/tag.html +8 -0
  47. package/core/_layouts/blueprint/careers.md +13 -0
  48. package/core/_layouts/blueprint/collection/category.html +9 -0
  49. package/core/_layouts/blueprint/collection/document.html +9 -0
  50. package/core/_layouts/blueprint/collection/index.html +9 -0
  51. package/core/_layouts/blueprint/connections/callback.html +11 -0
  52. package/core/_layouts/blueprint/contact.html +14 -0
  53. package/core/_layouts/blueprint/dashboard/index.html +10 -0
  54. package/core/_layouts/blueprint/download.html +20 -0
  55. package/core/_layouts/blueprint/extension/index.html +14 -0
  56. package/core/_layouts/blueprint/extension/installed.html +11 -0
  57. package/core/_layouts/blueprint/feedback.html +10 -0
  58. package/core/_layouts/blueprint/index.html +16 -0
  59. package/core/_layouts/blueprint/legal/cookies.md +57 -0
  60. package/core/_layouts/blueprint/legal/privacy.md +109 -0
  61. package/core/_layouts/blueprint/legal/terms.md +155 -0
  62. package/core/_layouts/blueprint/payment/checkout.html +15 -0
  63. package/core/_layouts/blueprint/payment/confirmation.html +14 -0
  64. package/core/_layouts/blueprint/portal/email-preferences.html +15 -0
  65. package/core/_layouts/blueprint/pricing.html +20 -0
  66. package/core/_layouts/blueprint/status.html +10 -0
  67. package/core/_layouts/blueprint/team/index.html +10 -0
  68. package/core/_layouts/blueprint/team/member.html +5 -0
  69. package/core/_layouts/blueprint/updates/index.html +10 -0
  70. package/core/_layouts/blueprint/updates/update.html +10 -0
  71. package/core/_layouts/core/root.html +45 -0
  72. package/core/_layouts/modules/utilities/redirect.html +129 -0
  73. package/core/css/_studio.scss +237 -0
  74. package/core/css/components/_index.scss +146 -0
  75. package/core/css/core/_.scss +0 -0
  76. package/core/css/core/_alert.scss +87 -0
  77. package/core/css/core/_animations.scss +343 -0
  78. package/core/css/core/_bindings.scss +116 -0
  79. package/core/css/core/_blog-search.scss +57 -0
  80. package/core/css/core/_chatsy.scss +61 -0
  81. package/core/css/core/_consent.scss +424 -0
  82. package/core/css/core/_custom-font-awesome.scss +146 -0
  83. package/core/css/core/_exit-popup.scss +42 -0
  84. package/core/css/core/_generated-badge.scss +33 -0
  85. package/core/css/core/_initialize.scss +29 -0
  86. package/core/css/core/_lazy-loading.scss +104 -0
  87. package/core/css/core/_social-sharing.scss +41 -0
  88. package/core/css/core/_tones.scss +32 -0
  89. package/core/css/core/_utilities.scss +157 -0
  90. package/core/css/main.scss +54 -0
  91. package/core/css/motion/_index.scss +368 -0
  92. package/core/css/pages/404/index.scss +0 -0
  93. package/core/css/pages/admin/calendar/index.scss +692 -0
  94. package/core/css/pages/admin/firebase/index.scss +33 -0
  95. package/core/css/pages/admin/index.scss +9 -0
  96. package/core/css/pages/admin/users/index.scss +9 -0
  97. package/core/css/pages/admin/verts/index.scss +9 -0
  98. package/core/css/pages/alternatives/[alternative]/index.scss +0 -0
  99. package/core/css/pages/blog/[slug].scss +55 -0
  100. package/core/css/pages/dashboard/account/index.scss +242 -0
  101. package/core/css/pages/download/index.scss +480 -0
  102. package/core/css/pages/extension/installed/index.scss +317 -0
  103. package/core/css/pages/feedback/index.scss +31 -0
  104. package/core/css/pages/payment/confirmation/index.scss +14 -0
  105. package/core/css/pages/pricing/index.scss +0 -0
  106. package/core/css/pages/status/index.scss +162 -0
  107. package/core/css/pages/test/libraries/layers/index.scss +28 -0
  108. package/core/css/pages/updates/[update].scss +46 -0
  109. package/core/css/pages/updates/index.scss +13 -0
  110. package/core/css/shell/_index.scss +207 -0
  111. package/core/css/tokens/_index.scss +166 -0
  112. package/core/icons/flags/ar.svg +1 -0
  113. package/core/icons/flags/bd.svg +1 -0
  114. package/core/icons/flags/ca.svg +1 -0
  115. package/core/icons/flags/ch.svg +1 -0
  116. package/core/icons/flags/cn.svg +1 -0
  117. package/core/icons/flags/co.svg +1 -0
  118. package/core/icons/flags/cw.svg +1 -0
  119. package/core/icons/flags/cz.svg +1 -0
  120. package/core/icons/flags/de.svg +1 -0
  121. package/core/icons/flags/dk.svg +1 -0
  122. package/core/icons/flags/eg.svg +1 -0
  123. package/core/icons/flags/es.svg +1 -0
  124. package/core/icons/flags/fi.svg +1 -0
  125. package/core/icons/flags/fr.svg +1 -0
  126. package/core/icons/flags/gb.svg +1 -0
  127. package/core/icons/flags/gq.svg +1 -0
  128. package/core/icons/flags/gr.svg +1 -0
  129. package/core/icons/flags/gt.svg +1 -0
  130. package/core/icons/flags/hn.svg +1 -0
  131. package/core/icons/flags/id.svg +1 -0
  132. package/core/icons/flags/ie.svg +1 -0
  133. package/core/icons/flags/in.svg +1 -0
  134. package/core/icons/flags/ir.svg +1 -0
  135. package/core/icons/flags/it.svg +1 -0
  136. package/core/icons/flags/jp.svg +1 -0
  137. package/core/icons/flags/kp.svg +1 -0
  138. package/core/icons/flags/kr.svg +1 -0
  139. package/core/icons/flags/ly.svg +1 -0
  140. package/core/icons/flags/ma.svg +1 -0
  141. package/core/icons/flags/mu.svg +1 -0
  142. package/core/icons/flags/mx.svg +1 -0
  143. package/core/icons/flags/ng.svg +1 -0
  144. package/core/icons/flags/pa.svg +1 -0
  145. package/core/icons/flags/ph.svg +1 -0
  146. package/core/icons/flags/pk.svg +1 -0
  147. package/core/icons/flags/pt.svg +1 -0
  148. package/core/icons/flags/ru.svg +1 -0
  149. package/core/icons/flags/sa.svg +1 -0
  150. package/core/icons/flags/sd.svg +1 -0
  151. package/core/icons/flags/se.svg +1 -0
  152. package/core/icons/flags/th.svg +1 -0
  153. package/core/icons/flags/tm.svg +1 -0
  154. package/core/icons/flags/tr.svg +1 -0
  155. package/core/icons/flags/us.svg +1 -0
  156. package/core/icons/flags/uy.svg +1 -0
  157. package/core/icons/flags/vn.svg +1 -0
  158. package/core/icons/flags/za.svg +1 -0
  159. package/core/images/exit-popup/subscriber-1.jpg +0 -0
  160. package/core/images/exit-popup/subscriber-2.jpg +0 -0
  161. package/core/images/exit-popup/subscriber-3.jpg +0 -0
  162. package/core/images/exit-popup/subscriber-4.jpg +0 -0
  163. package/core/images/placeholder/photo-1.jpg +0 -0
  164. package/core/images/placeholder/photo-2.jpg +0 -0
  165. package/core/images/placeholder/photo-3.jpg +0 -0
  166. package/core/js/core/analytics-loader.js +253 -0
  167. package/core/js/core/app-shell.js +136 -0
  168. package/core/js/core/appearance.js +195 -0
  169. package/core/js/core/auth.js +457 -0
  170. package/core/js/core/complete.js +72 -0
  171. package/core/js/core/consent.js +384 -0
  172. package/core/js/core/dev-icon-audit.js +63 -0
  173. package/core/js/core/dev-palette.js +670 -0
  174. package/core/js/core/dev-sections.js +53 -0
  175. package/core/js/core/exit-popup.js +276 -0
  176. package/core/js/core/initialize.js +8 -0
  177. package/core/js/core/language-switcher.js +167 -0
  178. package/core/js/core/lazy-loading.js +479 -0
  179. package/core/js/core/motion.js +28 -0
  180. package/core/js/core/query-strings.js +146 -0
  181. package/core/js/core/service-worker.js +28 -0
  182. package/core/js/core/social-sharing.js +293 -0
  183. package/core/js/first-paint.js +35 -0
  184. package/core/js/layouts/modules/utilities/redirect.js +122 -0
  185. package/core/js/libs/admin-helpers.js +62 -0
  186. package/core/js/libs/alert-dismiss.js +35 -0
  187. package/core/js/libs/analytics.js +368 -0
  188. package/core/js/libs/auth/email.js +144 -0
  189. package/core/js/libs/auth/errors.js +119 -0
  190. package/core/js/libs/auth/forms.js +206 -0
  191. package/core/js/libs/auth/index.js +181 -0
  192. package/core/js/libs/auth/oauth.js +394 -0
  193. package/core/js/libs/auth/orphan.js +110 -0
  194. package/core/js/libs/auth/password-toggle.js +44 -0
  195. package/core/js/libs/auth/session-params.js +266 -0
  196. package/core/js/libs/auth/tracking.js +41 -0
  197. package/core/js/libs/charts.js +516 -0
  198. package/core/js/libs/consent-region.js +127 -0
  199. package/core/js/libs/dev.js +150 -0
  200. package/core/js/libs/graph.js +201 -0
  201. package/core/js/libs/initialize-tooltips.js +31 -0
  202. package/core/js/libs/logger.js +38 -0
  203. package/core/js/libs/omega-copy.js +89 -0
  204. package/core/js/libs/path-prefix.js +44 -0
  205. package/core/js/libs/payment-config.js +76 -0
  206. package/core/js/libs/recaptcha.js +94 -0
  207. package/core/js/libs/sale-name.js +295 -0
  208. package/core/js/libs/showcase-frames.js +37 -0
  209. package/core/js/libs/srcset.js +69 -0
  210. package/core/js/libs/tracking-consent.js +161 -0
  211. package/core/js/main.js +144 -0
  212. package/core/js/pages/404/index.js +57 -0
  213. package/core/js/pages/admin/calendar/calendar-core.js +701 -0
  214. package/core/js/pages/admin/calendar/calendar-events.js +853 -0
  215. package/core/js/pages/admin/calendar/calendar-renderer.js +807 -0
  216. package/core/js/pages/admin/calendar/campaign-preview.js +105 -0
  217. package/core/js/pages/admin/calendar/index.js +40 -0
  218. package/core/js/pages/admin/firebase/index.js +727 -0
  219. package/core/js/pages/admin/index.js +531 -0
  220. package/core/js/pages/admin/posts/editor/index.js +230 -0
  221. package/core/js/pages/admin/posts/index.js +237 -0
  222. package/core/js/pages/admin/studio/index.js +538 -0
  223. package/core/js/pages/admin/users/index.js +669 -0
  224. package/core/js/pages/admin/users/new/index.js +65 -0
  225. package/core/js/pages/admin/verts/index.js +407 -0
  226. package/core/js/pages/alternatives/[alternative]/index.js +17 -0
  227. package/core/js/pages/app/index.js +135 -0
  228. package/core/js/pages/blog/[slug].js +132 -0
  229. package/core/js/pages/blog/_search.mjs +108 -0
  230. package/core/js/pages/blog/index.js +193 -0
  231. package/core/js/pages/blog/page/[num]/index.js +7 -0
  232. package/core/js/pages/connections/callback/index.js +148 -0
  233. package/core/js/pages/contact/index.js +170 -0
  234. package/core/js/pages/cookies.js +2 -0
  235. package/core/js/pages/dashboard/account/index.js +366 -0
  236. package/core/js/pages/dashboard/account/modules/orders.js +82 -0
  237. package/core/js/pages/dashboard/account/sections/api-keys.js +149 -0
  238. package/core/js/pages/dashboard/account/sections/billing.js +1667 -0
  239. package/core/js/pages/dashboard/account/sections/connections.js +333 -0
  240. package/core/js/pages/dashboard/account/sections/data-request.js +225 -0
  241. package/core/js/pages/dashboard/account/sections/delete.js +80 -0
  242. package/core/js/pages/dashboard/account/sections/notifications.js +167 -0
  243. package/core/js/pages/dashboard/account/sections/orders.js +151 -0
  244. package/core/js/pages/dashboard/account/sections/profile.js +200 -0
  245. package/core/js/pages/dashboard/account/sections/referrals.js +217 -0
  246. package/core/js/pages/dashboard/account/sections/refund.js +253 -0
  247. package/core/js/pages/dashboard/account/sections/security.js +726 -0
  248. package/core/js/pages/dashboard/account/sections/team.js +247 -0
  249. package/core/js/pages/download/index.js +418 -0
  250. package/core/js/pages/extension/index.js +164 -0
  251. package/core/js/pages/extension/installed/index.js +135 -0
  252. package/core/js/pages/feedback/index.js +193 -0
  253. package/core/js/pages/legal/_document.js +91 -0
  254. package/core/js/pages/payment/checkout/index.js +420 -0
  255. package/core/js/pages/payment/checkout/modules/api.js +139 -0
  256. package/core/js/pages/payment/checkout/modules/dev-section.js +175 -0
  257. package/core/js/pages/payment/checkout/modules/discount.js +69 -0
  258. package/core/js/pages/payment/checkout/modules/pricing.js +73 -0
  259. package/core/js/pages/payment/checkout/modules/state.js +339 -0
  260. package/core/js/pages/payment/checkout/modules/tracking.js +54 -0
  261. package/core/js/pages/payment/confirmation/index.js +91 -0
  262. package/core/js/pages/payment/confirmation/modules/celebration.js +45 -0
  263. package/core/js/pages/payment/confirmation/modules/state.js +112 -0
  264. package/core/js/pages/payment/confirmation/modules/tracking.js +133 -0
  265. package/core/js/pages/payment/confirmation/modules/verify.js +142 -0
  266. package/core/js/pages/portal/email-preferences/index.js +183 -0
  267. package/core/js/pages/pricing/index.js +425 -0
  268. package/core/js/pages/privacy.js +2 -0
  269. package/core/js/pages/reset/index.js +12 -0
  270. package/core/js/pages/signin/index.js +22 -0
  271. package/core/js/pages/signup/index.js +23 -0
  272. package/core/js/pages/status/index.js +687 -0
  273. package/core/js/pages/terms.js +2 -0
  274. package/core/js/pages/test/components/[category]/[name]/index.js +26 -0
  275. package/core/js/pages/test/libraries/appearance/index.js +220 -0
  276. package/core/js/pages/test/libraries/form-manager/index.js +328 -0
  277. package/core/js/pages/test/libraries/layers/index.js +16 -0
  278. package/core/js/pages/test/libraries/verts/index.js +68 -0
  279. package/core/js/pages/test/sections/[category]/[name]/index.js +28 -0
  280. package/core/js/pages/test/styleguide/index.js +35 -0
  281. package/core/js/pages/token/index.js +203 -0
  282. package/core/logos/brandmarks/original/apple-app-store.svg +1 -0
  283. package/core/logos/brandmarks/original/apple.svg +6 -0
  284. package/core/logos/brandmarks/original/bitbucket.svg +14 -0
  285. package/core/logos/brandmarks/original/bitcoin.svg +1 -0
  286. package/core/logos/brandmarks/original/bluesky.svg +7 -0
  287. package/core/logos/brandmarks/original/bootstrap.svg +43 -0
  288. package/core/logos/brandmarks/original/brave.svg +1 -0
  289. package/core/logos/brandmarks/original/chrome.svg +1 -0
  290. package/core/logos/brandmarks/original/discord.svg +1 -0
  291. package/core/logos/brandmarks/original/dropbox.svg +10 -0
  292. package/core/logos/brandmarks/original/edge.svg +1 -0
  293. package/core/logos/brandmarks/original/facebook-f.svg +1 -0
  294. package/core/logos/brandmarks/original/facebook.svg +8 -0
  295. package/core/logos/brandmarks/original/figma.svg +10 -0
  296. package/core/logos/brandmarks/original/firefox.svg +1 -0
  297. package/core/logos/brandmarks/original/github.svg +6 -0
  298. package/core/logos/brandmarks/original/gitlab.svg +17 -0
  299. package/core/logos/brandmarks/original/google-a-s.svg +1 -0
  300. package/core/logos/brandmarks/original/google-chrome-webstore.svg +49 -0
  301. package/core/logos/brandmarks/original/google-play-store.svg +1 -0
  302. package/core/logos/brandmarks/original/google-web-search.svg +1 -0
  303. package/core/logos/brandmarks/original/google.svg +1 -0
  304. package/core/logos/brandmarks/original/gulp.svg +4 -0
  305. package/core/logos/brandmarks/original/html-5.svg +1 -0
  306. package/core/logos/brandmarks/original/instagram.svg +1 -0
  307. package/core/logos/brandmarks/original/javascript.svg +1 -0
  308. package/core/logos/brandmarks/original/jira.svg +18 -0
  309. package/core/logos/brandmarks/original/kick.svg +7 -0
  310. package/core/logos/brandmarks/original/linkedin.svg +1 -0
  311. package/core/logos/brandmarks/original/linux.svg +28 -0
  312. package/core/logos/brandmarks/original/messenger.svg +16 -0
  313. package/core/logos/brandmarks/original/microsoft.svg +1 -0
  314. package/core/logos/brandmarks/original/npm.svg +8 -0
  315. package/core/logos/brandmarks/original/opera.svg +1 -0
  316. package/core/logos/brandmarks/original/patreon.svg +6 -0
  317. package/core/logos/brandmarks/original/pinterest.svg +6 -0
  318. package/core/logos/brandmarks/original/reddit.svg +1 -0
  319. package/core/logos/brandmarks/original/safari.svg +31 -0
  320. package/core/logos/brandmarks/original/sass.svg +3 -0
  321. package/core/logos/brandmarks/original/signal.svg +6 -0
  322. package/core/logos/brandmarks/original/skype.svg +47 -0
  323. package/core/logos/brandmarks/original/slack.svg +33 -0
  324. package/core/logos/brandmarks/original/soundcloud.svg +1 -0
  325. package/core/logos/brandmarks/original/spotify.svg +5 -0
  326. package/core/logos/brandmarks/original/steam.svg +6 -0
  327. package/core/logos/brandmarks/original/telegram.svg +14 -0
  328. package/core/logos/brandmarks/original/tiktok.svg +1 -0
  329. package/core/logos/brandmarks/original/trello.svg +16 -0
  330. package/core/logos/brandmarks/original/tumblr.svg +1 -0
  331. package/core/logos/brandmarks/original/twitch.svg +6 -0
  332. package/core/logos/brandmarks/original/twitter.svg +6 -0
  333. package/core/logos/brandmarks/original/unity.svg +6 -0
  334. package/core/logos/brandmarks/original/x.svg +7 -0
  335. package/core/logos/brandmarks/original/yahoo-y.svg +1 -0
  336. package/core/logos/brandmarks/original/youtube-square.svg +1 -0
  337. package/core/logos/brandmarks/original/youtube.svg +1 -0
  338. package/core/logos/combomarks/dark/airbnb.svg +30 -0
  339. package/core/logos/combomarks/dark/slack.svg +38 -0
  340. package/core/logos/combomarks/dark/spotify.svg +35 -0
  341. package/core/logos/combomarks/dark/twilio.svg +26 -0
  342. package/core/logos/combomarks/dark/weebly.svg +35 -0
  343. package/core/logos/combomarks/gray/airbnb.svg +33 -0
  344. package/core/logos/combomarks/gray/alphabet.svg +23 -0
  345. package/core/logos/combomarks/gray/amazon.svg +38 -0
  346. package/core/logos/combomarks/gray/boring-company.svg +91 -0
  347. package/core/logos/combomarks/gray/burberry.svg +239 -0
  348. package/core/logos/combomarks/gray/embark.svg +21 -0
  349. package/core/logos/combomarks/gray/fitbit.svg +61 -0
  350. package/core/logos/combomarks/gray/fred-perry.svg +94 -0
  351. package/core/logos/combomarks/gray/google.svg +27 -0
  352. package/core/logos/combomarks/gray/hollister.svg +34 -0
  353. package/core/logos/combomarks/gray/hubspot.svg +27 -0
  354. package/core/logos/combomarks/gray/kaplan.svg +33 -0
  355. package/core/logos/combomarks/gray/lenovo.svg +27 -0
  356. package/core/logos/combomarks/gray/levis.svg +25 -0
  357. package/core/logos/combomarks/gray/mapbox.svg +37 -0
  358. package/core/logos/combomarks/gray/netflix.svg +15 -0
  359. package/core/logos/combomarks/gray/new-balance.svg +32 -0
  360. package/core/logos/combomarks/gray/nike.svg +17 -0
  361. package/core/logos/combomarks/gray/paypal.svg +41 -0
  362. package/core/logos/combomarks/gray/puma.svg +82 -0
  363. package/core/logos/combomarks/gray/samsung.svg +26 -0
  364. package/core/logos/combomarks/gray/shopify.svg +36 -0
  365. package/core/logos/combomarks/gray/slack.svg +42 -0
  366. package/core/logos/combomarks/gray/spotify.svg +38 -0
  367. package/core/logos/combomarks/gray/stripe.svg +24 -0
  368. package/core/logos/combomarks/gray/tnf.svg +30 -0
  369. package/core/logos/combomarks/gray/twilio.svg +29 -0
  370. package/core/logos/combomarks/gray/uber.svg +24 -0
  371. package/core/logos/combomarks/gray/weebly.svg +38 -0
  372. package/core/logos/combomarks/original/airbnb.svg +33 -0
  373. package/core/logos/combomarks/original/alphabet.svg +23 -0
  374. package/core/logos/combomarks/original/amazon.svg +38 -0
  375. package/core/logos/combomarks/original/asana.svg +8 -0
  376. package/core/logos/combomarks/original/boring-company.svg +91 -0
  377. package/core/logos/combomarks/original/discord.svg +6 -0
  378. package/core/logos/combomarks/original/embark.svg +24 -0
  379. package/core/logos/combomarks/original/fitbit.svg +60 -0
  380. package/core/logos/combomarks/original/github.svg +6 -0
  381. package/core/logos/combomarks/original/gitlab.svg +20 -0
  382. package/core/logos/combomarks/original/google.svg +28 -0
  383. package/core/logos/combomarks/original/hubspot.svg +29 -0
  384. package/core/logos/combomarks/original/instagram.svg +7 -0
  385. package/core/logos/combomarks/original/kickstarter.svg +6 -0
  386. package/core/logos/combomarks/original/lenovo.svg +24 -0
  387. package/core/logos/combomarks/original/linkedin.svg +6 -0
  388. package/core/logos/combomarks/original/mapbox.svg +39 -0
  389. package/core/logos/combomarks/original/mastodon.svg +7 -0
  390. package/core/logos/combomarks/original/medium.svg +6 -0
  391. package/core/logos/combomarks/original/meta.svg +22 -0
  392. package/core/logos/combomarks/original/microsoft.svg +13 -0
  393. package/core/logos/combomarks/original/monday.svg +12 -0
  394. package/core/logos/combomarks/original/netflix.svg +15 -0
  395. package/core/logos/combomarks/original/notion.svg +9 -0
  396. package/core/logos/combomarks/original/paypal.svg +41 -0
  397. package/core/logos/combomarks/original/reddit.svg +13 -0
  398. package/core/logos/combomarks/original/samsung.svg +25 -0
  399. package/core/logos/combomarks/original/shopify.svg +35 -0
  400. package/core/logos/combomarks/original/slack.svg +47 -0
  401. package/core/logos/combomarks/original/spotify.svg +37 -0
  402. package/core/logos/combomarks/original/stackoverflow.svg +28 -0
  403. package/core/logos/combomarks/original/stripe.svg +24 -0
  404. package/core/logos/combomarks/original/tiktok.svg +12 -0
  405. package/core/logos/combomarks/original/tumblr.svg +6 -0
  406. package/core/logos/combomarks/original/uber.svg +24 -0
  407. package/core/logos/combomarks/original/weebly.svg +34 -0
  408. package/core/logos/combomarks/original/whatsapp.svg +20 -0
  409. package/core/logos/combomarks/original/youtube.svg +10 -0
  410. package/core/logos/combomarks/original/zoom.svg +7 -0
  411. package/core/logos/combomarks/white/airbnb.svg +33 -0
  412. package/core/logos/combomarks/white/alphabet.svg +23 -0
  413. package/core/logos/combomarks/white/amazon.svg +38 -0
  414. package/core/logos/combomarks/white/boring-company.svg +91 -0
  415. package/core/logos/combomarks/white/embark.svg +21 -0
  416. package/core/logos/combomarks/white/fitbit.svg +61 -0
  417. package/core/logos/combomarks/white/google.svg +27 -0
  418. package/core/logos/combomarks/white/hubspot.svg +27 -0
  419. package/core/logos/combomarks/white/kaplan.svg +33 -0
  420. package/core/logos/combomarks/white/lenovo.svg +27 -0
  421. package/core/logos/combomarks/white/mapbox.svg +37 -0
  422. package/core/logos/combomarks/white/netflix.svg +15 -0
  423. package/core/logos/combomarks/white/paypal.svg +40 -0
  424. package/core/logos/combomarks/white/samsung.svg +26 -0
  425. package/core/logos/combomarks/white/shopify.svg +36 -0
  426. package/core/logos/combomarks/white/slack.svg +42 -0
  427. package/core/logos/combomarks/white/spotify.svg +38 -0
  428. package/core/logos/combomarks/white/stripe.svg +24 -0
  429. package/core/logos/combomarks/white/twilio.svg +29 -0
  430. package/core/logos/combomarks/white/uber.svg +24 -0
  431. package/core/logos/combomarks/white/weebly.svg +38 -0
  432. package/defaults/pages/404.md +4 -0
  433. package/defaults/pages/about.md +4 -0
  434. package/defaults/pages/admin/calendar/index.html +4 -0
  435. package/defaults/pages/admin/firebase/index.html +4 -0
  436. package/defaults/pages/admin/index.md +4 -0
  437. package/defaults/pages/admin/posts/editor.html +4 -0
  438. package/defaults/pages/admin/posts/index.html +4 -0
  439. package/defaults/pages/admin/stackblitz/index.html +4 -0
  440. package/defaults/pages/admin/studio/index.html +4 -0
  441. package/defaults/pages/admin/users/index.html +4 -0
  442. package/defaults/pages/admin/users/new.html +4 -0
  443. package/defaults/pages/admin/verts/index.html +4 -0
  444. package/defaults/pages/ads-txt.html +11 -0
  445. package/defaults/pages/alternatives/index.md +4 -0
  446. package/defaults/pages/app.md +4 -0
  447. package/defaults/pages/auth/reset.md +4 -0
  448. package/defaults/pages/auth/signin.md +4 -0
  449. package/defaults/pages/auth/signup.md +4 -0
  450. package/defaults/pages/auth/token.md +4 -0
  451. package/defaults/pages/blog/categories/category.html +21 -0
  452. package/defaults/pages/blog/categories.md +4 -0
  453. package/defaults/pages/blog/index-json.html +27 -0
  454. package/defaults/pages/blog/tags/tag.html +21 -0
  455. package/defaults/pages/blog/tags.md +4 -0
  456. package/defaults/pages/blog.md +22 -0
  457. package/defaults/pages/careers.md +4 -0
  458. package/defaults/pages/connections/callback.md +4 -0
  459. package/defaults/pages/contact.md +4 -0
  460. package/defaults/pages/dashboard/account.md +4 -0
  461. package/defaults/pages/dashboard/index.md +12 -0
  462. package/defaults/pages/download.md +4 -0
  463. package/defaults/pages/extension/index.html +4 -0
  464. package/defaults/pages/extension/installed.html +4 -0
  465. package/defaults/pages/feedback.md +4 -0
  466. package/defaults/pages/feeds/posts-json.html +40 -0
  467. package/defaults/pages/feeds/posts-xml.html +38 -0
  468. package/defaults/pages/humans.html +25 -0
  469. package/defaults/pages/index.md +4 -0
  470. package/defaults/pages/legal/cookies.md +4 -0
  471. package/defaults/pages/legal/privacy.md +4 -0
  472. package/defaults/pages/legal/terms.md +4 -0
  473. package/defaults/pages/llms-txt.html +46 -0
  474. package/defaults/pages/opensearch.html +16 -0
  475. package/defaults/pages/pages-json.html +42 -0
  476. package/defaults/pages/payment/checkout.md +4 -0
  477. package/defaults/pages/payment/confirmation.md +4 -0
  478. package/defaults/pages/portal/email-preferences.md +4 -0
  479. package/defaults/pages/pricing.md +4 -0
  480. package/defaults/pages/redirects/account.md +12 -0
  481. package/defaults/pages/redirects/admin/dashboard.md +11 -0
  482. package/defaults/pages/redirects/auth/change-password.md +9 -0
  483. package/defaults/pages/redirects/auth/forgot.md +9 -0
  484. package/defaults/pages/redirects/auth/join.md +9 -0
  485. package/defaults/pages/redirects/auth/login.md +9 -0
  486. package/defaults/pages/redirects/auth/recover.md +9 -0
  487. package/defaults/pages/redirects/auth/register.md +9 -0
  488. package/defaults/pages/redirects/auth/reset-password.md +9 -0
  489. package/defaults/pages/redirects/billing/cancel.md +9 -0
  490. package/defaults/pages/redirects/billing/refund.md +9 -0
  491. package/defaults/pages/robots.html +36 -0
  492. package/defaults/pages/security-txt.html +11 -0
  493. package/defaults/pages/sitemap.html +37 -0
  494. package/defaults/pages/status.md +4 -0
  495. package/defaults/pages/team/index.md +4 -0
  496. package/defaults/pages/test/account/dashboard.html +16 -0
  497. package/defaults/pages/test/index.md +12 -0
  498. package/defaults/pages/test/libraries/appearance.html +268 -0
  499. package/defaults/pages/test/libraries/cover.html +50 -0
  500. package/defaults/pages/test/libraries/error.html +30 -0
  501. package/defaults/pages/test/libraries/firestore.html +202 -0
  502. package/defaults/pages/test/libraries/form-manager.html +374 -0
  503. package/defaults/pages/test/libraries/layers.html +52 -0
  504. package/defaults/pages/test/libraries/lazy-loading.html +450 -0
  505. package/defaults/pages/test/libraries/verts.html +149 -0
  506. package/defaults/pages/test/redirect/external.md +13 -0
  507. package/defaults/pages/test/redirect/internal.md +13 -0
  508. package/defaults/pages/test/styleguide/index.html +588 -0
  509. package/defaults/pages/test/translation/index.md +50 -0
  510. package/defaults/pages/updates/index.md +4 -0
  511. package/defaults/sample-posts/2026-01-12-welcome-to-the-blog.md +26 -0
  512. package/defaults/sample-posts/2026-02-03-a-field-guide-to-good-defaults.md +50 -0
  513. package/defaults/sample-posts/2026-02-24-shipping-week-notes.md +37 -0
  514. package/defaults/sample-posts/2026-03-17-the-case-for-one-config.md +36 -0
  515. package/defaults/sample-posts/2026-04-09-write-release-notes-people-read.md +34 -0
  516. package/defaults/sample-posts/2026-05-21-dark-mode-done-properly.md +38 -0
  517. package/defaults/sample-posts/2026-06-02-the-boring-deploy-is-the-good-deploy.md +30 -0
  518. package/defaults/sample-posts/2026-06-11-naming-things-a-survival-guide.md +30 -0
  519. package/defaults/sample-posts/2026-06-19-your-pricing-page-is-a-product.md +28 -0
  520. package/defaults/sample-posts/2026-06-30-email-is-an-api-with-feelings.md +28 -0
  521. package/defaults/sample-posts/2026-07-08-ship-the-docs-with-the-diff.md +30 -0
  522. package/defaults/sample-team/avery-quinn.md +22 -0
  523. package/defaults/sample-team/jordan-reyes.md +25 -0
  524. package/defaults/sample-team/riley-nakamura.md +22 -0
  525. package/defaults/sample-team/sam-okafor.md +22 -0
  526. package/defaults/sample-updates/v1.0.0.md +28 -0
  527. package/defaults/sample-updates/v1.1.0.md +27 -0
  528. package/defaults/sample-updates/v1.2.0.md +27 -0
  529. package/defaults/sample-updates/v1.3.0.md +28 -0
  530. package/defaults/showcase/components.html +62 -0
  531. package/defaults/showcase/entry.html +76 -0
  532. package/defaults/showcase/frame.html +62 -0
  533. package/defaults/showcase/index.html +59 -0
  534. package/dist/assets.js +1349 -0
  535. package/dist/brand-tokens.js +195 -0
  536. package/dist/build.js +192 -0
  537. package/dist/cachebreak-html.js +71 -0
  538. package/dist/cli-run.js +25 -0
  539. package/dist/cli.js +47 -0
  540. package/dist/collections.js +183 -0
  541. package/dist/commands/audit.js +470 -0
  542. package/dist/commands/build.js +197 -0
  543. package/dist/commands/clean.js +18 -0
  544. package/dist/commands/customize.js +125 -0
  545. package/dist/commands/deploy.js +441 -0
  546. package/dist/commands/dev.js +1067 -0
  547. package/dist/commands/install.js +31 -0
  548. package/dist/commands/lib/deploy-precheck.js +43 -0
  549. package/dist/commands/lib/ensure-target.js +115 -0
  550. package/dist/commands/migrate.js +86 -0
  551. package/dist/commands/purge.js +31 -0
  552. package/dist/commands/test.js +237 -0
  553. package/dist/commands/translate.js +57 -0
  554. package/dist/commands/update.js +22 -0
  555. package/dist/commands/version.js +11 -0
  556. package/dist/config-sections.js +245 -0
  557. package/dist/consumer-scan.js +118 -0
  558. package/dist/consumer.js +49 -0
  559. package/dist/customize.js +328 -0
  560. package/dist/decisions.js +153 -0
  561. package/dist/dist-audit.js +417 -0
  562. package/dist/dynamic-pages.js +357 -0
  563. package/dist/engine.js +1402 -0
  564. package/dist/firebase-auth-helpers.js +198 -0
  565. package/dist/font-metrics.js +420 -0
  566. package/dist/frontmatter-liquid.js +253 -0
  567. package/dist/github-secrets.js +80 -0
  568. package/dist/hero-animations.js +170 -0
  569. package/dist/imagemin.js +261 -0
  570. package/dist/index.js +41 -0
  571. package/dist/inline-icons.js +65 -0
  572. package/dist/language-flags.js +55 -0
  573. package/dist/layers.js +80 -0
  574. package/dist/layouts.js +44 -0
  575. package/dist/limit-collections.js +199 -0
  576. package/dist/link-resolver.js +303 -0
  577. package/dist/markdown-images.js +85 -0
  578. package/dist/merge.js +20 -0
  579. package/dist/migrate/codemod.js +172 -0
  580. package/dist/migrate/config-convert.js +448 -0
  581. package/dist/migrate/consumer-assets.js +130 -0
  582. package/dist/migrate/index.js +223 -0
  583. package/dist/migrate/lint.js +108 -0
  584. package/dist/migrate/rules.js +1929 -0
  585. package/dist/minify-html.js +148 -0
  586. package/dist/mode-helpers.js +96 -0
  587. package/dist/omega-bin.js +7 -0
  588. package/dist/overrides.js +190 -0
  589. package/dist/path-prefix.js +167 -0
  590. package/dist/paths.js +37 -0
  591. package/dist/pricing.js +301 -0
  592. package/dist/purge.js +95 -0
  593. package/dist/redirect-page.js +45 -0
  594. package/dist/sample-content.js +210 -0
  595. package/dist/scaffold.js +123 -0
  596. package/dist/sections.js +810 -0
  597. package/dist/service-worker.js +200 -0
  598. package/dist/social-pages.js +142 -0
  599. package/dist/srcset.js +67 -0
  600. package/dist/static-assets.js +154 -0
  601. package/dist/target-shortlinks.js +123 -0
  602. package/dist/theme-vocabulary.js +76 -0
  603. package/dist/translate/collect-text-nodes.js +93 -0
  604. package/dist/translate/default-routes.js +152 -0
  605. package/dist/translate/generate-defaults.js +297 -0
  606. package/dist/translate/index.js +568 -0
  607. package/dist/translate/packaged-defaults.js +127 -0
  608. package/dist/translate/sitemap.js +108 -0
  609. package/dist/vendor/account/engine.js +182 -0
  610. package/dist/vendor/account/features.js +220 -0
  611. package/dist/vendor/account/index.js +53 -0
  612. package/dist/vendor/account/schema.js +272 -0
  613. package/dist/vendor/account/subscription.js +38 -0
  614. package/dist/vendor/config/company.js +31 -0
  615. package/dist/vendor/config/defaults.js +173 -0
  616. package/dist/vendor/config/demo.js +18 -0
  617. package/dist/vendor/config/desktop-artifacts.js +110 -0
  618. package/dist/vendor/config/edit.js +769 -0
  619. package/dist/vendor/config/env-delivery.js +145 -0
  620. package/dist/vendor/config/env-rules.js +93 -0
  621. package/dist/vendor/config/env-schema.js +1078 -0
  622. package/dist/vendor/config/env.js +445 -0
  623. package/dist/vendor/config/hooks.js +97 -0
  624. package/dist/vendor/config/index.js +237 -0
  625. package/dist/vendor/config/instances.js +208 -0
  626. package/dist/vendor/config/load.js +490 -0
  627. package/dist/vendor/config/merge.js +68 -0
  628. package/dist/vendor/config/order.js +139 -0
  629. package/dist/vendor/config/ports.js +374 -0
  630. package/dist/vendor/config/providers.js +32 -0
  631. package/dist/vendor/config/repo.js +142 -0
  632. package/dist/vendor/config/retired-keys.js +430 -0
  633. package/dist/vendor/config/schema.js +1610 -0
  634. package/dist/vendor/config/secrets.js +50 -0
  635. package/dist/vendor/config/seed.js +34 -0
  636. package/dist/vendor/config/site-global.js +205 -0
  637. package/dist/vendor/config/validate.js +554 -0
  638. package/dist/vendor/config/winback.js +61 -0
  639. package/dist/vendor/devkit/actions-secrets.js +145 -0
  640. package/dist/vendor/devkit/attach-log-file.js +262 -0
  641. package/dist/vendor/devkit/bare-requires.js +153 -0
  642. package/dist/vendor/devkit/bundle.js +292 -0
  643. package/dist/vendor/devkit/ci-workflows.js +520 -0
  644. package/dist/vendor/devkit/cli-router.js +156 -0
  645. package/dist/vendor/devkit/command-path.js +46 -0
  646. package/dist/vendor/devkit/defaults-engine.js +372 -0
  647. package/dist/vendor/devkit/deploy-precheck.js +54 -0
  648. package/dist/vendor/devkit/deploy-record.js +180 -0
  649. package/dist/vendor/devkit/deploy.js +286 -0
  650. package/dist/vendor/devkit/env-watch.js +132 -0
  651. package/dist/vendor/devkit/framework-deps.js +46 -0
  652. package/dist/vendor/devkit/icons.js +178 -0
  653. package/dist/vendor/devkit/license.js +155 -0
  654. package/dist/vendor/devkit/local-https.js +360 -0
  655. package/dist/vendor/devkit/local.js +1905 -0
  656. package/dist/vendor/devkit/logger.js +128 -0
  657. package/dist/vendor/devkit/merge-line-files.js +296 -0
  658. package/dist/vendor/devkit/omega-bin.js +345 -0
  659. package/dist/vendor/devkit/reads.js +274 -0
  660. package/dist/vendor/devkit/safe-install.js +18 -0
  661. package/dist/vendor/devkit/scaffold-guard.js +96 -0
  662. package/dist/vendor/devkit/stop-signals.js +28 -0
  663. package/dist/vendor/devkit/strip-dev-blocks-plugin.js +29 -0
  664. package/dist/vendor/devkit/strip-dev-blocks.js +32 -0
  665. package/dist/vendor/devkit/target-secrets.js +165 -0
  666. package/dist/vendor/devkit/test/scope.js +162 -0
  667. package/dist/vendor/devkit/translate/cache.js +84 -0
  668. package/dist/vendor/devkit/translate/engine.js +243 -0
  669. package/dist/vendor/devkit/translate/index.js +49 -0
  670. package/dist/vendor/devkit/translate/languages.js +134 -0
  671. package/dist/vendor/devkit/translate/providers.js +188 -0
  672. package/dist/vendor/devkit/update.js +569 -0
  673. package/dist/vendor/template-kit/data/language-flags.js +54 -0
  674. package/dist/vendor/template-kit/data/languages.js +195 -0
  675. package/dist/vendor/template-kit/data/social-urls.js +26 -0
  676. package/dist/vendor/template-kit/filters.js +227 -0
  677. package/dist/vendor/template-kit/index.js +28 -0
  678. package/dist/vendor/template-kit/jekyll-compat.js +268 -0
  679. package/dist/vendor/template-kit/register-liquid.js +0 -0
  680. package/dist/vendor/template-kit/tags/collections.js +191 -0
  681. package/dist/vendor/template-kit/tags/conditionals.js +101 -0
  682. package/dist/vendor/template-kit/tags/content.js +175 -0
  683. package/dist/vendor/template-kit/tags/index.js +33 -0
  684. package/dist/vendor/template-kit/tags/media.js +376 -0
  685. package/dist/vendor/template-kit/variable-resolver.js +163 -0
  686. package/docs/ads-system.md +109 -0
  687. package/docs/classy-v2/DIRECTION.md +92 -0
  688. package/docs/classy-v2/draft-1.html +1932 -0
  689. package/docs/classy-v2/draft-2.html +1956 -0
  690. package/docs/frontmatter.md +153 -0
  691. package/docs/index.md +254 -0
  692. package/docs/libs.md +298 -0
  693. package/docs/omega-sections-spec.md +159 -0
  694. package/docs/page-contract.md +112 -0
  695. package/docs/sections.md +845 -0
  696. package/docs/shared/agent-docs.md +89 -0
  697. package/docs/shared/analytics.md +612 -0
  698. package/docs/shared/brands.md +51 -0
  699. package/docs/shared/breaking-changes.md +497 -0
  700. package/docs/shared/config.md +1387 -0
  701. package/docs/shared/deploys.md +215 -0
  702. package/docs/shared/icons.md +201 -0
  703. package/docs/shared/local-dev.md +147 -0
  704. package/docs/shared/logging.md +202 -0
  705. package/docs/shared/monitoring.md +153 -0
  706. package/docs/shared/publishing.md +183 -0
  707. package/docs/shared/rulings.md +34 -0
  708. package/docs/shared/testing.md +147 -0
  709. package/docs/shared/theming.md +604 -0
  710. package/docs/shared/translation.md +291 -0
  711. package/docs/shared/updates.md +61 -0
  712. package/docs/template-kit.md +128 -0
  713. package/docs/test-framework.md +163 -0
  714. package/package.json +122 -0
  715. package/runtime/boot.js +149 -0
  716. package/runtime/icons.js +77 -0
  717. package/runtime/manager.js +36 -0
  718. package/scaffold/.github/workflows/build.yml +139 -0
  719. package/scaffold/.nvmrc +1 -0
  720. package/scaffold/AGENTS.md +55 -0
  721. package/scaffold/CLAUDE.md +1 -0
  722. package/scaffold/_.gitattributes +4 -0
  723. package/scaffold/_.gitignore +27 -0
  724. package/scaffold/config/omega.json5 +20 -0
  725. package/scaffold/src/assets/css/pages/.gitkeep +0 -0
  726. package/scaffold/src/assets/images/.gitkeep +0 -0
  727. package/scaffold/src/assets/js/pages/.gitkeep +0 -0
  728. package/scaffold/src/pages/.gitkeep +0 -0
  729. package/scaffold/src/pages/example.md.txt +94 -0
  730. package/scaffold/src/service-worker.js +16 -0
  731. package/sw/entry.js +19 -0
  732. package/sw/manager.js +281 -0
  733. package/themes/_template/README.md +115 -0
  734. package/themes/_template/_config.scss +60 -0
  735. package/themes/_template/_theme.js +14 -0
  736. package/themes/_template/_theme.scss +28 -0
  737. package/themes/_template/css/base/_root.scss +19 -0
  738. package/themes/_template/css/components/_components.scss +23 -0
  739. package/themes/base/README.md +5 -0
  740. package/themes/base/_components/data/org-chart/component.html +33 -0
  741. package/themes/base/_components/data/org-chart/component.json5 +33 -0
  742. package/themes/base/_components/data/org-chart/component.scss +183 -0
  743. package/themes/base/_components/heading/masthead/component.html +22 -0
  744. package/themes/base/_components/heading/masthead/component.json5 +30 -0
  745. package/themes/base/_components/heading/section-head/component.html +18 -0
  746. package/themes/base/_components/heading/section-head/component.json5 +27 -0
  747. package/themes/base/_components/pricing/features/component.html +29 -0
  748. package/themes/base/_components/pricing/features/component.json5 +30 -0
  749. package/themes/base/_hero/orbit/index.html +30 -0
  750. package/themes/base/_hero/orbit/script.js +33 -0
  751. package/themes/base/_hero/orbit/style.scss +133 -0
  752. package/themes/base/_includes/admin/sections/sidebar.html +3 -0
  753. package/themes/base/_includes/admin/sections/topbar.html +3 -0
  754. package/themes/base/_includes/backend/sections/sidebar.html +3 -0
  755. package/themes/base/_includes/backend/sections/topbar.html +3 -0
  756. package/themes/base/_includes/frontend/components/connection-card.html +49 -0
  757. package/themes/base/_includes/frontend/components/post-card.html +54 -0
  758. package/themes/base/_includes/frontend/sections/account-connections.html +42 -0
  759. package/themes/base/_includes/frontend/sections/account-section-header.html +11 -0
  760. package/themes/base/_includes/frontend/sections/footer.html +154 -0
  761. package/themes/base/_includes/frontend/sections/nav.html +276 -0
  762. package/themes/base/_includes/global/sections/account.html +72 -0
  763. package/themes/base/_includes/global/sections/app-sidebar.html +248 -0
  764. package/themes/base/_includes/global/sections/app-topbar.html +228 -0
  765. package/themes/base/_includes/global/sections/page-header.html +99 -0
  766. package/themes/base/_layouts/admin/core/minimal-viewport-locked.html +22 -0
  767. package/themes/base/_layouts/admin/core/minimal.html +23 -0
  768. package/themes/base/_layouts/backend/core/base.html +57 -0
  769. package/themes/base/_layouts/backend/core/minimal-viewport-locked.html +32 -0
  770. package/themes/base/_layouts/backend/core/minimal.html +32 -0
  771. package/themes/base/_layouts/backend/pages/dashboard/index.html +230 -0
  772. package/themes/base/_layouts/frontend/core/base.html +31 -0
  773. package/themes/base/_layouts/frontend/core/cover.html +40 -0
  774. package/themes/base/_layouts/frontend/core/minimal.html +47 -0
  775. package/themes/base/_layouts/frontend/pages/404.html +54 -0
  776. package/themes/base/_layouts/frontend/pages/about.html +144 -0
  777. package/themes/base/_layouts/frontend/pages/account/index.html +2104 -0
  778. package/themes/base/_layouts/frontend/pages/alternatives/alternative.html +319 -0
  779. package/themes/base/_layouts/frontend/pages/alternatives/index.html +186 -0
  780. package/themes/base/_layouts/frontend/pages/app.html +142 -0
  781. package/themes/base/_layouts/frontend/pages/auth/reset.html +53 -0
  782. package/themes/base/_layouts/frontend/pages/auth/signin.html +90 -0
  783. package/themes/base/_layouts/frontend/pages/auth/signup.html +141 -0
  784. package/themes/base/_layouts/frontend/pages/auth/token.html +44 -0
  785. package/themes/base/_layouts/frontend/pages/blog/categories/category.html +88 -0
  786. package/themes/base/_layouts/frontend/pages/blog/categories/index.html +88 -0
  787. package/themes/base/_layouts/frontend/pages/blog/index.html +255 -0
  788. package/themes/base/_layouts/frontend/pages/blog/post.html +261 -0
  789. package/themes/base/_layouts/frontend/pages/blog/tags/index.html +84 -0
  790. package/themes/base/_layouts/frontend/pages/blog/tags/tag.html +88 -0
  791. package/themes/base/_layouts/frontend/pages/collection/category.html +72 -0
  792. package/themes/base/_layouts/frontend/pages/collection/document.html +54 -0
  793. package/themes/base/_layouts/frontend/pages/collection/index.html +84 -0
  794. package/themes/base/_layouts/frontend/pages/connections/callback.html +55 -0
  795. package/themes/base/_layouts/frontend/pages/contact.html +214 -0
  796. package/themes/base/_layouts/frontend/pages/download.html +793 -0
  797. package/themes/base/_layouts/frontend/pages/extension/index.html +253 -0
  798. package/themes/base/_layouts/frontend/pages/extension/installed.html +198 -0
  799. package/themes/base/_layouts/frontend/pages/feedback.html +171 -0
  800. package/themes/base/_layouts/frontend/pages/index.html +66 -0
  801. package/themes/base/_layouts/frontend/pages/legal/document.html +78 -0
  802. package/themes/base/_layouts/frontend/pages/payment/checkout.html +459 -0
  803. package/themes/base/_layouts/frontend/pages/payment/confirmation.html +131 -0
  804. package/themes/base/_layouts/frontend/pages/portal/email-preferences.html +104 -0
  805. package/themes/base/_layouts/frontend/pages/pricing.html +596 -0
  806. package/themes/base/_layouts/frontend/pages/status.html +361 -0
  807. package/themes/base/_layouts/frontend/pages/team/index.html +210 -0
  808. package/themes/base/_layouts/frontend/pages/team/member.html +125 -0
  809. package/themes/base/_layouts/frontend/pages/updates/index.html +119 -0
  810. package/themes/base/_layouts/frontend/pages/updates/update.html +118 -0
  811. package/themes/base/_sections/about/hero/section.html +68 -0
  812. package/themes/base/_sections/about/hero/section.json5 +58 -0
  813. package/themes/base/_sections/about/letter/section.html +60 -0
  814. package/themes/base/_sections/about/letter/section.json5 +56 -0
  815. package/themes/base/_sections/about/photo-band/section.html +24 -0
  816. package/themes/base/_sections/about/photo-band/section.json5 +23 -0
  817. package/themes/base/_sections/about/principles/section.html +17 -0
  818. package/themes/base/_sections/about/principles/section.json5 +34 -0
  819. package/themes/base/_sections/about/timeline/section.html +20 -0
  820. package/themes/base/_sections/about/timeline/section.json5 +34 -0
  821. package/themes/base/_sections/marketing/bento/section.html +91 -0
  822. package/themes/base/_sections/marketing/bento/section.json5 +152 -0
  823. package/themes/base/_sections/marketing/cta/section.html +44 -0
  824. package/themes/base/_sections/marketing/cta/section.json5 +47 -0
  825. package/themes/base/_sections/marketing/faq/section.html +52 -0
  826. package/themes/base/_sections/marketing/faq/section.json5 +68 -0
  827. package/themes/base/_sections/marketing/hero/section.html +349 -0
  828. package/themes/base/_sections/marketing/hero/section.json5 +335 -0
  829. package/themes/base/_sections/marketing/newsletter-cta/section.html +38 -0
  830. package/themes/base/_sections/marketing/newsletter-cta/section.js +86 -0
  831. package/themes/base/_sections/marketing/newsletter-cta/section.json5 +29 -0
  832. package/themes/base/_sections/marketing/pricing-cards/section.html +115 -0
  833. package/themes/base/_sections/marketing/pricing-cards/section.json5 +72 -0
  834. package/themes/base/_sections/marketing/product-demo/section.html +62 -0
  835. package/themes/base/_sections/marketing/product-demo/section.js +44 -0
  836. package/themes/base/_sections/marketing/product-demo/section.json5 +52 -0
  837. package/themes/base/_sections/marketing/prose/section.html +22 -0
  838. package/themes/base/_sections/marketing/prose/section.json5 +41 -0
  839. package/themes/base/_sections/marketing/showcase/section.html +35 -0
  840. package/themes/base/_sections/marketing/showcase/section.json5 +52 -0
  841. package/themes/base/_sections/marketing/stats/section.html +32 -0
  842. package/themes/base/_sections/marketing/stats/section.json5 +44 -0
  843. package/themes/base/_sections/marketing/testimonials/section.html +54 -0
  844. package/themes/base/_sections/marketing/testimonials/section.json5 +70 -0
  845. package/themes/base/_sections/marketing/trusted-by/section.html +30 -0
  846. package/themes/base/_sections/marketing/trusted-by/section.json5 +38 -0
  847. package/themes/base/_sections/verts/unit/section.html +7 -0
  848. package/themes/base/_sections/verts/unit/section.js +22 -0
  849. package/themes/base/_sections/verts/unit/section.json5 +24 -0
  850. package/themes/base/_sections/verts/unit/section.scss +24 -0
  851. package/themes/base/_theme.js +13 -0
  852. package/themes/base/_theme.scss +4 -0
  853. package/themes/bootstrap/_theme.js +16 -0
  854. package/themes/bootstrap/_theme.scss +11 -0
  855. package/themes/bootstrap/js/index.esm.js +19 -0
  856. package/themes/bootstrap/js/index.umd.js +34 -0
  857. package/themes/bootstrap/js/src/alert.js +87 -0
  858. package/themes/bootstrap/js/src/base-component.js +86 -0
  859. package/themes/bootstrap/js/src/button.js +72 -0
  860. package/themes/bootstrap/js/src/carousel.js +474 -0
  861. package/themes/bootstrap/js/src/collapse.js +297 -0
  862. package/themes/bootstrap/js/src/dom/data.js +55 -0
  863. package/themes/bootstrap/js/src/dom/event-handler.js +317 -0
  864. package/themes/bootstrap/js/src/dom/manipulator.js +71 -0
  865. package/themes/bootstrap/js/src/dom/selector-engine.js +126 -0
  866. package/themes/bootstrap/js/src/dropdown.js +458 -0
  867. package/themes/bootstrap/js/src/modal.js +378 -0
  868. package/themes/bootstrap/js/src/offcanvas.js +282 -0
  869. package/themes/bootstrap/js/src/popover.js +97 -0
  870. package/themes/bootstrap/js/src/scrollspy.js +296 -0
  871. package/themes/bootstrap/js/src/tab.js +315 -0
  872. package/themes/bootstrap/js/src/toast.js +224 -0
  873. package/themes/bootstrap/js/src/tooltip.js +632 -0
  874. package/themes/bootstrap/js/src/util/backdrop.js +151 -0
  875. package/themes/bootstrap/js/src/util/component-functions.js +35 -0
  876. package/themes/bootstrap/js/src/util/config.js +65 -0
  877. package/themes/bootstrap/js/src/util/focustrap.js +115 -0
  878. package/themes/bootstrap/js/src/util/index.js +306 -0
  879. package/themes/bootstrap/js/src/util/sanitizer.js +117 -0
  880. package/themes/bootstrap/js/src/util/scrollbar.js +114 -0
  881. package/themes/bootstrap/js/src/util/swipe.js +146 -0
  882. package/themes/bootstrap/js/src/util/template-factory.js +160 -0
  883. package/themes/bootstrap/overrides/_accordion.scss +21 -0
  884. package/themes/bootstrap/overrides/_avatars.scss +51 -0
  885. package/themes/bootstrap/overrides/_blog-images.scss +45 -0
  886. package/themes/bootstrap/overrides/_buttons-adaptive.scss +141 -0
  887. package/themes/bootstrap/overrides/_color-shades.scss +25 -0
  888. package/themes/bootstrap/overrides/_cursor-utilities.scss +13 -0
  889. package/themes/bootstrap/overrides/_index.scss +30 -0
  890. package/themes/bootstrap/overrides/_links.scss +26 -0
  891. package/themes/bootstrap/overrides/_soft-colors.scss +99 -0
  892. package/themes/bootstrap/overrides/_spacing-extended.scss +74 -0
  893. package/themes/bootstrap/overrides/_spinners.scss +22 -0
  894. package/themes/bootstrap/overrides/_typography-utilities.scss +40 -0
  895. package/themes/bootstrap/scss/_accordion.scss +153 -0
  896. package/themes/bootstrap/scss/_alert.scss +68 -0
  897. package/themes/bootstrap/scss/_badge.scss +38 -0
  898. package/themes/bootstrap/scss/_breadcrumb.scss +40 -0
  899. package/themes/bootstrap/scss/_button-group.scss +147 -0
  900. package/themes/bootstrap/scss/_buttons.scss +216 -0
  901. package/themes/bootstrap/scss/_card.scss +238 -0
  902. package/themes/bootstrap/scss/_carousel.scss +226 -0
  903. package/themes/bootstrap/scss/_close.scss +66 -0
  904. package/themes/bootstrap/scss/_containers.scss +41 -0
  905. package/themes/bootstrap/scss/_dropdown.scss +250 -0
  906. package/themes/bootstrap/scss/_forms.scss +9 -0
  907. package/themes/bootstrap/scss/_functions.scss +302 -0
  908. package/themes/bootstrap/scss/_grid.scss +39 -0
  909. package/themes/bootstrap/scss/_helpers.scss +12 -0
  910. package/themes/bootstrap/scss/_images.scss +42 -0
  911. package/themes/bootstrap/scss/_list-group.scss +199 -0
  912. package/themes/bootstrap/scss/_maps.scss +174 -0
  913. package/themes/bootstrap/scss/_mixins.scss +42 -0
  914. package/themes/bootstrap/scss/_modal.scss +240 -0
  915. package/themes/bootstrap/scss/_nav.scss +197 -0
  916. package/themes/bootstrap/scss/_navbar.scss +289 -0
  917. package/themes/bootstrap/scss/_offcanvas.scss +147 -0
  918. package/themes/bootstrap/scss/_pagination.scss +109 -0
  919. package/themes/bootstrap/scss/_placeholders.scss +51 -0
  920. package/themes/bootstrap/scss/_popover.scss +196 -0
  921. package/themes/bootstrap/scss/_progress.scss +68 -0
  922. package/themes/bootstrap/scss/_reboot.scss +611 -0
  923. package/themes/bootstrap/scss/_root.scss +187 -0
  924. package/themes/bootstrap/scss/_spinners.scss +85 -0
  925. package/themes/bootstrap/scss/_tables.scss +171 -0
  926. package/themes/bootstrap/scss/_toasts.scss +73 -0
  927. package/themes/bootstrap/scss/_tooltip.scss +119 -0
  928. package/themes/bootstrap/scss/_transitions.scss +27 -0
  929. package/themes/bootstrap/scss/_type.scss +106 -0
  930. package/themes/bootstrap/scss/_utilities.scss +806 -0
  931. package/themes/bootstrap/scss/_variables-dark.scss +102 -0
  932. package/themes/bootstrap/scss/_variables.scss +1753 -0
  933. package/themes/bootstrap/scss/bootstrap-grid.scss +62 -0
  934. package/themes/bootstrap/scss/bootstrap-reboot.scss +10 -0
  935. package/themes/bootstrap/scss/bootstrap-utilities.scss +19 -0
  936. package/themes/bootstrap/scss/bootstrap.scss +52 -0
  937. package/themes/bootstrap/scss/forms/_floating-labels.scss +97 -0
  938. package/themes/bootstrap/scss/forms/_form-check.scss +189 -0
  939. package/themes/bootstrap/scss/forms/_form-control.scss +214 -0
  940. package/themes/bootstrap/scss/forms/_form-range.scss +91 -0
  941. package/themes/bootstrap/scss/forms/_form-select.scss +80 -0
  942. package/themes/bootstrap/scss/forms/_form-text.scss +11 -0
  943. package/themes/bootstrap/scss/forms/_input-group.scss +132 -0
  944. package/themes/bootstrap/scss/forms/_labels.scss +36 -0
  945. package/themes/bootstrap/scss/forms/_validation.scss +12 -0
  946. package/themes/bootstrap/scss/helpers/_clearfix.scss +3 -0
  947. package/themes/bootstrap/scss/helpers/_color-bg.scss +7 -0
  948. package/themes/bootstrap/scss/helpers/_colored-links.scss +30 -0
  949. package/themes/bootstrap/scss/helpers/_focus-ring.scss +5 -0
  950. package/themes/bootstrap/scss/helpers/_icon-link.scss +25 -0
  951. package/themes/bootstrap/scss/helpers/_position.scss +36 -0
  952. package/themes/bootstrap/scss/helpers/_ratio.scss +26 -0
  953. package/themes/bootstrap/scss/helpers/_stacks.scss +15 -0
  954. package/themes/bootstrap/scss/helpers/_stretched-link.scss +15 -0
  955. package/themes/bootstrap/scss/helpers/_text-truncation.scss +7 -0
  956. package/themes/bootstrap/scss/helpers/_visually-hidden.scss +8 -0
  957. package/themes/bootstrap/scss/helpers/_vr.scss +8 -0
  958. package/themes/bootstrap/scss/mixins/_alert.scss +18 -0
  959. package/themes/bootstrap/scss/mixins/_backdrop.scss +14 -0
  960. package/themes/bootstrap/scss/mixins/_banner.scss +7 -0
  961. package/themes/bootstrap/scss/mixins/_border-radius.scss +78 -0
  962. package/themes/bootstrap/scss/mixins/_box-shadow.scss +18 -0
  963. package/themes/bootstrap/scss/mixins/_breakpoints.scss +127 -0
  964. package/themes/bootstrap/scss/mixins/_buttons.scss +70 -0
  965. package/themes/bootstrap/scss/mixins/_caret.scss +69 -0
  966. package/themes/bootstrap/scss/mixins/_clearfix.scss +9 -0
  967. package/themes/bootstrap/scss/mixins/_color-mode.scss +21 -0
  968. package/themes/bootstrap/scss/mixins/_color-scheme.scss +7 -0
  969. package/themes/bootstrap/scss/mixins/_container.scss +11 -0
  970. package/themes/bootstrap/scss/mixins/_deprecate.scss +10 -0
  971. package/themes/bootstrap/scss/mixins/_forms.scss +163 -0
  972. package/themes/bootstrap/scss/mixins/_gradients.scss +47 -0
  973. package/themes/bootstrap/scss/mixins/_grid.scss +151 -0
  974. package/themes/bootstrap/scss/mixins/_image.scss +16 -0
  975. package/themes/bootstrap/scss/mixins/_list-group.scss +26 -0
  976. package/themes/bootstrap/scss/mixins/_lists.scss +7 -0
  977. package/themes/bootstrap/scss/mixins/_pagination.scss +10 -0
  978. package/themes/bootstrap/scss/mixins/_reset-text.scss +17 -0
  979. package/themes/bootstrap/scss/mixins/_resize.scss +6 -0
  980. package/themes/bootstrap/scss/mixins/_table-variants.scss +24 -0
  981. package/themes/bootstrap/scss/mixins/_text-truncate.scss +8 -0
  982. package/themes/bootstrap/scss/mixins/_transition.scss +26 -0
  983. package/themes/bootstrap/scss/mixins/_utilities.scss +97 -0
  984. package/themes/bootstrap/scss/mixins/_visually-hidden.scss +38 -0
  985. package/themes/bootstrap/scss/tests/jasmine.js +16 -0
  986. package/themes/bootstrap/scss/tests/mixins/_auto-import-of-variables-dark.test.scss +7 -0
  987. package/themes/bootstrap/scss/tests/mixins/_color-modes.test.scss +69 -0
  988. package/themes/bootstrap/scss/tests/mixins/_media-query-color-mode-full.test.scss +8 -0
  989. package/themes/bootstrap/scss/tests/mixins/_utilities.test.scss +393 -0
  990. package/themes/bootstrap/scss/tests/sass-true/register.js +14 -0
  991. package/themes/bootstrap/scss/tests/sass-true/runner.js +17 -0
  992. package/themes/bootstrap/scss/tests/utilities/_api.test.scss +75 -0
  993. package/themes/bootstrap/scss/utilities/_api.scss +47 -0
  994. package/themes/bootstrap/scss/vendor/_rfs.scss +348 -0
  995. package/themes/classy/README.md +89 -0
  996. package/themes/classy/_config.scss +245 -0
  997. package/themes/classy/_theme.js +31 -0
  998. package/themes/classy/_theme.scss +57 -0
  999. package/themes/classy/css/app/_panels.scss +183 -0
  1000. package/themes/classy/css/base/_fonts.scss +79 -0
  1001. package/themes/classy/css/base/_no-raise.scss +49 -0
  1002. package/themes/classy/css/base/_root.scss +113 -0
  1003. package/themes/classy/css/base/_typography.scss +154 -0
  1004. package/themes/classy/css/base/_utilities.scss +284 -0
  1005. package/themes/classy/css/components/_alerts.scss +51 -0
  1006. package/themes/classy/css/components/_badges.scss +46 -0
  1007. package/themes/classy/css/components/_buttons.scss +175 -0
  1008. package/themes/classy/css/components/_cards.scss +41 -0
  1009. package/themes/classy/css/components/_dropdowns.scss +48 -0
  1010. package/themes/classy/css/components/_forms.scss +171 -0
  1011. package/themes/classy/css/components/_receipt.scss +45 -0
  1012. package/themes/classy/css/layout/_footer.scss +298 -0
  1013. package/themes/classy/css/layout/_general.scss +209 -0
  1014. package/themes/classy/css/layout/_nav.scss +154 -0
  1015. package/themes/classy/css/layout/_shell.scss +458 -0
  1016. package/themes/classy/css/marketing/_bento.scss +238 -0
  1017. package/themes/classy/css/marketing/_content.scss +1328 -0
  1018. package/themes/classy/css/marketing/_downloads.scss +246 -0
  1019. package/themes/classy/css/marketing/_hero.scss +311 -0
  1020. package/themes/classy/css/marketing/_sections.scss +649 -0
  1021. package/themes/classy/css/pages/404/index.scss +67 -0
  1022. package/themes/classy/css/pages/_auth.scss +235 -0
  1023. package/themes/classy/css/pages/admin/firebase/index.scss +22 -0
  1024. package/themes/classy/css/pages/blog/[slug].scss +56 -0
  1025. package/themes/classy/css/pages/cookies.scss +2 -0
  1026. package/themes/classy/css/pages/dashboard/account/index.scss +31 -0
  1027. package/themes/classy/css/pages/feedback/index.scss +39 -0
  1028. package/themes/classy/css/pages/legal/_document.scss +192 -0
  1029. package/themes/classy/css/pages/payment/checkout/index.scss +585 -0
  1030. package/themes/classy/css/pages/payment/confirmation/index.scss +9 -0
  1031. package/themes/classy/css/pages/privacy.scss +2 -0
  1032. package/themes/classy/css/pages/status/index.scss +164 -0
  1033. package/themes/classy/css/pages/terms.scss +2 -0
  1034. package/themes/classy/css/pages/updates/index.scss +128 -0
  1035. package/themes/classy/fonts/inter-italic-latin-ext.woff2 +0 -0
  1036. package/themes/classy/fonts/inter-italic-latin.woff2 +0 -0
  1037. package/themes/classy/fonts/inter-normal-latin-ext.woff2 +0 -0
  1038. package/themes/classy/fonts/inter-normal-latin.woff2 +0 -0
  1039. package/themes/classy/fonts/newsreader-italic-latin-ext.woff2 +0 -0
  1040. package/themes/classy/fonts/newsreader-italic-latin.woff2 +0 -0
  1041. package/themes/classy/fonts/newsreader-normal-latin-ext.woff2 +0 -0
  1042. package/themes/classy/fonts/newsreader-normal-latin.woff2 +0 -0
  1043. package/themes/classy/js/hero-demo-form.js +56 -0
  1044. package/themes/neobrutalism/README.md +118 -0
  1045. package/themes/neobrutalism/_config.scss +139 -0
  1046. package/themes/neobrutalism/_layouts/frontend/core/base.html +30 -0
  1047. package/themes/neobrutalism/_layouts/frontend/pages/index.html +275 -0
  1048. package/themes/neobrutalism/_theme.js +24 -0
  1049. package/themes/neobrutalism/_theme.scss +61 -0
  1050. package/themes/neobrutalism/css/base/_mixins.scss +46 -0
  1051. package/themes/neobrutalism/css/base/_root.scss +169 -0
  1052. package/themes/neobrutalism/css/base/_typography.scss +61 -0
  1053. package/themes/neobrutalism/css/base/_utilities.scss +89 -0
  1054. package/themes/neobrutalism/css/components/_billing-toggle.scss +74 -0
  1055. package/themes/neobrutalism/css/components/_buttons.scss +148 -0
  1056. package/themes/neobrutalism/css/components/_cards.scss +47 -0
  1057. package/themes/neobrutalism/css/components/_forms.scss +88 -0
  1058. package/themes/neobrutalism/css/components/_marketing.scss +244 -0
  1059. package/themes/neobrutalism/css/layout/_general.scss +213 -0
  1060. package/themes/neobrutalism/css/layout/_navigation.scss +171 -0
  1061. package/themes/neobrutalism/css/pages/index.scss +203 -0
  1062. package/themes/neobrutalism/css/pages/pricing/index.scss +58 -0
  1063. package/themes/neobrutalism/css/pages/test/libraries/layers/index.scss +7 -0
  1064. package/themes/neobrutalism/js/pages/test/libraries/layers/index.js +9 -0
  1065. package/themes/newsflash/README.md +117 -0
  1066. package/themes/newsflash/_components/heading/lede/component.html +14 -0
  1067. package/themes/newsflash/_components/heading/lede/component.json5 +23 -0
  1068. package/themes/newsflash/_components/heading/rule-head/component.html +17 -0
  1069. package/themes/newsflash/_components/heading/rule-head/component.json5 +23 -0
  1070. package/themes/newsflash/_components/news/byline/component.html +12 -0
  1071. package/themes/newsflash/_components/news/byline/component.json5 +18 -0
  1072. package/themes/newsflash/_components/news/story-card/component.html +25 -0
  1073. package/themes/newsflash/_components/news/story-card/component.json5 +21 -0
  1074. package/themes/newsflash/_config.scss +147 -0
  1075. package/themes/newsflash/_layouts/frontend/core/base.html +51 -0
  1076. package/themes/newsflash/_layouts/frontend/pages/blog/index.html +299 -0
  1077. package/themes/newsflash/_layouts/frontend/pages/blog/post.html +235 -0
  1078. package/themes/newsflash/_layouts/frontend/pages/index.html +328 -0
  1079. package/themes/newsflash/_sections/marketing/desks/section.html +39 -0
  1080. package/themes/newsflash/_sections/marketing/desks/section.json5 +49 -0
  1081. package/themes/newsflash/_sections/marketing/newsletter-cta/section.html +103 -0
  1082. package/themes/newsflash/_sections/marketing/newsletter-cta/section.json5 +50 -0
  1083. package/themes/newsflash/_sections/marketing/rundown/section.html +28 -0
  1084. package/themes/newsflash/_sections/marketing/rundown/section.json5 +40 -0
  1085. package/themes/newsflash/_theme.js +24 -0
  1086. package/themes/newsflash/_theme.scss +70 -0
  1087. package/themes/newsflash/css/base/_fonts.scss +80 -0
  1088. package/themes/newsflash/css/base/_mixins.scss +51 -0
  1089. package/themes/newsflash/css/base/_root.scss +257 -0
  1090. package/themes/newsflash/css/base/_typography.scss +49 -0
  1091. package/themes/newsflash/css/base/_utilities.scss +122 -0
  1092. package/themes/newsflash/css/components/_badges.scss +65 -0
  1093. package/themes/newsflash/css/components/_billing-toggle.scss +61 -0
  1094. package/themes/newsflash/css/components/_buttons.scss +139 -0
  1095. package/themes/newsflash/css/components/_cards.scss +47 -0
  1096. package/themes/newsflash/css/components/_editorial.scss +173 -0
  1097. package/themes/newsflash/css/components/_forms.scss +75 -0
  1098. package/themes/newsflash/css/components/_infinite-scroll.scss +102 -0
  1099. package/themes/newsflash/css/components/_panels.scss +156 -0
  1100. package/themes/newsflash/css/components/_ticker.scss +67 -0
  1101. package/themes/newsflash/css/layout/_general.scss +330 -0
  1102. package/themes/newsflash/css/layout/_navigation.scss +168 -0
  1103. package/themes/newsflash/css/pages/404/index.scss +79 -0
  1104. package/themes/newsflash/css/pages/blog/[slug].scss +186 -0
  1105. package/themes/newsflash/css/pages/blog/index.scss +17 -0
  1106. package/themes/newsflash/css/pages/index.scss +157 -0
  1107. package/themes/newsflash/css/pages/pricing/index.scss +55 -0
  1108. package/themes/newsflash/css/pages/test/libraries/layers/index.scss +7 -0
  1109. package/themes/newsflash/fonts/fraunces-italic-latin-ext.woff2 +0 -0
  1110. package/themes/newsflash/fonts/fraunces-italic-latin.woff2 +0 -0
  1111. package/themes/newsflash/fonts/fraunces-normal-latin-ext.woff2 +0 -0
  1112. package/themes/newsflash/fonts/fraunces-normal-latin.woff2 +0 -0
  1113. package/themes/newsflash/fonts/schibsted-grotesk-italic-latin-ext.woff2 +0 -0
  1114. package/themes/newsflash/fonts/schibsted-grotesk-italic-latin.woff2 +0 -0
  1115. package/themes/newsflash/fonts/schibsted-grotesk-normal-latin-ext.woff2 +0 -0
  1116. package/themes/newsflash/fonts/schibsted-grotesk-normal-latin.woff2 +0 -0
  1117. package/themes/newsflash/js/pages/blog/[slug].js +29 -0
  1118. package/themes/newsflash/js/pages/test/libraries/layers/index.js +9 -0
  1119. package/translations/es/pages/404.json +86 -0
  1120. package/translations/es/pages/account.json +36 -0
  1121. package/translations/es/pages/app.json +44 -0
  1122. package/translations/es/pages/cancel.json +36 -0
  1123. package/translations/es/pages/change-password.json +36 -0
  1124. package/translations/es/pages/connections/callback.json +41 -0
  1125. package/translations/es/pages/dashboard/account.json +475 -0
  1126. package/translations/es/pages/dashboard.json +36 -0
  1127. package/translations/es/pages/forgot.json +36 -0
  1128. package/translations/es/pages/join.json +36 -0
  1129. package/translations/es/pages/login.json +36 -0
  1130. package/translations/es/pages/payment/checkout.json +83 -0
  1131. package/translations/es/pages/payment/confirmation.json +62 -0
  1132. package/translations/es/pages/portal/email-preferences.json +46 -0
  1133. package/translations/es/pages/recover.json +36 -0
  1134. package/translations/es/pages/refund.json +36 -0
  1135. package/translations/es/pages/register.json +36 -0
  1136. package/translations/es/pages/reset-password.json +36 -0
  1137. package/translations/es/pages/reset.json +42 -0
  1138. package/translations/es/pages/signin.json +45 -0
  1139. package/translations/es/pages/signup.json +60 -0
  1140. package/translations/es/pages/token.json +39 -0
  1141. package/translations/fa/pages/404.json +86 -0
  1142. package/translations/fa/pages/account.json +36 -0
  1143. package/translations/fa/pages/app.json +44 -0
  1144. package/translations/fa/pages/cancel.json +36 -0
  1145. package/translations/fa/pages/change-password.json +36 -0
  1146. package/translations/fa/pages/connections/callback.json +41 -0
  1147. package/translations/fa/pages/dashboard/account.json +475 -0
  1148. package/translations/fa/pages/dashboard.json +36 -0
  1149. package/translations/fa/pages/forgot.json +36 -0
  1150. package/translations/fa/pages/join.json +36 -0
  1151. package/translations/fa/pages/login.json +36 -0
  1152. package/translations/fa/pages/payment/checkout.json +83 -0
  1153. package/translations/fa/pages/payment/confirmation.json +62 -0
  1154. package/translations/fa/pages/portal/email-preferences.json +46 -0
  1155. package/translations/fa/pages/recover.json +36 -0
  1156. package/translations/fa/pages/refund.json +36 -0
  1157. package/translations/fa/pages/register.json +36 -0
  1158. package/translations/fa/pages/reset-password.json +36 -0
  1159. package/translations/fa/pages/reset.json +42 -0
  1160. package/translations/fa/pages/signin.json +45 -0
  1161. package/translations/fa/pages/signup.json +60 -0
  1162. package/translations/fa/pages/token.json +39 -0
@@ -0,0 +1,1067 @@
1
+ /**
2
+ * `omega dev` — the development loop:
3
+ * 1. dev-mode assets (stable un-hashed names, no minify) → .omega/manifest
4
+ * 2. programmatic Eleventy watch + serve over src/
5
+ * 3. asset-source watchers (consumer src/assets + packaged theme/core
6
+ * layers) rebuild bundles IN PLACE — URLs are stable in dev, so the
7
+ * rendered HTML stays valid without a re-render; the dev server
8
+ * watches the built asset trees and live-reloads the browser (css
9
+ * hot-swaps, js reloads — no hand refresh).
10
+ *
11
+ * Port (N7): the website convention is 4000, resolved through the allocator —
12
+ * taken ports bump +1. Multi-instance web brands offset deterministically:
13
+ * each instance wants 4000 + its position in the instances array, so
14
+ * targets/website and targets/website-admin dev side-by-side. `omega dev
15
+ * --port=4001` (or a config `ports.website` entry) PINS the port instead:
16
+ * busy = hard error, never a silent bump. The
17
+ * resolved map of a live sibling backend (its `.temp/ports.json`) plus this
18
+ * website port and its resolved ORIGIN (protocol included,
19
+ * [#262](https://github.com/Omega-JS-Stack/omega/issues/262)) are injected into
20
+ * the page chrome as `dev` so
21
+ * @omega.js/client connects to the stack that is ACTUALLY running — read PER
22
+ * RESPONSE (the render-time bake is advisory, rewritten as the page is served,
23
+ * [#346](https://github.com/Omega-JS-Stack/omega/issues/346)) and per request
24
+ * for the auth-emulator proxy, because a backend that boots after this server
25
+ * (or restarts onto bumped ports) is the normal case
26
+ * ([#300](https://github.com/Omega-JS-Stack/omega/issues/300)).
27
+ *
28
+ * `omega dev --local` first links every @omega.js framework the brand uses to
29
+ * the local Omega monorepo (file: installs, idempotent) and starts the
30
+ * monorepo's src→dist watch, then runs the normal dev loop (master plan §8).
31
+ */
32
+ const fs = require('node:fs');
33
+ const http = require('node:http');
34
+ const path = require('node:path');
35
+ const jetpack = require('fs-jetpack');
36
+ const Logger = require('../vendor/devkit/logger.js');
37
+ const {
38
+ CLASSIC_PORTS, isPortFree, resolvePorts, envPort,
39
+ readSiblingPorts, writePortsFile, clearPortsFile,
40
+ findBrandRoot, hasOmegaConfig, loadConfig, instancePortOffset,
41
+ } = require('../vendor/config/index.js');
42
+ const { emitIcons } = require('../vendor/devkit/icons.js');
43
+ const { watchEnvChain } = require('../vendor/devkit/env-watch.js');
44
+ const { STOP_SIGNALS } = require('../vendor/devkit/stop-signals.js');
45
+ const attachLogFile = require('../vendor/devkit/attach-log-file.js');
46
+ const { ensureTarget } = require('./lib/ensure-target.js');
47
+ const { emitLanguageFlags } = require('../language-flags.js');
48
+ const { buildAssets } = require('../assets.js');
49
+ const { buildServiceWorker, writeBuildMeta } = require('../service-worker.js');
50
+ const { resolveStaticDirs, copyStaticAssets, hasFaviconSet, brandmarkSvgUrl } = require('../static-assets.js');
51
+ const { devImageFallback } = require('../imagemin.js');
52
+ const { configureOmega } = require('../engine.js');
53
+ const reads = require('../vendor/devkit/reads.js');
54
+ const { reconcileSampleContent } = require('../sample-content.js');
55
+ const { resolveThemeLayers } = require('../layers.js');
56
+ const { consumerPaths, loadSiteData } = require('../consumer.js');
57
+ const { PATHS, resolveClientEntry } = require('../paths.js');
58
+
59
+ const logger = new Logger('dev');
60
+
61
+ const WATCH_DEBOUNCE_MS = 250;
62
+ // The rescan lane settles faster than the asset lane: a scan is a readdir, and
63
+ // the sooner it lands the sooner a permalink collision is on screen.
64
+ const RESCAN_DEBOUNCE_MS = 50;
65
+ // How often a re-arming watcher probes for its directory to come back. A
66
+ // prepare's wipe-to-rewrite gap is a build's worth of time, so a coarse probe
67
+ // costs nothing and never busy-loops.
68
+ const REARM_POLL_MS = 200;
69
+
70
+ module.exports = async function (options) {
71
+ options = options || {};
72
+
73
+ // Tee the whole run to <targetRoot>/logs/dev.log — first statement of the verb
74
+ // so a crash on the way up is already in the file (#197).
75
+ attachLogFile(path.join(consumerPaths().root, 'logs', 'dev.log'));
76
+
77
+ // The local half of the retired `omega setup` (#675) — idempotent, offline,
78
+ // and quiet on a converged target.
79
+ ensureTarget({ projectDir: consumerPaths().root, log: (line) => logger.log(line), warn: (line) => logger.warn(line) });
80
+
81
+ if (options.local) {
82
+ await linkBrandToMonorepo();
83
+ }
84
+
85
+ const paths = consumerPaths();
86
+ const siteData = loadSiteData(paths.root);
87
+ // The target's own package version — read ONCE and handed to both consumers: the
88
+ // build manifest and the page chrome's Configuration block (the client's
89
+ // release tag, #380).
90
+ const version = jetpack.read(path.join(paths.root, 'package.json'), 'json')?.version;
91
+ const clientEntry = resolveClientEntry();
92
+ const { port, bumped } = await resolveWebsitePort(paths.root, Number(options.port) || null);
93
+
94
+ // HTTPS (same contract as the backend's serve/emulator): the PUBLIC website
95
+ // port speaks TLS through the shared mkcert proxy; eleventy sits on an
96
+ // internal plain-http port behind it (WebSocket live-reload tunnels through).
97
+ // `--no-https` or no mkcert → plain http on the public port, as before.
98
+ const { ensureLocalHttpsCerts, startLocalHttpsProxy, mkcertInstallHint } = require('../vendor/devkit/local-https.js');
99
+ let httpsCerts = null;
100
+ let internalPort = null;
101
+ if (options.https !== false) {
102
+ httpsCerts = await ensureLocalHttpsCerts({
103
+ certsDir: path.join(paths.root, '.temp', 'certs'),
104
+ log: (line) => logger.log(line),
105
+ });
106
+
107
+ if (httpsCerts) {
108
+ ({ ports: { internal: internalPort } } = await resolvePorts({ wanted: { internal: 4443 } }));
109
+ } else {
110
+ logger.log(`HTTPS disabled — could not obtain certificates (install mkcert: ${mkcertInstallHint()})`);
111
+ }
112
+ }
113
+
114
+ // The resolved website ORIGIN — protocol and port together, since only this
115
+ // point in the boot knows whether the public port speaks TLS. Everything that
116
+ // needs "where the dev website answers" reads THIS: site.url, the page chrome,
117
+ // and the ports file siblings read (#262).
118
+ const origin = devWebsiteOrigin(port, httpsCerts !== null);
119
+ applyDevSiteUrl(siteData, origin);
120
+
121
+ // LIVE, never a snapshot: both the baked page chrome and the auth-emulator
122
+ // proxy resolve the sibling backend's map at use time (#300).
123
+ const devPorts = devPortsOption(paths.root, port, origin);
124
+ const authPort = () => devPorts().ports.auth;
125
+
126
+ // ---- Sample content on disk (spec §8): mirror the injected filler under
127
+ // the gitignored .omega/sample-content/ so it can be read and copied —
128
+ // machine-owned, regenerated every boot, gone per-collection once the
129
+ // consumer owns that collection.
130
+ const samples = reconcileSampleContent({
131
+ targetRoot: paths.root,
132
+ consumerDir: paths.src,
133
+ defaultsDir: PATHS.defaults,
134
+ });
135
+ if (samples.written.length) {
136
+ logger.log(`Sample content: ${samples.written.length} files → ${path.relative(paths.root, samples.root)}/ (gitignored, regenerated each boot)`);
137
+ }
138
+ samples.removed.forEach((collectionDir) => logger.log(`Sample content: ${collectionDir} is yours now — materialized samples removed`));
139
+
140
+ const activeTheme = (siteData.theme && siteData.theme.id) || 'classy';
141
+ const themeLayerDirs = resolveAssetThemeLayers(paths, activeTheme);
142
+ const layers = [
143
+ ...(fs.existsSync(paths.assets) ? [paths.assets] : []),
144
+ ...themeLayerDirs,
145
+ PATHS.core,
146
+ ];
147
+
148
+ // ---- Fresh output + dev assets
149
+ fs.rmSync(paths.out, { recursive: true, force: true });
150
+
151
+ const build = (only) => buildAssets({
152
+ layers,
153
+ themeRoots: themeLayerDirs,
154
+ sectionRoots: [paths.src, ...themeLayerDirs],
155
+ themesDir: PATHS.themes,
156
+ coreDir: PATHS.core,
157
+ outDir: paths.out,
158
+ clientEntry,
159
+ dev: true,
160
+ only,
161
+ });
162
+
163
+ // Static assets (minted brand identity + src/assets) resolve up front —
164
+ // the manifest's favicon flag depends on what will ship
165
+ const staticDirs = resolveStaticDirs({
166
+ brandRoot: findBrandRoot(paths.root),
167
+ assetsDir: paths.assets,
168
+ });
169
+
170
+ const manifest = await build();
171
+ manifest.favicons = hasFaviconSet(staticDirs);
172
+ manifest.brandmarkSvg = brandmarkSvgUrl(staticDirs);
173
+ jetpack.write(paths.manifest, JSON.stringify(manifest, null, 2));
174
+ logger.log('Assets built (dev mode: stable names, no minify, sourcemaps)');
175
+
176
+ // ---- Service worker + build meta (/service-worker.js, /build.js,
177
+ // /build.json) — dev serves the REAL service worker so push/caching are
178
+ // testable; registration takeover + cache eviction keep one localhost
179
+ // port safe across different projects.
180
+ const buildSw = async () => {
181
+ writeBuildMeta({
182
+ siteData,
183
+ outDir: paths.out,
184
+ environment: 'development',
185
+ version,
186
+ consumerDir: paths.src,
187
+ clientEntry,
188
+ manifest,
189
+ });
190
+ await buildServiceWorker({
191
+ consumerDir: paths.src,
192
+ outDir: paths.out,
193
+ clientEntry,
194
+ dev: true,
195
+ });
196
+ };
197
+ await buildSw();
198
+
199
+ // Copied once at boot; they change rarely, so no watcher (restart to pick
200
+ // up new ones)
201
+ copyStaticAssets({
202
+ staticDirs,
203
+ outDir: paths.out,
204
+ });
205
+
206
+ // Runtime icon set (/assets/icons/) — the browser-side auto-renderer fetches
207
+ // these on demand (JS-set fa-* markup, e.g. the share buttons); emitted once
208
+ // at boot like the statics (the set never changes mid-dev).
209
+ emitIcons({
210
+ outDir: paths.out,
211
+ coreIconsDir: path.join(PATHS.core, 'icons'),
212
+ });
213
+ emitLanguageFlags({ outDir: paths.out });
214
+
215
+ // ---- Rebuild assets in place on source changes
216
+ const watchDirs = [
217
+ paths.assets,
218
+ ...themeLayerDirs,
219
+ path.join(PATHS.core, 'js'),
220
+ path.join(PATHS.core, 'css'),
221
+ // Consumer-local section/component assets (§7) live OUTSIDE the asset
222
+ // trees (src/_sections) — theme-layer sections are covered by the theme
223
+ // roots above.
224
+ path.join(paths.src, '_sections'),
225
+ path.join(paths.src, '_components'),
226
+ ].filter((dir) => fs.existsSync(dir));
227
+
228
+ // The rebuild folds back into the LIVE manifest (#765): the theme layers are
229
+ // watched here, so a theme's @font-face edit rebuilds the sheet — and the
230
+ // preload list it carries has to reach the served head, not wait for an
231
+ // unrelated template edit. The manifest file is the courier (see the
232
+ // watch target registered with Eleventy below).
233
+ watchAssetSources({
234
+ dirs: watchDirs,
235
+ clientDist: path.dirname(clientEntry),
236
+ build,
237
+ manifest,
238
+ manifestPath: paths.manifest,
239
+ });
240
+
241
+ // The .env chain is a dev INPUT too (#681): an edit to any layer reloads the
242
+ // cascade into process.env, so the next rebuild reads the new values instead
243
+ // of the ones this process booted with.
244
+ //
245
+ // Reach, exactly: a NEW key AND an EDITED value both land on that next
246
+ // rebuild, and a key dropped from the file is dropped from the process — the
247
+ // reload re-reads what a file layer owns (#724). A SHELL-set value still wins
248
+ // over every file, whatever the file now says.
249
+ watchEnvSources(paths.root);
250
+
251
+ // The consumer's service-worker entry lives OUTSIDE the asset trees
252
+ // (src/service-worker.js) — its own watcher; the browser picks the new
253
+ // worker up on the next reload's registration update check.
254
+ const consumerSwEntry = path.join(paths.src, 'service-worker.js');
255
+ if (fs.existsSync(consumerSwEntry)) {
256
+ let swTimer = null;
257
+ fs.watch(consumerSwEntry, () => {
258
+ clearTimeout(swTimer);
259
+ swTimer = setTimeout(() => {
260
+ buildSw()
261
+ .then(() => logger.log('Service worker rebuilt — reload to activate the new worker'))
262
+ .catch((error) => logger.error('Service worker rebuild failed:', error));
263
+ }, WATCH_DEBOUNCE_MS);
264
+ });
265
+ }
266
+
267
+ // ---- Eleventy watch + serve
268
+ const Eleventy = require('@11ty/eleventy').default;
269
+ let rescanWatchers = [];
270
+ const elev = new Eleventy(paths.src, paths.out, {
271
+ quietMode: true,
272
+ configPath: false,
273
+ config: (eleventyConfig) => {
274
+ eleventyConfig.setServerOptions(devServerOptions(paths.out, authPort, devPorts));
275
+ // The asset manifest is a template INPUT (the head reads its css/js URLs
276
+ // and its font preloads), and the asset watcher rewrites it when the
277
+ // preload list moves (#765). Watching the file is what re-renders the
278
+ // head then — no config reset, because the engine holds the manifest
279
+ // object by reference and the rebuild already updated it.
280
+ eleventyConfig.addWatchTarget(paths.manifest);
281
+ // Arms the watch registration for the config build below — the engine's
282
+ // captured reads are what fill it in (#200). The reset union goes to
283
+ // Eleventy, the rescan union to the light content watcher; a config
284
+ // reset re-runs this callback, so the previous rescan watchers close
285
+ // before the new union arms.
286
+ registerTemplateWatchTargets(eleventyConfig, {
287
+ onRescans: (rescans) => {
288
+ rescanWatchers.forEach((watcher) => watcher.close());
289
+ rescanWatchers = watchRescanTargets(rescans);
290
+ },
291
+ });
292
+ return configureOmega(eleventyConfig, {
293
+ consumerDir: paths.src,
294
+ siteData,
295
+ activeTheme,
296
+ assetManifest: manifest,
297
+ environment: 'development',
298
+ version,
299
+ dev: devPorts,
300
+ });
301
+ },
302
+ });
303
+
304
+ await elev.init();
305
+ await elev.watch();
306
+ elev.serve(httpsCerts ? internalPort : port);
307
+
308
+ // TLS terminator on the public port → eleventy on the internal one
309
+ if (httpsCerts) {
310
+ startLocalHttpsProxy({
311
+ port,
312
+ targetPort: internalPort,
313
+ certs: httpsCerts,
314
+ log: (line) => logger.log(line),
315
+ });
316
+ }
317
+
318
+ // Publish the resolved website port for sibling tools (same contract as the
319
+ // backend emulator's ports file) and retract it on shutdown. The PUBLIC
320
+ // port is the published one — the internal eleventy port is plumbing. The
321
+ // ORIGIN rides along, because a sibling reading `website: 4000` cannot know
322
+ // whether this run speaks TLS (#262).
323
+ writePortsFile(paths.root, { website: port }, { origin });
324
+ process.on('exit', () => clearPortsFile(paths.root));
325
+ // Every way this dev server is asked to stop exits deliberately, off the ONE
326
+ // devkit list ([#629](https://github.com/Omega-JS-Stack/omega/issues/629)):
327
+ // the `exit` hook above is what retracts the ports file, and a signal with no
328
+ // listener never runs it.
329
+ STOP_SIGNALS.forEach((signal) => process.on(signal, () => process.exit(0)));
330
+
331
+ if (bumped) {
332
+ logger.log(`Port ${CLASSIC_PORTS.website} was taken — bumped to ${port}`);
333
+ }
334
+ logger.log(`Dev server: ${httpsCerts ? 'https' : 'http'}://localhost:${port}`);
335
+ };
336
+
337
+ /**
338
+ * The asset lane's theme layer chain (#137). `resolveThemeLayers` probes
339
+ * `<consumerDir>/themes/<id>` for a consumer-local theme, and EVERY other
340
+ * caller — the engine, the production build, customize, the override map —
341
+ * passes the Eleventy input dir, so a consumer-local theme lives at
342
+ * `src/themes/<id>`. Resolving the asset lane from the target ROOT instead made
343
+ * that theme invisible to the scss/js build AND to the asset watcher (both
344
+ * derive from this list), so a brand's own theme silently rendered with the
345
+ * packaged theme's styles.
346
+ * @param {object} paths - consumerPaths() output
347
+ * @param {string} activeTheme - theme id
348
+ * @returns {string[]} ordered theme layer dirs
349
+ */
350
+ function resolveAssetThemeLayers(paths, activeTheme) {
351
+ return resolveThemeLayers({ activeTheme, consumerDir: paths.src, themesDir: PATHS.themes });
352
+ }
353
+
354
+ // The session's server-options objects, keyed by (outDir, authPort) — why they
355
+ // must be the IDENTICAL object on every config reset is in devServerOptions.
356
+ const SERVER_OPTIONS = new Map();
357
+
358
+ /**
359
+ * Dev-server options: the image-variant fallback middleware (dev never runs
360
+ * the responsive matrix — missing -NNNpx/.webp URLs rewrite to the verbatim
361
+ * original) + live-reload on ASSET rebuilds. Eleventy's dev server only
362
+ * reloads on its own template re-renders; our asset watcher writes bundles
363
+ * straight into the out dir, so the server chokidars those trees too — css
364
+ * changes hot-swap without a full reload, js changes reload the page. Kills
365
+ * the "refresh the browser" hand step.
366
+ *
367
+ * The auth-emulator proxy goes FIRST: it owns whole URL prefixes and answers
368
+ * them itself, so it must run before the clean-URL rewriter gets a chance to
369
+ * treat one as a page path.
370
+ *
371
+ * ONE object per (outDir, authPort), for the life of the process (#206). The
372
+ * config callback runs again on every config RESET, and Eleventy decides
373
+ * whether to restart the dev server by `assert.deepStrictEqual`-ing the
374
+ * config's serverOptions against the copy it saved at boot
375
+ * (EleventyServe.hasOptionsChanged) — where differing FUNCTION references can
376
+ * only ever read as "changed". Handing back a rebuilt object therefore
377
+ * restarted the server (close + relisten) on every single reset, and an edit
378
+ * burst raced a queued build's restart against a socket the previous one had
379
+ * not released yet: ERR_SERVER_ALREADY_LISTEN, process dead. Nothing here
380
+ * varies during a session — the middleware closes over outDir and the auth
381
+ * port RESOLVER, both fixed at boot — so the cache is the whole fix: Eleventy's
382
+ * DeepCopy of the object shares the middleware array and its function
383
+ * references, and the identical object compares equal across every reset.
384
+ * @param {string} outDir
385
+ * @param {number|function} [authPort] - the auth emulator port to proxy, or a
386
+ * GETTER resolving it per request (the live map, #300); a getter keys as
387
+ * `live`, since a session runs exactly one dev server and the getter's
388
+ * identity would otherwise change on every config reset
389
+ * @param {function} [devChrome] - the live dev-chrome getter (devPortsOption);
390
+ * given, every HTML response is rewritten to carry it (#346)
391
+ * @returns {object} setServerOptions() payload
392
+ */
393
+ function devServerOptions(outDir, authPort, devChrome) {
394
+ const key = `${outDir} ${typeof authPort === 'function' ? 'live' : authPort} ${devChrome ? 'inject' : 'plain'}`;
395
+
396
+ if (!SERVER_OPTIONS.has(key)) {
397
+ SERVER_OPTIONS.set(key, {
398
+ middleware: [
399
+ devAuthEmulator(authPort),
400
+ // After the proxy, which answers its own prefixes and returns: the
401
+ // emulator's pages are not this site's pages, and nothing rewrites them
402
+ ...(devChrome ? [devInjectDevPorts(devChrome)] : []),
403
+ devCleanUrls(outDir),
404
+ devImageFallback(outDir),
405
+ ],
406
+ watch: [
407
+ path.join(outDir, 'assets', 'css'),
408
+ path.join(outDir, 'assets', 'js'),
409
+ ],
410
+ });
411
+ }
412
+
413
+ return SERVER_OPTIONS.get(key);
414
+ }
415
+
416
+ /**
417
+ * Force a config RESET on edits under the template-source dirs (#49). Both
418
+ * layered layouts (registered as virtual templates, content read at config
419
+ * time) and the json-in-_includes data system (read into site.data._includes
420
+ * at config time) are CAPTURES — and Eleventy reuses one config across watch
421
+ * rebuilds unless the changed file triggers a reset, so without this the
422
+ * rebuild logs "Wrote N files" and re-renders the stale capture until the
423
+ * server is restarted.
424
+ *
425
+ * The targets are DERIVED, never listed (#200): `configureOmega` reads every
426
+ * config-time input through the captured-read helper (@omega.js/devkit/reads), which
427
+ * records the directory of each read — the union IS the set of dirs the
428
+ * capture depends on, so a capture added to the engine later registers itself.
429
+ * A hand list could only ever be the set someone remembered (#139).
430
+ *
431
+ * Ordering: Eleventy runs this before `configureOmega` in the same config
432
+ * callback, so it ARMS the registration instead of doing it — the recorded
433
+ * union only exists once the engine's capture scope closes, which happens on
434
+ * the way out of `configureOmega`, still inside this callback and long before
435
+ * Eleventy reads its watch targets.
436
+ *
437
+ * What lands in the union: each layer's machinery dirs (`_layouts`,
438
+ * `_includes`, `_sections`, `_components`, a theme's `fonts/`), the packaged
439
+ * `defaults` tree (#136), and the layer roots the theme chain PROBES — a
440
+ * consumer-local `src/themes/<id>` included, so an scss edit inside a brand's
441
+ * own theme rides BOTH lanes: the asset watcher's rebuild AND a config reset
442
+ * (the same accepted cost the `_sections` dirs already pay, #138).
443
+ *
444
+ * Packaged targets register REAL paths (the helper realpaths anything outside
445
+ * the consumer dir). A linked brand reaches the framework through a
446
+ * `node_modules/@omega.js/web` symlink, and Eleventy's watcher ignores
447
+ * everything under `node_modules` — the resolved path sidesteps it.
448
+ *
449
+ * BOTH path forms are registered for cwd-contained targets. The absolute form
450
+ * alone carries the reset today (the dev loop hands Eleventy absolute dirs, so
451
+ * the watcher's event arrives absolute and matches it). Registering the
452
+ * relative form ADDS a second, relative event for the same edit — each event
453
+ * decides the reset for itself and the last one wins the throttle, which is
454
+ * why the relative form must never be registered ALONE — and is kept as
455
+ * insurance so a reset still fires if Eleventy ever reports these edits in
456
+ * relative form. Its observable cost is a duplicate "File changed" line per
457
+ * save. A target OUTSIDE cwd (a linked brand's framework layers, a hoisted
458
+ * node_modules) registers ONLY absolute: an escaping `../` watch target makes
459
+ * Eleventy re-root its watcher to the common ancestor, after which NO event
460
+ * path matches ANY registered target and every reset dies — including the
461
+ * consumer ones (#134 verification).
462
+ *
463
+ * Dropping the relative form was TRIED and reverted (#344). It is not dead
464
+ * insurance: with only the absolute form registered, the packaged-layer reset
465
+ * starves — an interleaved A/B of dev-watch.test.js, one run per arm per
466
+ * round, went 0/8 red on both forms and 5/8 red on absolute-only. The extra
467
+ * registrations change how chokidar arranges its FSEvents streams (its
468
+ * consolidation threshold is a count of watched paths under one parent), and
469
+ * the arrangement the duplicates produce is the one that reliably delivers a
470
+ * freshly created packaged tmp dir's events. Measure before touching this.
471
+ *
472
+ * ONLY the reset union lands here. The same scope also records the RESCAN
473
+ * union (#200 Lane B) — the content scans, whose dirs must never carry a reset
474
+ * — and `options.onRescans` hands it to the lane that owns it
475
+ * (watchRescanTargets below).
476
+ * @param {object} eleventyConfig
477
+ * @param {object} [options]
478
+ * @param {function} [options.onRescans] - (rescanTargets) => void, the rescan lane
479
+ */
480
+ function registerTemplateWatchTargets(eleventyConfig, options) {
481
+ reads.onNextScope((targets, rescans) => {
482
+ for (const { dir } of targets) {
483
+ const relative = path.relative(process.cwd(), dir);
484
+ const forms = relative.startsWith('..') ? [dir] : new Set([dir, relative]);
485
+ for (const form of forms) {
486
+ eleventyConfig.addWatchTarget(form, { resetConfig: true });
487
+ }
488
+ }
489
+ if (options && options.onRescans) options.onRescans(rescans);
490
+ });
491
+ }
492
+
493
+ /**
494
+ * The ASSET lane's source watchers: one recursive fs.watch per asset source
495
+ * dir, all feeding ONE debounced rebuild.
496
+ *
497
+ * Narrowed rebuilds: a css-only change set rebuilds just the stylesheets — no
498
+ * js files are rewritten, so the dev server HOT-SWAPS the css without a page
499
+ * reload. js changes rebuild js (full reload — scripts need one), and an
500
+ * unknown/mixed set rebuilds everything.
501
+ *
502
+ * @omega.js/client's dist rides the same lane (#378). It reaches the bundle
503
+ * through the `@omega.js/client` alias, resolved once at boot — so without it
504
+ * here a client edit rebuilt the client's dist and stopped, and the site served
505
+ * its boot-time bytes until an unrelated asset edit or a stack restart.
506
+ * @param {object} options
507
+ * @param {string[]} options.dirs - the asset source dirs (existing ones only)
508
+ * @param {string} [options.clientDist] - the resolved @omega.js/client dist dir
509
+ * @param {function} options.build - (only) => Promise, the dev asset rebuild
510
+ * @param {object} [options.manifest] - the LIVE manifest the engine renders
511
+ * from; given with manifestPath, a rebuild that moved the font preload list
512
+ * folds into it and rewrites the file (#765)
513
+ * @param {string} [options.manifestPath] - where that manifest is written
514
+ * @returns {{ close: function }} the live watchers (the dev loop keeps them for
515
+ * the life of the process; tests close them)
516
+ */
517
+ function watchAssetSources(options) {
518
+ let timer = null;
519
+ let pendingKinds = new Set();
520
+ const kindOf = (file) => {
521
+ if (/\.(scss|css)$/.test(file || '')) return 'css';
522
+ if (/\.(js|mjs)$/.test(file || '')) return 'js';
523
+ return 'other';
524
+ };
525
+ const schedule = (file) => {
526
+ pendingKinds.add(kindOf(file));
527
+ clearTimeout(timer);
528
+ timer = setTimeout(() => {
529
+ const kinds = pendingKinds;
530
+ pendingKinds = new Set();
531
+ const only = kinds.size === 1 && !kinds.has('other') ? kinds.values().next().value : undefined;
532
+ options.build(only)
533
+ .then((next) => {
534
+ // #765: the head's font preloads are manifest CONTENT, not a stable
535
+ // dev URL, so a rebuild that moved them has to reach the browser.
536
+ // The list folds into the live manifest (the engine holds it by
537
+ // reference) and the manifest FILE is rewritten — Eleventy watches
538
+ // that file, so its re-render happens AFTER this build rather than
539
+ // racing it, and only when the head's list actually moved.
540
+ if (options.manifest && options.manifestPath && refreshLiveManifest(options.manifest, next)) {
541
+ jetpack.write(options.manifestPath, JSON.stringify(options.manifest, null, 2));
542
+ }
543
+ logger.log(`Assets rebuilt (${only || 'all'}) — browser live-reloads${only === 'css' ? ' via css hot-swap' : ''}`);
544
+ })
545
+ .catch((error) => logger.error('Asset rebuild failed:', error));
546
+ }, WATCH_DEBOUNCE_MS);
547
+ };
548
+
549
+ const watchers = options.dirs.map((dir) => fs.watch(dir, { recursive: true }, (event, file) => schedule(file)));
550
+
551
+ // The client dist is the one watched root that gets REPLACED rather than
552
+ // written into (its own `npm run prepare` deletes dist/ and writes it again),
553
+ // so it registers replace-safe. Absent at boot (no client installed) → not
554
+ // watched, the same existence rule the dirs above are filtered by.
555
+ if (options.clientDist && fs.existsSync(options.clientDist)) {
556
+ watchers.push(watchReplaceable(options.clientDist, schedule));
557
+ }
558
+
559
+ return {
560
+ close: () => {
561
+ clearTimeout(timer);
562
+ watchers.forEach((watcher) => watcher.close());
563
+ },
564
+ };
565
+ }
566
+
567
+ /**
568
+ * Fold a rebuild's manifest back into the LIVE one the engine renders from
569
+ * (#765). Dev hands Eleventy the boot manifest by reference, which is right
570
+ * for every asset URL — dev names are stable, so a rebuilt bundle keeps its
571
+ * URL. The font preload list is different: it is CONTENT (the first-paint
572
+ * faces the compiled sheet declares), so a theme's @font-face edit has to
573
+ * reach the next render instead of the boot capture.
574
+ *
575
+ * A js-only rebuild returns before the css lane and carries no list, so it
576
+ * leaves the live one alone; a css rebuild replaces it, an emptied list
577
+ * included. The answer is whether the list MOVED — the caller rewrites the
578
+ * manifest file on a change, and that file is what makes Eleventy re-render
579
+ * (see watchAssetSources), so an unchanged list must not trigger one.
580
+ * @param {object} manifest - the live manifest the engine holds
581
+ * @param {object} next - what the rebuild returned
582
+ * @returns {boolean} whether the preload list changed
583
+ */
584
+ function refreshLiveManifest(manifest, next) {
585
+ const preloads = next && next.fontPreloads;
586
+ if (!preloads || JSON.stringify(preloads) === JSON.stringify(manifest.fontPreloads)) return false;
587
+
588
+ manifest.fontPreloads = preloads;
589
+
590
+ return true;
591
+ }
592
+
593
+ /**
594
+ * The ENV lane's watcher (#681): every layer of the `.env` chain — company,
595
+ * brand, this target — and each layer's `.env.<environment>` overlay. A change
596
+ * reloads the cascade into process.env, and the log line names the FILE, never
597
+ * a value. Resolution and watching live in @omega.js/devkit/env-watch, shared
598
+ * with the desktop and extension dev lanes; this binds web's own target name.
599
+ * @param {string} root - the target root
600
+ * @param {object} [options]
601
+ * @param {string} [options.environment] - the environment whose overlay counts
602
+ * @returns {{ inputs: Array<{ layer: string, path: string }>, close: function }}
603
+ */
604
+ function watchEnvSources(root, options) {
605
+ return watchEnvChain({
606
+ projectDir: root,
607
+ target: 'web',
608
+ environment: options && options.environment,
609
+ log: (line) => logger.log(line),
610
+ });
611
+ }
612
+
613
+ /**
614
+ * A recursive fs.watch over a directory that may be REPLACED under it. A
615
+ * handle is bound to the directory it was opened on: once that directory is
616
+ * deleted, the handle is watching something the filesystem no longer resolves
617
+ * — on some platforms it errors or closes, on others it stays quietly useless.
618
+ * So: whenever the root is gone (an event that finds it missing, an `error`, a
619
+ * `close` nobody asked for), drop the handle, probe until the directory is back,
620
+ * watch the NEW one, and report the replacement as one change.
621
+ * @param {string} dir - the directory to watch
622
+ * @param {function} onChange - (file) => void, the same sink the plain watchers use
623
+ * @returns {{ close: function }}
624
+ */
625
+ function watchReplaceable(dir, onChange) {
626
+ let watcher = null;
627
+ let poll = null;
628
+ let closed = false;
629
+
630
+ const arm = () => {
631
+ watcher = fs.watch(dir, { recursive: true }, (event, file) => {
632
+ if (!fs.existsSync(dir)) return rearm();
633
+ return onChange(file);
634
+ });
635
+ watcher.on('error', rearm);
636
+ watcher.on('close', rearm);
637
+ };
638
+
639
+ // Arming the probe FIRST makes every re-entrant call (closing the handle
640
+ // emits its own 'close') a no-op instead of a second interval.
641
+ const rearm = () => {
642
+ if (closed || poll) return;
643
+
644
+ poll = setInterval(() => {
645
+ if (!fs.existsSync(dir)) return;
646
+ try {
647
+ arm();
648
+ } catch (error) {
649
+ return; // replaced again between the probe and the watch — keep probing
650
+ }
651
+ clearInterval(poll);
652
+ poll = null;
653
+ onChange(dir);
654
+ }, REARM_POLL_MS);
655
+
656
+ const dead = watcher;
657
+ watcher = null;
658
+ if (dead) dead.close();
659
+ };
660
+
661
+ arm();
662
+
663
+ return {
664
+ close: () => {
665
+ closed = true;
666
+ clearInterval(poll);
667
+ if (watcher) watcher.close();
668
+ },
669
+ };
670
+ }
671
+
672
+ /**
673
+ * The RESCAN lane (#200 Lane B): a light watcher per recorded rescan dir that
674
+ * re-runs just the capture whose input changed. No config reset ever — that is
675
+ * the entire reason these dirs are a separate union: they hold the brand's
676
+ * CONTENT (pages/, the collection dirs), and a reset there would drag every
677
+ * page edit off Eleventy's incremental lane.
678
+ *
679
+ * What a re-run buys: the live decision object is current the moment a file
680
+ * lands (the permalink-collision diagnostic re-emits right there, before any
681
+ * rebuild finishes). It is NOT what makes a render fresh — the engine
682
+ * re-scans on `eleventy.before`, so whichever watcher sees the file first, the
683
+ * render that follows reads current answers.
684
+ *
685
+ * Debounced like the asset lane: an editor's save is several events, and a
686
+ * scan per event is pure waste. A dir that does not exist yet is skipped —
687
+ * fs.watch cannot arm a missing path, and a collection dir appearing under
688
+ * Eleventy's input dir triggers a rebuild (and its re-scan) by itself.
689
+ *
690
+ * Closing DROPS the queued re-run: every config reset closes this union and
691
+ * opens the new one, and a debounce still in flight belongs to captures the
692
+ * previous build owned.
693
+ * @param {Array<{ dir: string, rerun: function }>} targets - the recorded rescan union
694
+ * @returns {Array<{ close: function }>} the live watchers (the caller closes them)
695
+ */
696
+ function watchRescanTargets(targets) {
697
+ return targets.filter((target) => fs.existsSync(target.dir)).map((target) => {
698
+ let timer = null;
699
+ const watcher = fs.watch(target.dir, { recursive: true }, () => {
700
+ clearTimeout(timer);
701
+ timer = setTimeout(() => {
702
+ try {
703
+ target.rerun();
704
+ } catch (error) {
705
+ logger.error('Rescan failed:', error);
706
+ }
707
+ }, RESCAN_DEBOUNCE_MS);
708
+ });
709
+
710
+ return {
711
+ close: () => {
712
+ clearTimeout(timer);
713
+ watcher.close();
714
+ },
715
+ };
716
+ });
717
+ }
718
+
719
+ /**
720
+ * Serve the Firebase auth emulator THROUGH the site origin (#156) — the dev
721
+ * counterpart of the self-hosted /__/auth/* helpers a production build ships
722
+ * (src/firebase-auth-helpers.js).
723
+ *
724
+ * The emulator's OAuth handler hands a redirect credential back by writing
725
+ * `firebase:redirectEvent:*` into sessionStorage on ITS OWN origin, and the
726
+ * SDK's helper iframe reads it back from there. Served on the emulator's port,
727
+ * that origin is a third party to the site, and browser storage partitioning
728
+ * gives the iframe a different, empty partition — the return leg dead-ends.
729
+ * Proxied here, handler and iframe are both first-party to the site, so they
730
+ * share one partition and signInWithRedirect completes in dev exactly as it
731
+ * does in production.
732
+ *
733
+ * The prefixes are the emulator's whole surface, mounted at the site ROOT
734
+ * because connectAuthEmulator() discards any path on the URL it is given
735
+ * (@firebase/auth: "Always replace path with /") — a sub-path mount is not
736
+ * available to us. `/emulator/*` covers the handler, the helper iframe and the
737
+ * out-of-band action links; the two googleapis.com prefixes are the REST
738
+ * surface, which the SDK addresses as `<emulator origin>/<apiHost><path>`.
739
+ * None of them can collide with a page URL.
740
+ *
741
+ * The target port is resolved PER REQUEST (#300). With the proxy on, this —
742
+ * not the baked `dev.ports` — is where every auth call actually goes, so a
743
+ * boot-time number kept sending sign-ins to whatever emulator held the
744
+ * classic 9099 (a neighbouring project's, in the report) long after this
745
+ * brand's suite came up bumped.
746
+ * @param {number|function} [authPort] - the port, or a getter for the live one
747
+ * @returns {function} connect-style middleware
748
+ */
749
+ function devAuthEmulator(authPort) {
750
+ const prefixes = ['/emulator', '/identitytoolkit.googleapis.com', '/securetoken.googleapis.com'];
751
+ const resolvePort = () => (typeof authPort === 'function' ? authPort() : authPort) || CLASSIC_PORTS.auth;
752
+
753
+ // Hop-by-hop framing headers belong to THIS connection, not the upstream's —
754
+ // copying them makes Node chunk a body it is already re-chunking.
755
+ const skipHeaders = new Set(['connection', 'keep-alive', 'transfer-encoding']);
756
+
757
+ // setHeader + statusCode, never writeHead. Eleventy's dev server wraps `res`
758
+ // to inject its live-reload script (eleventy-dev-server/server/wrapResponse):
759
+ // a writeHead carrying a text/html content-type is DEFERRED into a replay
760
+ // queue, but a piped Buffer write flushes the real headers first, and the
761
+ // replay then throws ERR_HTTP_HEADERS_SENT and takes the whole dev server
762
+ // down. Going through setHeader keeps that queue empty. It also keeps the
763
+ // wrapper's html transform off the emulator's pages — the live-reload script
764
+ // has no business inside the OAuth handler.
765
+ const answer = (res, status, headers) => {
766
+ res.statusCode = status;
767
+ for (const [name, value] of Object.entries(headers)) {
768
+ if (!skipHeaders.has(name.toLowerCase())) {
769
+ res.setHeader(name, value);
770
+ }
771
+ }
772
+ };
773
+
774
+ // The emulator deliberately binds 127.0.0.1 only, while the site listens on
775
+ // every interface — proxying for a LAN client would silently remove that
776
+ // safety property and hand the emulator's whole REST surface to the network.
777
+ const isLoopback = (address) => address === '::1'
778
+ || (address || '').startsWith('127.')
779
+ || (address || '').startsWith('::ffff:127.');
780
+
781
+ return (req, res, next) => {
782
+ const pathname = (req.url || '').split('?')[0];
783
+
784
+ if (!prefixes.some((prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`))) {
785
+ return next();
786
+ }
787
+ if (!isLoopback(req.socket?.remoteAddress)) {
788
+ return next();
789
+ }
790
+
791
+ const port = resolvePort();
792
+ const upstream = http.request({
793
+ host: '127.0.0.1',
794
+ port,
795
+ method: req.method,
796
+ path: req.url,
797
+ headers: { ...req.headers, host: `127.0.0.1:${port}` },
798
+ }, (upstreamRes) => {
799
+ answer(res, upstreamRes.statusCode, upstreamRes.headers);
800
+ upstreamRes.pipe(res);
801
+ });
802
+
803
+ // A website-only dev session (no emulator suite running) is an expected
804
+ // external condition, not our bug: answer the auth call with a 502 that
805
+ // names the port instead of hanging the request.
806
+ upstream.on('error', (error) => {
807
+ logger.error(`Auth emulator proxy: ${pathname} → :${port} failed (${error.message})`);
808
+ answer(res, 502, { 'content-type': 'text/plain; charset=utf-8' });
809
+ res.end(Buffer.from(`Auth emulator on port ${port} is not reachable`));
810
+ });
811
+
812
+ return req.pipe(upstream);
813
+ };
814
+ }
815
+
816
+ /**
817
+ * The `dev:` value of the Configuration chrome, as `core/_includes/core/foot.html`
818
+ * renders it (`dev: {{ jekyll.dev | jsonify }},`) — one compact JSON line, or
819
+ * `null` on a build that bakes no dev chrome. The lookahead is what makes the
820
+ * non-greedy body stop at the object's OWN close brace rather than the nested
821
+ * ports one. The coupling to that template is pinned by the served-page test,
822
+ * which rewrites a REAL rendered page.
823
+ */
824
+ const DEV_CHROME = /(\n\s*dev: )(?:\{.*?\}|null)(?=,\n)/s;
825
+
826
+ /**
827
+ * Serve-time dev-ports injection (#346): every HTML response leaves this server
828
+ * carrying the map of the stack running RIGHT NOW, whatever its page baked.
829
+ *
830
+ * The render-time bake is a snapshot of the moment a page was built, and the
831
+ * normal boot order builds every page before the backend publishes anything:
832
+ * the website build finishes in under a second while the emulator suite seeds
833
+ * for minutes, so the whole initial fleet bakes `{ website }` alone and nothing
834
+ * re-renders it — no source file changed. Same hole for a mid-session emulator
835
+ * restart onto bumped numbers. Rewriting the chrome as the page goes out covers
836
+ * both by construction; the bake stays as it is on disk, advisory, and the
837
+ * built output is byte-for-byte what the build wrote.
838
+ *
839
+ * The rewrite wraps `res.end` rather than the response object: eleventy wrapped
840
+ * `res` before the middleware chain ran (its live-reload injection), so ours is
841
+ * the OUTER end — it rewrites the string the static handler hands over, and
842
+ * eleventy's transform then runs on the rewritten html and sizes the body from
843
+ * it. HTML only, and only a response whose body arrives as a string, which is
844
+ * how eleventy serves a page. A response with no chrome (a redirect stub, an
845
+ * error page) matches nothing and passes through untouched.
846
+ * @param {function} devChrome - the live dev-chrome getter (devPortsOption)
847
+ * @returns {function} connect-style middleware
848
+ */
849
+ function devInjectDevPorts(devChrome) {
850
+ return (req, res, next) => {
851
+ const end = res.end;
852
+
853
+ res.end = (data, ...rest) => {
854
+ const contentType = String(res.getHeader('content-type') || '');
855
+
856
+ if (typeof data === 'string' && contentType.startsWith('text/html')) {
857
+ return end.call(res, data.replace(DEV_CHROME, (match, open) => `${open}${JSON.stringify(devChrome())}`), ...rest);
858
+ }
859
+
860
+ return end.call(res, data, ...rest);
861
+ };
862
+
863
+ return next();
864
+ };
865
+ }
866
+
867
+ /**
868
+ * Clean-URL resolution, the legacy serve.js contract: pages are flat `.html`
869
+ * files with slash-free URLs, so `/signin` (and a stray `/signin/`) serves
870
+ * `signin.html`. Mirrors production GitHub Pages, which resolves extensionless
871
+ * paths against `.html` files natively.
872
+ * @param {string} outDir
873
+ * @returns {function} connect-style middleware
874
+ */
875
+ function devCleanUrls(outDir) {
876
+ const root = path.resolve(outDir);
877
+
878
+ return (req, res, next) => {
879
+ const [pathname, query] = (req.url || '').split('?');
880
+
881
+ // A malformed percent-escape throws URIError — not a clean-URL
882
+ // candidate, fall through to the static handler.
883
+ let decoded;
884
+ try {
885
+ decoded = decodeURIComponent(pathname);
886
+ } catch (e) {
887
+ return next();
888
+ }
889
+
890
+ const clean = decoded.replace(/\/+$/, '');
891
+
892
+ if (!clean) {
893
+ return next();
894
+ }
895
+
896
+ // Legacy serve.js contract: rewrite only when the request doesn't hit a
897
+ // real file but `<path>.html` exists. No extension sniffing — dotted
898
+ // slugs (/updates/v1.0.0) are page URLs too.
899
+ const original = path.resolve(root, `.${decoded}`);
900
+ const resolved = path.resolve(root, `.${clean}.html`);
901
+ if (
902
+ resolved.startsWith(root + path.sep)
903
+ && jetpack.exists(original) !== 'file'
904
+ && jetpack.exists(resolved) === 'file'
905
+ ) {
906
+ req.url = `${clean}.html${query ? `?${query}` : ''}`;
907
+ }
908
+
909
+ return next();
910
+ };
911
+ }
912
+
913
+ /**
914
+ * The dev website ORIGIN this run answers on — the ONE place protocol and port
915
+ * are put together (#262). Every consumer of "where the dev website is" derives
916
+ * from this: site.url, the published ports file, and the page chrome.
917
+ * @param {number} port - the resolved dev-server (public) port
918
+ * @param {boolean} [https] - whether the public port speaks TLS (mkcert proxy)
919
+ * @returns {string} the origin, protocol included
920
+ */
921
+ function devWebsiteOrigin(port, https) {
922
+ return `${https ? 'https' : 'http'}://localhost:${port}`;
923
+ }
924
+
925
+ /**
926
+ * Dev builds link to THIS server, never the live site (legacy _config_dev.yml
927
+ * url-override parity): site.url is the one root every absolute-URL surface
928
+ * derives from — canonicals/og tags, omega_external, absolute_url, redirect
929
+ * pages, nav — so pointing it at the local origin keeps every click in dev.
930
+ * @param {object} siteData - the loaded site global (mutated)
931
+ * @param {string} origin - the resolved dev website origin (devWebsiteOrigin)
932
+ */
933
+ function applyDevSiteUrl(siteData, origin) {
934
+ siteData.url = origin;
935
+ }
936
+
937
+ /**
938
+ * Resolve the website port through the allocator (N7). An explicit `--port`
939
+ * flag or a config `ports.website` entry PINS the port (busy = hard error);
940
+ * otherwise start from OMEGA_WEBSITE_PORT (a parent that already allocated)
941
+ * or the classic 4000 and bump +1 while taken.
942
+ */
943
+ async function resolveWebsitePort(root, flagPort) {
944
+ const pins = {};
945
+
946
+ if (flagPort) {
947
+ if (!(await isPortFree(flagPort))) {
948
+ throw new Error(`Port ${flagPort} (pinned via --port) is already in use — free it or pick another`);
949
+ }
950
+ pins.website = flagPort;
951
+ } else {
952
+ const configPin = loadPortPins(root).website;
953
+ if (typeof configPin === 'number') {
954
+ pins.website = configPin;
955
+ }
956
+ }
957
+
958
+ const wanted = { website: websiteWantedPort(root) };
959
+ const { ports, bumped } = await resolvePorts({ wanted, pins });
960
+ return { port: ports.website, bumped: bumped.length > 0 };
961
+ }
962
+
963
+ /**
964
+ * The wanted (pre-allocator) website port: OMEGA_WEBSITE_PORT (a parent that
965
+ * already allocated) or the classic 4000, plus this target's deterministic
966
+ * instance offset (multi-instance targets: an instance wants base + its
967
+ * position in the instances array, so N instances dev side-by-side off the
968
+ * same base). Lenient like loadPortPins — no config means no offset.
969
+ */
970
+ function websiteWantedPort(root) {
971
+ const base = envPort('website') || CLASSIC_PORTS.website;
972
+
973
+ try {
974
+ if (!hasOmegaConfig(root)) {
975
+ return base;
976
+ }
977
+ const { config, instance } = loadConfig(root, 'web');
978
+ return base + instancePortOffset(config.targets?.web, instance);
979
+ } catch (error) {
980
+ return base;
981
+ }
982
+ }
983
+
984
+ /**
985
+ * Read explicit port pins from the consumer's config `ports` section.
986
+ * Lenient — a missing/broken config means no pins, never a dev-loop failure.
987
+ */
988
+ function loadPortPins(root) {
989
+ try {
990
+ if (!hasOmegaConfig(root)) {
991
+ return {};
992
+ }
993
+ const config = loadConfig(root, 'web').config;
994
+ return config.ports && typeof config.ports === 'object' ? config.ports : {};
995
+ } catch (error) {
996
+ return {};
997
+ }
998
+ }
999
+
1000
+ /**
1001
+ * The `dev` chrome the engine bakes into every page — as a GETTER, called per
1002
+ * render (#300). The sibling backend's published map (its live emulator
1003
+ * ports) merges OVER this server's own website port, so the browser always
1004
+ * connects to the stack that is actually running: a backend that booted after
1005
+ * this server, or an emulator that restarted onto bumped numbers, lands in
1006
+ * the very next render instead of never.
1007
+ *
1008
+ * The website ORIGIN rides the same map (#262): a page knows its own origin,
1009
+ * but a desktop/extension surface reading this chrome does not, and protocol is
1010
+ * not derivable from a port number.
1011
+ * @param {string} root - this target's root (its own ports file is skipped)
1012
+ * @param {number} port - the resolved website port
1013
+ * @param {string} origin - the resolved website origin (devWebsiteOrigin)
1014
+ * @returns {function} () => the dev chrome object
1015
+ */
1016
+ function devPortsOption(root, port, origin) {
1017
+ return () => ({
1018
+ ports: { ...readSiblingPorts(root), website: port },
1019
+ origin,
1020
+ authEmulatorProxy: true,
1021
+ });
1022
+ }
1023
+
1024
+ /**
1025
+ * `--local` prelude: file:-install every @omega.js framework used anywhere in
1026
+ * this brand (all targets, walked up from cwd) from the local Omega monorepo,
1027
+ * then start the monorepo's src→dist watch as a session-scoped child.
1028
+ */
1029
+ // Exposed for tests (the command function stays the main export)
1030
+ module.exports.resolveWebsitePort = resolveWebsitePort;
1031
+ module.exports.websiteWantedPort = websiteWantedPort;
1032
+ module.exports.devPortsOption = devPortsOption;
1033
+ module.exports.devServerOptions = devServerOptions;
1034
+ module.exports.resolveAssetThemeLayers = resolveAssetThemeLayers;
1035
+ module.exports.registerTemplateWatchTargets = registerTemplateWatchTargets;
1036
+ module.exports.watchAssetSources = watchAssetSources;
1037
+ module.exports.watchEnvSources = watchEnvSources;
1038
+ module.exports.refreshLiveManifest = refreshLiveManifest;
1039
+ module.exports.watchRescanTargets = watchRescanTargets;
1040
+ module.exports.applyDevSiteUrl = applyDevSiteUrl;
1041
+ module.exports.devWebsiteOrigin = devWebsiteOrigin;
1042
+
1043
+ async function linkBrandToMonorepo() {
1044
+ const local = require('../vendor/devkit/local.js');
1045
+ const monorepoRoot = local.resolveMonorepoRoot();
1046
+ const brandRoot = local.findBrandRoot(process.cwd());
1047
+ logger.log(`Local mode: linking @omega.js packages from ${monorepoRoot}`);
1048
+
1049
+ for (const targetDir of local.discoverTargets(brandRoot)) {
1050
+ await local.linkLocalPackages({ dir: targetDir, monorepoRoot, logger });
1051
+ }
1052
+
1053
+ // Session-scoped by the helper itself — the watch dies with this dev server
1054
+ // (no orphans), the same way the brand-root `omega dev` gets it (#587). All
1055
+ // that is left here is the dev server's own Ctrl-C policy: a SIGINT listener
1056
+ // suppresses node's default kill, so it has to exit deliberately.
1057
+ const watch = local.startMonorepoWatch({ monorepoRoot, logger });
1058
+ if (watch.child) {
1059
+ STOP_SIGNALS.forEach((signal) => process.on(signal, () => process.exit(0)));
1060
+ }
1061
+
1062
+ // The same gate the brand-root boot uses (#670): nothing reads a dist while a
1063
+ // prepare is still rewriting it — a fresh watch's initial pass, and an
1064
+ // already-running watch's, read from its log (#622). Awaited on BOTH
1065
+ // branches, which is why this prelude never had the skip #622 fixed.
1066
+ await watch.ready;
1067
+ }