@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
package/dist/sections.js
ADDED
|
@@ -0,0 +1,810 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The section/component library machinery (docs/web/omega-sections-spec.md):
|
|
3
|
+
* `{% section "marketing/hero", key: value %}` and `{% component "frame/x" %}`
|
|
4
|
+
* Liquid tags. One tag, two authoring forms:
|
|
5
|
+
*
|
|
6
|
+
* inline — {% section "marketing/hero", headline: "Ship it", data: resolved.hero %}
|
|
7
|
+
* block — {% section "marketing/testimonials" %}
|
|
8
|
+
* headline: "What builders say"
|
|
9
|
+
* items:
|
|
10
|
+
* - quote: "…"
|
|
11
|
+
* {% endsection %}
|
|
12
|
+
*
|
|
13
|
+
* The block body is YAML (same dialect as frontmatter); using inline named
|
|
14
|
+
* args AND a body on one call is an error. The reserved `data:` arg deep-
|
|
15
|
+
* spreads an object between defaults and named args — the bridge that keeps
|
|
16
|
+
* today's frontmatter-key overrides working (layouts pass `data: resolved.X`).
|
|
17
|
+
*
|
|
18
|
+
* Slots (Ian 2026-07-18): a body may carry named markup blocks —
|
|
19
|
+
* {% slot demo %}<any html>{% endslot %} — alongside the YAML (or alongside
|
|
20
|
+
* inline args: the XOR rule applies to the YAML remainder only). Slot content
|
|
21
|
+
* renders in the CALLER's scope (site.*, captures, omega_* tags all work) and
|
|
22
|
+
* reaches the section as a finished-HTML string arg (schema type 'html'),
|
|
23
|
+
* merged OUTERMOST after call-site liquification — so slot output never
|
|
24
|
+
* re-renders and literal braces (code samples via {% raw %}) survive. An
|
|
25
|
+
* empty slot passes '' — the absence spine: it kills a default the same way
|
|
26
|
+
* explicit-empty kills everywhere else. Same-tag nesting inside a slot
|
|
27
|
+
* ({% section %} in a section slot) is not supported — the dual-form scan
|
|
28
|
+
* would misread it (loud parse error); nest the OTHER tag instead
|
|
29
|
+
* (components inside section slots, sections inside component slots).
|
|
30
|
+
*
|
|
31
|
+
* Resolution walks the layer chain (consumer `_sections`/`_components` →
|
|
32
|
+
* active theme → base — first match wins), mirroring themes/layouts.
|
|
33
|
+
* Each entry is a folder owning `section.html` + optional `section.json5`
|
|
34
|
+
* ({ description, args, defaults, demo }) — defaults merge under passed args,
|
|
35
|
+
* top-level args validate against the schema (warn + did-you-mean, never
|
|
36
|
+
* throw).
|
|
37
|
+
*
|
|
38
|
+
* The name is usually a quoted literal; a bare expression that resolves to
|
|
39
|
+
* an id string is also legal ({% section entry.id, data: variant.args %}) —
|
|
40
|
+
* the auto-generated showcase's mechanism (spec §9), and how data-driven
|
|
41
|
+
* composition stays one tag. The expression runs up to the first comma.
|
|
42
|
+
*
|
|
43
|
+
* Context-free rule (load-bearing): the markup renders against `{ args }`
|
|
44
|
+
* ONLY — no page globals. Interpolation happens at the CALL site instead:
|
|
45
|
+
* string values (passed or default) containing Liquid render against the
|
|
46
|
+
* caller's scope before the section sees them, so defaults like
|
|
47
|
+
* "Introducing {{ site.brand.name }}" work while markup stays portable to
|
|
48
|
+
* any surface any framework builds.
|
|
49
|
+
*
|
|
50
|
+
* {% composition %}…{% endcomposition %} (spec §8) wraps a page layout's
|
|
51
|
+
* default section composition. Two page states, both byte-parity with the
|
|
52
|
+
* `{{ content | omega_content_format }}` layout line the wrap replaces:
|
|
53
|
+
* - empty page → the wrapped one-liners render (absence is the spine)
|
|
54
|
+
* - body content → the body REPLACES the composition (a page that writes
|
|
55
|
+
* a body means it — Ian's 2026-07-19 ruling; what `omega customize
|
|
56
|
+
* <url>` materializes supersedes the default while the sections inside
|
|
57
|
+
* keep flowing from the theme)
|
|
58
|
+
*
|
|
59
|
+
* The legacy UJM add-below flag (`append: true`) is GONE (#607, Ian
|
|
60
|
+
* 2026-08-26): a page that wants the default bands AND its own prose writes
|
|
61
|
+
* the bands itself — `omega customize <url>` materializes exactly that — and
|
|
62
|
+
* body content always renders below the sections THE BODY ITSELF calls, never
|
|
63
|
+
* below the layout composition it replaced.
|
|
64
|
+
*/
|
|
65
|
+
const fs = require('node:fs');
|
|
66
|
+
const path = require('node:path');
|
|
67
|
+
const JSON5 = require('json5');
|
|
68
|
+
const yaml = require('js-yaml');
|
|
69
|
+
const reads = require('./vendor/devkit/reads.js');
|
|
70
|
+
const { deepMerge } = require('./merge.js');
|
|
71
|
+
const { registerHeroAnimationTag } = require('./hero-animations.js');
|
|
72
|
+
const Logger = require('./vendor/devkit/logger.js');
|
|
73
|
+
|
|
74
|
+
// The warning sink's default: build-time output stamps the identity tag
|
|
75
|
+
// itself, so no message hand-writes a module prefix of its own (#12).
|
|
76
|
+
// Callers that inject a sink (tests, the engine) still own their formatting.
|
|
77
|
+
const logger = new Logger('sections');
|
|
78
|
+
|
|
79
|
+
// The two tiers share one implementation — only the folder family, the
|
|
80
|
+
// filenames ({% section %} → _sections/<id>/section.*) and the gallery url
|
|
81
|
+
// space differ.
|
|
82
|
+
//
|
|
83
|
+
// `gallery` is a kind's whole showcase URL SPACE
|
|
84
|
+
// ([#602](https://github.com/Omega-JS-Stack/omega/issues/602)): `url` is its
|
|
85
|
+
// index, `base` is what its entry pages hang off (`<base>/<id>`, frames at
|
|
86
|
+
// `<base>/<id>/frames/<slug>`), `label` names it on both. The two galleries
|
|
87
|
+
// MIRROR each other — an index, one page per entry, frames beside it — in
|
|
88
|
+
// SEPARATE spaces: components used to live under the section space, which made
|
|
89
|
+
// /test/components read like a second view of /test/sections instead of a
|
|
90
|
+
// library of its own. ONE generator, kind-aware paths: the showcase templates
|
|
91
|
+
// read these off the entry and never compose a url.
|
|
92
|
+
//
|
|
93
|
+
// The two spellings are HARMONIZED (Ian's #602 addendum, 2026-08-26): `base`
|
|
94
|
+
// IS `url` on both, so an entry is `<index>/<id>` in either library and
|
|
95
|
+
// neither carries a kind segment the other lacks. Sections used to hang off
|
|
96
|
+
// `/test/sections/section/<id>`, which read as a leftover of the era when the
|
|
97
|
+
// section space held both kinds; a gallery is dev-only (#554), so that
|
|
98
|
+
// spelling just goes — no redirects. The index's own permalink gains the
|
|
99
|
+
// `.html` Jekyll extension (engine.js jekyllPermalink), so `/test/sections`
|
|
100
|
+
// the FILE and `/test/sections/` the DIRECTORY never collide.
|
|
101
|
+
const KINDS = {
|
|
102
|
+
section: {
|
|
103
|
+
dirname: '_sections',
|
|
104
|
+
basename: 'section',
|
|
105
|
+
gallery: { kind: 'section', url: '/test/sections', base: '/test/sections', label: 'Section library' },
|
|
106
|
+
},
|
|
107
|
+
component: {
|
|
108
|
+
dirname: '_components',
|
|
109
|
+
basename: 'component',
|
|
110
|
+
gallery: { kind: 'component', url: '/test/components', base: '/test/components', label: 'Component library' },
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Section ids are kebab-case category paths (marketing/hero) — never
|
|
115
|
+
// dotted/absolute/traversal paths.
|
|
116
|
+
const NAME_SHAPE = /^[a-z0-9][a-z0-9-]*(\/[a-z0-9][a-z0-9-]*)*$/;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Levenshtein distance — small inputs only (arg-name did-you-mean).
|
|
120
|
+
* @param {string} a
|
|
121
|
+
* @param {string} b
|
|
122
|
+
* @returns {number}
|
|
123
|
+
*/
|
|
124
|
+
function levenshtein(a, b) {
|
|
125
|
+
const rows = Array.from({ length: a.length + 1 }, (unused, i) => [i]);
|
|
126
|
+
for (let j = 1; j <= b.length; j++) rows[0][j] = j;
|
|
127
|
+
for (let i = 1; i <= a.length; i++) {
|
|
128
|
+
for (let j = 1; j <= b.length; j++) {
|
|
129
|
+
rows[i][j] = Math.min(
|
|
130
|
+
rows[i - 1][j] + 1,
|
|
131
|
+
rows[i][j - 1] + 1,
|
|
132
|
+
rows[i - 1][j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return rows[a.length][b.length];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* The nearest known arg name within edit distance 2, for warning text.
|
|
141
|
+
* @param {string} key
|
|
142
|
+
* @param {string[]} known
|
|
143
|
+
* @returns {string} ' — did you mean "x"?' or ''
|
|
144
|
+
*/
|
|
145
|
+
function suggest(key, known) {
|
|
146
|
+
let best = null;
|
|
147
|
+
let bestDistance = 3;
|
|
148
|
+
for (const candidate of known) {
|
|
149
|
+
const distance = levenshtein(key, candidate);
|
|
150
|
+
if (distance < bestDistance) {
|
|
151
|
+
best = candidate;
|
|
152
|
+
bestDistance = distance;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return best ? ` — did you mean "${best}"?` : '';
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Parse the inline named-arg list after the section name:
|
|
160
|
+
* `headline: page.title, meta: "a, b"` → [{ key, expr }]. Quote-aware — a
|
|
161
|
+
* comma inside a quoted value never splits. Value expressions are handed to
|
|
162
|
+
* LiquidJS's evalValue verbatim (literals, dotted paths, filters all work).
|
|
163
|
+
* @param {string} rest - the markup after the quoted name (leading comma ok)
|
|
164
|
+
* @returns {Array<{key: string, expr: string}>}
|
|
165
|
+
*/
|
|
166
|
+
function parseInlineArgs(rest) {
|
|
167
|
+
const pairs = [];
|
|
168
|
+
let text = rest.trim().replace(/^,/, '');
|
|
169
|
+
while (text.trim()) {
|
|
170
|
+
const match = text.match(/^\s*([\w-]+)\s*:/);
|
|
171
|
+
if (!match) throw new Error(`bad inline args near "${text.trim().slice(0, 40)}" — expected key: value`);
|
|
172
|
+
let i = match[0].length;
|
|
173
|
+
let quote = null;
|
|
174
|
+
for (; i < text.length; i++) {
|
|
175
|
+
const ch = text[i];
|
|
176
|
+
if (quote) {
|
|
177
|
+
if (ch === quote) quote = null;
|
|
178
|
+
} else if (ch === '"' || ch === "'") {
|
|
179
|
+
quote = ch;
|
|
180
|
+
} else if (ch === ',') {
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const expr = text.slice(match[0].length, i).trim();
|
|
185
|
+
if (!expr) throw new Error(`inline arg "${match[1]}" has no value`);
|
|
186
|
+
pairs.push({ key: match[1], expr });
|
|
187
|
+
text = text.slice(i + 1);
|
|
188
|
+
}
|
|
189
|
+
return pairs;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// {% slot name %}…{% endslot %} regions inside a section/component block
|
|
193
|
+
// body. Not a registered tag — pure body-text grammar, so a stray slot
|
|
194
|
+
// outside a block call fails loudly as an unknown tag.
|
|
195
|
+
const SLOT_RE = /\{%-?\s*slot\s+([A-Za-z_][\w-]*)\s*-?%\}([\s\S]*?)\{%-?\s*endslot\s*-?%\}/g;
|
|
196
|
+
const SLOT_STRAY_RE = /\{%-?\s*(?:slot|endslot)\b/;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Split a block body into its YAML remainder and its named slot blocks.
|
|
200
|
+
* @param {string} bodyText - raw captured block body
|
|
201
|
+
* @returns {{yamlText: string, slots: Array<{name: string, source: string}>}}
|
|
202
|
+
*/
|
|
203
|
+
function extractSlots(bodyText) {
|
|
204
|
+
const slots = [];
|
|
205
|
+
const seen = new Set();
|
|
206
|
+
const yamlText = bodyText.replace(SLOT_RE, (match, slotName, source) => {
|
|
207
|
+
if (seen.has(slotName)) throw new Error(`duplicate {% slot ${slotName} %} — one block per name`);
|
|
208
|
+
seen.add(slotName);
|
|
209
|
+
slots.push({ name: slotName, source });
|
|
210
|
+
return '';
|
|
211
|
+
});
|
|
212
|
+
if (SLOT_STRAY_RE.test(yamlText)) {
|
|
213
|
+
throw new Error('malformed slot block — every {% slot name %} needs a name and a matching {% endslot %}');
|
|
214
|
+
}
|
|
215
|
+
return { yamlText, slots };
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Render every Liquid-carrying string in an args tree against the caller's
|
|
220
|
+
* scope — fresh containers, source never mutated.
|
|
221
|
+
* @param {object} liquid - the LiquidJS engine
|
|
222
|
+
* @param {object} scope - plain scope object (context.getAll())
|
|
223
|
+
* @param {*} value
|
|
224
|
+
* @returns {Promise<*>}
|
|
225
|
+
*/
|
|
226
|
+
async function liquifyDeep(liquid, scope, value) {
|
|
227
|
+
if (typeof value === 'string') {
|
|
228
|
+
return value.includes('{{') || value.includes('{%')
|
|
229
|
+
? liquid.parseAndRender(value, scope)
|
|
230
|
+
: value;
|
|
231
|
+
}
|
|
232
|
+
if (Array.isArray(value)) {
|
|
233
|
+
return Promise.all(value.map((item) => liquifyDeep(liquid, scope, item)));
|
|
234
|
+
}
|
|
235
|
+
if (value && typeof value === 'object') {
|
|
236
|
+
const out = {};
|
|
237
|
+
for (const [key, item] of Object.entries(value)) out[key] = await liquifyDeep(liquid, scope, item);
|
|
238
|
+
return out;
|
|
239
|
+
}
|
|
240
|
+
return value;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Validate a value against a schema type name. Warn-only machinery — callers
|
|
245
|
+
* turn `false` into a message.
|
|
246
|
+
* @param {*} value
|
|
247
|
+
* @param {string} type - 'string' | 'number' | 'boolean' | 'array' | 'object'
|
|
248
|
+
* @returns {boolean}
|
|
249
|
+
*/
|
|
250
|
+
function matchesType(value, type) {
|
|
251
|
+
if (value === null || value === undefined) return true; // explicit null = "remove" — always legal
|
|
252
|
+
switch (type) {
|
|
253
|
+
case 'array': return Array.isArray(value);
|
|
254
|
+
case 'object': return typeof value === 'object' && !Array.isArray(value);
|
|
255
|
+
case 'html': return typeof value === 'string'; // finished markup — slot blocks or capture-passed
|
|
256
|
+
case 'string': case 'number': case 'boolean': return typeof value === type;
|
|
257
|
+
default: return true; // unknown schema type — never punish the caller
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// The §7 lanes an override folder may declare `inherit` for. html can't be
|
|
262
|
+
// inherited (not overriding it IS inheritance) and json5 can't (the folder is
|
|
263
|
+
// its own manifest — theme defaults are theme identity).
|
|
264
|
+
const INHERITABLE_LANES = new Set(['js', 'scss']);
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Read an entry folder's declared inherit lanes from its json5. Absent file,
|
|
268
|
+
* unreadable file (resolveEntry warns that at render time), or no `inherit`
|
|
269
|
+
* key → []. A malformed declaration throws — a contradictory manifest is a
|
|
270
|
+
* structural error, like traversal ids.
|
|
271
|
+
* @param {string} entryDir
|
|
272
|
+
* @param {string} basename - 'section' | 'component'
|
|
273
|
+
* @returns {string[]} validated lane names
|
|
274
|
+
*/
|
|
275
|
+
function readInheritLanes(entryDir, basename) {
|
|
276
|
+
const metaPath = path.join(entryDir, `${basename}.json5`);
|
|
277
|
+
if (!fs.existsSync(metaPath)) return [];
|
|
278
|
+
let meta;
|
|
279
|
+
try {
|
|
280
|
+
meta = JSON5.parse(fs.readFileSync(metaPath, 'utf8'));
|
|
281
|
+
} catch {
|
|
282
|
+
return [];
|
|
283
|
+
}
|
|
284
|
+
if (meta.inherit === undefined) return [];
|
|
285
|
+
if (!Array.isArray(meta.inherit) || meta.inherit.some((lane) => !INHERITABLE_LANES.has(lane))) {
|
|
286
|
+
throw new Error(`[sections] ${metaPath}: inherit must be an array drawn from ${[...INHERITABLE_LANES].join('/')} — got ${JSON.stringify(meta.inherit)}`);
|
|
287
|
+
}
|
|
288
|
+
return meta.inherit;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Collect every section/component ASSET (section.scss / section.js and the
|
|
293
|
+
* component.* twins) across the layer chain — the spec §7 asset lanes. Same
|
|
294
|
+
* resolution semantics as the tags: first root owning the entry's .html wins
|
|
295
|
+
* the WHOLE entry (markup + assets travel together — a consumer overriding a
|
|
296
|
+
* section owns its styles/behavior too), with ONE declared exception: the
|
|
297
|
+
* winning folder's json5 may carry `inherit: ['js']` (and/or 'scss') — lanes
|
|
298
|
+
* it deliberately leaves to the chain, filled from the first LOWER full entry
|
|
299
|
+
* (a folder owning the .html) that has the file. That's how a theme override
|
|
300
|
+
* replaces markup while keeping the base section's behavior riding the
|
|
301
|
+
* bundle without a copy (the newsflash newsletter-cta pattern — the base
|
|
302
|
+
* js's DOM contract becomes part of the override's markup contract).
|
|
303
|
+
* Declaring a lane the folder also ships throws (contradictory manifest);
|
|
304
|
+
* a declaration no lower layer can fill warns and stays null. Sorted
|
|
305
|
+
* (kind, id) for deterministic sheet/bundle order.
|
|
306
|
+
* @param {string[]} baseDirs - resolution bases in precedence order
|
|
307
|
+
* (consumer dir first, then theme layers — registerSectionTags' order)
|
|
308
|
+
* @param {object} [options]
|
|
309
|
+
* @param {function} [options.warn] - warning sink (default console.warn)
|
|
310
|
+
* @returns {Array<{kind: string, id: string, scss: string|null, js: string|null}>}
|
|
311
|
+
*/
|
|
312
|
+
function collectSectionAssets(baseDirs, options = {}) {
|
|
313
|
+
const warn = options.warn || logger.warn.bind(logger);
|
|
314
|
+
const entries = new Map(); // `${kind}:${id}` → {kind, id, scss, js}
|
|
315
|
+
const pending = new Map(); // `${kind}:${id}` → Set of inherit lanes still unfilled
|
|
316
|
+
|
|
317
|
+
const walk = (root, dir, kind, prefix) => {
|
|
318
|
+
const basename = KINDS[kind].basename;
|
|
319
|
+
for (const item of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
320
|
+
if (!item.isDirectory()) continue;
|
|
321
|
+
const id = prefix ? `${prefix}/${item.name}` : item.name;
|
|
322
|
+
if (!NAME_SHAPE.test(id)) continue;
|
|
323
|
+
const entryDir = path.join(dir, item.name);
|
|
324
|
+
const html = path.join(entryDir, `${basename}.html`);
|
|
325
|
+
if (fs.existsSync(html)) {
|
|
326
|
+
const key = `${kind}:${id}`;
|
|
327
|
+
if (!entries.has(key)) {
|
|
328
|
+
const scss = path.join(entryDir, `${basename}.scss`);
|
|
329
|
+
const js = path.join(entryDir, `${basename}.js`);
|
|
330
|
+
const entry = {
|
|
331
|
+
kind,
|
|
332
|
+
id,
|
|
333
|
+
scss: fs.existsSync(scss) ? scss : null,
|
|
334
|
+
js: fs.existsSync(js) ? js : null,
|
|
335
|
+
};
|
|
336
|
+
const lanes = readInheritLanes(entryDir, basename);
|
|
337
|
+
for (const lane of lanes) {
|
|
338
|
+
if (entry[lane]) {
|
|
339
|
+
throw new Error(`[sections] ${entryDir}: declares inherit "${lane}" but ships its own ${basename}.${lane} — remove one`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
entries.set(key, entry);
|
|
343
|
+
if (lanes.length) pending.set(key, new Set(lanes));
|
|
344
|
+
} else if (pending.has(key)) {
|
|
345
|
+
// A LOWER layer's full entry at the same id — fill declared lanes
|
|
346
|
+
// from the first layer that has each file (the chain continues past
|
|
347
|
+
// layers lacking it).
|
|
348
|
+
const lanes = pending.get(key);
|
|
349
|
+
for (const lane of [...lanes]) {
|
|
350
|
+
const file = path.join(entryDir, `${basename}.${lane}`);
|
|
351
|
+
if (fs.existsSync(file)) {
|
|
352
|
+
entries.get(key)[lane] = file;
|
|
353
|
+
lanes.delete(lane);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (!lanes.size) pending.delete(key);
|
|
357
|
+
}
|
|
358
|
+
} else {
|
|
359
|
+
walk(root, entryDir, kind, id);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
for (const root of baseDirs) {
|
|
365
|
+
for (const kind of Object.keys(KINDS)) {
|
|
366
|
+
const dir = path.join(root, KINDS[kind].dirname);
|
|
367
|
+
if (fs.existsSync(dir)) walk(root, dir, kind, '');
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
for (const [key, lanes] of pending) {
|
|
372
|
+
warn(`${key}: declares inherit ${[...lanes].join(', ')} but no lower layer owns the file — nothing inherited`);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return [...entries.values()].sort((a, b) => (a.kind + a.id).localeCompare(b.kind + b.id));
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* The resolved library with meta, for the auto-generated showcase + schema
|
|
380
|
+
* docs (spec §9). Same first-match-wins resolution as the tags — the entry a
|
|
381
|
+
* page composing that id would actually render — with the winning folder's
|
|
382
|
+
* json5 normalized for template consumption:
|
|
383
|
+
*
|
|
384
|
+
* argsTable — [{ name, type, description }] rows (the reference docs;
|
|
385
|
+
* a shorthand `name: 'string'` schema yields type only)
|
|
386
|
+
* defaultsJson — pretty-printed defaults ('' when none): display copy for
|
|
387
|
+
* the docs, showing the raw {{ site.brand.name }} tokens a
|
|
388
|
+
* consumer would see in the file
|
|
389
|
+
*
|
|
390
|
+
* Display strings (description, argsTable descriptions, defaultsJson) are
|
|
391
|
+
* HTML-ESCAPED here, including `{` → { — templates print them verbatim
|
|
392
|
+
* (no | escape). That's load-bearing, not cosmetic: the library rides the
|
|
393
|
+
* page data cascade, whose frontmatter/resolved walkers liquify any string
|
|
394
|
+
* containing {{ — raw tokens would either render (wrong: docs must show the
|
|
395
|
+
* contract) or throw (JSON.stringify's escaped quotes inside a token are
|
|
396
|
+
* invalid Liquid). Demo args stay RAW — they liquify at the tag's call site
|
|
397
|
+
* like every real composition.
|
|
398
|
+
* demo — [{ label, slug, url, argsJson, args?, stage_class? }]
|
|
399
|
+
* variants, each rendered in its own EMBEDDED FRAME page
|
|
400
|
+
* (#463) that the entry page iframes in (args ride the data
|
|
401
|
+
* bridge, so json5 defaults still apply underneath — exactly
|
|
402
|
+
* the consumer experience); malformed variants warn + drop.
|
|
403
|
+
* `slug` is the kebab-cased label, de-duplicated within the
|
|
404
|
+
* entry (-2, -3 …) — it names the frame page's URL segment;
|
|
405
|
+
* `url` is that frame page's permalink; `argsJson` is the
|
|
406
|
+
* escaped authored-args display copy
|
|
407
|
+
* url — the entry page's own permalink, off its KIND's gallery base
|
|
408
|
+
* (#602) — the showcase templates never compose one
|
|
409
|
+
* gallery — that kind's whole url space ({ kind, url, base, label }),
|
|
410
|
+
* so an entry page can name its own library
|
|
411
|
+
* source — which layer owns the entry: 'consumer' or the layer dir's
|
|
412
|
+
* basename ('classy', 'newsflash')
|
|
413
|
+
* inherit — declared §7 inherit lanes, for the docs chip
|
|
414
|
+
*
|
|
415
|
+
* `groups` clusters entries by (kind, category folder) for the index page —
|
|
416
|
+
* sections first, then components, categories alphabetical (the spec §2
|
|
417
|
+
* "the showcase groups by folder automatically"). `variants` is the same demo
|
|
418
|
+
* variants FLATTENED across every entry ({ kind, id, source, label, slug, url,
|
|
419
|
+
* gallery, args, stage_class }) — the pagination data of the per-variant frame pages,
|
|
420
|
+
* one page per item.
|
|
421
|
+
*
|
|
422
|
+
* @param {object} options
|
|
423
|
+
* @param {string[]} options.baseDirs - resolution bases in precedence order
|
|
424
|
+
* (registerSectionTags' order: consumer dir first, then theme layers)
|
|
425
|
+
* @param {string} [options.consumerDir] - labeled 'consumer' when it wins
|
|
426
|
+
* @param {function} [options.warn] - warning sink (default console.warn)
|
|
427
|
+
* @returns {{ entries: Array<object>, groups: Array<{kind: string, category: string, entries: Array<object>}>, variants: Array<object>, galleries: Array<object> }}
|
|
428
|
+
*/
|
|
429
|
+
function buildSectionLibrary(options) {
|
|
430
|
+
const warn = options.warn || logger.warn.bind(logger);
|
|
431
|
+
const entries = new Map(); // `${kind}:${id}` → entry
|
|
432
|
+
|
|
433
|
+
// Display-ready HTML text (see the JSDoc: the { escape makes the string
|
|
434
|
+
// liquid-inert, which the data-cascade walkers require).
|
|
435
|
+
const escapeHtml = (text) => String(text)
|
|
436
|
+
.replace(/&/g, '&')
|
|
437
|
+
.replace(/</g, '<')
|
|
438
|
+
.replace(/>/g, '>')
|
|
439
|
+
.replace(/"/g, '"')
|
|
440
|
+
.replace(/'/g, ''')
|
|
441
|
+
.replace(/{/g, '{');
|
|
442
|
+
|
|
443
|
+
// A demo variant's URL segment on its frame page: kebab-case of the label,
|
|
444
|
+
// de-duplicated within the entry (two "Default"s become default, default-2).
|
|
445
|
+
const slugify = (text) => String(text).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'demo';
|
|
446
|
+
|
|
447
|
+
const normalizeMeta = (meta, label) => {
|
|
448
|
+
const argsTable = Object.entries(meta.args || {}).map(([name, spec]) => ({
|
|
449
|
+
name,
|
|
450
|
+
type: typeof spec === 'string' ? spec : (spec && spec.type) || '',
|
|
451
|
+
description: escapeHtml((spec && typeof spec === 'object' && spec.description) || ''),
|
|
452
|
+
}));
|
|
453
|
+
let demo = [];
|
|
454
|
+
if (meta.demo !== undefined) {
|
|
455
|
+
if (!Array.isArray(meta.demo)) {
|
|
456
|
+
warn(`showcase ${label}: demo must be an array of { label, args } variants — ignoring`);
|
|
457
|
+
} else {
|
|
458
|
+
const taken = new Map(); // base slug → how many variants claimed it
|
|
459
|
+
demo = meta.demo.filter((variant) => {
|
|
460
|
+
const ok = variant && typeof variant === 'object' && typeof variant.label === 'string' && variant.label;
|
|
461
|
+
if (!ok) warn(`showcase ${label}: demo variant without a label — dropped`);
|
|
462
|
+
return ok;
|
|
463
|
+
}).map((variant) => {
|
|
464
|
+
const base = slugify(variant.label);
|
|
465
|
+
const seen = (taken.get(base) || 0) + 1;
|
|
466
|
+
taken.set(base, seen);
|
|
467
|
+
return {
|
|
468
|
+
...variant,
|
|
469
|
+
slug: seen === 1 ? base : `${base}-${seen}`,
|
|
470
|
+
argsJson: variant.args && Object.keys(variant.args).length
|
|
471
|
+
? escapeHtml(JSON.stringify(variant.args, null, 2))
|
|
472
|
+
: '',
|
|
473
|
+
};
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return {
|
|
478
|
+
description: escapeHtml(meta.description || ''),
|
|
479
|
+
argsTable,
|
|
480
|
+
defaultsJson: meta.defaults && Object.keys(meta.defaults).length
|
|
481
|
+
? escapeHtml(JSON.stringify(meta.defaults, null, 2))
|
|
482
|
+
: '',
|
|
483
|
+
demo,
|
|
484
|
+
inherit: Array.isArray(meta.inherit) ? meta.inherit : [],
|
|
485
|
+
};
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
// The walk reads through the captured-read helper (#200): this runs at
|
|
489
|
+
// CONFIG time (the library is a global data value), so every dir it probes
|
|
490
|
+
// becomes a dev config-reset target — including the entry folders a brand
|
|
491
|
+
// has not authored yet.
|
|
492
|
+
const walk = (source, dir, kind, prefix) => {
|
|
493
|
+
const basename = KINDS[kind].basename;
|
|
494
|
+
for (const item of reads.readdir(dir, { withFileTypes: true })) {
|
|
495
|
+
if (!item.isDirectory()) continue;
|
|
496
|
+
const id = prefix ? `${prefix}/${item.name}` : item.name;
|
|
497
|
+
if (!NAME_SHAPE.test(id)) continue;
|
|
498
|
+
const entryDir = path.join(dir, item.name);
|
|
499
|
+
if (!reads.fileExists(path.join(entryDir, `${basename}.html`))) {
|
|
500
|
+
walk(source, entryDir, kind, id);
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
const key = `${kind}:${id}`;
|
|
504
|
+
if (entries.has(key)) continue; // a higher layer already won
|
|
505
|
+
let meta = {};
|
|
506
|
+
const metaPath = path.join(entryDir, `${basename}.json5`);
|
|
507
|
+
if (reads.fileExists(metaPath)) {
|
|
508
|
+
try {
|
|
509
|
+
meta = JSON5.parse(reads.read(metaPath));
|
|
510
|
+
} catch (error) {
|
|
511
|
+
warn(`showcase: unreadable ${metaPath} (${error.message}) — listing with empty meta`);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
// The gallery urls are computed HERE, once (#602): the entry page's own
|
|
515
|
+
// permalink, and one per demo variant for its frame. Every showcase
|
|
516
|
+
// template reads them off the entry, so a kind's url space has ONE home.
|
|
517
|
+
const gallery = KINDS[kind].gallery;
|
|
518
|
+
const entry = { kind, id, source, gallery, url: `${gallery.base}/${id}`, ...normalizeMeta(meta, key) };
|
|
519
|
+
entry.demo = entry.demo.map((variant) => ({ ...variant, url: `${entry.url}/frames/${variant.slug}` }));
|
|
520
|
+
entries.set(key, entry);
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
for (const root of options.baseDirs) {
|
|
525
|
+
const source = root === options.consumerDir ? 'consumer' : path.basename(root);
|
|
526
|
+
for (const kind of Object.keys(KINDS)) {
|
|
527
|
+
const dir = path.join(root, KINDS[kind].dirname);
|
|
528
|
+
if (reads.dirExists(dir)) walk(source, dir, kind, '');
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
const sorted = [...entries.values()].sort((a, b) => (a.kind + a.id).localeCompare(b.kind + b.id));
|
|
533
|
+
|
|
534
|
+
const groupMap = new Map(); // `${kind}:${category}` → group
|
|
535
|
+
for (const entry of sorted) {
|
|
536
|
+
const category = entry.id.includes('/') ? entry.id.split('/').slice(0, -1).join('/') : '';
|
|
537
|
+
const key = `${entry.kind}:${category}`;
|
|
538
|
+
if (!groupMap.has(key)) groupMap.set(key, { kind: entry.kind, category, entries: [] });
|
|
539
|
+
groupMap.get(key).entries.push(entry);
|
|
540
|
+
}
|
|
541
|
+
const groups = [...groupMap.values()].sort((a, b) => (
|
|
542
|
+
a.kind === b.kind ? a.category.localeCompare(b.category) : (a.kind === 'section' ? -1 : 1)
|
|
543
|
+
));
|
|
544
|
+
|
|
545
|
+
// The frame pages' pagination data (#463): every entry's demo variants,
|
|
546
|
+
// flattened, each carrying the entry coordinates its own page needs.
|
|
547
|
+
const variants = sorted.flatMap((entry) => entry.demo.map((variant) => ({
|
|
548
|
+
kind: entry.kind,
|
|
549
|
+
id: entry.id,
|
|
550
|
+
source: entry.source,
|
|
551
|
+
label: variant.label,
|
|
552
|
+
slug: variant.slug,
|
|
553
|
+
url: variant.url, // the frame page's own permalink (#602)
|
|
554
|
+
gallery: entry.gallery, // …and the library it belongs to, for its title
|
|
555
|
+
args: variant.args,
|
|
556
|
+
stage_class: variant.stage_class,
|
|
557
|
+
})));
|
|
558
|
+
|
|
559
|
+
// The gallery url spaces themselves (#602) — the index pages select their
|
|
560
|
+
// own out of this list, so a label or a url has ONE home for the whole
|
|
561
|
+
// showcase (KINDS above).
|
|
562
|
+
const galleries = Object.values(KINDS).map((kind) => kind.gallery);
|
|
563
|
+
|
|
564
|
+
return { entries: sorted, groups, variants, galleries };
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Register the {% section %} and {% component %} tags on a LiquidJS engine —
|
|
569
|
+
* and, with them, `{% hero_animation %}` (#441): section MARKUP calls it
|
|
570
|
+
* (`marketing/hero`'s custom demo branch does), so registering the family
|
|
571
|
+
* without it leaves a tag no engine can parse. One call, one registration
|
|
572
|
+
* point, and no harness can forget half of it.
|
|
573
|
+
* @param {object} engine - LiquidJS engine (Eleventy's, via amendLibrary)
|
|
574
|
+
* @param {object} options
|
|
575
|
+
* @param {string[]} options.baseDirs - resolution bases in precedence order:
|
|
576
|
+
* consumer dir first, then theme layers (each probed for
|
|
577
|
+
* _sections/_components/_hero)
|
|
578
|
+
* @param {function} [options.warn] - warning sink (default console.warn)
|
|
579
|
+
*/
|
|
580
|
+
function registerSectionTags(engine, options) {
|
|
581
|
+
const warn = options.warn || logger.warn.bind(logger);
|
|
582
|
+
|
|
583
|
+
registerHeroAnimationTag(engine, { baseDirs: options.baseDirs });
|
|
584
|
+
|
|
585
|
+
for (const [tagName, kind] of Object.entries(KINDS)) {
|
|
586
|
+
const roots = options.baseDirs
|
|
587
|
+
.map((dir) => path.join(dir, kind.dirname))
|
|
588
|
+
.filter((dir) => fs.existsSync(dir));
|
|
589
|
+
|
|
590
|
+
// Per-registration caches — roots are fixed for a build, so entries and
|
|
591
|
+
// parsed templates never go stale within one; a new build re-registers.
|
|
592
|
+
const entryCache = new Map(); // name → { templatePath, meta } | null
|
|
593
|
+
const templateCache = new Map(); // abs path → parsed templates
|
|
594
|
+
|
|
595
|
+
const resolveEntry = (name) => {
|
|
596
|
+
if (entryCache.has(name)) return entryCache.get(name);
|
|
597
|
+
let entry = null;
|
|
598
|
+
for (const root of roots) {
|
|
599
|
+
const dir = path.join(root, name);
|
|
600
|
+
const templatePath = path.join(dir, `${kind.basename}.html`);
|
|
601
|
+
if (!fs.existsSync(templatePath)) continue;
|
|
602
|
+
let meta = {};
|
|
603
|
+
const metaPath = path.join(dir, `${kind.basename}.json5`);
|
|
604
|
+
if (fs.existsSync(metaPath)) {
|
|
605
|
+
try {
|
|
606
|
+
meta = JSON5.parse(fs.readFileSync(metaPath, 'utf8'));
|
|
607
|
+
} catch (error) {
|
|
608
|
+
warn(`${tagName} "${name}": unreadable ${kind.basename}.json5 (${error.message}) — treating as empty`);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
entry = { templatePath, meta };
|
|
612
|
+
break;
|
|
613
|
+
}
|
|
614
|
+
entryCache.set(name, entry);
|
|
615
|
+
return entry;
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
engine.registerTag(tagName, {
|
|
619
|
+
parse(tagToken, remainTokens) {
|
|
620
|
+
this.markup = String(tagToken.args || '').trim();
|
|
621
|
+
this.bodyText = null;
|
|
622
|
+
|
|
623
|
+
// Dual-form discrimination: block iff the matching end tag appears
|
|
624
|
+
// before the next same-tag open in the remaining stream. Sound for
|
|
625
|
+
// all legal inputs — YAML bodies never contain {% section %} tags.
|
|
626
|
+
let isBlock = false;
|
|
627
|
+
for (const token of remainTokens) {
|
|
628
|
+
if (token.name === tagName) break;
|
|
629
|
+
if (token.name === `end${tagName}`) { isBlock = true; break; }
|
|
630
|
+
}
|
|
631
|
+
if (!isBlock) return;
|
|
632
|
+
|
|
633
|
+
const parts = [];
|
|
634
|
+
while (remainTokens.length) {
|
|
635
|
+
const token = remainTokens.shift();
|
|
636
|
+
if (token.name === `end${tagName}`) {
|
|
637
|
+
this.bodyText = parts.join('');
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
// Raw source capture — output tokens ({{ site.brand.name }}) ride
|
|
641
|
+
// into the YAML verbatim and liquify at render, like every string arg.
|
|
642
|
+
parts.push(typeof token.getText === 'function'
|
|
643
|
+
? token.getText()
|
|
644
|
+
: token.input.slice(token.begin, token.end));
|
|
645
|
+
}
|
|
646
|
+
throw new Error(`{% ${tagName} %} block not closed with {% end${tagName} %}`);
|
|
647
|
+
},
|
|
648
|
+
|
|
649
|
+
* render(context, emitter) {
|
|
650
|
+
const nameMatch = this.markup.match(/^"([^"]+)"|^'([^']+)'/);
|
|
651
|
+
let name;
|
|
652
|
+
let rest;
|
|
653
|
+
if (nameMatch) {
|
|
654
|
+
name = nameMatch[1] ?? nameMatch[2];
|
|
655
|
+
rest = this.markup.slice(nameMatch[0].length);
|
|
656
|
+
} else {
|
|
657
|
+
// Expression name (the showcase's lane): everything up to the
|
|
658
|
+
// first comma evaluates against the caller's scope and must yield
|
|
659
|
+
// an id string. Bare paths only — a filter taking comma-separated
|
|
660
|
+
// params needs a {% capture %} first.
|
|
661
|
+
const comma = this.markup.indexOf(',');
|
|
662
|
+
const expr = (comma === -1 ? this.markup : this.markup.slice(0, comma)).trim();
|
|
663
|
+
if (!expr) throw new Error(`{% ${tagName} %} needs a name: {% ${tagName} "marketing/hero" %} (or an expression resolving to an id)`);
|
|
664
|
+
name = yield this.liquid.evalValue(expr, context);
|
|
665
|
+
if (typeof name !== 'string' || !name) {
|
|
666
|
+
throw new Error(`{% ${tagName} ${expr} %}: the name expression must resolve to an entry id string — got ${JSON.stringify(name)}`);
|
|
667
|
+
}
|
|
668
|
+
rest = comma === -1 ? '' : this.markup.slice(comma);
|
|
669
|
+
}
|
|
670
|
+
if (!NAME_SHAPE.test(name)) throw new Error(`{% ${tagName} "${name}" %}: ids are kebab-case category paths (marketing/hero)`);
|
|
671
|
+
|
|
672
|
+
const entry = resolveEntry(name);
|
|
673
|
+
if (!entry) {
|
|
674
|
+
throw new Error(`{% ${tagName} "${name}" %}: no ${kind.dirname}/${name}/${kind.basename}.html in any layer (${roots.join(', ') || 'no roots'})`);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// ---- gather passed args (inline XOR YAML remainder; slots ride either)
|
|
678
|
+
const inlinePairs = parseInlineArgs(rest);
|
|
679
|
+
const { yamlText, slots } = this.bodyText !== null
|
|
680
|
+
? (this.slotSplit ||= extractSlots(this.bodyText))
|
|
681
|
+
: { yamlText: null, slots: [] };
|
|
682
|
+
if (yamlText !== null && yamlText.trim() && inlinePairs.length) {
|
|
683
|
+
throw new Error(`{% ${tagName} "${name}" %}: use inline args OR a YAML body, not both (slot blocks compose with either)`);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
let passed = {};
|
|
687
|
+
let dataArg;
|
|
688
|
+
for (const { key, expr } of inlinePairs) {
|
|
689
|
+
const value = yield this.liquid.evalValue(expr, context);
|
|
690
|
+
if (key === 'data') dataArg = value;
|
|
691
|
+
else passed[key] = value;
|
|
692
|
+
}
|
|
693
|
+
if (yamlText !== null && yamlText.trim()) {
|
|
694
|
+
const parsed = yaml.load(yamlText);
|
|
695
|
+
if (parsed === null || parsed === undefined) {
|
|
696
|
+
// whitespace-only body — nothing passed
|
|
697
|
+
} else if (typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
698
|
+
throw new Error(`{% ${tagName} "${name}" %}: the YAML body must be a mapping of args`);
|
|
699
|
+
} else {
|
|
700
|
+
({ data: dataArg, ...passed } = parsed);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
if (dataArg !== undefined && dataArg !== null && (typeof dataArg !== 'object' || Array.isArray(dataArg))) {
|
|
704
|
+
warn(`${tagName} "${name}": data must be an object — ignoring ${typeof dataArg}`);
|
|
705
|
+
dataArg = undefined;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// ---- slots render NOW, in the caller's scope (site.*, captures,
|
|
709
|
+
// omega_* tags) — finished HTML that merges outermost below, after
|
|
710
|
+
// call-site liquification, so it never re-renders.
|
|
711
|
+
const scope = typeof context.getAll === 'function' ? context.getAll() : context.environments;
|
|
712
|
+
const slotValues = {};
|
|
713
|
+
for (const slot of slots) {
|
|
714
|
+
// Untrimmed — surrounding whitespace is cosmetic in HTML but load-
|
|
715
|
+
// bearing for byte-exact conversions; whitespace-ONLY collapses to
|
|
716
|
+
// '' so an empty slot reads as explicit-empty (kills a default).
|
|
717
|
+
const rendered = yield this.liquid.parseAndRender(slot.source, scope);
|
|
718
|
+
slotValues[slot.name] = rendered.trim() === '' ? '' : rendered;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// ---- schema validation (top level, warn-only)
|
|
722
|
+
const schema = entry.meta.args;
|
|
723
|
+
if (schema && typeof schema === 'object') {
|
|
724
|
+
const known = Object.keys(schema);
|
|
725
|
+
const incoming = { ...(dataArg || {}), ...passed, ...slotValues };
|
|
726
|
+
for (const [key, value] of Object.entries(incoming)) {
|
|
727
|
+
if (!known.includes(key)) {
|
|
728
|
+
warn(`${tagName} "${name}": unknown arg "${key}"${suggest(key, known)}`);
|
|
729
|
+
} else {
|
|
730
|
+
const type = typeof schema[key] === 'string' ? schema[key] : schema[key]?.type;
|
|
731
|
+
if (type && !matchesType(value, type)) {
|
|
732
|
+
warn(`${tagName} "${name}": arg "${key}" should be ${type}`);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// ---- defaults ← data ← named args, then call-site liquification,
|
|
739
|
+
// then slots (outermost — already rendered)
|
|
740
|
+
let args = deepMerge(entry.meta.defaults || {}, dataArg || {});
|
|
741
|
+
args = deepMerge(args, passed);
|
|
742
|
+
args = yield liquifyDeep(this.liquid, scope, args);
|
|
743
|
+
Object.assign(args, slotValues);
|
|
744
|
+
|
|
745
|
+
// ---- context-free render: { args } is the whole scope
|
|
746
|
+
let templates = templateCache.get(entry.templatePath);
|
|
747
|
+
if (!templates) {
|
|
748
|
+
templates = this.liquid.parse(fs.readFileSync(entry.templatePath, 'utf8'), entry.templatePath);
|
|
749
|
+
templateCache.set(entry.templatePath, templates);
|
|
750
|
+
}
|
|
751
|
+
emitter.write(yield this.liquid.render(templates, { args }));
|
|
752
|
+
},
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// ---- {% composition %}…{% endcomposition %} (spec §8): the page-body
|
|
757
|
+
// replacement guard. Wraps a layout's default composition; page content
|
|
758
|
+
// (blank for every default page) picks the branch. Parity templates parse
|
|
759
|
+
// lazily per engine so the non-blank branch renders the exact line the
|
|
760
|
+
// wrap replaced.
|
|
761
|
+
let contentParity = null;
|
|
762
|
+
engine.registerTag('composition', {
|
|
763
|
+
parse(tagToken, remainTokens) {
|
|
764
|
+
this.tpls = [];
|
|
765
|
+
let closed = false;
|
|
766
|
+
while (remainTokens.length) {
|
|
767
|
+
const token = remainTokens.shift();
|
|
768
|
+
if (token.name === 'endcomposition') {
|
|
769
|
+
closed = true;
|
|
770
|
+
break;
|
|
771
|
+
}
|
|
772
|
+
this.tpls.push(this.liquid.parser.parseToken(token, remainTokens));
|
|
773
|
+
}
|
|
774
|
+
if (!closed) throw new Error('{% composition %} not closed with {% endcomposition %}');
|
|
775
|
+
},
|
|
776
|
+
|
|
777
|
+
* render(context, emitter) {
|
|
778
|
+
const read = (key) => {
|
|
779
|
+
try {
|
|
780
|
+
return context.getSync([key]);
|
|
781
|
+
} catch {
|
|
782
|
+
return undefined;
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
const content = read('content');
|
|
786
|
+
const blank = typeof content !== 'string' || content.trim() === '';
|
|
787
|
+
|
|
788
|
+
// Ian's ruling (2026-07-19): a page that writes a body MEANS it — the
|
|
789
|
+
// body REPLACES the layout's default composition, no flag needed (the
|
|
790
|
+
// old `composition: true` key is retired, and #607 retired the legacy
|
|
791
|
+
// add-below `append: true` escape hatch with it — a page that wants the
|
|
792
|
+
// default bands writes them, which is what `omega customize` hands it).
|
|
793
|
+
if (!blank) {
|
|
794
|
+
if (!contentParity) contentParity = this.liquid.parse('{{ content | omega_content_format }}');
|
|
795
|
+
emitter.write(yield this.liquid.renderer.renderTemplates(contentParity, context));
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
emitter.write(yield this.liquid.renderer.renderTemplates(this.tpls, context));
|
|
800
|
+
// Blank content still flows through (it is only whitespace) — byte-
|
|
801
|
+
// parity with the replaced layout line, which emitted the chain's
|
|
802
|
+
// newlines.
|
|
803
|
+
if (typeof content === 'string') emitter.write(content);
|
|
804
|
+
},
|
|
805
|
+
});
|
|
806
|
+
|
|
807
|
+
return engine;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
module.exports = { registerSectionTags, collectSectionAssets, buildSectionLibrary, parseInlineArgs, levenshtein, KINDS };
|