@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.
- package/LICENSE +98 -0
- package/README.md +640 -0
- package/bin/omega +2 -0
- package/bin/omega-web +2 -0
- package/bin/omg +2 -0
- package/core/_includes/admin/sections/sidebar.json +100 -0
- package/core/_includes/admin/sections/topbar.json +11 -0
- package/core/_includes/backend/sections/sidebar.json +39 -0
- package/core/_includes/backend/sections/topbar.json +16 -0
- package/core/_includes/core/body.html +102 -0
- package/core/_includes/core/foot.html +536 -0
- package/core/_includes/core/head.html +423 -0
- package/core/_includes/core/pricing/price-per-unit.html +33 -0
- package/core/_includes/core/showcase/entry-body.html +94 -0
- package/core/_includes/core/showcase/index-body.html +43 -0
- package/core/_includes/core/showcase/nav.html +60 -0
- package/core/_includes/frontend/sections/footer.json +74 -0
- package/core/_includes/frontend/sections/nav.json +70 -0
- package/core/_includes/global/sections/account.json +31 -0
- package/core/_includes/modules/engagement/giscus.html +26 -0
- package/core/_layouts/blueprint/404.html +10 -0
- package/core/_layouts/blueprint/about.html +10 -0
- package/core/_layouts/blueprint/account/index.html +11 -0
- package/core/_layouts/blueprint/admin/calendar/index.html +590 -0
- package/core/_layouts/blueprint/admin/dashboard/index.html +301 -0
- package/core/_layouts/blueprint/admin/firebase/index.html +214 -0
- package/core/_layouts/blueprint/admin/posts/editor.html +157 -0
- package/core/_layouts/blueprint/admin/posts/index.html +126 -0
- package/core/_layouts/blueprint/admin/stackblitz/index.html +30 -0
- package/core/_layouts/blueprint/admin/studio/index.html +85 -0
- package/core/_layouts/blueprint/admin/users/index.html +272 -0
- package/core/_layouts/blueprint/admin/users/new.html +82 -0
- package/core/_layouts/blueprint/admin/verts/index.html +204 -0
- package/core/_layouts/blueprint/alternatives/alternative.html +15 -0
- package/core/_layouts/blueprint/alternatives/index.html +10 -0
- package/core/_layouts/blueprint/app.html +10 -0
- package/core/_layouts/blueprint/auth/reset.html +19 -0
- package/core/_layouts/blueprint/auth/signin.html +19 -0
- package/core/_layouts/blueprint/auth/signup.html +19 -0
- package/core/_layouts/blueprint/auth/token.html +19 -0
- package/core/_layouts/blueprint/blog/categories/category.html +8 -0
- package/core/_layouts/blueprint/blog/categories/index.html +11 -0
- package/core/_layouts/blueprint/blog/index.html +10 -0
- package/core/_layouts/blueprint/blog/post.html +5 -0
- package/core/_layouts/blueprint/blog/tags/index.html +11 -0
- package/core/_layouts/blueprint/blog/tags/tag.html +8 -0
- package/core/_layouts/blueprint/careers.md +13 -0
- package/core/_layouts/blueprint/collection/category.html +9 -0
- package/core/_layouts/blueprint/collection/document.html +9 -0
- package/core/_layouts/blueprint/collection/index.html +9 -0
- package/core/_layouts/blueprint/connections/callback.html +11 -0
- package/core/_layouts/blueprint/contact.html +14 -0
- package/core/_layouts/blueprint/dashboard/index.html +10 -0
- package/core/_layouts/blueprint/download.html +20 -0
- package/core/_layouts/blueprint/extension/index.html +14 -0
- package/core/_layouts/blueprint/extension/installed.html +11 -0
- package/core/_layouts/blueprint/feedback.html +10 -0
- package/core/_layouts/blueprint/index.html +16 -0
- package/core/_layouts/blueprint/legal/cookies.md +57 -0
- package/core/_layouts/blueprint/legal/privacy.md +109 -0
- package/core/_layouts/blueprint/legal/terms.md +155 -0
- package/core/_layouts/blueprint/payment/checkout.html +15 -0
- package/core/_layouts/blueprint/payment/confirmation.html +14 -0
- package/core/_layouts/blueprint/portal/email-preferences.html +15 -0
- package/core/_layouts/blueprint/pricing.html +20 -0
- package/core/_layouts/blueprint/status.html +10 -0
- package/core/_layouts/blueprint/team/index.html +10 -0
- package/core/_layouts/blueprint/team/member.html +5 -0
- package/core/_layouts/blueprint/updates/index.html +10 -0
- package/core/_layouts/blueprint/updates/update.html +10 -0
- package/core/_layouts/core/root.html +45 -0
- package/core/_layouts/modules/utilities/redirect.html +129 -0
- package/core/css/_studio.scss +237 -0
- package/core/css/components/_index.scss +146 -0
- package/core/css/core/_.scss +0 -0
- package/core/css/core/_alert.scss +87 -0
- package/core/css/core/_animations.scss +343 -0
- package/core/css/core/_bindings.scss +116 -0
- package/core/css/core/_blog-search.scss +57 -0
- package/core/css/core/_chatsy.scss +61 -0
- package/core/css/core/_consent.scss +424 -0
- package/core/css/core/_custom-font-awesome.scss +146 -0
- package/core/css/core/_exit-popup.scss +42 -0
- package/core/css/core/_generated-badge.scss +33 -0
- package/core/css/core/_initialize.scss +29 -0
- package/core/css/core/_lazy-loading.scss +104 -0
- package/core/css/core/_social-sharing.scss +41 -0
- package/core/css/core/_tones.scss +32 -0
- package/core/css/core/_utilities.scss +157 -0
- package/core/css/main.scss +54 -0
- package/core/css/motion/_index.scss +368 -0
- package/core/css/pages/404/index.scss +0 -0
- package/core/css/pages/admin/calendar/index.scss +692 -0
- package/core/css/pages/admin/firebase/index.scss +33 -0
- package/core/css/pages/admin/index.scss +9 -0
- package/core/css/pages/admin/users/index.scss +9 -0
- package/core/css/pages/admin/verts/index.scss +9 -0
- package/core/css/pages/alternatives/[alternative]/index.scss +0 -0
- package/core/css/pages/blog/[slug].scss +55 -0
- package/core/css/pages/dashboard/account/index.scss +242 -0
- package/core/css/pages/download/index.scss +480 -0
- package/core/css/pages/extension/installed/index.scss +317 -0
- package/core/css/pages/feedback/index.scss +31 -0
- package/core/css/pages/payment/confirmation/index.scss +14 -0
- package/core/css/pages/pricing/index.scss +0 -0
- package/core/css/pages/status/index.scss +162 -0
- package/core/css/pages/test/libraries/layers/index.scss +28 -0
- package/core/css/pages/updates/[update].scss +46 -0
- package/core/css/pages/updates/index.scss +13 -0
- package/core/css/shell/_index.scss +207 -0
- package/core/css/tokens/_index.scss +166 -0
- package/core/icons/flags/ar.svg +1 -0
- package/core/icons/flags/bd.svg +1 -0
- package/core/icons/flags/ca.svg +1 -0
- package/core/icons/flags/ch.svg +1 -0
- package/core/icons/flags/cn.svg +1 -0
- package/core/icons/flags/co.svg +1 -0
- package/core/icons/flags/cw.svg +1 -0
- package/core/icons/flags/cz.svg +1 -0
- package/core/icons/flags/de.svg +1 -0
- package/core/icons/flags/dk.svg +1 -0
- package/core/icons/flags/eg.svg +1 -0
- package/core/icons/flags/es.svg +1 -0
- package/core/icons/flags/fi.svg +1 -0
- package/core/icons/flags/fr.svg +1 -0
- package/core/icons/flags/gb.svg +1 -0
- package/core/icons/flags/gq.svg +1 -0
- package/core/icons/flags/gr.svg +1 -0
- package/core/icons/flags/gt.svg +1 -0
- package/core/icons/flags/hn.svg +1 -0
- package/core/icons/flags/id.svg +1 -0
- package/core/icons/flags/ie.svg +1 -0
- package/core/icons/flags/in.svg +1 -0
- package/core/icons/flags/ir.svg +1 -0
- package/core/icons/flags/it.svg +1 -0
- package/core/icons/flags/jp.svg +1 -0
- package/core/icons/flags/kp.svg +1 -0
- package/core/icons/flags/kr.svg +1 -0
- package/core/icons/flags/ly.svg +1 -0
- package/core/icons/flags/ma.svg +1 -0
- package/core/icons/flags/mu.svg +1 -0
- package/core/icons/flags/mx.svg +1 -0
- package/core/icons/flags/ng.svg +1 -0
- package/core/icons/flags/pa.svg +1 -0
- package/core/icons/flags/ph.svg +1 -0
- package/core/icons/flags/pk.svg +1 -0
- package/core/icons/flags/pt.svg +1 -0
- package/core/icons/flags/ru.svg +1 -0
- package/core/icons/flags/sa.svg +1 -0
- package/core/icons/flags/sd.svg +1 -0
- package/core/icons/flags/se.svg +1 -0
- package/core/icons/flags/th.svg +1 -0
- package/core/icons/flags/tm.svg +1 -0
- package/core/icons/flags/tr.svg +1 -0
- package/core/icons/flags/us.svg +1 -0
- package/core/icons/flags/uy.svg +1 -0
- package/core/icons/flags/vn.svg +1 -0
- package/core/icons/flags/za.svg +1 -0
- package/core/images/exit-popup/subscriber-1.jpg +0 -0
- package/core/images/exit-popup/subscriber-2.jpg +0 -0
- package/core/images/exit-popup/subscriber-3.jpg +0 -0
- package/core/images/exit-popup/subscriber-4.jpg +0 -0
- package/core/images/placeholder/photo-1.jpg +0 -0
- package/core/images/placeholder/photo-2.jpg +0 -0
- package/core/images/placeholder/photo-3.jpg +0 -0
- package/core/js/core/analytics-loader.js +253 -0
- package/core/js/core/app-shell.js +136 -0
- package/core/js/core/appearance.js +195 -0
- package/core/js/core/auth.js +457 -0
- package/core/js/core/complete.js +72 -0
- package/core/js/core/consent.js +384 -0
- package/core/js/core/dev-icon-audit.js +63 -0
- package/core/js/core/dev-palette.js +670 -0
- package/core/js/core/dev-sections.js +53 -0
- package/core/js/core/exit-popup.js +276 -0
- package/core/js/core/initialize.js +8 -0
- package/core/js/core/language-switcher.js +167 -0
- package/core/js/core/lazy-loading.js +479 -0
- package/core/js/core/motion.js +28 -0
- package/core/js/core/query-strings.js +146 -0
- package/core/js/core/service-worker.js +28 -0
- package/core/js/core/social-sharing.js +293 -0
- package/core/js/first-paint.js +35 -0
- package/core/js/layouts/modules/utilities/redirect.js +122 -0
- package/core/js/libs/admin-helpers.js +62 -0
- package/core/js/libs/alert-dismiss.js +35 -0
- package/core/js/libs/analytics.js +368 -0
- package/core/js/libs/auth/email.js +144 -0
- package/core/js/libs/auth/errors.js +119 -0
- package/core/js/libs/auth/forms.js +206 -0
- package/core/js/libs/auth/index.js +181 -0
- package/core/js/libs/auth/oauth.js +394 -0
- package/core/js/libs/auth/orphan.js +110 -0
- package/core/js/libs/auth/password-toggle.js +44 -0
- package/core/js/libs/auth/session-params.js +266 -0
- package/core/js/libs/auth/tracking.js +41 -0
- package/core/js/libs/charts.js +516 -0
- package/core/js/libs/consent-region.js +127 -0
- package/core/js/libs/dev.js +150 -0
- package/core/js/libs/graph.js +201 -0
- package/core/js/libs/initialize-tooltips.js +31 -0
- package/core/js/libs/logger.js +38 -0
- package/core/js/libs/omega-copy.js +89 -0
- package/core/js/libs/path-prefix.js +44 -0
- package/core/js/libs/payment-config.js +76 -0
- package/core/js/libs/recaptcha.js +94 -0
- package/core/js/libs/sale-name.js +295 -0
- package/core/js/libs/showcase-frames.js +37 -0
- package/core/js/libs/srcset.js +69 -0
- package/core/js/libs/tracking-consent.js +161 -0
- package/core/js/main.js +144 -0
- package/core/js/pages/404/index.js +57 -0
- package/core/js/pages/admin/calendar/calendar-core.js +701 -0
- package/core/js/pages/admin/calendar/calendar-events.js +853 -0
- package/core/js/pages/admin/calendar/calendar-renderer.js +807 -0
- package/core/js/pages/admin/calendar/campaign-preview.js +105 -0
- package/core/js/pages/admin/calendar/index.js +40 -0
- package/core/js/pages/admin/firebase/index.js +727 -0
- package/core/js/pages/admin/index.js +531 -0
- package/core/js/pages/admin/posts/editor/index.js +230 -0
- package/core/js/pages/admin/posts/index.js +237 -0
- package/core/js/pages/admin/studio/index.js +538 -0
- package/core/js/pages/admin/users/index.js +669 -0
- package/core/js/pages/admin/users/new/index.js +65 -0
- package/core/js/pages/admin/verts/index.js +407 -0
- package/core/js/pages/alternatives/[alternative]/index.js +17 -0
- package/core/js/pages/app/index.js +135 -0
- package/core/js/pages/blog/[slug].js +132 -0
- package/core/js/pages/blog/_search.mjs +108 -0
- package/core/js/pages/blog/index.js +193 -0
- package/core/js/pages/blog/page/[num]/index.js +7 -0
- package/core/js/pages/connections/callback/index.js +148 -0
- package/core/js/pages/contact/index.js +170 -0
- package/core/js/pages/cookies.js +2 -0
- package/core/js/pages/dashboard/account/index.js +366 -0
- package/core/js/pages/dashboard/account/modules/orders.js +82 -0
- package/core/js/pages/dashboard/account/sections/api-keys.js +149 -0
- package/core/js/pages/dashboard/account/sections/billing.js +1667 -0
- package/core/js/pages/dashboard/account/sections/connections.js +333 -0
- package/core/js/pages/dashboard/account/sections/data-request.js +225 -0
- package/core/js/pages/dashboard/account/sections/delete.js +80 -0
- package/core/js/pages/dashboard/account/sections/notifications.js +167 -0
- package/core/js/pages/dashboard/account/sections/orders.js +151 -0
- package/core/js/pages/dashboard/account/sections/profile.js +200 -0
- package/core/js/pages/dashboard/account/sections/referrals.js +217 -0
- package/core/js/pages/dashboard/account/sections/refund.js +253 -0
- package/core/js/pages/dashboard/account/sections/security.js +726 -0
- package/core/js/pages/dashboard/account/sections/team.js +247 -0
- package/core/js/pages/download/index.js +418 -0
- package/core/js/pages/extension/index.js +164 -0
- package/core/js/pages/extension/installed/index.js +135 -0
- package/core/js/pages/feedback/index.js +193 -0
- package/core/js/pages/legal/_document.js +91 -0
- package/core/js/pages/payment/checkout/index.js +420 -0
- package/core/js/pages/payment/checkout/modules/api.js +139 -0
- package/core/js/pages/payment/checkout/modules/dev-section.js +175 -0
- package/core/js/pages/payment/checkout/modules/discount.js +69 -0
- package/core/js/pages/payment/checkout/modules/pricing.js +73 -0
- package/core/js/pages/payment/checkout/modules/state.js +339 -0
- package/core/js/pages/payment/checkout/modules/tracking.js +54 -0
- package/core/js/pages/payment/confirmation/index.js +91 -0
- package/core/js/pages/payment/confirmation/modules/celebration.js +45 -0
- package/core/js/pages/payment/confirmation/modules/state.js +112 -0
- package/core/js/pages/payment/confirmation/modules/tracking.js +133 -0
- package/core/js/pages/payment/confirmation/modules/verify.js +142 -0
- package/core/js/pages/portal/email-preferences/index.js +183 -0
- package/core/js/pages/pricing/index.js +425 -0
- package/core/js/pages/privacy.js +2 -0
- package/core/js/pages/reset/index.js +12 -0
- package/core/js/pages/signin/index.js +22 -0
- package/core/js/pages/signup/index.js +23 -0
- package/core/js/pages/status/index.js +687 -0
- package/core/js/pages/terms.js +2 -0
- package/core/js/pages/test/components/[category]/[name]/index.js +26 -0
- package/core/js/pages/test/libraries/appearance/index.js +220 -0
- package/core/js/pages/test/libraries/form-manager/index.js +328 -0
- package/core/js/pages/test/libraries/layers/index.js +16 -0
- package/core/js/pages/test/libraries/verts/index.js +68 -0
- package/core/js/pages/test/sections/[category]/[name]/index.js +28 -0
- package/core/js/pages/test/styleguide/index.js +35 -0
- package/core/js/pages/token/index.js +203 -0
- package/core/logos/brandmarks/original/apple-app-store.svg +1 -0
- package/core/logos/brandmarks/original/apple.svg +6 -0
- package/core/logos/brandmarks/original/bitbucket.svg +14 -0
- package/core/logos/brandmarks/original/bitcoin.svg +1 -0
- package/core/logos/brandmarks/original/bluesky.svg +7 -0
- package/core/logos/brandmarks/original/bootstrap.svg +43 -0
- package/core/logos/brandmarks/original/brave.svg +1 -0
- package/core/logos/brandmarks/original/chrome.svg +1 -0
- package/core/logos/brandmarks/original/discord.svg +1 -0
- package/core/logos/brandmarks/original/dropbox.svg +10 -0
- package/core/logos/brandmarks/original/edge.svg +1 -0
- package/core/logos/brandmarks/original/facebook-f.svg +1 -0
- package/core/logos/brandmarks/original/facebook.svg +8 -0
- package/core/logos/brandmarks/original/figma.svg +10 -0
- package/core/logos/brandmarks/original/firefox.svg +1 -0
- package/core/logos/brandmarks/original/github.svg +6 -0
- package/core/logos/brandmarks/original/gitlab.svg +17 -0
- package/core/logos/brandmarks/original/google-a-s.svg +1 -0
- package/core/logos/brandmarks/original/google-chrome-webstore.svg +49 -0
- package/core/logos/brandmarks/original/google-play-store.svg +1 -0
- package/core/logos/brandmarks/original/google-web-search.svg +1 -0
- package/core/logos/brandmarks/original/google.svg +1 -0
- package/core/logos/brandmarks/original/gulp.svg +4 -0
- package/core/logos/brandmarks/original/html-5.svg +1 -0
- package/core/logos/brandmarks/original/instagram.svg +1 -0
- package/core/logos/brandmarks/original/javascript.svg +1 -0
- package/core/logos/brandmarks/original/jira.svg +18 -0
- package/core/logos/brandmarks/original/kick.svg +7 -0
- package/core/logos/brandmarks/original/linkedin.svg +1 -0
- package/core/logos/brandmarks/original/linux.svg +28 -0
- package/core/logos/brandmarks/original/messenger.svg +16 -0
- package/core/logos/brandmarks/original/microsoft.svg +1 -0
- package/core/logos/brandmarks/original/npm.svg +8 -0
- package/core/logos/brandmarks/original/opera.svg +1 -0
- package/core/logos/brandmarks/original/patreon.svg +6 -0
- package/core/logos/brandmarks/original/pinterest.svg +6 -0
- package/core/logos/brandmarks/original/reddit.svg +1 -0
- package/core/logos/brandmarks/original/safari.svg +31 -0
- package/core/logos/brandmarks/original/sass.svg +3 -0
- package/core/logos/brandmarks/original/signal.svg +6 -0
- package/core/logos/brandmarks/original/skype.svg +47 -0
- package/core/logos/brandmarks/original/slack.svg +33 -0
- package/core/logos/brandmarks/original/soundcloud.svg +1 -0
- package/core/logos/brandmarks/original/spotify.svg +5 -0
- package/core/logos/brandmarks/original/steam.svg +6 -0
- package/core/logos/brandmarks/original/telegram.svg +14 -0
- package/core/logos/brandmarks/original/tiktok.svg +1 -0
- package/core/logos/brandmarks/original/trello.svg +16 -0
- package/core/logos/brandmarks/original/tumblr.svg +1 -0
- package/core/logos/brandmarks/original/twitch.svg +6 -0
- package/core/logos/brandmarks/original/twitter.svg +6 -0
- package/core/logos/brandmarks/original/unity.svg +6 -0
- package/core/logos/brandmarks/original/x.svg +7 -0
- package/core/logos/brandmarks/original/yahoo-y.svg +1 -0
- package/core/logos/brandmarks/original/youtube-square.svg +1 -0
- package/core/logos/brandmarks/original/youtube.svg +1 -0
- package/core/logos/combomarks/dark/airbnb.svg +30 -0
- package/core/logos/combomarks/dark/slack.svg +38 -0
- package/core/logos/combomarks/dark/spotify.svg +35 -0
- package/core/logos/combomarks/dark/twilio.svg +26 -0
- package/core/logos/combomarks/dark/weebly.svg +35 -0
- package/core/logos/combomarks/gray/airbnb.svg +33 -0
- package/core/logos/combomarks/gray/alphabet.svg +23 -0
- package/core/logos/combomarks/gray/amazon.svg +38 -0
- package/core/logos/combomarks/gray/boring-company.svg +91 -0
- package/core/logos/combomarks/gray/burberry.svg +239 -0
- package/core/logos/combomarks/gray/embark.svg +21 -0
- package/core/logos/combomarks/gray/fitbit.svg +61 -0
- package/core/logos/combomarks/gray/fred-perry.svg +94 -0
- package/core/logos/combomarks/gray/google.svg +27 -0
- package/core/logos/combomarks/gray/hollister.svg +34 -0
- package/core/logos/combomarks/gray/hubspot.svg +27 -0
- package/core/logos/combomarks/gray/kaplan.svg +33 -0
- package/core/logos/combomarks/gray/lenovo.svg +27 -0
- package/core/logos/combomarks/gray/levis.svg +25 -0
- package/core/logos/combomarks/gray/mapbox.svg +37 -0
- package/core/logos/combomarks/gray/netflix.svg +15 -0
- package/core/logos/combomarks/gray/new-balance.svg +32 -0
- package/core/logos/combomarks/gray/nike.svg +17 -0
- package/core/logos/combomarks/gray/paypal.svg +41 -0
- package/core/logos/combomarks/gray/puma.svg +82 -0
- package/core/logos/combomarks/gray/samsung.svg +26 -0
- package/core/logos/combomarks/gray/shopify.svg +36 -0
- package/core/logos/combomarks/gray/slack.svg +42 -0
- package/core/logos/combomarks/gray/spotify.svg +38 -0
- package/core/logos/combomarks/gray/stripe.svg +24 -0
- package/core/logos/combomarks/gray/tnf.svg +30 -0
- package/core/logos/combomarks/gray/twilio.svg +29 -0
- package/core/logos/combomarks/gray/uber.svg +24 -0
- package/core/logos/combomarks/gray/weebly.svg +38 -0
- package/core/logos/combomarks/original/airbnb.svg +33 -0
- package/core/logos/combomarks/original/alphabet.svg +23 -0
- package/core/logos/combomarks/original/amazon.svg +38 -0
- package/core/logos/combomarks/original/asana.svg +8 -0
- package/core/logos/combomarks/original/boring-company.svg +91 -0
- package/core/logos/combomarks/original/discord.svg +6 -0
- package/core/logos/combomarks/original/embark.svg +24 -0
- package/core/logos/combomarks/original/fitbit.svg +60 -0
- package/core/logos/combomarks/original/github.svg +6 -0
- package/core/logos/combomarks/original/gitlab.svg +20 -0
- package/core/logos/combomarks/original/google.svg +28 -0
- package/core/logos/combomarks/original/hubspot.svg +29 -0
- package/core/logos/combomarks/original/instagram.svg +7 -0
- package/core/logos/combomarks/original/kickstarter.svg +6 -0
- package/core/logos/combomarks/original/lenovo.svg +24 -0
- package/core/logos/combomarks/original/linkedin.svg +6 -0
- package/core/logos/combomarks/original/mapbox.svg +39 -0
- package/core/logos/combomarks/original/mastodon.svg +7 -0
- package/core/logos/combomarks/original/medium.svg +6 -0
- package/core/logos/combomarks/original/meta.svg +22 -0
- package/core/logos/combomarks/original/microsoft.svg +13 -0
- package/core/logos/combomarks/original/monday.svg +12 -0
- package/core/logos/combomarks/original/netflix.svg +15 -0
- package/core/logos/combomarks/original/notion.svg +9 -0
- package/core/logos/combomarks/original/paypal.svg +41 -0
- package/core/logos/combomarks/original/reddit.svg +13 -0
- package/core/logos/combomarks/original/samsung.svg +25 -0
- package/core/logos/combomarks/original/shopify.svg +35 -0
- package/core/logos/combomarks/original/slack.svg +47 -0
- package/core/logos/combomarks/original/spotify.svg +37 -0
- package/core/logos/combomarks/original/stackoverflow.svg +28 -0
- package/core/logos/combomarks/original/stripe.svg +24 -0
- package/core/logos/combomarks/original/tiktok.svg +12 -0
- package/core/logos/combomarks/original/tumblr.svg +6 -0
- package/core/logos/combomarks/original/uber.svg +24 -0
- package/core/logos/combomarks/original/weebly.svg +34 -0
- package/core/logos/combomarks/original/whatsapp.svg +20 -0
- package/core/logos/combomarks/original/youtube.svg +10 -0
- package/core/logos/combomarks/original/zoom.svg +7 -0
- package/core/logos/combomarks/white/airbnb.svg +33 -0
- package/core/logos/combomarks/white/alphabet.svg +23 -0
- package/core/logos/combomarks/white/amazon.svg +38 -0
- package/core/logos/combomarks/white/boring-company.svg +91 -0
- package/core/logos/combomarks/white/embark.svg +21 -0
- package/core/logos/combomarks/white/fitbit.svg +61 -0
- package/core/logos/combomarks/white/google.svg +27 -0
- package/core/logos/combomarks/white/hubspot.svg +27 -0
- package/core/logos/combomarks/white/kaplan.svg +33 -0
- package/core/logos/combomarks/white/lenovo.svg +27 -0
- package/core/logos/combomarks/white/mapbox.svg +37 -0
- package/core/logos/combomarks/white/netflix.svg +15 -0
- package/core/logos/combomarks/white/paypal.svg +40 -0
- package/core/logos/combomarks/white/samsung.svg +26 -0
- package/core/logos/combomarks/white/shopify.svg +36 -0
- package/core/logos/combomarks/white/slack.svg +42 -0
- package/core/logos/combomarks/white/spotify.svg +38 -0
- package/core/logos/combomarks/white/stripe.svg +24 -0
- package/core/logos/combomarks/white/twilio.svg +29 -0
- package/core/logos/combomarks/white/uber.svg +24 -0
- package/core/logos/combomarks/white/weebly.svg +38 -0
- package/defaults/pages/404.md +4 -0
- package/defaults/pages/about.md +4 -0
- package/defaults/pages/admin/calendar/index.html +4 -0
- package/defaults/pages/admin/firebase/index.html +4 -0
- package/defaults/pages/admin/index.md +4 -0
- package/defaults/pages/admin/posts/editor.html +4 -0
- package/defaults/pages/admin/posts/index.html +4 -0
- package/defaults/pages/admin/stackblitz/index.html +4 -0
- package/defaults/pages/admin/studio/index.html +4 -0
- package/defaults/pages/admin/users/index.html +4 -0
- package/defaults/pages/admin/users/new.html +4 -0
- package/defaults/pages/admin/verts/index.html +4 -0
- package/defaults/pages/ads-txt.html +11 -0
- package/defaults/pages/alternatives/index.md +4 -0
- package/defaults/pages/app.md +4 -0
- package/defaults/pages/auth/reset.md +4 -0
- package/defaults/pages/auth/signin.md +4 -0
- package/defaults/pages/auth/signup.md +4 -0
- package/defaults/pages/auth/token.md +4 -0
- package/defaults/pages/blog/categories/category.html +21 -0
- package/defaults/pages/blog/categories.md +4 -0
- package/defaults/pages/blog/index-json.html +27 -0
- package/defaults/pages/blog/tags/tag.html +21 -0
- package/defaults/pages/blog/tags.md +4 -0
- package/defaults/pages/blog.md +22 -0
- package/defaults/pages/careers.md +4 -0
- package/defaults/pages/connections/callback.md +4 -0
- package/defaults/pages/contact.md +4 -0
- package/defaults/pages/dashboard/account.md +4 -0
- package/defaults/pages/dashboard/index.md +12 -0
- package/defaults/pages/download.md +4 -0
- package/defaults/pages/extension/index.html +4 -0
- package/defaults/pages/extension/installed.html +4 -0
- package/defaults/pages/feedback.md +4 -0
- package/defaults/pages/feeds/posts-json.html +40 -0
- package/defaults/pages/feeds/posts-xml.html +38 -0
- package/defaults/pages/humans.html +25 -0
- package/defaults/pages/index.md +4 -0
- package/defaults/pages/legal/cookies.md +4 -0
- package/defaults/pages/legal/privacy.md +4 -0
- package/defaults/pages/legal/terms.md +4 -0
- package/defaults/pages/llms-txt.html +46 -0
- package/defaults/pages/opensearch.html +16 -0
- package/defaults/pages/pages-json.html +42 -0
- package/defaults/pages/payment/checkout.md +4 -0
- package/defaults/pages/payment/confirmation.md +4 -0
- package/defaults/pages/portal/email-preferences.md +4 -0
- package/defaults/pages/pricing.md +4 -0
- package/defaults/pages/redirects/account.md +12 -0
- package/defaults/pages/redirects/admin/dashboard.md +11 -0
- package/defaults/pages/redirects/auth/change-password.md +9 -0
- package/defaults/pages/redirects/auth/forgot.md +9 -0
- package/defaults/pages/redirects/auth/join.md +9 -0
- package/defaults/pages/redirects/auth/login.md +9 -0
- package/defaults/pages/redirects/auth/recover.md +9 -0
- package/defaults/pages/redirects/auth/register.md +9 -0
- package/defaults/pages/redirects/auth/reset-password.md +9 -0
- package/defaults/pages/redirects/billing/cancel.md +9 -0
- package/defaults/pages/redirects/billing/refund.md +9 -0
- package/defaults/pages/robots.html +36 -0
- package/defaults/pages/security-txt.html +11 -0
- package/defaults/pages/sitemap.html +37 -0
- package/defaults/pages/status.md +4 -0
- package/defaults/pages/team/index.md +4 -0
- package/defaults/pages/test/account/dashboard.html +16 -0
- package/defaults/pages/test/index.md +12 -0
- package/defaults/pages/test/libraries/appearance.html +268 -0
- package/defaults/pages/test/libraries/cover.html +50 -0
- package/defaults/pages/test/libraries/error.html +30 -0
- package/defaults/pages/test/libraries/firestore.html +202 -0
- package/defaults/pages/test/libraries/form-manager.html +374 -0
- package/defaults/pages/test/libraries/layers.html +52 -0
- package/defaults/pages/test/libraries/lazy-loading.html +450 -0
- package/defaults/pages/test/libraries/verts.html +149 -0
- package/defaults/pages/test/redirect/external.md +13 -0
- package/defaults/pages/test/redirect/internal.md +13 -0
- package/defaults/pages/test/styleguide/index.html +588 -0
- package/defaults/pages/test/translation/index.md +50 -0
- package/defaults/pages/updates/index.md +4 -0
- package/defaults/sample-posts/2026-01-12-welcome-to-the-blog.md +26 -0
- package/defaults/sample-posts/2026-02-03-a-field-guide-to-good-defaults.md +50 -0
- package/defaults/sample-posts/2026-02-24-shipping-week-notes.md +37 -0
- package/defaults/sample-posts/2026-03-17-the-case-for-one-config.md +36 -0
- package/defaults/sample-posts/2026-04-09-write-release-notes-people-read.md +34 -0
- package/defaults/sample-posts/2026-05-21-dark-mode-done-properly.md +38 -0
- package/defaults/sample-posts/2026-06-02-the-boring-deploy-is-the-good-deploy.md +30 -0
- package/defaults/sample-posts/2026-06-11-naming-things-a-survival-guide.md +30 -0
- package/defaults/sample-posts/2026-06-19-your-pricing-page-is-a-product.md +28 -0
- package/defaults/sample-posts/2026-06-30-email-is-an-api-with-feelings.md +28 -0
- package/defaults/sample-posts/2026-07-08-ship-the-docs-with-the-diff.md +30 -0
- package/defaults/sample-team/avery-quinn.md +22 -0
- package/defaults/sample-team/jordan-reyes.md +25 -0
- package/defaults/sample-team/riley-nakamura.md +22 -0
- package/defaults/sample-team/sam-okafor.md +22 -0
- package/defaults/sample-updates/v1.0.0.md +28 -0
- package/defaults/sample-updates/v1.1.0.md +27 -0
- package/defaults/sample-updates/v1.2.0.md +27 -0
- package/defaults/sample-updates/v1.3.0.md +28 -0
- package/defaults/showcase/components.html +62 -0
- package/defaults/showcase/entry.html +76 -0
- package/defaults/showcase/frame.html +62 -0
- package/defaults/showcase/index.html +59 -0
- package/dist/assets.js +1349 -0
- package/dist/brand-tokens.js +195 -0
- package/dist/build.js +192 -0
- package/dist/cachebreak-html.js +71 -0
- package/dist/cli-run.js +25 -0
- package/dist/cli.js +47 -0
- package/dist/collections.js +183 -0
- package/dist/commands/audit.js +470 -0
- package/dist/commands/build.js +197 -0
- package/dist/commands/clean.js +18 -0
- package/dist/commands/customize.js +125 -0
- package/dist/commands/deploy.js +441 -0
- package/dist/commands/dev.js +1067 -0
- package/dist/commands/install.js +31 -0
- package/dist/commands/lib/deploy-precheck.js +43 -0
- package/dist/commands/lib/ensure-target.js +115 -0
- package/dist/commands/migrate.js +86 -0
- package/dist/commands/purge.js +31 -0
- package/dist/commands/test.js +237 -0
- package/dist/commands/translate.js +57 -0
- package/dist/commands/update.js +22 -0
- package/dist/commands/version.js +11 -0
- package/dist/config-sections.js +245 -0
- package/dist/consumer-scan.js +118 -0
- package/dist/consumer.js +49 -0
- package/dist/customize.js +328 -0
- package/dist/decisions.js +153 -0
- package/dist/dist-audit.js +417 -0
- package/dist/dynamic-pages.js +357 -0
- package/dist/engine.js +1402 -0
- package/dist/firebase-auth-helpers.js +198 -0
- package/dist/font-metrics.js +420 -0
- package/dist/frontmatter-liquid.js +253 -0
- package/dist/github-secrets.js +80 -0
- package/dist/hero-animations.js +170 -0
- package/dist/imagemin.js +261 -0
- package/dist/index.js +41 -0
- package/dist/inline-icons.js +65 -0
- package/dist/language-flags.js +55 -0
- package/dist/layers.js +80 -0
- package/dist/layouts.js +44 -0
- package/dist/limit-collections.js +199 -0
- package/dist/link-resolver.js +303 -0
- package/dist/markdown-images.js +85 -0
- package/dist/merge.js +20 -0
- package/dist/migrate/codemod.js +172 -0
- package/dist/migrate/config-convert.js +448 -0
- package/dist/migrate/consumer-assets.js +130 -0
- package/dist/migrate/index.js +223 -0
- package/dist/migrate/lint.js +108 -0
- package/dist/migrate/rules.js +1929 -0
- package/dist/minify-html.js +148 -0
- package/dist/mode-helpers.js +96 -0
- package/dist/omega-bin.js +7 -0
- package/dist/overrides.js +190 -0
- package/dist/path-prefix.js +167 -0
- package/dist/paths.js +37 -0
- package/dist/pricing.js +301 -0
- package/dist/purge.js +95 -0
- package/dist/redirect-page.js +45 -0
- package/dist/sample-content.js +210 -0
- package/dist/scaffold.js +123 -0
- package/dist/sections.js +810 -0
- package/dist/service-worker.js +200 -0
- package/dist/social-pages.js +142 -0
- package/dist/srcset.js +67 -0
- package/dist/static-assets.js +154 -0
- package/dist/target-shortlinks.js +123 -0
- package/dist/theme-vocabulary.js +76 -0
- package/dist/translate/collect-text-nodes.js +93 -0
- package/dist/translate/default-routes.js +152 -0
- package/dist/translate/generate-defaults.js +297 -0
- package/dist/translate/index.js +568 -0
- package/dist/translate/packaged-defaults.js +127 -0
- package/dist/translate/sitemap.js +108 -0
- package/dist/vendor/account/engine.js +182 -0
- package/dist/vendor/account/features.js +220 -0
- package/dist/vendor/account/index.js +53 -0
- package/dist/vendor/account/schema.js +272 -0
- package/dist/vendor/account/subscription.js +38 -0
- package/dist/vendor/config/company.js +31 -0
- package/dist/vendor/config/defaults.js +173 -0
- package/dist/vendor/config/demo.js +18 -0
- package/dist/vendor/config/desktop-artifacts.js +110 -0
- package/dist/vendor/config/edit.js +769 -0
- package/dist/vendor/config/env-delivery.js +145 -0
- package/dist/vendor/config/env-rules.js +93 -0
- package/dist/vendor/config/env-schema.js +1078 -0
- package/dist/vendor/config/env.js +445 -0
- package/dist/vendor/config/hooks.js +97 -0
- package/dist/vendor/config/index.js +237 -0
- package/dist/vendor/config/instances.js +208 -0
- package/dist/vendor/config/load.js +490 -0
- package/dist/vendor/config/merge.js +68 -0
- package/dist/vendor/config/order.js +139 -0
- package/dist/vendor/config/ports.js +374 -0
- package/dist/vendor/config/providers.js +32 -0
- package/dist/vendor/config/repo.js +142 -0
- package/dist/vendor/config/retired-keys.js +430 -0
- package/dist/vendor/config/schema.js +1610 -0
- package/dist/vendor/config/secrets.js +50 -0
- package/dist/vendor/config/seed.js +34 -0
- package/dist/vendor/config/site-global.js +205 -0
- package/dist/vendor/config/validate.js +554 -0
- package/dist/vendor/config/winback.js +61 -0
- package/dist/vendor/devkit/actions-secrets.js +145 -0
- package/dist/vendor/devkit/attach-log-file.js +262 -0
- package/dist/vendor/devkit/bare-requires.js +153 -0
- package/dist/vendor/devkit/bundle.js +292 -0
- package/dist/vendor/devkit/ci-workflows.js +520 -0
- package/dist/vendor/devkit/cli-router.js +156 -0
- package/dist/vendor/devkit/command-path.js +46 -0
- package/dist/vendor/devkit/defaults-engine.js +372 -0
- package/dist/vendor/devkit/deploy-precheck.js +54 -0
- package/dist/vendor/devkit/deploy-record.js +180 -0
- package/dist/vendor/devkit/deploy.js +286 -0
- package/dist/vendor/devkit/env-watch.js +132 -0
- package/dist/vendor/devkit/framework-deps.js +46 -0
- package/dist/vendor/devkit/icons.js +178 -0
- package/dist/vendor/devkit/license.js +155 -0
- package/dist/vendor/devkit/local-https.js +360 -0
- package/dist/vendor/devkit/local.js +1905 -0
- package/dist/vendor/devkit/logger.js +128 -0
- package/dist/vendor/devkit/merge-line-files.js +296 -0
- package/dist/vendor/devkit/omega-bin.js +345 -0
- package/dist/vendor/devkit/reads.js +274 -0
- package/dist/vendor/devkit/safe-install.js +18 -0
- package/dist/vendor/devkit/scaffold-guard.js +96 -0
- package/dist/vendor/devkit/stop-signals.js +28 -0
- package/dist/vendor/devkit/strip-dev-blocks-plugin.js +29 -0
- package/dist/vendor/devkit/strip-dev-blocks.js +32 -0
- package/dist/vendor/devkit/target-secrets.js +165 -0
- package/dist/vendor/devkit/test/scope.js +162 -0
- package/dist/vendor/devkit/translate/cache.js +84 -0
- package/dist/vendor/devkit/translate/engine.js +243 -0
- package/dist/vendor/devkit/translate/index.js +49 -0
- package/dist/vendor/devkit/translate/languages.js +134 -0
- package/dist/vendor/devkit/translate/providers.js +188 -0
- package/dist/vendor/devkit/update.js +569 -0
- package/dist/vendor/template-kit/data/language-flags.js +54 -0
- package/dist/vendor/template-kit/data/languages.js +195 -0
- package/dist/vendor/template-kit/data/social-urls.js +26 -0
- package/dist/vendor/template-kit/filters.js +227 -0
- package/dist/vendor/template-kit/index.js +28 -0
- package/dist/vendor/template-kit/jekyll-compat.js +268 -0
- package/dist/vendor/template-kit/register-liquid.js +0 -0
- package/dist/vendor/template-kit/tags/collections.js +191 -0
- package/dist/vendor/template-kit/tags/conditionals.js +101 -0
- package/dist/vendor/template-kit/tags/content.js +175 -0
- package/dist/vendor/template-kit/tags/index.js +33 -0
- package/dist/vendor/template-kit/tags/media.js +376 -0
- package/dist/vendor/template-kit/variable-resolver.js +163 -0
- package/docs/ads-system.md +109 -0
- package/docs/classy-v2/DIRECTION.md +92 -0
- package/docs/classy-v2/draft-1.html +1932 -0
- package/docs/classy-v2/draft-2.html +1956 -0
- package/docs/frontmatter.md +153 -0
- package/docs/index.md +254 -0
- package/docs/libs.md +298 -0
- package/docs/omega-sections-spec.md +159 -0
- package/docs/page-contract.md +112 -0
- package/docs/sections.md +845 -0
- package/docs/shared/agent-docs.md +89 -0
- package/docs/shared/analytics.md +612 -0
- package/docs/shared/brands.md +51 -0
- package/docs/shared/breaking-changes.md +497 -0
- package/docs/shared/config.md +1387 -0
- package/docs/shared/deploys.md +215 -0
- package/docs/shared/icons.md +201 -0
- package/docs/shared/local-dev.md +147 -0
- package/docs/shared/logging.md +202 -0
- package/docs/shared/monitoring.md +153 -0
- package/docs/shared/publishing.md +183 -0
- package/docs/shared/rulings.md +34 -0
- package/docs/shared/testing.md +147 -0
- package/docs/shared/theming.md +604 -0
- package/docs/shared/translation.md +291 -0
- package/docs/shared/updates.md +61 -0
- package/docs/template-kit.md +128 -0
- package/docs/test-framework.md +163 -0
- package/package.json +122 -0
- package/runtime/boot.js +149 -0
- package/runtime/icons.js +77 -0
- package/runtime/manager.js +36 -0
- package/scaffold/.github/workflows/build.yml +139 -0
- package/scaffold/.nvmrc +1 -0
- package/scaffold/AGENTS.md +55 -0
- package/scaffold/CLAUDE.md +1 -0
- package/scaffold/_.gitattributes +4 -0
- package/scaffold/_.gitignore +27 -0
- package/scaffold/config/omega.json5 +20 -0
- package/scaffold/src/assets/css/pages/.gitkeep +0 -0
- package/scaffold/src/assets/images/.gitkeep +0 -0
- package/scaffold/src/assets/js/pages/.gitkeep +0 -0
- package/scaffold/src/pages/.gitkeep +0 -0
- package/scaffold/src/pages/example.md.txt +94 -0
- package/scaffold/src/service-worker.js +16 -0
- package/sw/entry.js +19 -0
- package/sw/manager.js +281 -0
- package/themes/_template/README.md +115 -0
- package/themes/_template/_config.scss +60 -0
- package/themes/_template/_theme.js +14 -0
- package/themes/_template/_theme.scss +28 -0
- package/themes/_template/css/base/_root.scss +19 -0
- package/themes/_template/css/components/_components.scss +23 -0
- package/themes/base/README.md +5 -0
- package/themes/base/_components/data/org-chart/component.html +33 -0
- package/themes/base/_components/data/org-chart/component.json5 +33 -0
- package/themes/base/_components/data/org-chart/component.scss +183 -0
- package/themes/base/_components/heading/masthead/component.html +22 -0
- package/themes/base/_components/heading/masthead/component.json5 +30 -0
- package/themes/base/_components/heading/section-head/component.html +18 -0
- package/themes/base/_components/heading/section-head/component.json5 +27 -0
- package/themes/base/_components/pricing/features/component.html +29 -0
- package/themes/base/_components/pricing/features/component.json5 +30 -0
- package/themes/base/_hero/orbit/index.html +30 -0
- package/themes/base/_hero/orbit/script.js +33 -0
- package/themes/base/_hero/orbit/style.scss +133 -0
- package/themes/base/_includes/admin/sections/sidebar.html +3 -0
- package/themes/base/_includes/admin/sections/topbar.html +3 -0
- package/themes/base/_includes/backend/sections/sidebar.html +3 -0
- package/themes/base/_includes/backend/sections/topbar.html +3 -0
- package/themes/base/_includes/frontend/components/connection-card.html +49 -0
- package/themes/base/_includes/frontend/components/post-card.html +54 -0
- package/themes/base/_includes/frontend/sections/account-connections.html +42 -0
- package/themes/base/_includes/frontend/sections/account-section-header.html +11 -0
- package/themes/base/_includes/frontend/sections/footer.html +154 -0
- package/themes/base/_includes/frontend/sections/nav.html +276 -0
- package/themes/base/_includes/global/sections/account.html +72 -0
- package/themes/base/_includes/global/sections/app-sidebar.html +248 -0
- package/themes/base/_includes/global/sections/app-topbar.html +228 -0
- package/themes/base/_includes/global/sections/page-header.html +99 -0
- package/themes/base/_layouts/admin/core/minimal-viewport-locked.html +22 -0
- package/themes/base/_layouts/admin/core/minimal.html +23 -0
- package/themes/base/_layouts/backend/core/base.html +57 -0
- package/themes/base/_layouts/backend/core/minimal-viewport-locked.html +32 -0
- package/themes/base/_layouts/backend/core/minimal.html +32 -0
- package/themes/base/_layouts/backend/pages/dashboard/index.html +230 -0
- package/themes/base/_layouts/frontend/core/base.html +31 -0
- package/themes/base/_layouts/frontend/core/cover.html +40 -0
- package/themes/base/_layouts/frontend/core/minimal.html +47 -0
- package/themes/base/_layouts/frontend/pages/404.html +54 -0
- package/themes/base/_layouts/frontend/pages/about.html +144 -0
- package/themes/base/_layouts/frontend/pages/account/index.html +2104 -0
- package/themes/base/_layouts/frontend/pages/alternatives/alternative.html +319 -0
- package/themes/base/_layouts/frontend/pages/alternatives/index.html +186 -0
- package/themes/base/_layouts/frontend/pages/app.html +142 -0
- package/themes/base/_layouts/frontend/pages/auth/reset.html +53 -0
- package/themes/base/_layouts/frontend/pages/auth/signin.html +90 -0
- package/themes/base/_layouts/frontend/pages/auth/signup.html +141 -0
- package/themes/base/_layouts/frontend/pages/auth/token.html +44 -0
- package/themes/base/_layouts/frontend/pages/blog/categories/category.html +88 -0
- package/themes/base/_layouts/frontend/pages/blog/categories/index.html +88 -0
- package/themes/base/_layouts/frontend/pages/blog/index.html +255 -0
- package/themes/base/_layouts/frontend/pages/blog/post.html +261 -0
- package/themes/base/_layouts/frontend/pages/blog/tags/index.html +84 -0
- package/themes/base/_layouts/frontend/pages/blog/tags/tag.html +88 -0
- package/themes/base/_layouts/frontend/pages/collection/category.html +72 -0
- package/themes/base/_layouts/frontend/pages/collection/document.html +54 -0
- package/themes/base/_layouts/frontend/pages/collection/index.html +84 -0
- package/themes/base/_layouts/frontend/pages/connections/callback.html +55 -0
- package/themes/base/_layouts/frontend/pages/contact.html +214 -0
- package/themes/base/_layouts/frontend/pages/download.html +793 -0
- package/themes/base/_layouts/frontend/pages/extension/index.html +253 -0
- package/themes/base/_layouts/frontend/pages/extension/installed.html +198 -0
- package/themes/base/_layouts/frontend/pages/feedback.html +171 -0
- package/themes/base/_layouts/frontend/pages/index.html +66 -0
- package/themes/base/_layouts/frontend/pages/legal/document.html +78 -0
- package/themes/base/_layouts/frontend/pages/payment/checkout.html +459 -0
- package/themes/base/_layouts/frontend/pages/payment/confirmation.html +131 -0
- package/themes/base/_layouts/frontend/pages/portal/email-preferences.html +104 -0
- package/themes/base/_layouts/frontend/pages/pricing.html +596 -0
- package/themes/base/_layouts/frontend/pages/status.html +361 -0
- package/themes/base/_layouts/frontend/pages/team/index.html +210 -0
- package/themes/base/_layouts/frontend/pages/team/member.html +125 -0
- package/themes/base/_layouts/frontend/pages/updates/index.html +119 -0
- package/themes/base/_layouts/frontend/pages/updates/update.html +118 -0
- package/themes/base/_sections/about/hero/section.html +68 -0
- package/themes/base/_sections/about/hero/section.json5 +58 -0
- package/themes/base/_sections/about/letter/section.html +60 -0
- package/themes/base/_sections/about/letter/section.json5 +56 -0
- package/themes/base/_sections/about/photo-band/section.html +24 -0
- package/themes/base/_sections/about/photo-band/section.json5 +23 -0
- package/themes/base/_sections/about/principles/section.html +17 -0
- package/themes/base/_sections/about/principles/section.json5 +34 -0
- package/themes/base/_sections/about/timeline/section.html +20 -0
- package/themes/base/_sections/about/timeline/section.json5 +34 -0
- package/themes/base/_sections/marketing/bento/section.html +91 -0
- package/themes/base/_sections/marketing/bento/section.json5 +152 -0
- package/themes/base/_sections/marketing/cta/section.html +44 -0
- package/themes/base/_sections/marketing/cta/section.json5 +47 -0
- package/themes/base/_sections/marketing/faq/section.html +52 -0
- package/themes/base/_sections/marketing/faq/section.json5 +68 -0
- package/themes/base/_sections/marketing/hero/section.html +349 -0
- package/themes/base/_sections/marketing/hero/section.json5 +335 -0
- package/themes/base/_sections/marketing/newsletter-cta/section.html +38 -0
- package/themes/base/_sections/marketing/newsletter-cta/section.js +86 -0
- package/themes/base/_sections/marketing/newsletter-cta/section.json5 +29 -0
- package/themes/base/_sections/marketing/pricing-cards/section.html +115 -0
- package/themes/base/_sections/marketing/pricing-cards/section.json5 +72 -0
- package/themes/base/_sections/marketing/product-demo/section.html +62 -0
- package/themes/base/_sections/marketing/product-demo/section.js +44 -0
- package/themes/base/_sections/marketing/product-demo/section.json5 +52 -0
- package/themes/base/_sections/marketing/prose/section.html +22 -0
- package/themes/base/_sections/marketing/prose/section.json5 +41 -0
- package/themes/base/_sections/marketing/showcase/section.html +35 -0
- package/themes/base/_sections/marketing/showcase/section.json5 +52 -0
- package/themes/base/_sections/marketing/stats/section.html +32 -0
- package/themes/base/_sections/marketing/stats/section.json5 +44 -0
- package/themes/base/_sections/marketing/testimonials/section.html +54 -0
- package/themes/base/_sections/marketing/testimonials/section.json5 +70 -0
- package/themes/base/_sections/marketing/trusted-by/section.html +30 -0
- package/themes/base/_sections/marketing/trusted-by/section.json5 +38 -0
- package/themes/base/_sections/verts/unit/section.html +7 -0
- package/themes/base/_sections/verts/unit/section.js +22 -0
- package/themes/base/_sections/verts/unit/section.json5 +24 -0
- package/themes/base/_sections/verts/unit/section.scss +24 -0
- package/themes/base/_theme.js +13 -0
- package/themes/base/_theme.scss +4 -0
- package/themes/bootstrap/_theme.js +16 -0
- package/themes/bootstrap/_theme.scss +11 -0
- package/themes/bootstrap/js/index.esm.js +19 -0
- package/themes/bootstrap/js/index.umd.js +34 -0
- package/themes/bootstrap/js/src/alert.js +87 -0
- package/themes/bootstrap/js/src/base-component.js +86 -0
- package/themes/bootstrap/js/src/button.js +72 -0
- package/themes/bootstrap/js/src/carousel.js +474 -0
- package/themes/bootstrap/js/src/collapse.js +297 -0
- package/themes/bootstrap/js/src/dom/data.js +55 -0
- package/themes/bootstrap/js/src/dom/event-handler.js +317 -0
- package/themes/bootstrap/js/src/dom/manipulator.js +71 -0
- package/themes/bootstrap/js/src/dom/selector-engine.js +126 -0
- package/themes/bootstrap/js/src/dropdown.js +458 -0
- package/themes/bootstrap/js/src/modal.js +378 -0
- package/themes/bootstrap/js/src/offcanvas.js +282 -0
- package/themes/bootstrap/js/src/popover.js +97 -0
- package/themes/bootstrap/js/src/scrollspy.js +296 -0
- package/themes/bootstrap/js/src/tab.js +315 -0
- package/themes/bootstrap/js/src/toast.js +224 -0
- package/themes/bootstrap/js/src/tooltip.js +632 -0
- package/themes/bootstrap/js/src/util/backdrop.js +151 -0
- package/themes/bootstrap/js/src/util/component-functions.js +35 -0
- package/themes/bootstrap/js/src/util/config.js +65 -0
- package/themes/bootstrap/js/src/util/focustrap.js +115 -0
- package/themes/bootstrap/js/src/util/index.js +306 -0
- package/themes/bootstrap/js/src/util/sanitizer.js +117 -0
- package/themes/bootstrap/js/src/util/scrollbar.js +114 -0
- package/themes/bootstrap/js/src/util/swipe.js +146 -0
- package/themes/bootstrap/js/src/util/template-factory.js +160 -0
- package/themes/bootstrap/overrides/_accordion.scss +21 -0
- package/themes/bootstrap/overrides/_avatars.scss +51 -0
- package/themes/bootstrap/overrides/_blog-images.scss +45 -0
- package/themes/bootstrap/overrides/_buttons-adaptive.scss +141 -0
- package/themes/bootstrap/overrides/_color-shades.scss +25 -0
- package/themes/bootstrap/overrides/_cursor-utilities.scss +13 -0
- package/themes/bootstrap/overrides/_index.scss +30 -0
- package/themes/bootstrap/overrides/_links.scss +26 -0
- package/themes/bootstrap/overrides/_soft-colors.scss +99 -0
- package/themes/bootstrap/overrides/_spacing-extended.scss +74 -0
- package/themes/bootstrap/overrides/_spinners.scss +22 -0
- package/themes/bootstrap/overrides/_typography-utilities.scss +40 -0
- package/themes/bootstrap/scss/_accordion.scss +153 -0
- package/themes/bootstrap/scss/_alert.scss +68 -0
- package/themes/bootstrap/scss/_badge.scss +38 -0
- package/themes/bootstrap/scss/_breadcrumb.scss +40 -0
- package/themes/bootstrap/scss/_button-group.scss +147 -0
- package/themes/bootstrap/scss/_buttons.scss +216 -0
- package/themes/bootstrap/scss/_card.scss +238 -0
- package/themes/bootstrap/scss/_carousel.scss +226 -0
- package/themes/bootstrap/scss/_close.scss +66 -0
- package/themes/bootstrap/scss/_containers.scss +41 -0
- package/themes/bootstrap/scss/_dropdown.scss +250 -0
- package/themes/bootstrap/scss/_forms.scss +9 -0
- package/themes/bootstrap/scss/_functions.scss +302 -0
- package/themes/bootstrap/scss/_grid.scss +39 -0
- package/themes/bootstrap/scss/_helpers.scss +12 -0
- package/themes/bootstrap/scss/_images.scss +42 -0
- package/themes/bootstrap/scss/_list-group.scss +199 -0
- package/themes/bootstrap/scss/_maps.scss +174 -0
- package/themes/bootstrap/scss/_mixins.scss +42 -0
- package/themes/bootstrap/scss/_modal.scss +240 -0
- package/themes/bootstrap/scss/_nav.scss +197 -0
- package/themes/bootstrap/scss/_navbar.scss +289 -0
- package/themes/bootstrap/scss/_offcanvas.scss +147 -0
- package/themes/bootstrap/scss/_pagination.scss +109 -0
- package/themes/bootstrap/scss/_placeholders.scss +51 -0
- package/themes/bootstrap/scss/_popover.scss +196 -0
- package/themes/bootstrap/scss/_progress.scss +68 -0
- package/themes/bootstrap/scss/_reboot.scss +611 -0
- package/themes/bootstrap/scss/_root.scss +187 -0
- package/themes/bootstrap/scss/_spinners.scss +85 -0
- package/themes/bootstrap/scss/_tables.scss +171 -0
- package/themes/bootstrap/scss/_toasts.scss +73 -0
- package/themes/bootstrap/scss/_tooltip.scss +119 -0
- package/themes/bootstrap/scss/_transitions.scss +27 -0
- package/themes/bootstrap/scss/_type.scss +106 -0
- package/themes/bootstrap/scss/_utilities.scss +806 -0
- package/themes/bootstrap/scss/_variables-dark.scss +102 -0
- package/themes/bootstrap/scss/_variables.scss +1753 -0
- package/themes/bootstrap/scss/bootstrap-grid.scss +62 -0
- package/themes/bootstrap/scss/bootstrap-reboot.scss +10 -0
- package/themes/bootstrap/scss/bootstrap-utilities.scss +19 -0
- package/themes/bootstrap/scss/bootstrap.scss +52 -0
- package/themes/bootstrap/scss/forms/_floating-labels.scss +97 -0
- package/themes/bootstrap/scss/forms/_form-check.scss +189 -0
- package/themes/bootstrap/scss/forms/_form-control.scss +214 -0
- package/themes/bootstrap/scss/forms/_form-range.scss +91 -0
- package/themes/bootstrap/scss/forms/_form-select.scss +80 -0
- package/themes/bootstrap/scss/forms/_form-text.scss +11 -0
- package/themes/bootstrap/scss/forms/_input-group.scss +132 -0
- package/themes/bootstrap/scss/forms/_labels.scss +36 -0
- package/themes/bootstrap/scss/forms/_validation.scss +12 -0
- package/themes/bootstrap/scss/helpers/_clearfix.scss +3 -0
- package/themes/bootstrap/scss/helpers/_color-bg.scss +7 -0
- package/themes/bootstrap/scss/helpers/_colored-links.scss +30 -0
- package/themes/bootstrap/scss/helpers/_focus-ring.scss +5 -0
- package/themes/bootstrap/scss/helpers/_icon-link.scss +25 -0
- package/themes/bootstrap/scss/helpers/_position.scss +36 -0
- package/themes/bootstrap/scss/helpers/_ratio.scss +26 -0
- package/themes/bootstrap/scss/helpers/_stacks.scss +15 -0
- package/themes/bootstrap/scss/helpers/_stretched-link.scss +15 -0
- package/themes/bootstrap/scss/helpers/_text-truncation.scss +7 -0
- package/themes/bootstrap/scss/helpers/_visually-hidden.scss +8 -0
- package/themes/bootstrap/scss/helpers/_vr.scss +8 -0
- package/themes/bootstrap/scss/mixins/_alert.scss +18 -0
- package/themes/bootstrap/scss/mixins/_backdrop.scss +14 -0
- package/themes/bootstrap/scss/mixins/_banner.scss +7 -0
- package/themes/bootstrap/scss/mixins/_border-radius.scss +78 -0
- package/themes/bootstrap/scss/mixins/_box-shadow.scss +18 -0
- package/themes/bootstrap/scss/mixins/_breakpoints.scss +127 -0
- package/themes/bootstrap/scss/mixins/_buttons.scss +70 -0
- package/themes/bootstrap/scss/mixins/_caret.scss +69 -0
- package/themes/bootstrap/scss/mixins/_clearfix.scss +9 -0
- package/themes/bootstrap/scss/mixins/_color-mode.scss +21 -0
- package/themes/bootstrap/scss/mixins/_color-scheme.scss +7 -0
- package/themes/bootstrap/scss/mixins/_container.scss +11 -0
- package/themes/bootstrap/scss/mixins/_deprecate.scss +10 -0
- package/themes/bootstrap/scss/mixins/_forms.scss +163 -0
- package/themes/bootstrap/scss/mixins/_gradients.scss +47 -0
- package/themes/bootstrap/scss/mixins/_grid.scss +151 -0
- package/themes/bootstrap/scss/mixins/_image.scss +16 -0
- package/themes/bootstrap/scss/mixins/_list-group.scss +26 -0
- package/themes/bootstrap/scss/mixins/_lists.scss +7 -0
- package/themes/bootstrap/scss/mixins/_pagination.scss +10 -0
- package/themes/bootstrap/scss/mixins/_reset-text.scss +17 -0
- package/themes/bootstrap/scss/mixins/_resize.scss +6 -0
- package/themes/bootstrap/scss/mixins/_table-variants.scss +24 -0
- package/themes/bootstrap/scss/mixins/_text-truncate.scss +8 -0
- package/themes/bootstrap/scss/mixins/_transition.scss +26 -0
- package/themes/bootstrap/scss/mixins/_utilities.scss +97 -0
- package/themes/bootstrap/scss/mixins/_visually-hidden.scss +38 -0
- package/themes/bootstrap/scss/tests/jasmine.js +16 -0
- package/themes/bootstrap/scss/tests/mixins/_auto-import-of-variables-dark.test.scss +7 -0
- package/themes/bootstrap/scss/tests/mixins/_color-modes.test.scss +69 -0
- package/themes/bootstrap/scss/tests/mixins/_media-query-color-mode-full.test.scss +8 -0
- package/themes/bootstrap/scss/tests/mixins/_utilities.test.scss +393 -0
- package/themes/bootstrap/scss/tests/sass-true/register.js +14 -0
- package/themes/bootstrap/scss/tests/sass-true/runner.js +17 -0
- package/themes/bootstrap/scss/tests/utilities/_api.test.scss +75 -0
- package/themes/bootstrap/scss/utilities/_api.scss +47 -0
- package/themes/bootstrap/scss/vendor/_rfs.scss +348 -0
- package/themes/classy/README.md +89 -0
- package/themes/classy/_config.scss +245 -0
- package/themes/classy/_theme.js +31 -0
- package/themes/classy/_theme.scss +57 -0
- package/themes/classy/css/app/_panels.scss +183 -0
- package/themes/classy/css/base/_fonts.scss +79 -0
- package/themes/classy/css/base/_no-raise.scss +49 -0
- package/themes/classy/css/base/_root.scss +113 -0
- package/themes/classy/css/base/_typography.scss +154 -0
- package/themes/classy/css/base/_utilities.scss +284 -0
- package/themes/classy/css/components/_alerts.scss +51 -0
- package/themes/classy/css/components/_badges.scss +46 -0
- package/themes/classy/css/components/_buttons.scss +175 -0
- package/themes/classy/css/components/_cards.scss +41 -0
- package/themes/classy/css/components/_dropdowns.scss +48 -0
- package/themes/classy/css/components/_forms.scss +171 -0
- package/themes/classy/css/components/_receipt.scss +45 -0
- package/themes/classy/css/layout/_footer.scss +298 -0
- package/themes/classy/css/layout/_general.scss +209 -0
- package/themes/classy/css/layout/_nav.scss +154 -0
- package/themes/classy/css/layout/_shell.scss +458 -0
- package/themes/classy/css/marketing/_bento.scss +238 -0
- package/themes/classy/css/marketing/_content.scss +1328 -0
- package/themes/classy/css/marketing/_downloads.scss +246 -0
- package/themes/classy/css/marketing/_hero.scss +311 -0
- package/themes/classy/css/marketing/_sections.scss +649 -0
- package/themes/classy/css/pages/404/index.scss +67 -0
- package/themes/classy/css/pages/_auth.scss +235 -0
- package/themes/classy/css/pages/admin/firebase/index.scss +22 -0
- package/themes/classy/css/pages/blog/[slug].scss +56 -0
- package/themes/classy/css/pages/cookies.scss +2 -0
- package/themes/classy/css/pages/dashboard/account/index.scss +31 -0
- package/themes/classy/css/pages/feedback/index.scss +39 -0
- package/themes/classy/css/pages/legal/_document.scss +192 -0
- package/themes/classy/css/pages/payment/checkout/index.scss +585 -0
- package/themes/classy/css/pages/payment/confirmation/index.scss +9 -0
- package/themes/classy/css/pages/privacy.scss +2 -0
- package/themes/classy/css/pages/status/index.scss +164 -0
- package/themes/classy/css/pages/terms.scss +2 -0
- package/themes/classy/css/pages/updates/index.scss +128 -0
- package/themes/classy/fonts/inter-italic-latin-ext.woff2 +0 -0
- package/themes/classy/fonts/inter-italic-latin.woff2 +0 -0
- package/themes/classy/fonts/inter-normal-latin-ext.woff2 +0 -0
- package/themes/classy/fonts/inter-normal-latin.woff2 +0 -0
- package/themes/classy/fonts/newsreader-italic-latin-ext.woff2 +0 -0
- package/themes/classy/fonts/newsreader-italic-latin.woff2 +0 -0
- package/themes/classy/fonts/newsreader-normal-latin-ext.woff2 +0 -0
- package/themes/classy/fonts/newsreader-normal-latin.woff2 +0 -0
- package/themes/classy/js/hero-demo-form.js +56 -0
- package/themes/neobrutalism/README.md +118 -0
- package/themes/neobrutalism/_config.scss +139 -0
- package/themes/neobrutalism/_layouts/frontend/core/base.html +30 -0
- package/themes/neobrutalism/_layouts/frontend/pages/index.html +275 -0
- package/themes/neobrutalism/_theme.js +24 -0
- package/themes/neobrutalism/_theme.scss +61 -0
- package/themes/neobrutalism/css/base/_mixins.scss +46 -0
- package/themes/neobrutalism/css/base/_root.scss +169 -0
- package/themes/neobrutalism/css/base/_typography.scss +61 -0
- package/themes/neobrutalism/css/base/_utilities.scss +89 -0
- package/themes/neobrutalism/css/components/_billing-toggle.scss +74 -0
- package/themes/neobrutalism/css/components/_buttons.scss +148 -0
- package/themes/neobrutalism/css/components/_cards.scss +47 -0
- package/themes/neobrutalism/css/components/_forms.scss +88 -0
- package/themes/neobrutalism/css/components/_marketing.scss +244 -0
- package/themes/neobrutalism/css/layout/_general.scss +213 -0
- package/themes/neobrutalism/css/layout/_navigation.scss +171 -0
- package/themes/neobrutalism/css/pages/index.scss +203 -0
- package/themes/neobrutalism/css/pages/pricing/index.scss +58 -0
- package/themes/neobrutalism/css/pages/test/libraries/layers/index.scss +7 -0
- package/themes/neobrutalism/js/pages/test/libraries/layers/index.js +9 -0
- package/themes/newsflash/README.md +117 -0
- package/themes/newsflash/_components/heading/lede/component.html +14 -0
- package/themes/newsflash/_components/heading/lede/component.json5 +23 -0
- package/themes/newsflash/_components/heading/rule-head/component.html +17 -0
- package/themes/newsflash/_components/heading/rule-head/component.json5 +23 -0
- package/themes/newsflash/_components/news/byline/component.html +12 -0
- package/themes/newsflash/_components/news/byline/component.json5 +18 -0
- package/themes/newsflash/_components/news/story-card/component.html +25 -0
- package/themes/newsflash/_components/news/story-card/component.json5 +21 -0
- package/themes/newsflash/_config.scss +147 -0
- package/themes/newsflash/_layouts/frontend/core/base.html +51 -0
- package/themes/newsflash/_layouts/frontend/pages/blog/index.html +299 -0
- package/themes/newsflash/_layouts/frontend/pages/blog/post.html +235 -0
- package/themes/newsflash/_layouts/frontend/pages/index.html +328 -0
- package/themes/newsflash/_sections/marketing/desks/section.html +39 -0
- package/themes/newsflash/_sections/marketing/desks/section.json5 +49 -0
- package/themes/newsflash/_sections/marketing/newsletter-cta/section.html +103 -0
- package/themes/newsflash/_sections/marketing/newsletter-cta/section.json5 +50 -0
- package/themes/newsflash/_sections/marketing/rundown/section.html +28 -0
- package/themes/newsflash/_sections/marketing/rundown/section.json5 +40 -0
- package/themes/newsflash/_theme.js +24 -0
- package/themes/newsflash/_theme.scss +70 -0
- package/themes/newsflash/css/base/_fonts.scss +80 -0
- package/themes/newsflash/css/base/_mixins.scss +51 -0
- package/themes/newsflash/css/base/_root.scss +257 -0
- package/themes/newsflash/css/base/_typography.scss +49 -0
- package/themes/newsflash/css/base/_utilities.scss +122 -0
- package/themes/newsflash/css/components/_badges.scss +65 -0
- package/themes/newsflash/css/components/_billing-toggle.scss +61 -0
- package/themes/newsflash/css/components/_buttons.scss +139 -0
- package/themes/newsflash/css/components/_cards.scss +47 -0
- package/themes/newsflash/css/components/_editorial.scss +173 -0
- package/themes/newsflash/css/components/_forms.scss +75 -0
- package/themes/newsflash/css/components/_infinite-scroll.scss +102 -0
- package/themes/newsflash/css/components/_panels.scss +156 -0
- package/themes/newsflash/css/components/_ticker.scss +67 -0
- package/themes/newsflash/css/layout/_general.scss +330 -0
- package/themes/newsflash/css/layout/_navigation.scss +168 -0
- package/themes/newsflash/css/pages/404/index.scss +79 -0
- package/themes/newsflash/css/pages/blog/[slug].scss +186 -0
- package/themes/newsflash/css/pages/blog/index.scss +17 -0
- package/themes/newsflash/css/pages/index.scss +157 -0
- package/themes/newsflash/css/pages/pricing/index.scss +55 -0
- package/themes/newsflash/css/pages/test/libraries/layers/index.scss +7 -0
- package/themes/newsflash/fonts/fraunces-italic-latin-ext.woff2 +0 -0
- package/themes/newsflash/fonts/fraunces-italic-latin.woff2 +0 -0
- package/themes/newsflash/fonts/fraunces-normal-latin-ext.woff2 +0 -0
- package/themes/newsflash/fonts/fraunces-normal-latin.woff2 +0 -0
- package/themes/newsflash/fonts/schibsted-grotesk-italic-latin-ext.woff2 +0 -0
- package/themes/newsflash/fonts/schibsted-grotesk-italic-latin.woff2 +0 -0
- package/themes/newsflash/fonts/schibsted-grotesk-normal-latin-ext.woff2 +0 -0
- package/themes/newsflash/fonts/schibsted-grotesk-normal-latin.woff2 +0 -0
- package/themes/newsflash/js/pages/blog/[slug].js +29 -0
- package/themes/newsflash/js/pages/test/libraries/layers/index.js +9 -0
- package/translations/es/pages/404.json +86 -0
- package/translations/es/pages/account.json +36 -0
- package/translations/es/pages/app.json +44 -0
- package/translations/es/pages/cancel.json +36 -0
- package/translations/es/pages/change-password.json +36 -0
- package/translations/es/pages/connections/callback.json +41 -0
- package/translations/es/pages/dashboard/account.json +475 -0
- package/translations/es/pages/dashboard.json +36 -0
- package/translations/es/pages/forgot.json +36 -0
- package/translations/es/pages/join.json +36 -0
- package/translations/es/pages/login.json +36 -0
- package/translations/es/pages/payment/checkout.json +83 -0
- package/translations/es/pages/payment/confirmation.json +62 -0
- package/translations/es/pages/portal/email-preferences.json +46 -0
- package/translations/es/pages/recover.json +36 -0
- package/translations/es/pages/refund.json +36 -0
- package/translations/es/pages/register.json +36 -0
- package/translations/es/pages/reset-password.json +36 -0
- package/translations/es/pages/reset.json +42 -0
- package/translations/es/pages/signin.json +45 -0
- package/translations/es/pages/signup.json +60 -0
- package/translations/es/pages/token.json +39 -0
- package/translations/fa/pages/404.json +86 -0
- package/translations/fa/pages/account.json +36 -0
- package/translations/fa/pages/app.json +44 -0
- package/translations/fa/pages/cancel.json +36 -0
- package/translations/fa/pages/change-password.json +36 -0
- package/translations/fa/pages/connections/callback.json +41 -0
- package/translations/fa/pages/dashboard/account.json +475 -0
- package/translations/fa/pages/dashboard.json +36 -0
- package/translations/fa/pages/forgot.json +36 -0
- package/translations/fa/pages/join.json +36 -0
- package/translations/fa/pages/login.json +36 -0
- package/translations/fa/pages/payment/checkout.json +83 -0
- package/translations/fa/pages/payment/confirmation.json +62 -0
- package/translations/fa/pages/portal/email-preferences.json +46 -0
- package/translations/fa/pages/recover.json +36 -0
- package/translations/fa/pages/refund.json +36 -0
- package/translations/fa/pages/register.json +36 -0
- package/translations/fa/pages/reset-password.json +36 -0
- package/translations/fa/pages/reset.json +42 -0
- package/translations/fa/pages/signin.json +45 -0
- package/translations/fa/pages/signup.json +60 -0
- package/translations/fa/pages/token.json +39 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-host Firebase's OAuth helper files into the built site: /__/auth/*
|
|
3
|
+
* plus /__/firebase/init.json, fetched from {projectId}.firebaseapp.com at
|
|
4
|
+
* production build time (UJM fetchFirebaseAuth parity). This is what lets
|
|
5
|
+
* authDomain be the BRAND host on static hosting with no proxy (GitHub
|
|
6
|
+
* Pages): the sign-in redirect stays first-party — which keeps
|
|
7
|
+
* signInWithRedirect working under browser storage partitioning — and
|
|
8
|
+
* /__/auth/handler resolves on the site domain instead of 404ing.
|
|
9
|
+
*
|
|
10
|
+
* Skips (logged, not fatal): no cloud.config.projectId, a demo-* project
|
|
11
|
+
* (offline fixtures), or OMEGA_SKIP_FIREBASE_AUTH=true.
|
|
12
|
+
*
|
|
13
|
+
* The fetch is WRITE-THROUGH to the brand's persistent cache (#548): a
|
|
14
|
+
* failure serves the last good copy with a loud, dated warn instead of
|
|
15
|
+
* failing a build that already emitted every page — offline, sandboxed and
|
|
16
|
+
* rate-limited builds all survive on it. A failure with NOTHING cached is
|
|
17
|
+
* still fatal, because a site shipped without the handler silently breaks
|
|
18
|
+
* sign-in and there is nothing to serve. A framework-baked copy cannot exist:
|
|
19
|
+
* /__/firebase/init.json is project-specific, so the cache is keyed by
|
|
20
|
+
* project id.
|
|
21
|
+
*/
|
|
22
|
+
const crypto = require('node:crypto');
|
|
23
|
+
const path = require('node:path');
|
|
24
|
+
const jetpack = require('fs-jetpack');
|
|
25
|
+
|
|
26
|
+
// The two PAGE files land as .html and their extensionless names are never
|
|
27
|
+
// emitted: GitHub Pages serves a literal extensionless FILE as
|
|
28
|
+
// application/octet-stream (found live on omegajs.dev, #135) — the browser
|
|
29
|
+
// downloads the sign-in page instead of rendering it. The extensionless URL
|
|
30
|
+
// Firebase redirects to (/__/auth/handler) resolves to handler.html via
|
|
31
|
+
// Pages' clean-URL fallback, which only applies when no literal file exists.
|
|
32
|
+
// The iframe page references iframe.js relatively; the ?cb= rewrite busts
|
|
33
|
+
// the long-lived edge cache (the scaffolded Cloudflare cache rule pins
|
|
34
|
+
// /__/auth/iframe.js for a year). The breaker is a HASH of the fetched
|
|
35
|
+
// iframe.js content — it changes exactly when Firebase ships a new helper,
|
|
36
|
+
// and stays stable (cache-friendly, idempotent builds) when they don't.
|
|
37
|
+
const HELPER_FILES = [
|
|
38
|
+
{ remote: '__/auth/handler', local: '__/auth/handler.html' },
|
|
39
|
+
{ remote: '__/auth/handler.js' },
|
|
40
|
+
{ remote: '__/auth/experiments.js' },
|
|
41
|
+
{ remote: '__/auth/iframe', local: '__/auth/iframe.html' },
|
|
42
|
+
{ remote: '__/auth/iframe.js' },
|
|
43
|
+
{ remote: '__/firebase/init.json' },
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
// The cache's own file: the six helpers land under the cache root at their
|
|
47
|
+
// remote paths, and this stamps WHEN they were fetched (the staleness the
|
|
48
|
+
// fallback warn names).
|
|
49
|
+
const CACHE_META = 'fetched.json';
|
|
50
|
+
|
|
51
|
+
const IFRAME_PAGE = '__/auth/iframe';
|
|
52
|
+
const IFRAME_SCRIPT = '__/auth/iframe.js';
|
|
53
|
+
const IFRAME_SRC_MARKER = 'src="iframe.js"';
|
|
54
|
+
|
|
55
|
+
const TRIES = 3;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Fetch one helper file with retries.
|
|
59
|
+
* @param {string} url
|
|
60
|
+
* @returns {Promise<string>}
|
|
61
|
+
*/
|
|
62
|
+
async function fetchText(url) {
|
|
63
|
+
let lastError;
|
|
64
|
+
for (let attempt = 1; attempt <= TRIES; attempt++) {
|
|
65
|
+
try {
|
|
66
|
+
const response = await fetch(url);
|
|
67
|
+
if (!response.ok) {
|
|
68
|
+
const error = new Error(`HTTP ${response.status}`);
|
|
69
|
+
// A 4xx from the static helper host is not transient (wrong project
|
|
70
|
+
// id, helper path gone) — fail fast; retry only network errors + 5xx.
|
|
71
|
+
error.permanent = response.status >= 400 && response.status < 500;
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
return await response.text();
|
|
75
|
+
} catch (error) {
|
|
76
|
+
lastError = error;
|
|
77
|
+
if (error.permanent) {
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
throw new Error(`Failed to fetch Firebase auth helper ${url}: ${lastError.message}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Read a complete cached helper set. A PARTIAL cache is no cache — a build
|
|
87
|
+
* shipped from half a helper set breaks sign-in the same way an empty one
|
|
88
|
+
* does, so the miss falls through to the fetch error.
|
|
89
|
+
* @param {string} cacheRoot - per-project cache dir
|
|
90
|
+
* @returns {{ contents: Map<string, string>, fetchedAt: string }|null}
|
|
91
|
+
*/
|
|
92
|
+
function readCache(cacheRoot) {
|
|
93
|
+
const meta = jetpack.read(path.join(cacheRoot, CACHE_META), 'json');
|
|
94
|
+
if (!meta || !meta.fetchedAt) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const contents = new Map();
|
|
99
|
+
for (const file of HELPER_FILES) {
|
|
100
|
+
const content = jetpack.read(path.join(cacheRoot, file.remote));
|
|
101
|
+
if (content === undefined) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
contents.set(file.remote, content);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return { contents, fetchedAt: meta.fetchedAt };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Write the freshly fetched helper set through to the cache (the RAW fetched
|
|
112
|
+
* bytes — the iframe rewrite is derived from them on every build, so a cached
|
|
113
|
+
* build emits the same file the fetched one did).
|
|
114
|
+
* @param {string} cacheRoot - per-project cache dir
|
|
115
|
+
* @param {Map<string, string>} contents - remote path → content
|
|
116
|
+
*/
|
|
117
|
+
function writeCache(cacheRoot, contents) {
|
|
118
|
+
for (const file of HELPER_FILES) {
|
|
119
|
+
jetpack.write(path.join(cacheRoot, file.remote), contents.get(file.remote));
|
|
120
|
+
}
|
|
121
|
+
jetpack.write(path.join(cacheRoot, CACHE_META), { fetchedAt: new Date().toISOString() });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Fetch the Firebase auth helper files into the built site.
|
|
126
|
+
* @param {object} options
|
|
127
|
+
* @param {object} options.siteData - resolved omega config shape (reads cloud.config.projectId)
|
|
128
|
+
* @param {string} options.outDir - built-site output dir
|
|
129
|
+
* @param {object} options.logger - devkit logger
|
|
130
|
+
* @param {string} [options.baseUrl] - source origin override (tests serve the fixture files locally)
|
|
131
|
+
* @param {string} [options.cacheDir] - persistent cache root (the brand's .omega/cache/firebase-auth)
|
|
132
|
+
* @returns {Promise<{ skipped: string|false, cached?: boolean }>}
|
|
133
|
+
*/
|
|
134
|
+
async function fetchFirebaseAuthHelpers(options) {
|
|
135
|
+
const { siteData, outDir, logger } = options;
|
|
136
|
+
const projectId = siteData.cloud && siteData.cloud.config && siteData.cloud.config.projectId;
|
|
137
|
+
|
|
138
|
+
if (process.env.OMEGA_SKIP_FIREBASE_AUTH === 'true') {
|
|
139
|
+
logger.warn('firebase-auth: skipped via OMEGA_SKIP_FIREBASE_AUTH — sign-in redirects will 404 on this build');
|
|
140
|
+
return { skipped: 'env' };
|
|
141
|
+
}
|
|
142
|
+
if (!projectId) {
|
|
143
|
+
logger.log('firebase-auth: no cloud.config.projectId — helper files skipped');
|
|
144
|
+
return { skipped: 'no-project' };
|
|
145
|
+
}
|
|
146
|
+
if (projectId.startsWith('demo-')) {
|
|
147
|
+
logger.log(`firebase-auth: offline project ${projectId} — helper files skipped`);
|
|
148
|
+
return { skipped: 'demo-project' };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const base = options.baseUrl || `https://${projectId}.firebaseapp.com`;
|
|
152
|
+
// init.json is project-specific, so one cache per project id
|
|
153
|
+
const cacheRoot = options.cacheDir ? path.join(options.cacheDir, projectId) : null;
|
|
154
|
+
|
|
155
|
+
// Fetch everything first — the iframe rewrite needs iframe.js' content
|
|
156
|
+
let contents;
|
|
157
|
+
let cached = false;
|
|
158
|
+
try {
|
|
159
|
+
contents = new Map(await Promise.all(HELPER_FILES.map(async (file) => {
|
|
160
|
+
const content = await fetchText(`${base}/${file.remote}`);
|
|
161
|
+
return [file.remote, content];
|
|
162
|
+
})));
|
|
163
|
+
if (cacheRoot) {
|
|
164
|
+
writeCache(cacheRoot, contents);
|
|
165
|
+
}
|
|
166
|
+
} catch (error) {
|
|
167
|
+
// Nothing cached = nothing to serve: a site without the handler breaks
|
|
168
|
+
// sign-in silently, so the build still fails loudly.
|
|
169
|
+
const fallback = cacheRoot && readCache(cacheRoot);
|
|
170
|
+
if (!fallback) {
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const age = Math.floor((Date.now() - Date.parse(fallback.fetchedAt)) / 86400000);
|
|
175
|
+
logger.warn(`firebase-auth: fetch from ${base} failed (${error.message}) — serving the CACHED helper files fetched ${fallback.fetchedAt} (${age} day(s) old); rerun online to refresh them`);
|
|
176
|
+
contents = fallback.contents;
|
|
177
|
+
cached = true;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const scriptHash = crypto.createHash('md5').update(contents.get(IFRAME_SCRIPT)).digest('hex').slice(0, 8);
|
|
181
|
+
const iframePage = contents.get(IFRAME_PAGE);
|
|
182
|
+
if (iframePage.includes(IFRAME_SRC_MARKER)) {
|
|
183
|
+
contents.set(IFRAME_PAGE, iframePage.replace(IFRAME_SRC_MARKER, `src="iframe.js?cb=${scriptHash}"`));
|
|
184
|
+
} else {
|
|
185
|
+
// Firebase changed the iframe markup — the year-long edge cache on
|
|
186
|
+
// iframe.js can now serve a stale script against a new handler.
|
|
187
|
+
logger.warn(`firebase-auth: ${IFRAME_SRC_MARKER} not found in ${IFRAME_PAGE} — cache breaker NOT applied; check Firebase's helper markup`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
for (const file of HELPER_FILES) {
|
|
191
|
+
jetpack.write(path.join(outDir, file.local || file.remote), contents.get(file.remote));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
logger.log(`firebase-auth: self-hosted ${HELPER_FILES.length} helper files from ${cached ? 'the local cache' : `${projectId}.firebaseapp.com`} → /__/`);
|
|
195
|
+
return { skipped: false, cached };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
module.exports = { fetchFirebaseAuthHelpers, HELPER_FILES };
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The font metric reader (#768): the five numbers a metric-matched fallback
|
|
3
|
+
* face is built from, read straight out of a font FILE.
|
|
4
|
+
*
|
|
5
|
+
* unitsPerEm, ascent, descent, lineGap, avgCharWidth
|
|
6
|
+
*
|
|
7
|
+
* It reads a WOFF2 (what every theme vendors) and a bare sfnt / collection
|
|
8
|
+
* (what a system family on the build machine is) with NO dependency: a WOFF2
|
|
9
|
+
* is a header, a table directory, then ONE brotli stream holding the tables in
|
|
10
|
+
* directory order, so node's own `zlib.brotliDecompressSync` plus the
|
|
11
|
+
* directory parse below reaches every table exactly. Nothing here decodes a
|
|
12
|
+
* glyph OUTLINE, only `head`, `hhea`, `OS/2`, `cmap` and the advance widths
|
|
13
|
+
* in `hmtx`, which is why one file covers what a font library would.
|
|
14
|
+
*
|
|
15
|
+
* Which ascent/descent: `OS/2`'s sTypo* values when the face sets fsSelection
|
|
16
|
+
* bit 7 (USE_TYPO_METRICS), the bit whose whole meaning is "use these", else
|
|
17
|
+
* `hhea`'s. That is what a browser does, so the overrides computed from these
|
|
18
|
+
* numbers describe the box the browser will actually lay out.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
// Libraries
|
|
22
|
+
const zlib = require('node:zlib');
|
|
23
|
+
const fs = require('fs-jetpack');
|
|
24
|
+
|
|
25
|
+
// Signatures. A WOFF2 is 'wOF2'; a bare sfnt is 1.0 (TrueType outlines),
|
|
26
|
+
// 'OTTO' (CFF outlines) or the old Apple 'true'; a collection is 'ttcf'.
|
|
27
|
+
const WOFF2 = 0x774f4632;
|
|
28
|
+
const TTCF = 0x74746366;
|
|
29
|
+
const SFNT = new Set([0x00010000, 0x4f54544f, 0x74727565]);
|
|
30
|
+
|
|
31
|
+
const WOFF2_HEADER_BYTES = 48;
|
|
32
|
+
const SFNT_RECORD_BYTES = 16;
|
|
33
|
+
|
|
34
|
+
// The WOFF2 known-tag table (spec § 5.2, Table 4), in ITS order: a directory
|
|
35
|
+
// entry's low 6 bits index it. The one index that is not a lookup is 63: it
|
|
36
|
+
// means the table does not name this tag, and the 4 bytes follow inline.
|
|
37
|
+
const CUSTOM_TAG = 0x3f;
|
|
38
|
+
const KNOWN_TAGS = [
|
|
39
|
+
'cmap', 'head', 'hhea', 'hmtx', 'maxp', 'name', 'OS/2', 'post',
|
|
40
|
+
'cvt ', 'fpgm', 'glyf', 'loca', 'prep', 'CFF ', 'VORG', 'EBDT',
|
|
41
|
+
'EBLC', 'gasp', 'hdmx', 'kern', 'LTSH', 'PCLT', 'VDMX', 'vhea',
|
|
42
|
+
'vmtx', 'BASE', 'GDEF', 'GPOS', 'GSUB', 'EBSC', 'JSTF', 'MATH',
|
|
43
|
+
'CBDT', 'CBLC', 'COLR', 'CPAL', 'SVG ', 'sbix', 'acnt', 'avar',
|
|
44
|
+
'bdat', 'bloc', 'bsln', 'cvar', 'fdsc', 'feat', 'fmtx', 'fvar',
|
|
45
|
+
'gvar', 'hsty', 'just', 'lcar', 'ltag', 'morx', 'mort', 'opbd',
|
|
46
|
+
'prop', 'trak', 'Zapf', 'Silf', 'Glat', 'Gloc', 'Feat', 'Sill',
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
// Table field offsets, for the tables this reader reads fields from, by their spec
|
|
50
|
+
// layouts (head § 5.2.2, hhea § 5.2.3, OS/2 § 5.2.4 of the OpenType spec).
|
|
51
|
+
const HEAD_UNITS_PER_EM = 18;
|
|
52
|
+
const HHEA_ASCENDER = 4;
|
|
53
|
+
const HHEA_NUM_H_METRICS = 34;
|
|
54
|
+
const OS2_FS_SELECTION = 62;
|
|
55
|
+
const OS2_TYPO_ASCENDER = 68;
|
|
56
|
+
const OS2_MIN_BYTES = 78;
|
|
57
|
+
const USE_TYPO_METRICS = 0x80; // fsSelection bit 7
|
|
58
|
+
const CMAP_PLATFORM_UNICODE = 0;
|
|
59
|
+
const CMAP_PLATFORM_WINDOWS = 3;
|
|
60
|
+
|
|
61
|
+
// The width sample: ordinary English prose, MEASURED per font as the mean
|
|
62
|
+
// advance over its characters. It is the honest way to ask the one question
|
|
63
|
+
// size-adjust answers: "how much wider does this family set the same text?"
|
|
64
|
+
//
|
|
65
|
+
// OS/2's own xAvgCharWidth is NOT that number and cannot be compared across
|
|
66
|
+
// families. The spec redefined it (version 0-1: an English-weighted average of
|
|
67
|
+
// the lowercase letters; version 3+: the arithmetic mean of every non-zero
|
|
68
|
+
// advance), and a vendor restating the table version does not restate the
|
|
69
|
+
// value: Arial's file says version 3 and still carries 904, its 1990s
|
|
70
|
+
// lowercase figure, while its measured mean advance over this sample is 891.
|
|
71
|
+
// So a ratio of two xAvgCharWidth fields compares two different quantities:
|
|
72
|
+
// off OS/2, classy's Newsreader fallback would size-adjust to 123.5% of
|
|
73
|
+
// Georgia when the text it sets measures 91.2% of Georgia's width, and Inter's
|
|
74
|
+
// would be 145.0% of Arial instead of 106.9%. Measuring both sides here keeps
|
|
75
|
+
// ONE definition on both ends of every ratio.
|
|
76
|
+
const WIDTH_SAMPLE = 'the sun rose over the quiet harbor, and a small boat set out with the morning tide';
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @typedef {object} FontMetrics
|
|
80
|
+
* @property {number} unitsPerEm - the em square, every other value's unit
|
|
81
|
+
* @property {number} ascent - above the baseline, positive
|
|
82
|
+
* @property {number} descent - below it, NEGATIVE (as the font stores it)
|
|
83
|
+
* @property {number} lineGap - the leading between two lines
|
|
84
|
+
* @property {number} avgCharWidth - the mean advance over WIDTH_SAMPLE, what size-adjust matches on
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Read one font's metrics.
|
|
89
|
+
* @param {Buffer} buffer - a WOFF2, sfnt (ttf/otf) or collection file
|
|
90
|
+
* @param {number} [fontIndex] - which font of a collection (default the first)
|
|
91
|
+
* @returns {FontMetrics}
|
|
92
|
+
*/
|
|
93
|
+
function readFontMetrics(buffer, fontIndex = 0) {
|
|
94
|
+
const { tables, transformed } = readTables(buffer, fontIndex);
|
|
95
|
+
const head = tables.get('head');
|
|
96
|
+
const hhea = tables.get('hhea');
|
|
97
|
+
const os2 = tables.get('OS/2');
|
|
98
|
+
if (!head || head.length < HEAD_UNITS_PER_EM + 2) throw new Error('font file: no readable head table');
|
|
99
|
+
if (!hhea || hhea.length < HHEA_ASCENDER + 6) throw new Error('font file: no readable hhea table');
|
|
100
|
+
if (!os2 || os2.length < OS2_MIN_BYTES) throw new Error('font file: no readable OS/2 table');
|
|
101
|
+
|
|
102
|
+
const typo = (os2.readUInt16BE(OS2_FS_SELECTION) & USE_TYPO_METRICS) !== 0;
|
|
103
|
+
const vertical = typo ? os2 : hhea;
|
|
104
|
+
const at = typo ? OS2_TYPO_ASCENDER : HHEA_ASCENDER;
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
unitsPerEm: head.readUInt16BE(HEAD_UNITS_PER_EM),
|
|
108
|
+
ascent: vertical.readInt16BE(at),
|
|
109
|
+
descent: vertical.readInt16BE(at + 2),
|
|
110
|
+
lineGap: vertical.readInt16BE(at + 4),
|
|
111
|
+
avgCharWidth: averageCharWidth(tables, transformed, hhea),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The mean advance width over WIDTH_SAMPLE, in font units: `cmap` maps each
|
|
117
|
+
* character to its glyph, `hmtx` carries that glyph's advance. A character the
|
|
118
|
+
* face does not cover is left out of the mean rather than counted as zero.
|
|
119
|
+
* @param {Map<string, Buffer>} tables - the font's tables
|
|
120
|
+
* @param {Set<string>} transformed - the tags stored in a WOFF2 transform
|
|
121
|
+
* @param {Buffer} hhea - the hhea table (it names how many advances hmtx holds)
|
|
122
|
+
* @returns {number}
|
|
123
|
+
*/
|
|
124
|
+
function averageCharWidth(tables, transformed, hhea) {
|
|
125
|
+
const cmap = tables.get('cmap');
|
|
126
|
+
const hmtx = tables.get('hmtx');
|
|
127
|
+
if (!cmap || !hmtx) throw new Error('font file: no readable cmap/hmtx tables');
|
|
128
|
+
|
|
129
|
+
const glyphOf = characterMap(cmap);
|
|
130
|
+
const advanceOf = advanceReader(hmtx, hhea.readUInt16BE(HHEA_NUM_H_METRICS), transformed.has('hmtx'));
|
|
131
|
+
let total = 0;
|
|
132
|
+
let counted = 0;
|
|
133
|
+
for (const character of WIDTH_SAMPLE) {
|
|
134
|
+
const glyph = glyphOf(character.codePointAt(0));
|
|
135
|
+
if (glyph === 0) continue;
|
|
136
|
+
|
|
137
|
+
total += advanceOf(glyph);
|
|
138
|
+
counted += 1;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (counted === 0) throw new Error('font file: covers none of the width sample');
|
|
142
|
+
|
|
143
|
+
return total / counted;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* A glyph's advance width. A `hmtx` stored in a WOFF2 transform drops the left
|
|
148
|
+
* side bearings but keeps every advance, behind one flags byte, and those
|
|
149
|
+
* advances are the whole reason this reader opens the table. The last advance covers
|
|
150
|
+
* every glyph past `numberOfHMetrics` (a monospaced tail).
|
|
151
|
+
* @param {Buffer} hmtx - the hmtx table
|
|
152
|
+
* @param {number} numberOfHMetrics - hhea's count of full metric records
|
|
153
|
+
* @param {boolean} transformed - is this the WOFF2 transformed form?
|
|
154
|
+
* @returns {function(number): number}
|
|
155
|
+
*/
|
|
156
|
+
function advanceReader(hmtx, numberOfHMetrics, transformed) {
|
|
157
|
+
return (glyph) => {
|
|
158
|
+
const index = Math.min(glyph, numberOfHMetrics - 1);
|
|
159
|
+
const at = transformed ? 1 + index * 2 : index * 4;
|
|
160
|
+
if (at + 2 > hmtx.length) throw new Error('font file: truncated hmtx table');
|
|
161
|
+
|
|
162
|
+
return hmtx.readUInt16BE(at);
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* A codepoint → glyph id lookup over the font's best unicode `cmap` subtable:
|
|
168
|
+
* format 12 (full unicode) when the face ships one, else format 4 (the BMP
|
|
169
|
+
* form every latin face carries). 0 means "not covered" in both.
|
|
170
|
+
* @param {Buffer} cmap - the cmap table
|
|
171
|
+
* @returns {function(number): number}
|
|
172
|
+
*/
|
|
173
|
+
function characterMap(cmap) {
|
|
174
|
+
let best = null;
|
|
175
|
+
const count = cmap.readUInt16BE(2);
|
|
176
|
+
for (let i = 0; i < count; i += 1) {
|
|
177
|
+
const platform = cmap.readUInt16BE(4 + i * 8);
|
|
178
|
+
const offset = cmap.readUInt32BE(8 + i * 8);
|
|
179
|
+
if (platform !== CMAP_PLATFORM_UNICODE && platform !== CMAP_PLATFORM_WINDOWS) continue;
|
|
180
|
+
|
|
181
|
+
const format = cmap.readUInt16BE(offset);
|
|
182
|
+
if (format !== 4 && format !== 12) continue;
|
|
183
|
+
if (!best || format > best.format) best = { offset, format };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (!best) throw new Error('font file: no unicode cmap subtable');
|
|
187
|
+
|
|
188
|
+
return best.format === 12 ? segmentedCoverage(cmap, best.offset) : segmentMapping(cmap, best.offset);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* cmap format 4: parallel arrays of segments, each mapping a codepoint range
|
|
193
|
+
* either by a delta or through the glyph id array that follows.
|
|
194
|
+
* @param {Buffer} cmap - the cmap table
|
|
195
|
+
* @param {number} offset - the subtable's offset
|
|
196
|
+
* @returns {function(number): number}
|
|
197
|
+
*/
|
|
198
|
+
function segmentMapping(cmap, offset) {
|
|
199
|
+
const segments = cmap.readUInt16BE(offset + 6) / 2;
|
|
200
|
+
const ends = offset + 14;
|
|
201
|
+
const starts = ends + segments * 2 + 2;
|
|
202
|
+
const deltas = starts + segments * 2;
|
|
203
|
+
const ranges = deltas + segments * 2;
|
|
204
|
+
|
|
205
|
+
return (codepoint) => {
|
|
206
|
+
if (codepoint > 0xffff) return 0;
|
|
207
|
+
|
|
208
|
+
for (let i = 0; i < segments; i += 1) {
|
|
209
|
+
if (codepoint > cmap.readUInt16BE(ends + i * 2)) continue;
|
|
210
|
+
if (codepoint < cmap.readUInt16BE(starts + i * 2)) return 0;
|
|
211
|
+
|
|
212
|
+
const delta = cmap.readInt16BE(deltas + i * 2);
|
|
213
|
+
const range = cmap.readUInt16BE(ranges + i * 2);
|
|
214
|
+
if (range === 0) return (codepoint + delta) & 0xffff;
|
|
215
|
+
|
|
216
|
+
const glyph = cmap.readUInt16BE(ranges + i * 2 + range + (codepoint - cmap.readUInt16BE(starts + i * 2)) * 2);
|
|
217
|
+
|
|
218
|
+
return glyph === 0 ? 0 : (glyph + delta) & 0xffff;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return 0;
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* cmap format 12: groups of contiguous codepoints, each naming the glyph its
|
|
227
|
+
* first codepoint maps to.
|
|
228
|
+
* @param {Buffer} cmap - the cmap table
|
|
229
|
+
* @param {number} offset - the subtable's offset
|
|
230
|
+
* @returns {function(number): number}
|
|
231
|
+
*/
|
|
232
|
+
function segmentedCoverage(cmap, offset) {
|
|
233
|
+
const groups = cmap.readUInt32BE(offset + 12);
|
|
234
|
+
|
|
235
|
+
return (codepoint) => {
|
|
236
|
+
for (let i = 0; i < groups; i += 1) {
|
|
237
|
+
const group = offset + 16 + i * 12;
|
|
238
|
+
const start = cmap.readUInt32BE(group);
|
|
239
|
+
if (codepoint < start) return 0;
|
|
240
|
+
if (codepoint > cmap.readUInt32BE(group + 4)) continue;
|
|
241
|
+
|
|
242
|
+
return cmap.readUInt32BE(group + 8) + (codepoint - start);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return 0;
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Read one font file's metrics from disk.
|
|
251
|
+
* @param {string} file - path to a WOFF2 / sfnt / collection
|
|
252
|
+
* @param {number} [fontIndex] - which font of a collection
|
|
253
|
+
* @returns {FontMetrics}
|
|
254
|
+
*/
|
|
255
|
+
function readFontMetricsFile(file, fontIndex = 0) {
|
|
256
|
+
const buffer = fs.read(file, 'buffer');
|
|
257
|
+
if (!buffer) throw new Error(`font file: ${file} does not exist`);
|
|
258
|
+
|
|
259
|
+
return readFontMetrics(buffer, fontIndex);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* The tables of a font file, by tag, and which of them are stored in a WOFF2
|
|
264
|
+
* transform (a transformed table's bytes are not its sfnt bytes). WOFF2
|
|
265
|
+
* decompresses; sfnt and collections are sliced in place.
|
|
266
|
+
* @param {Buffer} buffer - the file
|
|
267
|
+
* @param {number} fontIndex - which font of a collection
|
|
268
|
+
* @returns {{tables: Map<string, Buffer>, transformed: Set<string>}}
|
|
269
|
+
*/
|
|
270
|
+
function readTables(buffer, fontIndex) {
|
|
271
|
+
if (!Buffer.isBuffer(buffer) || buffer.length < WOFF2_HEADER_BYTES) {
|
|
272
|
+
throw new Error('font file: truncated, too short to hold a font header');
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const signature = buffer.readUInt32BE(0);
|
|
276
|
+
if (signature === WOFF2) return woff2Tables(buffer);
|
|
277
|
+
if (signature === TTCF) return sfntTables(buffer, buffer.readUInt32BE(12 + fontIndex * 4));
|
|
278
|
+
if (SFNT.has(signature)) return sfntTables(buffer, 0);
|
|
279
|
+
|
|
280
|
+
throw new Error(`font file: unrecognized signature 0x${signature.toString(16)}: not a woff2, sfnt or collection`);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* The tables of a bare sfnt: an offset table, then 16-byte records naming a
|
|
285
|
+
* tag and an absolute slice of the file (absolute even inside a collection,
|
|
286
|
+
* which is what makes a collection a list of offset tables and nothing more).
|
|
287
|
+
* @param {Buffer} buffer - the file
|
|
288
|
+
* @param {number} offset - where this font's offset table starts
|
|
289
|
+
* @returns {{tables: Map<string, Buffer>, transformed: Set<string>}}
|
|
290
|
+
*/
|
|
291
|
+
function sfntTables(buffer, offset) {
|
|
292
|
+
const numTables = buffer.readUInt16BE(offset + 4);
|
|
293
|
+
const tables = new Map();
|
|
294
|
+
for (let i = 0; i < numTables; i += 1) {
|
|
295
|
+
const record = offset + 12 + i * SFNT_RECORD_BYTES;
|
|
296
|
+
if (record + SFNT_RECORD_BYTES > buffer.length) throw new Error('font file: truncated table directory');
|
|
297
|
+
|
|
298
|
+
const tag = buffer.toString('latin1', record, record + 4);
|
|
299
|
+
const start = buffer.readUInt32BE(record + 8);
|
|
300
|
+
const length = buffer.readUInt32BE(record + 12);
|
|
301
|
+
if (start + length <= buffer.length) tables.set(tag, buffer.subarray(start, start + length));
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return { tables, transformed: new Set() };
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* The tables of a WOFF2: the directory names each table and its length, and
|
|
309
|
+
* ONE brotli stream holds their bytes end to end in directory order.
|
|
310
|
+
* @param {Buffer} buffer - the file
|
|
311
|
+
* @returns {{tables: Map<string, Buffer>, transformed: Set<string>}}
|
|
312
|
+
*/
|
|
313
|
+
function woff2Tables(buffer) {
|
|
314
|
+
if (buffer.readUInt32BE(4) === TTCF) throw new Error('font file: WOFF2 collections are not supported');
|
|
315
|
+
|
|
316
|
+
const numTables = buffer.readUInt16BE(12);
|
|
317
|
+
const compressedLength = buffer.readUInt32BE(20);
|
|
318
|
+
const transformed = new Set();
|
|
319
|
+
const directory = [];
|
|
320
|
+
let at = WOFF2_HEADER_BYTES;
|
|
321
|
+
for (let i = 0; i < numTables; i += 1) {
|
|
322
|
+
if (at >= buffer.length) throw new Error('font file: truncated WOFF2 table directory');
|
|
323
|
+
|
|
324
|
+
const flags = buffer[at];
|
|
325
|
+
at += 1;
|
|
326
|
+
let tag = KNOWN_TAGS[flags & CUSTOM_TAG];
|
|
327
|
+
if ((flags & CUSTOM_TAG) === CUSTOM_TAG) {
|
|
328
|
+
tag = buffer.toString('latin1', at, at + 4);
|
|
329
|
+
at += 4;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
let length;
|
|
333
|
+
[length, at] = readUIntBase128(buffer, at);
|
|
334
|
+
// A transformed table stores its TRANSFORMED length too, and that is the
|
|
335
|
+
// length its bytes occupy in the stream. The version lives in the flag's
|
|
336
|
+
// top two bits, and the null transform is version 0, except for
|
|
337
|
+
// glyf/loca, whose null transform is version 3 (WOFF2 spec § 5.2).
|
|
338
|
+
const version = flags >> 6;
|
|
339
|
+
if ((tag === 'glyf' || tag === 'loca') ? version !== 3 : version !== 0) {
|
|
340
|
+
transformed.add(tag);
|
|
341
|
+
[length, at] = readUIntBase128(buffer, at);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
directory.push({ tag, length });
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (at + compressedLength > buffer.length) throw new Error('font file: truncated WOFF2 payload');
|
|
348
|
+
|
|
349
|
+
const stream = zlib.brotliDecompressSync(buffer.subarray(at, at + compressedLength));
|
|
350
|
+
const tables = new Map();
|
|
351
|
+
let cursor = 0;
|
|
352
|
+
for (const { tag, length } of directory) {
|
|
353
|
+
if (cursor + length <= stream.length) tables.set(tag, stream.subarray(cursor, cursor + length));
|
|
354
|
+
cursor += length;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return { tables, transformed };
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* A WOFF2 UIntBase128: up to five bytes, seven value bits each, the high bit
|
|
362
|
+
* marking "one more byte".
|
|
363
|
+
* @param {Buffer} buffer - the file
|
|
364
|
+
* @param {number} offset - where the number starts
|
|
365
|
+
* @returns {[number, number]} the value and the offset past it
|
|
366
|
+
*/
|
|
367
|
+
function readUIntBase128(buffer, offset) {
|
|
368
|
+
let value = 0;
|
|
369
|
+
for (let i = 0; i < 5; i += 1) {
|
|
370
|
+
if (offset + i >= buffer.length) throw new Error('font file: truncated UIntBase128');
|
|
371
|
+
|
|
372
|
+
const byte = buffer[offset + i];
|
|
373
|
+
value = value * 128 + (byte & 0x7f);
|
|
374
|
+
if ((byte & 0x80) === 0) return [value, offset + i + 1];
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
throw new Error('font file: malformed UIntBase128');
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// The system side of every ratio. A build machine cannot read the font a
|
|
381
|
+
// VISITOR falls back to, so these are checked in, MEASURED, never typed from
|
|
382
|
+
// memory: each row is `readFontMetricsFile()` run on 2026-09-02 against the
|
|
383
|
+
// macOS 15 (Darwin 25.6) system file named beside it, so a re-measure
|
|
384
|
+
// reproduces them exactly. The two collections are read at font 0, whose
|
|
385
|
+
// vertical metrics match the published Helvetica (1577/-471/0) and Helvetica
|
|
386
|
+
// Neue (952/-213/28) values, which is the cross-check that font 0 is the regular.
|
|
387
|
+
//
|
|
388
|
+
// Keys are lowercase (a css font stack writes a family name however it likes),
|
|
389
|
+
// and each row carries the family's canonical spelling for the generated
|
|
390
|
+
// `local()` to name.
|
|
391
|
+
const SYSTEM_FONT_METRICS = {
|
|
392
|
+
// /System/Library/Fonts/Supplemental/Arial.ttf
|
|
393
|
+
arial: { family: 'Arial', unitsPerEm: 2048, ascent: 1854, descent: -434, lineGap: 67, avgCharWidth: 891.317 },
|
|
394
|
+
// /System/Library/Fonts/Helvetica.ttc (font 0)
|
|
395
|
+
helvetica: { family: 'Helvetica', unitsPerEm: 2048, ascent: 1577, descent: -471, lineGap: 0, avgCharWidth: 891.317 },
|
|
396
|
+
// /System/Library/Fonts/HelveticaNeue.ttc (font 0)
|
|
397
|
+
'helvetica neue': { family: 'Helvetica Neue', unitsPerEm: 1000, ascent: 952, descent: -213, lineGap: 28, avgCharWidth: 440.951 },
|
|
398
|
+
// /System/Library/Fonts/Supplemental/Georgia.ttf
|
|
399
|
+
georgia: { family: 'Georgia', unitsPerEm: 2048, ascent: 1878, descent: -449, lineGap: 0, avgCharWidth: 891.878 },
|
|
400
|
+
// /System/Library/Fonts/Supplemental/Times New Roman.ttf
|
|
401
|
+
'times new roman': { family: 'Times New Roman', unitsPerEm: 2048, ascent: 1825, descent: -443, lineGap: 87, avgCharWidth: 803.890 },
|
|
402
|
+
// /System/Library/Fonts/Supplemental/Verdana.ttf
|
|
403
|
+
verdana: { family: 'Verdana', unitsPerEm: 2048, ascent: 2059, descent: -430, lineGap: 0, avgCharWidth: 1036.415 },
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* The metrics of the common system families, MEASURED with the reader above
|
|
408
|
+
* from the files on a macOS build machine (see the provenance comment on
|
|
409
|
+
* SYSTEM_FONT_METRICS): the other half of every override, since the fallback
|
|
410
|
+
* face is a system font no build can read on every platform it renders on.
|
|
411
|
+
* @param {string} family - a family name as a css font stack writes it
|
|
412
|
+
* @returns {FontMetrics|null} null when the table does not know the family
|
|
413
|
+
*/
|
|
414
|
+
function systemFontMetrics(family) {
|
|
415
|
+
const name = String(family).trim().replace(/^['"]|['"]$/g, '').toLowerCase();
|
|
416
|
+
|
|
417
|
+
return SYSTEM_FONT_METRICS[name] || null;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
module.exports = { readFontMetrics, readFontMetricsFile, systemFontMetrics, SYSTEM_FONT_METRICS };
|