@morphemecms/cms 0.0.0-stage → 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 +21 -0
- package/README.md +51 -3
- package/astro.d.mts +2 -0
- package/astro.mjs +162 -0
- package/bin/morpheme.mjs +38 -0
- package/client.d.ts +10 -0
- package/defaults/blockTexts.ts +33 -0
- package/defaults/collections.ts +774 -0
- package/defaults/colors.ts +125 -0
- package/defaults/company.ts +20 -0
- package/defaults/editor.ts +178 -0
- package/defaults/internalLinks.ts +30 -0
- package/defaults/opens.ts +18 -0
- package/defaults/popup.tsx +93 -0
- package/defaults/privacy.ts +79 -0
- package/defaults/rules.ts +450 -0
- package/defaults/schema.ts +16 -0
- package/defaults/sitedata.ts +129 -0
- package/defaults/standard.ts +106 -0
- package/defaults/standardPages.ts +87 -0
- package/defaults/texts.ts +481 -0
- package/demo/README.md +26 -0
- package/demo/public/apple-touch-icon.png +0 -0
- package/demo/public/editor/apple-touch-icon.png +0 -0
- package/demo/public/editor/icon-192.png +0 -0
- package/demo/public/editor/icon-512.png +0 -0
- package/demo/public/editor/icon-maskable-512.png +0 -0
- package/demo/public/favicon.ico +0 -0
- package/demo/public/favicon.svg +1 -0
- package/demo/public/images/uploads/2026/10/andromeda.webp +0 -0
- package/demo/public/images/uploads/2026/10/earth-from-space.webp +0 -0
- package/demo/public/images/uploads/2026/10/editor-blog.webp +0 -0
- package/demo/public/images/uploads/2026/10/editor-colors.webp +0 -0
- package/demo/public/images/uploads/2026/10/editor-home.webp +0 -0
- package/demo/public/images/uploads/2026/10/editor-page.webp +0 -0
- package/demo/public/images/uploads/2026/10/editor-pages.webp +0 -0
- package/demo/public/images/uploads/2026/10/editor-seo.webp +0 -0
- package/demo/public/images/uploads/2026/10/editor-start.webp +0 -0
- package/demo/public/images/uploads/2026/10/editor-themes.webp +0 -0
- package/demo/public/images/uploads/2026/10/moon.webp +0 -0
- package/demo/public/images/uploads/2026/10/saturn.webp +0 -0
- package/demo/public/logo.svg +1 -0
- package/demo/src/content/blog/build-a-page-from-blocks.md +19 -0
- package/demo/src/content/blog/colors-everyone-can-read.md +19 -0
- package/demo/src/content/blog/edit-your-website-from-your-phone.md +21 -0
- package/demo/src/content/blog/every-save-is-a-version.md +21 -0
- package/demo/src/content/blog/schedule-a-post.md +17 -0
- package/demo/src/content/blog/secure-from-day-one.md +17 -0
- package/demo/src/content/blog/seo-without-the-guesswork.md +23 -0
- package/demo/src/content/blog/switch-themes-without-losing-anything.md +23 -0
- package/demo/src/content/blog/the-app-store.md +21 -0
- package/demo/src/content/pages/about.md +22 -0
- package/demo/src/content/pages/app-store.md +30 -0
- package/demo/src/content/pages/blocks.md +98 -0
- package/demo/src/content/pages/blog-page.md +11 -0
- package/demo/src/content/pages/contact.md +16 -0
- package/demo/src/content/pages/get-started.md +20 -0
- package/demo/src/content/pages/home.md +26 -0
- package/demo/src/content/pages/page-not-found.md +11 -0
- package/demo/src/content/pages/privacy-policy.md +24 -0
- package/demo/src/data/blocks.json +25 -0
- package/demo/src/data/booking.json +6 -0
- package/demo/src/data/categories/apps.json +6 -0
- package/demo/src/data/categories/design.json +6 -0
- package/demo/src/data/categories/editing.json +6 -0
- package/demo/src/data/categories/security.json +6 -0
- package/demo/src/data/categories/seo.json +6 -0
- package/demo/src/data/colors.json +75 -0
- package/demo/src/data/contact.json +8 -0
- package/demo/src/data/cookies.json +21 -0
- package/demo/src/data/footer.json +27 -0
- package/demo/src/data/menu.json +35 -0
- package/demo/src/data/mobile-menu.json +25 -0
- package/demo/src/data/popups/booking-bar.json +13 -0
- package/demo/src/data/popups/try-the-editor.json +16 -0
- package/demo/src/data/standard-pages.json +8 -0
- package/demo/src/data/testimonials/sample-bakery.json +10 -0
- package/demo/src/data/testimonials/sample-clinic.json +10 -0
- package/demo/src/data/testimonials/sample-studio.json +10 -0
- package/demo/src/site/colors.ts +11 -0
- package/demo/src/site/config.ts +19 -0
- package/icons/lucide/LICENSE +43 -0
- package/icons/lucide/LICENSE-material-design-icons +20 -0
- package/icons/lucide/address-book.svg +1 -0
- package/icons/lucide/app-window.svg +1 -0
- package/icons/lucide/arrow-counter-clockwise.svg +1 -0
- package/icons/lucide/arrow-down.svg +1 -0
- package/icons/lucide/arrow-left.svg +1 -0
- package/icons/lucide/arrow-right.svg +1 -0
- package/icons/lucide/arrow-square-out.svg +1 -0
- package/icons/lucide/arrow-u-up-left.svg +1 -0
- package/icons/lucide/arrow-u-up-right.svg +1 -0
- package/icons/lucide/arrow-up-right.svg +1 -0
- package/icons/lucide/arrow-up.svg +1 -0
- package/icons/lucide/arrows-down-up.svg +1 -0
- package/icons/lucide/arrows-in-line-horizontal.svg +1 -0
- package/icons/lucide/arrows-out-line-horizontal.svg +1 -0
- package/icons/lucide/article.svg +1 -0
- package/icons/lucide/bank.svg +1 -0
- package/icons/lucide/bell.svg +1 -0
- package/icons/lucide/bicycle.svg +1 -0
- package/icons/lucide/binoculars.svg +1 -0
- package/icons/lucide/book-open-text.svg +1 -0
- package/icons/lucide/book-open.svg +1 -0
- package/icons/lucide/browser.svg +1 -0
- package/icons/lucide/buildings.svg +1 -0
- package/icons/lucide/bus.svg +1 -0
- package/icons/lucide/calendar-blank.svg +1 -0
- package/icons/lucide/calendar-check.svg +1 -0
- package/icons/lucide/car.svg +1 -0
- package/icons/lucide/cards.svg +1 -0
- package/icons/lucide/caret-down.svg +1 -0
- package/icons/lucide/caret-left.svg +1 -0
- package/icons/lucide/caret-right.svg +1 -0
- package/icons/lucide/caret-up.svg +1 -0
- package/icons/lucide/certificate.svg +1 -0
- package/icons/lucide/chart-line-up.svg +1 -0
- package/icons/lucide/chats.svg +1 -0
- package/icons/lucide/check-circle.svg +1 -0
- package/icons/lucide/check.svg +1 -0
- package/icons/lucide/circle-half.svg +1 -0
- package/icons/lucide/circle.svg +1 -0
- package/icons/lucide/clock-counter-clockwise.svg +1 -0
- package/icons/lucide/clock.svg +1 -0
- package/icons/lucide/code.svg +1 -0
- package/icons/lucide/coffee.svg +1 -0
- package/icons/lucide/columns.svg +1 -0
- package/icons/lucide/cookie.svg +1 -0
- package/icons/lucide/copy.svg +1 -0
- package/icons/lucide/credit-card.svg +1 -0
- package/icons/lucide/currency-circle-dollar.svg +1 -0
- package/icons/lucide/cursor-click.svg +1 -0
- package/icons/lucide/database.svg +1 -0
- package/icons/lucide/desktop.svg +1 -0
- package/icons/lucide/device-mobile.svg +1 -0
- package/icons/lucide/door-open.svg +1 -0
- package/icons/lucide/download-simple.svg +1 -0
- package/icons/lucide/envelope-simple.svg +1 -0
- package/icons/lucide/eye-slash.svg +1 -0
- package/icons/lucide/eye.svg +1 -0
- package/icons/lucide/file-pdf.svg +1 -0
- package/icons/lucide/file-text.svg +1 -0
- package/icons/lucide/file-video.svg +1 -0
- package/icons/lucide/file-zip.svg +1 -0
- package/icons/lucide/flower-lotus.svg +1 -0
- package/icons/lucide/folder-simple.svg +1 -0
- package/icons/lucide/funnel.svg +1 -0
- package/icons/lucide/gauge.svg +1 -0
- package/icons/lucide/gear.svg +1 -0
- package/icons/lucide/github-logo.svg +1 -0
- package/icons/lucide/globe.svg +1 -0
- package/icons/lucide/google-logo.svg +1 -0
- package/icons/lucide/graduation-cap.svg +1 -0
- package/icons/lucide/hammer.svg +1 -0
- package/icons/lucide/hand-heart.svg +1 -0
- package/icons/lucide/handshake.svg +1 -0
- package/icons/lucide/hard-drives.svg +1 -0
- package/icons/lucide/heart.svg +1 -0
- package/icons/lucide/house.svg +1 -0
- package/icons/lucide/image-square.svg +1 -0
- package/icons/lucide/image.svg +1 -0
- package/icons/lucide/info.svg +1 -0
- package/icons/lucide/keyboard.svg +1 -0
- package/icons/lucide/leaf.svg +1 -0
- package/icons/lucide/lifebuoy.svg +1 -0
- package/icons/lucide/lightbulb.svg +1 -0
- package/icons/lucide/link-break.svg +1 -0
- package/icons/lucide/link-simple.svg +1 -0
- package/icons/lucide/list-bullets.svg +1 -0
- package/icons/lucide/list-checks.svg +1 -0
- package/icons/lucide/list-numbers.svg +1 -0
- package/icons/lucide/list.svg +1 -0
- package/icons/lucide/lock-simple-open.svg +1 -0
- package/icons/lucide/lock-simple.svg +1 -0
- package/icons/lucide/magnifying-glass.svg +1 -0
- package/icons/lucide/map-pin.svg +1 -0
- package/icons/lucide/map-trifold.svg +1 -0
- package/icons/lucide/medal.svg +1 -0
- package/icons/lucide/megaphone.svg +1 -0
- package/icons/lucide/minus.svg +1 -0
- package/icons/lucide/moon.svg +1 -0
- package/icons/lucide/newspaper.svg +1 -0
- package/icons/lucide/pack.json +23 -0
- package/icons/lucide/paint-brush-broad.svg +1 -0
- package/icons/lucide/palette.svg +1 -0
- package/icons/lucide/paper-plane-tilt.svg +1 -0
- package/icons/lucide/pencil-simple.svg +1 -0
- package/icons/lucide/phone.svg +1 -0
- package/icons/lucide/play-fill.svg +1 -0
- package/icons/lucide/plus.svg +1 -0
- package/icons/lucide/prohibit.svg +1 -0
- package/icons/lucide/puzzle-piece.svg +1 -0
- package/icons/lucide/question.svg +1 -0
- package/icons/lucide/quotes.svg +1 -0
- package/icons/lucide/rows.svg +1 -0
- package/icons/lucide/ruler.svg +1 -0
- package/icons/lucide/scan.svg +1 -0
- package/icons/lucide/shapes.svg +1 -0
- package/icons/lucide/share-network.svg +1 -0
- package/icons/lucide/shield-check.svg +1 -0
- package/icons/lucide/sidebar-simple.svg +1 -0
- package/icons/lucide/sign-out.svg +1 -0
- package/icons/lucide/signpost.svg +1 -0
- package/icons/lucide/sliders-horizontal.svg +1 -0
- package/icons/lucide/smiley.svg +1 -0
- package/icons/lucide/sparkle.svg +1 -0
- package/icons/lucide/square-half-bottom.svg +1 -0
- package/icons/lucide/square.svg +1 -0
- package/icons/lucide/squares-four.svg +1 -0
- package/icons/lucide/sticker.svg +1 -0
- package/icons/lucide/storefront.svg +1 -0
- package/icons/lucide/sun.svg +1 -0
- package/icons/lucide/swatches.svg +1 -0
- package/icons/lucide/tag.svg +1 -0
- package/icons/lucide/text-aa.svg +1 -0
- package/icons/lucide/text-align-left.svg +1 -0
- package/icons/lucide/text-b.svg +1 -0
- package/icons/lucide/text-h-one.svg +1 -0
- package/icons/lucide/text-h-three.svg +1 -0
- package/icons/lucide/text-h-two.svg +1 -0
- package/icons/lucide/text-italic.svg +1 -0
- package/icons/lucide/text-t.svg +1 -0
- package/icons/lucide/ticket.svg +1 -0
- package/icons/lucide/toggle-right.svg +1 -0
- package/icons/lucide/train.svg +1 -0
- package/icons/lucide/trash.svg +1 -0
- package/icons/lucide/upload-simple.svg +1 -0
- package/icons/lucide/user-circle.svg +1 -0
- package/icons/lucide/user.svg +1 -0
- package/icons/lucide/users-three.svg +1 -0
- package/icons/lucide/users.svg +1 -0
- package/icons/lucide/video-camera.svg +1 -0
- package/icons/lucide/warning-circle.svg +1 -0
- package/icons/lucide/warning.svg +1 -0
- package/icons/lucide/wave-sine.svg +1 -0
- package/icons/lucide/wheelchair.svg +1 -0
- package/icons/lucide/wrench.svg +1 -0
- package/icons/lucide/x.svg +1 -0
- package/icons/material-symbols/LICENSE +201 -0
- package/icons/material-symbols/LICENSE-material-design-icons +20 -0
- package/icons/material-symbols/address-book.svg +1 -0
- package/icons/material-symbols/app-window.svg +1 -0
- package/icons/material-symbols/arrow-counter-clockwise.svg +1 -0
- package/icons/material-symbols/arrow-down.svg +1 -0
- package/icons/material-symbols/arrow-left.svg +1 -0
- package/icons/material-symbols/arrow-right.svg +1 -0
- package/icons/material-symbols/arrow-square-out.svg +1 -0
- package/icons/material-symbols/arrow-u-up-left.svg +1 -0
- package/icons/material-symbols/arrow-u-up-right.svg +1 -0
- package/icons/material-symbols/arrow-up-right.svg +1 -0
- package/icons/material-symbols/arrow-up.svg +1 -0
- package/icons/material-symbols/arrows-down-up.svg +1 -0
- package/icons/material-symbols/arrows-in-line-horizontal.svg +1 -0
- package/icons/material-symbols/arrows-out-line-horizontal.svg +1 -0
- package/icons/material-symbols/article.svg +1 -0
- package/icons/material-symbols/bank.svg +1 -0
- package/icons/material-symbols/bell.svg +1 -0
- package/icons/material-symbols/bicycle.svg +1 -0
- package/icons/material-symbols/binoculars.svg +1 -0
- package/icons/material-symbols/book-open-text.svg +1 -0
- package/icons/material-symbols/book-open.svg +1 -0
- package/icons/material-symbols/browser.svg +1 -0
- package/icons/material-symbols/buildings.svg +1 -0
- package/icons/material-symbols/bus.svg +1 -0
- package/icons/material-symbols/calendar-blank.svg +1 -0
- package/icons/material-symbols/calendar-check.svg +1 -0
- package/icons/material-symbols/car.svg +1 -0
- package/icons/material-symbols/cards.svg +1 -0
- package/icons/material-symbols/caret-down.svg +1 -0
- package/icons/material-symbols/caret-left.svg +1 -0
- package/icons/material-symbols/caret-right.svg +1 -0
- package/icons/material-symbols/caret-up.svg +1 -0
- package/icons/material-symbols/certificate.svg +1 -0
- package/icons/material-symbols/chart-line-up.svg +1 -0
- package/icons/material-symbols/chats.svg +1 -0
- package/icons/material-symbols/check-circle.svg +1 -0
- package/icons/material-symbols/check.svg +1 -0
- package/icons/material-symbols/circle-half.svg +1 -0
- package/icons/material-symbols/circle.svg +1 -0
- package/icons/material-symbols/clock-counter-clockwise.svg +1 -0
- package/icons/material-symbols/clock.svg +1 -0
- package/icons/material-symbols/code.svg +1 -0
- package/icons/material-symbols/coffee.svg +1 -0
- package/icons/material-symbols/columns.svg +1 -0
- package/icons/material-symbols/cookie.svg +1 -0
- package/icons/material-symbols/copy.svg +1 -0
- package/icons/material-symbols/credit-card.svg +1 -0
- package/icons/material-symbols/currency-circle-dollar.svg +1 -0
- package/icons/material-symbols/cursor-click.svg +1 -0
- package/icons/material-symbols/database.svg +1 -0
- package/icons/material-symbols/desktop.svg +1 -0
- package/icons/material-symbols/device-mobile.svg +1 -0
- package/icons/material-symbols/door-open.svg +1 -0
- package/icons/material-symbols/download-simple.svg +1 -0
- package/icons/material-symbols/envelope-simple.svg +1 -0
- package/icons/material-symbols/eye-slash.svg +1 -0
- package/icons/material-symbols/eye.svg +1 -0
- package/icons/material-symbols/file-pdf.svg +1 -0
- package/icons/material-symbols/file-text.svg +1 -0
- package/icons/material-symbols/file-video.svg +1 -0
- package/icons/material-symbols/file-zip.svg +1 -0
- package/icons/material-symbols/flower-lotus.svg +1 -0
- package/icons/material-symbols/folder-simple.svg +1 -0
- package/icons/material-symbols/funnel.svg +1 -0
- package/icons/material-symbols/gauge.svg +1 -0
- package/icons/material-symbols/gear.svg +1 -0
- package/icons/material-symbols/github-logo.svg +1 -0
- package/icons/material-symbols/globe.svg +1 -0
- package/icons/material-symbols/google-logo.svg +1 -0
- package/icons/material-symbols/graduation-cap.svg +1 -0
- package/icons/material-symbols/hammer.svg +1 -0
- package/icons/material-symbols/hand-heart.svg +1 -0
- package/icons/material-symbols/handshake.svg +1 -0
- package/icons/material-symbols/hard-drives.svg +1 -0
- package/icons/material-symbols/heart.svg +1 -0
- package/icons/material-symbols/house.svg +1 -0
- package/icons/material-symbols/image-square.svg +1 -0
- package/icons/material-symbols/image.svg +1 -0
- package/icons/material-symbols/info.svg +1 -0
- package/icons/material-symbols/keyboard.svg +1 -0
- package/icons/material-symbols/leaf.svg +1 -0
- package/icons/material-symbols/lifebuoy.svg +1 -0
- package/icons/material-symbols/lightbulb.svg +1 -0
- package/icons/material-symbols/link-break.svg +1 -0
- package/icons/material-symbols/link-simple.svg +1 -0
- package/icons/material-symbols/list-bullets.svg +1 -0
- package/icons/material-symbols/list-checks.svg +1 -0
- package/icons/material-symbols/list-numbers.svg +1 -0
- package/icons/material-symbols/list.svg +1 -0
- package/icons/material-symbols/lock-simple-open.svg +1 -0
- package/icons/material-symbols/lock-simple.svg +1 -0
- package/icons/material-symbols/magnifying-glass.svg +1 -0
- package/icons/material-symbols/map-pin.svg +1 -0
- package/icons/material-symbols/map-trifold.svg +1 -0
- package/icons/material-symbols/medal.svg +1 -0
- package/icons/material-symbols/megaphone.svg +1 -0
- package/icons/material-symbols/minus.svg +1 -0
- package/icons/material-symbols/moon.svg +1 -0
- package/icons/material-symbols/newspaper.svg +1 -0
- package/icons/material-symbols/pack.json +29 -0
- package/icons/material-symbols/paint-brush-broad.svg +1 -0
- package/icons/material-symbols/palette.svg +1 -0
- package/icons/material-symbols/paper-plane-tilt.svg +1 -0
- package/icons/material-symbols/pencil-simple.svg +1 -0
- package/icons/material-symbols/phone.svg +1 -0
- package/icons/material-symbols/play-fill.svg +1 -0
- package/icons/material-symbols/plus.svg +1 -0
- package/icons/material-symbols/prohibit.svg +1 -0
- package/icons/material-symbols/puzzle-piece.svg +1 -0
- package/icons/material-symbols/question.svg +1 -0
- package/icons/material-symbols/quotes.svg +1 -0
- package/icons/material-symbols/rows.svg +1 -0
- package/icons/material-symbols/ruler.svg +1 -0
- package/icons/material-symbols/scan.svg +1 -0
- package/icons/material-symbols/shapes.svg +1 -0
- package/icons/material-symbols/share-network.svg +1 -0
- package/icons/material-symbols/shield-check.svg +1 -0
- package/icons/material-symbols/sidebar-simple.svg +1 -0
- package/icons/material-symbols/sign-out.svg +1 -0
- package/icons/material-symbols/signpost.svg +1 -0
- package/icons/material-symbols/sliders-horizontal.svg +1 -0
- package/icons/material-symbols/smiley.svg +1 -0
- package/icons/material-symbols/sparkle.svg +1 -0
- package/icons/material-symbols/square-half-bottom.svg +1 -0
- package/icons/material-symbols/square.svg +1 -0
- package/icons/material-symbols/squares-four.svg +1 -0
- package/icons/material-symbols/sticker.svg +1 -0
- package/icons/material-symbols/storefront.svg +1 -0
- package/icons/material-symbols/sun.svg +1 -0
- package/icons/material-symbols/swatches.svg +1 -0
- package/icons/material-symbols/tag.svg +1 -0
- package/icons/material-symbols/text-aa.svg +1 -0
- package/icons/material-symbols/text-align-left.svg +1 -0
- package/icons/material-symbols/text-b.svg +1 -0
- package/icons/material-symbols/text-h-one.svg +1 -0
- package/icons/material-symbols/text-h-three.svg +1 -0
- package/icons/material-symbols/text-h-two.svg +1 -0
- package/icons/material-symbols/text-italic.svg +1 -0
- package/icons/material-symbols/text-t.svg +1 -0
- package/icons/material-symbols/ticket.svg +1 -0
- package/icons/material-symbols/toggle-right.svg +1 -0
- package/icons/material-symbols/train.svg +1 -0
- package/icons/material-symbols/trash.svg +1 -0
- package/icons/material-symbols/upload-simple.svg +1 -0
- package/icons/material-symbols/user-circle.svg +1 -0
- package/icons/material-symbols/user.svg +1 -0
- package/icons/material-symbols/users-three.svg +1 -0
- package/icons/material-symbols/users.svg +1 -0
- package/icons/material-symbols/video-camera.svg +1 -0
- package/icons/material-symbols/warning-circle.svg +1 -0
- package/icons/material-symbols/warning.svg +1 -0
- package/icons/material-symbols/wave-sine.svg +1 -0
- package/icons/material-symbols/wheelchair.svg +1 -0
- package/icons/material-symbols/wrench.svg +1 -0
- package/icons/material-symbols/x.svg +1 -0
- package/icons/phosphor/LICENSE +21 -0
- package/icons/phosphor/address-book.svg +1 -0
- package/icons/phosphor/app-window.svg +1 -0
- package/icons/phosphor/arrow-counter-clockwise.svg +1 -0
- package/icons/phosphor/arrow-down.svg +1 -0
- package/icons/phosphor/arrow-left.svg +1 -0
- package/icons/phosphor/arrow-right.svg +1 -0
- package/icons/phosphor/arrow-square-out.svg +1 -0
- package/icons/phosphor/arrow-u-up-left.svg +1 -0
- package/icons/phosphor/arrow-u-up-right.svg +1 -0
- package/icons/phosphor/arrow-up-right.svg +1 -0
- package/icons/phosphor/arrow-up.svg +1 -0
- package/icons/phosphor/arrows-down-up.svg +1 -0
- package/icons/phosphor/arrows-in-line-horizontal.svg +1 -0
- package/icons/phosphor/arrows-out-line-horizontal.svg +1 -0
- package/icons/phosphor/article.svg +1 -0
- package/icons/phosphor/bank.svg +1 -0
- package/icons/phosphor/bell.svg +1 -0
- package/icons/phosphor/bicycle.svg +1 -0
- package/icons/phosphor/binoculars.svg +1 -0
- package/icons/phosphor/book-open-text.svg +1 -0
- package/icons/phosphor/book-open.svg +1 -0
- package/icons/phosphor/browser.svg +1 -0
- package/icons/phosphor/buildings.svg +1 -0
- package/icons/phosphor/bus.svg +1 -0
- package/icons/phosphor/calendar-blank.svg +1 -0
- package/icons/phosphor/calendar-check.svg +1 -0
- package/icons/phosphor/car.svg +1 -0
- package/icons/phosphor/cards.svg +1 -0
- package/icons/phosphor/caret-down.svg +1 -0
- package/icons/phosphor/caret-left.svg +1 -0
- package/icons/phosphor/caret-right.svg +1 -0
- package/icons/phosphor/caret-up.svg +1 -0
- package/icons/phosphor/certificate.svg +1 -0
- package/icons/phosphor/chart-line-up.svg +1 -0
- package/icons/phosphor/chats.svg +1 -0
- package/icons/phosphor/check-circle.svg +1 -0
- package/icons/phosphor/check.svg +1 -0
- package/icons/phosphor/circle-half.svg +1 -0
- package/icons/phosphor/circle.svg +1 -0
- package/icons/phosphor/clock-counter-clockwise.svg +1 -0
- package/icons/phosphor/clock.svg +1 -0
- package/icons/phosphor/code.svg +1 -0
- package/icons/phosphor/coffee.svg +1 -0
- package/icons/phosphor/columns.svg +1 -0
- package/icons/phosphor/cookie.svg +1 -0
- package/icons/phosphor/copy.svg +1 -0
- package/icons/phosphor/credit-card.svg +1 -0
- package/icons/phosphor/currency-circle-dollar.svg +1 -0
- package/icons/phosphor/cursor-click.svg +1 -0
- package/icons/phosphor/database.svg +1 -0
- package/icons/phosphor/desktop.svg +1 -0
- package/icons/phosphor/device-mobile.svg +1 -0
- package/icons/phosphor/door-open.svg +1 -0
- package/icons/phosphor/download-simple.svg +1 -0
- package/icons/phosphor/envelope-simple.svg +1 -0
- package/icons/phosphor/eye-slash.svg +1 -0
- package/icons/phosphor/eye.svg +1 -0
- package/icons/phosphor/file-pdf.svg +1 -0
- package/icons/phosphor/file-text.svg +1 -0
- package/icons/phosphor/file-video.svg +1 -0
- package/icons/phosphor/file-zip.svg +1 -0
- package/icons/phosphor/flower-lotus.svg +1 -0
- package/icons/phosphor/folder-simple.svg +1 -0
- package/icons/phosphor/funnel.svg +1 -0
- package/icons/phosphor/gauge.svg +1 -0
- package/icons/phosphor/gear.svg +1 -0
- package/icons/phosphor/github-logo.svg +1 -0
- package/icons/phosphor/globe.svg +1 -0
- package/icons/phosphor/google-logo.svg +1 -0
- package/icons/phosphor/graduation-cap.svg +1 -0
- package/icons/phosphor/hammer.svg +1 -0
- package/icons/phosphor/hand-heart.svg +1 -0
- package/icons/phosphor/handshake.svg +1 -0
- package/icons/phosphor/hard-drives.svg +1 -0
- package/icons/phosphor/heart.svg +1 -0
- package/icons/phosphor/house.svg +1 -0
- package/icons/phosphor/image-square.svg +1 -0
- package/icons/phosphor/image.svg +1 -0
- package/icons/phosphor/info.svg +1 -0
- package/icons/phosphor/keyboard.svg +1 -0
- package/icons/phosphor/leaf.svg +1 -0
- package/icons/phosphor/lifebuoy.svg +1 -0
- package/icons/phosphor/lightbulb.svg +1 -0
- package/icons/phosphor/link-break.svg +1 -0
- package/icons/phosphor/link-simple.svg +1 -0
- package/icons/phosphor/list-bullets.svg +1 -0
- package/icons/phosphor/list-checks.svg +1 -0
- package/icons/phosphor/list-numbers.svg +1 -0
- package/icons/phosphor/list.svg +1 -0
- package/icons/phosphor/lock-simple-open.svg +1 -0
- package/icons/phosphor/lock-simple.svg +1 -0
- package/icons/phosphor/magnifying-glass.svg +1 -0
- package/icons/phosphor/map-pin.svg +1 -0
- package/icons/phosphor/map-trifold.svg +1 -0
- package/icons/phosphor/medal.svg +1 -0
- package/icons/phosphor/megaphone.svg +1 -0
- package/icons/phosphor/minus.svg +1 -0
- package/icons/phosphor/moon.svg +1 -0
- package/icons/phosphor/newspaper.svg +1 -0
- package/icons/phosphor/pack.json +8 -0
- package/icons/phosphor/paint-brush-broad.svg +1 -0
- package/icons/phosphor/palette.svg +1 -0
- package/icons/phosphor/paper-plane-tilt.svg +1 -0
- package/icons/phosphor/pencil-simple.svg +1 -0
- package/icons/phosphor/phone.svg +1 -0
- package/icons/phosphor/play-fill.svg +1 -0
- package/icons/phosphor/plus.svg +1 -0
- package/icons/phosphor/prohibit.svg +1 -0
- package/icons/phosphor/puzzle-piece.svg +1 -0
- package/icons/phosphor/question.svg +1 -0
- package/icons/phosphor/quotes.svg +1 -0
- package/icons/phosphor/rows.svg +1 -0
- package/icons/phosphor/ruler.svg +1 -0
- package/icons/phosphor/scan.svg +1 -0
- package/icons/phosphor/shapes.svg +1 -0
- package/icons/phosphor/share-network.svg +1 -0
- package/icons/phosphor/shield-check.svg +1 -0
- package/icons/phosphor/sidebar-simple.svg +1 -0
- package/icons/phosphor/sign-out.svg +1 -0
- package/icons/phosphor/signpost.svg +1 -0
- package/icons/phosphor/sliders-horizontal.svg +1 -0
- package/icons/phosphor/smiley.svg +1 -0
- package/icons/phosphor/sparkle.svg +1 -0
- package/icons/phosphor/square-half-bottom.svg +1 -0
- package/icons/phosphor/square.svg +1 -0
- package/icons/phosphor/squares-four.svg +1 -0
- package/icons/phosphor/sticker.svg +1 -0
- package/icons/phosphor/storefront.svg +1 -0
- package/icons/phosphor/sun.svg +1 -0
- package/icons/phosphor/swatches.svg +1 -0
- package/icons/phosphor/tag.svg +1 -0
- package/icons/phosphor/text-aa.svg +1 -0
- package/icons/phosphor/text-align-left.svg +1 -0
- package/icons/phosphor/text-b.svg +1 -0
- package/icons/phosphor/text-h-one.svg +1 -0
- package/icons/phosphor/text-h-three.svg +1 -0
- package/icons/phosphor/text-h-two.svg +1 -0
- package/icons/phosphor/text-italic.svg +1 -0
- package/icons/phosphor/text-t.svg +1 -0
- package/icons/phosphor/ticket.svg +1 -0
- package/icons/phosphor/toggle-right.svg +1 -0
- package/icons/phosphor/train.svg +1 -0
- package/icons/phosphor/trash.svg +1 -0
- package/icons/phosphor/upload-simple.svg +1 -0
- package/icons/phosphor/user-circle.svg +1 -0
- package/icons/phosphor/user.svg +1 -0
- package/icons/phosphor/users-three.svg +1 -0
- package/icons/phosphor/users.svg +1 -0
- package/icons/phosphor/video-camera.svg +1 -0
- package/icons/phosphor/warning-circle.svg +1 -0
- package/icons/phosphor/warning.svg +1 -0
- package/icons/phosphor/wave-sine.svg +1 -0
- package/icons/phosphor/wheelchair.svg +1 -0
- package/icons/phosphor/wrench.svg +1 -0
- package/icons/phosphor/x.svg +1 -0
- package/lib/apps.d.mts +28 -0
- package/lib/apps.mjs +139 -0
- package/lib/blocks.d.mts +23 -0
- package/lib/blocks.mjs +90 -0
- package/lib/colors.ts +86 -0
- package/lib/contactBar.ts +18 -0
- package/lib/cookieCategories.d.mts +17 -0
- package/lib/cookieCategories.mjs +28 -0
- package/lib/crop.d.mts +34 -0
- package/lib/crop.mjs +83 -0
- package/lib/csp.d.mts +22 -0
- package/lib/csp.mjs +130 -0
- package/lib/cspSources.d.mts +24 -0
- package/lib/cspSources.mjs +60 -0
- package/lib/dynamic-colors.ts +426 -0
- package/lib/git.d.mts +24 -0
- package/lib/git.mjs +64 -0
- package/lib/hooks.ts +51 -0
- package/lib/inline.ts +20 -0
- package/lib/license-texts/Apache-2.0.txt +191 -0
- package/lib/license-texts/BSD-2-Clause.txt +24 -0
- package/lib/license-texts/BSD-3-Clause.txt +28 -0
- package/lib/license-texts/ISC.txt +15 -0
- package/lib/license-texts/MIT.txt +21 -0
- package/lib/licenses.d.mts +190 -0
- package/lib/licenses.mjs +683 -0
- package/lib/markdown.ts +42 -0
- package/lib/motion-schemes.d.mts +2 -0
- package/lib/motion-schemes.mjs +5 -0
- package/lib/motion.ts +131 -0
- package/lib/notice.d.mts +3 -0
- package/lib/notice.mjs +34 -0
- package/lib/scheduled.d.mts +15 -0
- package/lib/scheduled.mjs +37 -0
- package/lib/snackbar.ts +149 -0
- package/lib/status.d.mts +7 -0
- package/lib/status.mjs +18 -0
- package/lib/svg.d.mts +22 -0
- package/lib/svg.mjs +231 -0
- package/lib/text-colors.d.mts +11 -0
- package/lib/text-colors.mjs +43 -0
- package/lib/video-id.d.mts +14 -0
- package/lib/video-id.mjs +72 -0
- package/lib/video.d.mts +20 -0
- package/lib/video.mjs +91 -0
- package/package.json +131 -6
- package/pages/404.astro +10 -0
- package/pages/[...slug].astro +51 -0
- package/pages/_headers.txt +31 -0
- package/pages/blog/index.astro +10 -0
- package/pages/blog/kategori/[category].astro +18 -0
- package/pages/editor/code-images.json.js +25 -0
- package/pages/editor/index.astro +75 -0
- package/pages/editor/manifest.webmanifest.js +23 -0
- package/pages/editor/sw.js +33 -0
- package/pages/editor/sw.js.js +4 -0
- package/pages/editor/thumbnails.json.js +21 -0
- package/pages/editor/version.json.js +22 -0
- package/pages/headers.js +4 -0
- package/pages/index.astro +10 -0
- package/pages/ny.astro +6 -0
- package/pages/robots.txt.js +3 -0
- package/pages/rss.xml.js +20 -0
- package/scripts/app-screenshots.mjs +164 -0
- package/scripts/app-workers.mjs +6 -0
- package/scripts/bin.mjs +12 -0
- package/scripts/built-site.mjs +99 -0
- package/scripts/check-consent.mjs +113 -0
- package/scripts/check-content.mjs +149 -0
- package/scripts/check-demo.mjs +24 -0
- package/scripts/check-themes.mjs +45 -0
- package/scripts/check-worker.mjs +569 -0
- package/scripts/compare-html.mjs +81 -0
- package/scripts/demo-site.mjs +42 -0
- package/scripts/editor-icons.mjs +56 -0
- package/scripts/editor-roundtrip.mjs +134 -0
- package/scripts/editor-screens.mjs +101 -0
- package/scripts/git-env.mjs +9 -0
- package/scripts/icon-packs.mjs +151 -0
- package/scripts/link-counts.mjs +22 -0
- package/scripts/page-colors.mjs +42 -0
- package/scripts/releases.d.mts +10 -0
- package/scripts/releases.mjs +80 -0
- package/scripts/responsive-images.mjs +94 -0
- package/scripts/scheduled-list.mjs +15 -0
- package/scripts/theme-screenshots.mjs +88 -0
- package/scripts/types.mjs +21 -0
- package/scripts/video-thumbnails.mjs +89 -0
- package/scripts/worker-modules.mjs +34 -0
- package/site/appCookies.d.mts +9 -0
- package/site/appCookies.mjs +74 -0
- package/site/apps.ts +21 -0
- package/site/autolinks.d.mts +11 -0
- package/site/autolinks.mjs +200 -0
- package/site/blockScripts.ts +31 -0
- package/site/categories.ts +16 -0
- package/site/consent.ts +26 -0
- package/site/content.config.ts +84 -0
- package/site/content.ts +104 -0
- package/site/cookieList.ts +17 -0
- package/site/defineSite.d.mts +142 -0
- package/site/defineSite.mjs +136 -0
- package/site/directives/interact.d.mts +2 -0
- package/site/directives/interact.mjs +31 -0
- package/site/editor-version.d.mts +1 -0
- package/site/editor-version.mjs +26 -0
- package/site/fill.ts +13 -0
- package/site/format.ts +11 -0
- package/site/home.ts +66 -0
- package/site/iconPacks.d.mts +20 -0
- package/site/iconPacks.mjs +43 -0
- package/site/icons.d.mts +693 -0
- package/site/icons.mjs +605 -0
- package/site/images.d.mts +43 -0
- package/site/images.mjs +157 -0
- package/site/motion.ts +13 -0
- package/site/noindex.d.mts +6 -0
- package/site/noindex.mjs +21 -0
- package/site/pageColors.ts +110 -0
- package/site/popups.ts +98 -0
- package/site/schema.ts +189 -0
- package/site/sections.ts +3 -0
- package/site/seo.ts +28 -0
- package/site/site.ts +76 -0
- package/site/siteConfig.d.mts +1 -0
- package/site/siteConfig.mjs +8 -0
- package/site/siteCsp.d.mts +10 -0
- package/site/siteCsp.mjs +75 -0
- package/site/siteModules.d.mts +7 -0
- package/site/siteModules.mjs +27 -0
- package/site/standardPages.ts +59 -0
- package/site/testimonials.ts +48 -0
- package/site/text.ts +43 -0
- package/site/theme.d.mts +83 -0
- package/site/theme.mjs +472 -0
- package/site/tracking.client.ts +225 -0
- package/site/tracking.ts +9 -0
- package/src/ActionParts.tsx +205 -0
- package/src/Advanced.tsx +152 -0
- package/src/App.tsx +904 -0
- package/src/AppList.tsx +1345 -0
- package/src/BlockDialog.tsx +360 -0
- package/src/BlockParts.tsx +652 -0
- package/src/BlockSettings.tsx +533 -0
- package/src/BrandForm.tsx +164 -0
- package/src/Colors.tsx +476 -0
- package/src/CommunicationParts.tsx +199 -0
- package/src/CompanyForm.tsx +209 -0
- package/src/Consents.tsx +175 -0
- package/src/ContainmentParts.tsx +185 -0
- package/src/Crop.tsx +152 -0
- package/src/DataForm.tsx +434 -0
- package/src/Deleted.tsx +177 -0
- package/src/EntryForm.tsx +740 -0
- package/src/FileView.tsx +30 -0
- package/src/FormFrame.tsx +237 -0
- package/src/Keywords.tsx +225 -0
- package/src/Library.tsx +1563 -0
- package/src/Licenses.tsx +336 -0
- package/src/LinkSheet.tsx +138 -0
- package/src/MarkdownEditor.tsx +1075 -0
- package/src/Media.tsx +677 -0
- package/src/NavigationParts.tsx +350 -0
- package/src/NavigationRestParts.tsx +247 -0
- package/src/Notifications.tsx +59 -0
- package/src/PagePicker.tsx +136 -0
- package/src/Parts.tsx +991 -0
- package/src/PartsShown.tsx +168 -0
- package/src/PickerParts.tsx +183 -0
- package/src/Redirects.tsx +450 -0
- package/src/Screen.tsx +184 -0
- package/src/SectionsField.tsx +65 -0
- package/src/SelectionParts.tsx +134 -0
- package/src/SeoScores.tsx +184 -0
- package/src/Sheet.tsx +35 -0
- package/src/ThemeStore.tsx +376 -0
- package/src/Tokens.tsx +346 -0
- package/src/Versions.tsx +214 -0
- package/src/addresses.ts +75 -0
- package/src/allIcons.ts +7 -0
- package/src/appFiles.ts +29 -0
- package/src/apps.ts +281 -0
- package/src/ask.tsx +123 -0
- package/src/blocks.ts +251 -0
- package/src/brand.ts +153 -0
- package/src/cache.ts +42 -0
- package/src/check.ts +285 -0
- package/src/checkSite.ts +256 -0
- package/src/consents.ts +26 -0
- package/src/cookieList.ts +70 -0
- package/src/countries.ts +59 -0
- package/src/deploy.ts +155 -0
- package/src/editor.css +602 -0
- package/src/examples.ts +85 -0
- package/src/fields.tsx +942 -0
- package/src/frontmatter.d.mts +6 -0
- package/src/frontmatter.mjs +42 -0
- package/src/github.ts +376 -0
- package/src/i18n/da-DK/advanced.ts +28 -0
- package/src/i18n/da-DK/app.ts +71 -0
- package/src/i18n/da-DK/apps.ts +90 -0
- package/src/i18n/da-DK/blockSettings.ts +38 -0
- package/src/i18n/da-DK/blocks.ts +408 -0
- package/src/i18n/da-DK/check.ts +25 -0
- package/src/i18n/da-DK/colors.ts +64 -0
- package/src/i18n/da-DK/common.ts +118 -0
- package/src/i18n/da-DK/company.ts +24 -0
- package/src/i18n/da-DK/consents.ts +23 -0
- package/src/i18n/da-DK/forms.ts +116 -0
- package/src/i18n/da-DK/history.ts +35 -0
- package/src/i18n/da-DK/index.ts +49 -0
- package/src/i18n/da-DK/keywords.ts +19 -0
- package/src/i18n/da-DK/library.ts +135 -0
- package/src/i18n/da-DK/licenses.ts +25 -0
- package/src/i18n/da-DK/media.ts +79 -0
- package/src/i18n/da-DK/parts.ts +696 -0
- package/src/i18n/da-DK/preview.ts +13 -0
- package/src/i18n/da-DK/redirects.ts +51 -0
- package/src/i18n/da-DK/seo.ts +20 -0
- package/src/i18n/da-DK/text.ts +35 -0
- package/src/i18n/da-DK/theme.ts +41 -0
- package/src/i18n/en-US/advanced.ts +32 -0
- package/src/i18n/en-US/app.ts +84 -0
- package/src/i18n/en-US/apps.ts +134 -0
- package/src/i18n/en-US/blockSettings.ts +48 -0
- package/src/i18n/en-US/blocks.ts +441 -0
- package/src/i18n/en-US/check.ts +31 -0
- package/src/i18n/en-US/colors.ts +82 -0
- package/src/i18n/en-US/common.ts +144 -0
- package/src/i18n/en-US/company.ts +25 -0
- package/src/i18n/en-US/consents.ts +25 -0
- package/src/i18n/en-US/forms.ts +145 -0
- package/src/i18n/en-US/history.ts +43 -0
- package/src/i18n/en-US/index.ts +51 -0
- package/src/i18n/en-US/keywords.ts +24 -0
- package/src/i18n/en-US/library.ts +176 -0
- package/src/i18n/en-US/licenses.ts +36 -0
- package/src/i18n/en-US/media.ts +80 -0
- package/src/i18n/en-US/parts.ts +718 -0
- package/src/i18n/en-US/preview.ts +15 -0
- package/src/i18n/en-US/redirects.ts +66 -0
- package/src/i18n/en-US/seo.ts +26 -0
- package/src/i18n/en-US/text.ts +41 -0
- package/src/i18n/en-US/theme.ts +41 -0
- package/src/i18n/index.ts +124 -0
- package/src/icon.tsx +160 -0
- package/src/iconPacks.ts +89 -0
- package/src/images.ts +163 -0
- package/src/licenses.ts +79 -0
- package/src/markdown.d.mts +12 -0
- package/src/markdown.mjs +204 -0
- package/src/nav.ts +68 -0
- package/src/notFound.ts +28 -0
- package/src/notifications.ts +223 -0
- package/src/pagePreview.tsx +204 -0
- package/src/r2Caching.ts +55 -0
- package/src/redirects.ts +149 -0
- package/src/registry.tsx +188 -0
- package/src/schema.ts +417 -0
- package/src/sections.d.mts +45 -0
- package/src/sections.mjs +303 -0
- package/src/seo.ts +333 -0
- package/src/shared.ts +44 -0
- package/src/sidebar.ts +31 -0
- package/src/site.ts +317 -0
- package/src/standard/Block.astro +19 -0
- package/src/standard/BlockSite.astro +18 -0
- package/src/standard/accordion/index.tsx +47 -0
- package/src/standard/accordion/load.ts +23 -0
- package/src/standard/accordion/shared.ts +15 -0
- package/src/standard/accordion/view.ts +32 -0
- package/src/standard/buttons/fields.ts +98 -0
- package/src/standard/buttons/index.tsx +23 -0
- package/src/standard/buttons/load.ts +34 -0
- package/src/standard/buttons/shared.ts +12 -0
- package/src/standard/buttons/view.ts +30 -0
- package/src/standard/cards/index.tsx +71 -0
- package/src/standard/cards/load.ts +17 -0
- package/src/standard/cards/shared.ts +27 -0
- package/src/standard/cards/view.ts +29 -0
- package/src/standard/checklist/index.tsx +27 -0
- package/src/standard/checklist/load.ts +5 -0
- package/src/standard/checklist/view.ts +13 -0
- package/src/standard/cookies/index.tsx +17 -0
- package/src/standard/cookies/list.ts +56 -0
- package/src/standard/cookies/load.ts +11 -0
- package/src/standard/cookies/shared.ts +20 -0
- package/src/standard/cookies/view.ts +28 -0
- package/src/standard/faq/index.tsx +29 -0
- package/src/standard/faq/load.ts +14 -0
- package/src/standard/faq/view.ts +21 -0
- package/src/standard/head.ts +23 -0
- package/src/standard/hero/fields.ts +48 -0
- package/src/standard/hero/index.tsx +57 -0
- package/src/standard/hero/load.ts +23 -0
- package/src/standard/hero/view.ts +38 -0
- package/src/standard/links/index.tsx +41 -0
- package/src/standard/links/load.ts +17 -0
- package/src/standard/links/view.ts +25 -0
- package/src/standard/list/index.tsx +50 -0
- package/src/standard/list/load.ts +5 -0
- package/src/standard/list/view.ts +18 -0
- package/src/standard/load.ts +7 -0
- package/src/standard/notice/index.tsx +30 -0
- package/src/standard/notice/load.ts +16 -0
- package/src/standard/notice/view.ts +10 -0
- package/src/standard/points/index.tsx +42 -0
- package/src/standard/points/load.ts +5 -0
- package/src/standard/points/view.ts +12 -0
- package/src/standard/posts/index.tsx +132 -0
- package/src/standard/posts/load.ts +36 -0
- package/src/standard/posts/shared.ts +21 -0
- package/src/standard/posts/view.ts +63 -0
- package/src/standard/pricecards/index.tsx +57 -0
- package/src/standard/pricecards/load.ts +11 -0
- package/src/standard/pricecards/view.ts +50 -0
- package/src/standard/sharedTexts.ts +6 -0
- package/src/standard/site.ts +124 -0
- package/src/standard/siteLooks.ts +19 -0
- package/src/standard/sites.ts +13 -0
- package/src/standard/steps/index.tsx +28 -0
- package/src/standard/steps/load.ts +5 -0
- package/src/standard/steps/view.ts +11 -0
- package/src/standard/testimonials/index.tsx +87 -0
- package/src/standard/testimonials/list.ts +43 -0
- package/src/standard/testimonials/load.ts +58 -0
- package/src/standard/testimonials/shared.ts +13 -0
- package/src/standard/testimonials/view.ts +76 -0
- package/src/standard/themeBlocks.ts +13 -0
- package/src/standard/video/index.tsx +23 -0
- package/src/standard/video/load.ts +10 -0
- package/src/standard/video/view.ts +42 -0
- package/src/standard/view.tsx +105 -0
- package/src/standard/views.ts +37 -0
- package/src/store.ts +499 -0
- package/src/theme.ts +90 -0
- package/src/themeUi.ts +97 -0
- package/src/themes.ts +91 -0
- package/src/ui.tsx +3402 -0
- package/src/virtual.d.ts +5 -0
- package/src/when.ts +22 -0
- package/starter/.githooks/pre-push +4 -0
- package/starter/.nvmrc +1 -0
- package/starter/.prettierignore +11 -0
- package/starter/.prettierrc.json +7 -0
- package/starter/README.md +26 -0
- package/starter/astro.config.mjs +5 -0
- package/starter/package.json +67 -0
- package/starter/public/_redirects +1 -0
- package/starter/public/apple-touch-icon.png +0 -0
- package/starter/public/editor/apple-touch-icon.png +0 -0
- package/starter/public/editor/icon-192.png +0 -0
- package/starter/public/editor/icon-512.png +0 -0
- package/starter/public/editor/icon-maskable-512.png +0 -0
- package/starter/public/favicon.ico +0 -0
- package/starter/public/favicon.svg +1 -0
- package/starter/public/logo.svg +1 -0
- package/starter/src/content/pages/blog.md +8 -0
- package/starter/src/content/pages/forside.md +9 -0
- package/starter/src/content/pages/kontakt.md +7 -0
- package/starter/src/content/pages/privatlivspolitik.md +9 -0
- package/starter/src/content/pages/siden-findes-ikke.md +7 -0
- package/starter/src/content.config.ts +2 -0
- package/starter/src/data/apps.json +1 -0
- package/starter/src/data/block-settings.json +3 -0
- package/starter/src/data/blocks.json +1 -0
- package/starter/src/data/booking.json +6 -0
- package/starter/src/data/colors.json +70 -0
- package/starter/src/data/contact.json +8 -0
- package/starter/src/data/cookies.json +21 -0
- package/starter/src/data/csp.json +1 -0
- package/starter/src/data/footer.json +15 -0
- package/starter/src/data/internal-links.json +4 -0
- package/starter/src/data/menu.json +4 -0
- package/starter/src/data/mobile-menu.json +4 -0
- package/starter/src/data/old-addresses.json +1 -0
- package/starter/src/data/redirects.json +1 -0
- package/starter/src/data/standard-pages.json +8 -0
- package/starter/src/data/theme.json +1 -0
- package/starter/src/env.d.ts +2 -0
- package/starter/src/site/config.ts +13 -0
- package/starter/src/site/worker.js +14 -0
- package/starter/tsconfig.json +17 -0
- package/starter/worker/apps.js +6 -0
- package/starter/wrangler.jsonc +39 -0
- package/theme/LICENSE +21 -0
- package/theme/blocks/ArrowLink.tsx +14 -0
- package/theme/blocks/BlockHead.tsx +26 -0
- package/theme/blocks/Panel.tsx +32 -0
- package/theme/blocks/Person.tsx +26 -0
- package/theme/blocks/accordion/PageRow.tsx +25 -0
- package/theme/blocks/accordion/View.tsx +17 -0
- package/theme/blocks/buttons/Buttons.tsx +28 -0
- package/theme/blocks/buttons/View.tsx +12 -0
- package/theme/blocks/cards/LinkCards.tsx +72 -0
- package/theme/blocks/cards/View.tsx +20 -0
- package/theme/blocks/checklist/Checks.tsx +15 -0
- package/theme/blocks/checklist/View.tsx +14 -0
- package/theme/blocks/cookies/View.tsx +36 -0
- package/theme/blocks/faq/Accordion.tsx +34 -0
- package/theme/blocks/faq/View.tsx +16 -0
- package/theme/blocks/faq/script.ts +56 -0
- package/theme/blocks/hero/View.tsx +44 -0
- package/theme/blocks/links/LinkGroups.tsx +24 -0
- package/theme/blocks/links/View.tsx +17 -0
- package/theme/blocks/list/Rows.tsx +24 -0
- package/theme/blocks/list/View.tsx +14 -0
- package/theme/blocks/notice/View.tsx +13 -0
- package/theme/blocks/points/PointList.tsx +34 -0
- package/theme/blocks/points/View.tsx +14 -0
- package/theme/blocks/posts/View.tsx +26 -0
- package/theme/blocks/pricecards/View.tsx +40 -0
- package/theme/blocks/steps/StepList.tsx +23 -0
- package/theme/blocks/steps/View.tsx +14 -0
- package/theme/blocks/testimonials/List.tsx +46 -0
- package/theme/blocks/testimonials/Slider.tsx +44 -0
- package/theme/blocks/testimonials/Testimonial.tsx +124 -0
- package/theme/blocks/testimonials/View.tsx +21 -0
- package/theme/blocks/testimonials/script.ts +52 -0
- package/theme/blocks/video/View.tsx +41 -0
- package/theme/components/ActionBar.astro +63 -0
- package/theme/components/AppSlot.astro +21 -0
- package/theme/components/ArrowLink.tsx +21 -0
- package/theme/components/BlogIndex.astro +48 -0
- package/theme/components/BlogPosts.astro +18 -0
- package/theme/components/BlogPosts.tsx +45 -0
- package/theme/components/BookButton.tsx +22 -0
- package/theme/components/Container.astro +11 -0
- package/theme/components/CookieConsent.astro +121 -0
- package/theme/components/EndBlock.astro +21 -0
- package/theme/components/FontPreload.astro +6 -0
- package/theme/components/Footer.astro +85 -0
- package/theme/components/Header.astro +186 -0
- package/theme/components/Icon.astro +16 -0
- package/theme/components/Img.astro +29 -0
- package/theme/components/Img.tsx +33 -0
- package/theme/components/Inline.astro +11 -0
- package/theme/components/Logo.astro +23 -0
- package/theme/components/LogoMark.astro +10 -0
- package/theme/components/Markdown.astro +17 -0
- package/theme/components/MobileMenu.tsx +224 -0
- package/theme/components/MobileNav.astro +33 -0
- package/theme/components/PageHeader.astro +22 -0
- package/theme/components/PageSection.astro +24 -0
- package/theme/components/PhoneButton.tsx +11 -0
- package/theme/components/Popup.astro +145 -0
- package/theme/components/PopupButton.tsx +24 -0
- package/theme/components/PopupView.tsx +48 -0
- package/theme/components/PostList.tsx +58 -0
- package/theme/components/PostMeta.tsx +17 -0
- package/theme/components/RichText.astro +28 -0
- package/theme/components/Section.astro +29 -0
- package/theme/components/SectionHeading.tsx +8 -0
- package/theme/components/TextSection.astro +16 -0
- package/theme/components/home/PageBlock.astro +19 -0
- package/theme/components/home/Text.astro +13 -0
- package/theme/components/loadPopup.ts +22 -0
- package/theme/components/loadPosts.ts +16 -0
- package/theme/components/posts.ts +15 -0
- package/theme/editor/looks.mjs +7 -0
- package/theme/editor/previews.tsx +56 -0
- package/theme/layouts/Base.astro +273 -0
- package/theme/layouts/PageLayout.astro +126 -0
- package/theme/layouts/PostLayout.astro +137 -0
- package/theme/screenshots/1-front.jpg +0 -0
- package/theme/screenshots/2-front-dark.jpg +0 -0
- package/theme/screenshots/3-blog.jpg +0 -0
- package/theme/screenshots/4-contact.jpg +0 -0
- package/theme/scripts/motion.ts +29 -0
- package/theme/styles/base.css +320 -0
- package/theme/styles/blocks.css +1808 -0
- package/theme/styles/components.css +206 -0
- package/theme/styles/global.css +1302 -0
- package/theme/styles/ui.css +6544 -0
- package/theme/templates/Blog.astro +38 -0
- package/theme/templates/Category.astro +19 -0
- package/theme/templates/Home.astro +36 -0
- package/theme/templates/New.astro +68 -0
- package/theme/templates/NotFound.astro +117 -0
- package/theme/theme.json +28 -0
- package/theme/ui/Badge.tsx +45 -0
- package/theme/ui/BottomSheet.tsx +148 -0
- package/theme/ui/Button.tsx +79 -0
- package/theme/ui/ButtonGroup.tsx +31 -0
- package/theme/ui/Card.tsx +45 -0
- package/theme/ui/Carousel.tsx +124 -0
- package/theme/ui/Checkbox.tsx +59 -0
- package/theme/ui/Chip.tsx +101 -0
- package/theme/ui/ChipSet.tsx +27 -0
- package/theme/ui/DatePicker.tsx +149 -0
- package/theme/ui/DatePickerContainer.tsx +316 -0
- package/theme/ui/Dialog.tsx +100 -0
- package/theme/ui/Divider.tsx +27 -0
- package/theme/ui/ExposedDropdownMenu.tsx +77 -0
- package/theme/ui/Fab.tsx +88 -0
- package/theme/ui/FabMenu.tsx +67 -0
- package/theme/ui/IconButton.tsx +78 -0
- package/theme/ui/List.tsx +287 -0
- package/theme/ui/LoadingIndicator.tsx +29 -0
- package/theme/ui/Menu.tsx +278 -0
- package/theme/ui/NavigationBar.tsx +62 -0
- package/theme/ui/NavigationDrawer.tsx +80 -0
- package/theme/ui/NavigationRail.tsx +154 -0
- package/theme/ui/ProgressIndicator.tsx +162 -0
- package/theme/ui/RadioButton.tsx +50 -0
- package/theme/ui/Search.tsx +129 -0
- package/theme/ui/SegmentedButton.tsx +49 -0
- package/theme/ui/SideSheet.tsx +54 -0
- package/theme/ui/Slider.tsx +155 -0
- package/theme/ui/Snackbar.tsx +67 -0
- package/theme/ui/SplitButton.tsx +67 -0
- package/theme/ui/Switch.tsx +60 -0
- package/theme/ui/Tabs.tsx +114 -0
- package/theme/ui/TextField.tsx +278 -0
- package/theme/ui/TimePicker.tsx +128 -0
- package/theme/ui/TimePickerContainer.tsx +234 -0
- package/theme/ui/Toolbar.tsx +67 -0
- package/theme/ui/Tooltip.tsx +58 -0
- package/theme/ui/TopAppBar.tsx +77 -0
- package/theme/ui/bottomSheet.script.ts +8 -0
- package/theme/ui/bottomSheet.ts +211 -0
- package/theme/ui/carousel.script.ts +28 -0
- package/theme/ui/carouselLayout.ts +229 -0
- package/theme/ui/checkbox.script.ts +8 -0
- package/theme/ui/datePicker.script.ts +302 -0
- package/theme/ui/dates.ts +185 -0
- package/theme/ui/dialog.ts +48 -0
- package/theme/ui/dropdownMenu.script.ts +166 -0
- package/theme/ui/fabMenu.script.ts +57 -0
- package/theme/ui/navigationRail.script.ts +47 -0
- package/theme/ui/ripple.script.ts +159 -0
- package/theme/ui/search.script.ts +92 -0
- package/theme/ui/sideSheet.ts +48 -0
- package/theme/ui/slider.script.ts +12 -0
- package/theme/ui/sliderUpdate.ts +52 -0
- package/theme/ui/snackbar.script.ts +16 -0
- package/theme/ui/splitButton.script.ts +63 -0
- package/theme/ui/tabs.script.ts +48 -0
- package/theme/ui/textField.script.ts +17 -0
- package/theme/ui/textFieldUpdate.ts +44 -0
- package/theme/ui/timePicker.script.ts +248 -0
- package/theme/ui/toolbar.script.ts +43 -0
- package/theme/ui/tooltip.script.ts +68 -0
- package/worker/consent.js +141 -0
- package/worker/editor-github.js +167 -0
- package/worker/editor-host.js +74 -0
- package/worker/files.js +401 -0
- package/worker/github.js +36 -0
- package/worker/index.js +184 -0
- package/worker/not-found.js +97 -0
- package/worker/oauth.js +95 -0
- package/worker/publish.js +52 -0
- package/worker/push.js +270 -0
- package/worker/r2-status.js +50 -0
- package/worker/session.js +58 -0
package/lib/markdown.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Markdown as HTML in the editor, at once: as the site makes it (Astro's pipeline, inline.ts: GitHub's Markdown,
|
|
2
|
+
// typographic quotes, the HTML written in it) with what runs in a browser, so a block drawn in the editor shows its
|
|
3
|
+
// text as on the site (bold, italic, links, lists). The site itself uses Astro's (inline.ts), which does not run in a
|
|
4
|
+
// browser.
|
|
5
|
+
import { unified } from 'unified';
|
|
6
|
+
import remarkParse from 'remark-parse';
|
|
7
|
+
import remarkGfm from 'remark-gfm';
|
|
8
|
+
import remarkSmartypants from 'remark-smartypants';
|
|
9
|
+
import remarkRehype from 'remark-rehype';
|
|
10
|
+
import rehypeRaw from 'rehype-raw';
|
|
11
|
+
import rehypeStringify from 'rehype-stringify';
|
|
12
|
+
|
|
13
|
+
/** The pipeline, also for a whole page's text (pagePreview.tsx). */
|
|
14
|
+
export const processor = unified()
|
|
15
|
+
.use(remarkParse)
|
|
16
|
+
.use(remarkGfm)
|
|
17
|
+
.use(remarkSmartypants)
|
|
18
|
+
.use(remarkRehype, { allowDangerousHtml: true })
|
|
19
|
+
.use(rehypeRaw)
|
|
20
|
+
.use(rehypeStringify, { allowDangerousHtml: true });
|
|
21
|
+
|
|
22
|
+
/** A short text's HTML made to stand inside a <p> of its own: its paragraphs separated by a line break, and anything
|
|
23
|
+
* that cannot stand there (a list, a picture) as its text, still escaped HTML. */
|
|
24
|
+
export function inlineOf(html: string): string {
|
|
25
|
+
const paragraphs = [...html.matchAll(/<p>([\s\S]*?)<\/p>/g)];
|
|
26
|
+
if (paragraphs.map((m) => m[0]).join('\n') === html) return paragraphs.map((m) => m[1]).join('<br>');
|
|
27
|
+
return html
|
|
28
|
+
.replace(/<img\b[^>]*>/g, '')
|
|
29
|
+
.replace(/<[^>]+>/g, ' ')
|
|
30
|
+
.replace(/\s+/g, ' ')
|
|
31
|
+
.trim();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// A link only drawn: without its address it looks as one, but leads nowhere from the editor.
|
|
35
|
+
const drawn = (html: string) => html.replace(/<a\b([^>]*?)\s+href="[^"]*"/g, '<a$1');
|
|
36
|
+
|
|
37
|
+
/** A longer text (an answer, a hero's text) as HTML to draw in the editor: paragraphs, lists, bold, italic and links
|
|
38
|
+
* (only drawn). */
|
|
39
|
+
export const markdownNow = (markdown: string) => drawn(String(processor.processSync(markdown)).trim());
|
|
40
|
+
|
|
41
|
+
/** A short text for a component that shows it inside its own <p> (inlineHtml on the site). */
|
|
42
|
+
export const inlineNow = (markdown: string) => inlineOf(markdownNow(markdown));
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// The motion schemes by name (lib/motion.ts has their springs), here alone so what checks a theme's or the site's choice
|
|
2
|
+
// in plain Node can read them (themeProblems and motionProblems in site/theme.mjs, check:content).
|
|
3
|
+
|
|
4
|
+
/** @type {readonly ['expressive', 'standard', 'calm']} */
|
|
5
|
+
export const MOTION_SCHEMES = ['expressive', 'standard', 'calm'];
|
package/lib/motion.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// How the site moves: Material 3's motion schemes (m3.material.io/styles/motion/overview/how-it-works), springs that
|
|
2
|
+
// say how something moves (spatial: a sheet that slides in, a button that changes shape) and how something changes
|
|
3
|
+
// (effects: a colour, something that fades), each fast, default or slow. A scheme is the owner's choice under
|
|
4
|
+
// "Udseende" › "Bevægelse" (config.motion, e.g. src/data/motion.json: `{ "scheme": "expressive" }`), else the theme's
|
|
5
|
+
// ("motion" in its theme.json), else the standard theme's (schemeInUse):
|
|
6
|
+
// expressive Material 3 Expressive's: what moves overshoots a little and settles, as on a phone
|
|
7
|
+
// standard Material 3's standard: what moves glides into place
|
|
8
|
+
// calm ours: what moves does so quickly without overshooting, and the sections are shown at once (no reveal)
|
|
9
|
+
// The site writes the scheme's springs into the <head> of its pages as CSS variables (motionCss, with data-motion on
|
|
10
|
+
// <html>), which every transition and animation of the theme takes (ui.css, blocks.css: `transition: transform
|
|
11
|
+
// var(--motion-spatial-fast)`), and its scripts animate with the same springs (motionSpring, for Motion). A visitor who
|
|
12
|
+
// has asked for reduced motion gets less, whatever the scheme. No React or browser here: the build uses it too.
|
|
13
|
+
|
|
14
|
+
import { MOTION_SCHEMES } from './motion-schemes.mjs';
|
|
15
|
+
|
|
16
|
+
export { MOTION_SCHEMES };
|
|
17
|
+
export type MotionScheme = (typeof MOTION_SCHEMES)[number];
|
|
18
|
+
/** The standard theme's, when neither the owner nor the theme has chosen one. */
|
|
19
|
+
export const DEFAULT_SCHEME: MotionScheme = 'standard';
|
|
20
|
+
|
|
21
|
+
export const MOTION_KINDS = ['spatial', 'effects'] as const;
|
|
22
|
+
export type MotionKind = (typeof MOTION_KINDS)[number];
|
|
23
|
+
export const MOTION_SPEEDS = ['fast', 'default', 'slow'] as const;
|
|
24
|
+
export type MotionSpeed = (typeof MOTION_SPEEDS)[number];
|
|
25
|
+
|
|
26
|
+
/** A spring with a mass of 1: how damped it is (1: it does not overshoot; less: it does, and settles) and how stiff. */
|
|
27
|
+
export type Spring = { damping: number; stiffness: number };
|
|
28
|
+
type Springs = Record<MotionKind, Record<MotionSpeed, Spring>>;
|
|
29
|
+
|
|
30
|
+
// Material's effects springs, the same in both of its schemes: they never overshoot (a colour cannot).
|
|
31
|
+
const EFFECTS: Record<MotionSpeed, Spring> = {
|
|
32
|
+
fast: { damping: 1, stiffness: 3800 },
|
|
33
|
+
default: { damping: 1, stiffness: 1600 },
|
|
34
|
+
slow: { damping: 1, stiffness: 800 },
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/** Each scheme's springs: Material 3's tokens (md.sys.motion.spring.*) for expressive and standard. */
|
|
38
|
+
export const SPRINGS: Record<MotionScheme, Springs> = {
|
|
39
|
+
expressive: {
|
|
40
|
+
spatial: { fast: { damping: 0.6, stiffness: 800 }, default: { damping: 0.8, stiffness: 380 }, slow: { damping: 0.8, stiffness: 200 } },
|
|
41
|
+
effects: EFFECTS,
|
|
42
|
+
},
|
|
43
|
+
standard: {
|
|
44
|
+
spatial: { fast: { damping: 0.9, stiffness: 1400 }, default: { damping: 0.9, stiffness: 700 }, slow: { damping: 0.9, stiffness: 300 } },
|
|
45
|
+
effects: EFFECTS,
|
|
46
|
+
},
|
|
47
|
+
calm: { spatial: EFFECTS, effects: EFFECTS },
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** Whether a value is one of the schemes. */
|
|
51
|
+
export const isMotionScheme = (value: unknown): value is MotionScheme => MOTION_SCHEMES.includes(value as MotionScheme);
|
|
52
|
+
|
|
53
|
+
/** The scheme the site moves by: the one chosen (config.motion's `scheme`), else the theme's ("motion" in its theme.json),
|
|
54
|
+
* else the standard theme's, else DEFAULT_SCHEME. One that is not a scheme counts as none (check:content says so). */
|
|
55
|
+
export function schemeInUse(chosen: unknown, theme: unknown, standard?: unknown): MotionScheme {
|
|
56
|
+
return [chosen, theme, standard].find(isMotionScheme) ?? DEFAULT_SCHEME;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// How far from where it is going a spring counts as there, and how often the curve is drawn.
|
|
60
|
+
const SETTLED = 0.001;
|
|
61
|
+
const STEP = 1 / 60;
|
|
62
|
+
|
|
63
|
+
/** Where a spring that starts still at 0 is at `t` seconds, on its way to 1. */
|
|
64
|
+
function position({ damping, stiffness }: Spring, t: number): number {
|
|
65
|
+
const w = Math.sqrt(stiffness);
|
|
66
|
+
if (damping >= 1) return 1 - Math.exp(-w * t) * (1 + w * t);
|
|
67
|
+
const wd = w * Math.sqrt(1 - damping * damping);
|
|
68
|
+
return 1 - Math.exp(-damping * w * t) * (Math.cos(wd * t) + ((damping * w) / wd) * Math.sin(wd * t));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** A spring as CSS: how long it takes to settle, and its curve as a linear() easing (the spring's own way there, overshoot
|
|
72
|
+
* and all), for `transition` and `animation`. */
|
|
73
|
+
export function springCss(spring: Spring): { duration: number; easing: string } {
|
|
74
|
+
// The last moment it is not yet there, to the millisecond.
|
|
75
|
+
let settled = 0;
|
|
76
|
+
for (let t = 0; t < 3; t += 0.001) if (Math.abs(1 - position(spring, t)) >= SETTLED) settled = t;
|
|
77
|
+
const duration = Math.ceil(settled * 100) / 100;
|
|
78
|
+
const steps = Math.max(Math.round(duration / STEP), 8);
|
|
79
|
+
const points = Array.from({ length: steps + 1 }, (_, i) => (i === steps ? 1 : +position(spring, (i / steps) * duration).toFixed(3)));
|
|
80
|
+
return { duration: Math.round(duration * 1000), easing: `linear(${points.join(',')})` };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** A spring's CSS variable: `--motion-spatial-fast`, `--motion-effects` (default), `--motion-effects-slow`. */
|
|
84
|
+
export const motionVariable = (kind: MotionKind, speed: MotionSpeed) => `--motion-${kind}${speed === 'default' ? '' : `-${speed}`}`;
|
|
85
|
+
|
|
86
|
+
/** A scheme as CSS for a <style> in the <head>: each spring as its duration and curve
|
|
87
|
+
* (`--motion-spatial-fast: 290ms linear(…)`), to use as `transition: transform var(--motion-spatial-fast)`, and its
|
|
88
|
+
* duration alone (`--motion-spatial-fast-duration`), for what must last as long as it (a `visibility` that waits for it,
|
|
89
|
+
* a `display … allow-discrete`); and the default spatial and effects curves alone (--motion-ease, --motion-ease-quick),
|
|
90
|
+
* for what has its own duration (--block-ease and --block-ease-quick in blocks.css, --ease in base.css). */
|
|
91
|
+
export function motionCss(scheme: MotionScheme): string {
|
|
92
|
+
const springs = SPRINGS[scheme];
|
|
93
|
+
const declarations = MOTION_KINDS.flatMap((kind) =>
|
|
94
|
+
MOTION_SPEEDS.map((speed) => {
|
|
95
|
+
const { duration, easing } = springCss(springs[kind][speed]);
|
|
96
|
+
const name = motionVariable(kind, speed);
|
|
97
|
+
return `${name}:${duration}ms ${easing};${name}-duration:${duration}ms;`;
|
|
98
|
+
}),
|
|
99
|
+
);
|
|
100
|
+
const ease = springCss(springs.spatial.default).easing;
|
|
101
|
+
const quick = springCss(springs.effects.default).easing;
|
|
102
|
+
return `:root{${declarations.join('')}--motion-ease:${ease};--motion-ease-quick:${quick};}`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** A spring as Motion takes it (motion.dev: `animate(el, …, motionSpring('spatial'))`), in the scheme on the page
|
|
106
|
+
* (data-motion-scheme on <html>, set where motionCss is), else DEFAULT_SCHEME: its stiffness and its damping as a force, for a
|
|
107
|
+
* mass of 1. */
|
|
108
|
+
export function motionSpring(kind: MotionKind, speed: MotionSpeed = 'default', scheme: MotionScheme = pageScheme()) {
|
|
109
|
+
const { damping, stiffness } = SPRINGS[scheme][kind][speed];
|
|
110
|
+
return { type: 'spring' as const, stiffness, damping: 2 * damping * Math.sqrt(stiffness), mass: 1 };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** A spring as the browser's own animations take it (`el.animate(keyframes, motionTiming('spatial'))`), in the scheme on
|
|
114
|
+
* the page: how long it takes, and its curve. */
|
|
115
|
+
export function motionTiming(kind: MotionKind, speed: MotionSpeed = 'default', scheme: MotionScheme = pageScheme()) {
|
|
116
|
+
return springCss(SPRINGS[scheme][kind][speed]);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** The scheme the page moves by (data-motion-scheme on <html>), else DEFAULT_SCHEME; without a browser, DEFAULT_SCHEME. */
|
|
120
|
+
export function pageScheme(): MotionScheme {
|
|
121
|
+
if (typeof document === 'undefined') return DEFAULT_SCHEME;
|
|
122
|
+
const scheme = document.documentElement.dataset.motionScheme;
|
|
123
|
+
return isMotionScheme(scheme) ? scheme : DEFAULT_SCHEME;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Whether the page's things should only appear, not move in: the calm scheme, or a visitor who has asked for reduced
|
|
127
|
+
* motion. */
|
|
128
|
+
export function motionReduced(): boolean {
|
|
129
|
+
if (typeof document === 'undefined') return true;
|
|
130
|
+
return pageScheme() === 'calm' || matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
131
|
+
}
|
package/lib/notice.d.mts
ADDED
package/lib/notice.mjs
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// "Besked", a notice in the text (the standard block in standard/notice/), can be shown until a date and time,
|
|
2
|
+
// written in Danish time ("2026-03-01T12:00"). The site leaves it out when it is built after that time,
|
|
3
|
+
// and a visitor's browser removes it once the time has come between two builds (its load.ts), so it
|
|
4
|
+
// goes at the time without the site being built again.
|
|
5
|
+
const ZONE = 'Europe/Copenhagen';
|
|
6
|
+
const parts = new Intl.DateTimeFormat('en-US', {
|
|
7
|
+
timeZone: ZONE,
|
|
8
|
+
hourCycle: 'h23',
|
|
9
|
+
year: 'numeric',
|
|
10
|
+
month: '2-digit',
|
|
11
|
+
day: '2-digit',
|
|
12
|
+
hour: '2-digit',
|
|
13
|
+
minute: '2-digit',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// How far Danish time is ahead of UTC at a moment (one or two hours), in milliseconds.
|
|
17
|
+
function offset(at) {
|
|
18
|
+
const p = Object.fromEntries(parts.formatToParts(at).map((x) => [x.type, x.value]));
|
|
19
|
+
return Date.UTC(+p.year, +p.month - 1, +p.day, +p.hour, +p.minute) - at;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** A Danish date and time ("2026-03-01T12:00") as milliseconds since 1970, or null. */
|
|
23
|
+
export function untilTime(local) {
|
|
24
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})$/.exec(local ?? '');
|
|
25
|
+
if (!m) return null;
|
|
26
|
+
const wall = Date.UTC(+m[1], +m[2] - 1, +m[3], +m[4], +m[5]);
|
|
27
|
+
return wall - offset(wall - offset(wall));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Whether a notice shown until `local` is over. */
|
|
31
|
+
export const isOver = (local, now = Date.now()) => {
|
|
32
|
+
const at = untilTime(local);
|
|
33
|
+
return at !== null && now >= at;
|
|
34
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** The status and time in a file's front matter. */
|
|
2
|
+
export function scheduleOf(text: any): {
|
|
3
|
+
status: any;
|
|
4
|
+
publishAt: any;
|
|
5
|
+
};
|
|
6
|
+
/** The file Udgivet: its front matter without `status` and `publishAt`. */
|
|
7
|
+
export function published(text: any): any;
|
|
8
|
+
/** A file as a commit names it: `blogindlæg "x"`. */
|
|
9
|
+
export function nameOf(path: any): string;
|
|
10
|
+
/** The folders with pages and posts, and what one is called in a commit. */
|
|
11
|
+
export const KINDS: {
|
|
12
|
+
dir: string;
|
|
13
|
+
name: string;
|
|
14
|
+
}[];
|
|
15
|
+
export function isDue(publishAt: any, now?: number): boolean;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// The pages and blog posts that are Planlagt (`status: "scheduled"` with `publishAt`, packages/editor/lib/status.mjs), for
|
|
2
|
+
// publishing them once their time has come: the build lists them (packages/editor/scripts/scheduled-list.mjs), and each hour the
|
|
3
|
+
// site's Worker makes those whose time has come Udgivet in one commit on main (packages/editor/worker/publish.js), which builds the
|
|
4
|
+
// site. No dependencies, so the Worker can use it.
|
|
5
|
+
import { stateOf } from './status.mjs';
|
|
6
|
+
|
|
7
|
+
const FENCE = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
8
|
+
// The two fields as the editor writes them (packages/editor/src/frontmatter.mjs), one line each.
|
|
9
|
+
const line = (name) => new RegExp(`^${name}: *"?([^"\\r\\n]*)"?\\r?\\n`, 'm');
|
|
10
|
+
|
|
11
|
+
/** The folders with pages and posts, and what one is called in a commit. */
|
|
12
|
+
export const KINDS = [
|
|
13
|
+
{ dir: 'src/content/blog', name: 'blogindlæg' },
|
|
14
|
+
{ dir: 'src/content/pages', name: 'side' },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
/** The status and time in a file's front matter. */
|
|
18
|
+
export function scheduleOf(text) {
|
|
19
|
+
const yaml = text.match(FENCE)?.[1] ?? '';
|
|
20
|
+
return { status: yaml.match(line('status'))?.[1], publishAt: yaml.match(line('publishAt'))?.[1] };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Whether a Planlagt page or post with this time is to be published at `now`. */
|
|
24
|
+
export const isDue = (publishAt, now = Date.now()) => stateOf({ status: 'scheduled', publishAt }, now) === 'published';
|
|
25
|
+
|
|
26
|
+
/** The file Udgivet: its front matter without `status` and `publishAt`. */
|
|
27
|
+
export function published(text) {
|
|
28
|
+
const yaml = text.match(FENCE)?.[1] ?? '';
|
|
29
|
+
const rest = `${yaml}\n`.replace(line('status'), '').replace(line('publishAt'), '').replace(/\n$/, '');
|
|
30
|
+
return text.replace(FENCE, `---\n${rest}\n---`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** A file as a commit names it: `blogindlæg "x"`. */
|
|
34
|
+
export function nameOf(path) {
|
|
35
|
+
const kind = KINDS.find((k) => path.startsWith(`${k.dir}/`));
|
|
36
|
+
return `${kind?.name ?? 'fil'} "${path.slice((kind?.dir.length ?? -1) + 1).replace(/(\/index)?\.md$/, '')}"`;
|
|
37
|
+
}
|
package/lib/snackbar.ts
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// The messages at the bottom of the screen (snackbars), the same in the editor (notify in App.tsx) and on
|
|
2
|
+
// the site (a new version of a page, PageLayout.astro): in the middle, the newest lowest and the ones before
|
|
3
|
+
// it moved up. Their look and place are the theme's Snackbar (.snackbar-stack and .snackbar in
|
|
4
|
+
// packages/editor/theme/styles/ui.css). The editor's are drawn here, a text and links; the site's are drawn by
|
|
5
|
+
// the theme's part (packages/editor/theme/ui/Snackbar.tsx, with its action and close button) and shown with
|
|
6
|
+
// `element` (ui/snackbar.script.ts).
|
|
7
|
+
//
|
|
8
|
+
// A message goes away by itself after a few seconds (an error after a little longer; not while the
|
|
9
|
+
// mouse or a finger is on it or a link in it has focus), when it is tapped, or when it is swiped left
|
|
10
|
+
// or right: it follows the finger (or the mouse) sideways and fades; let go far enough (a third of its
|
|
11
|
+
// width) or fast enough, and it slides out to that side, else it slides back. Up and down still
|
|
12
|
+
// scroll the page. A swipe that started on a link does not also follow it.
|
|
13
|
+
// One about something going on ("Gemmer…") stays until the next message replaces it; snackbar(null) only
|
|
14
|
+
// takes that one away.
|
|
15
|
+
import arrow from '@phosphor-icons/core/assets/regular/arrow-right.svg?raw';
|
|
16
|
+
|
|
17
|
+
export type SnackbarLink = { text: string; href: string; onClick?: (e: MouseEvent) => void };
|
|
18
|
+
export type SnackbarMessage = {
|
|
19
|
+
text: string;
|
|
20
|
+
error?: boolean;
|
|
21
|
+
/** Links after the text, each with an arrow. */
|
|
22
|
+
links?: SnackbarLink[];
|
|
23
|
+
/** How long it stays, when longer than usual (e.g. with links to read). */
|
|
24
|
+
ms?: number;
|
|
25
|
+
/** The message as the site's theme draws it (its Snackbar part), shown in place of the text and links. */
|
|
26
|
+
element?: HTMLElement;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const SNACKBAR_MS = 5000;
|
|
30
|
+
const SNACKBAR_ERROR_MS = 8000;
|
|
31
|
+
|
|
32
|
+
let stack: HTMLDivElement | undefined;
|
|
33
|
+
const reduce = () => matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
34
|
+
const working = (text: string) => text.endsWith('…');
|
|
35
|
+
|
|
36
|
+
/** Shows a message at the bottom (or with null takes away the one about something going on). */
|
|
37
|
+
export function snackbar(next: SnackbarMessage | null) {
|
|
38
|
+
stack ??= Object.assign(document.createElement('div'), { className: 'snackbar-stack' });
|
|
39
|
+
// A popover, so it is in front of an open sheet or dialog too (they are in the top layer).
|
|
40
|
+
stack.popover = 'manual';
|
|
41
|
+
if (!stack.isConnected) document.body.append(stack);
|
|
42
|
+
for (const el of stack.querySelectorAll<HTMLElement>('.snackbar')) {
|
|
43
|
+
if (working(el.dataset.text!) || el.dataset.text === next?.text) el.remove();
|
|
44
|
+
}
|
|
45
|
+
if (next) show(stack, next);
|
|
46
|
+
if (!stack.childElementCount) return stack.remove();
|
|
47
|
+
// Shown again for each message, so it comes in front of a sheet opened after the last one.
|
|
48
|
+
if (stack.showPopover) {
|
|
49
|
+
if (stack.matches(':popover-open')) stack.hidePopover();
|
|
50
|
+
stack.showPopover();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function show(stack: HTMLDivElement, { text, error, links = [], ms, element }: SnackbarMessage) {
|
|
55
|
+
const el = element ?? document.createElement('p');
|
|
56
|
+
el.dataset.text = text;
|
|
57
|
+
if (!element) {
|
|
58
|
+
el.className = 'snackbar';
|
|
59
|
+
el.setAttribute('role', error ? 'alert' : 'status');
|
|
60
|
+
el.append(text);
|
|
61
|
+
}
|
|
62
|
+
for (const link of element ? [] : links) {
|
|
63
|
+
const a = document.createElement('a');
|
|
64
|
+
a.className = 'snackbar-link';
|
|
65
|
+
a.href = link.href;
|
|
66
|
+
a.innerHTML = arrow.replace('<svg', '<svg width="14" height="14" fill="currentColor" aria-hidden="true"');
|
|
67
|
+
a.prepend(link.text);
|
|
68
|
+
if (link.onClick) a.addEventListener('click', link.onClick);
|
|
69
|
+
el.append(' ', a);
|
|
70
|
+
}
|
|
71
|
+
stack.append(el);
|
|
72
|
+
|
|
73
|
+
const remove = () => {
|
|
74
|
+
clearTimeout(timer);
|
|
75
|
+
el.remove();
|
|
76
|
+
if (!stack.childElementCount) stack.remove();
|
|
77
|
+
};
|
|
78
|
+
// Goes by itself, but not while it is being read or swiped.
|
|
79
|
+
const wait = working(text) ? 0 : (ms ?? (error ? SNACKBAR_ERROR_MS : SNACKBAR_MS));
|
|
80
|
+
let timer = wait ? setTimeout(remove, wait) : undefined;
|
|
81
|
+
const hold = () => clearTimeout(timer);
|
|
82
|
+
const resume = () => {
|
|
83
|
+
clearTimeout(timer);
|
|
84
|
+
if (wait && el.isConnected && !el.matches(':hover, :focus-within')) timer = setTimeout(remove, wait / 2);
|
|
85
|
+
};
|
|
86
|
+
el.addEventListener('pointerenter', hold);
|
|
87
|
+
el.addEventListener('pointerleave', resume);
|
|
88
|
+
el.addEventListener('focusin', hold);
|
|
89
|
+
el.addEventListener('focusout', resume);
|
|
90
|
+
// The theme's (with a close button): Escape closes it too, while it has focus.
|
|
91
|
+
if (element) el.addEventListener('keydown', (e) => e.key === 'Escape' && remove());
|
|
92
|
+
|
|
93
|
+
// Swipe.
|
|
94
|
+
let start: { x: number; y: number; t: number; id: number } | null = null;
|
|
95
|
+
let dx = 0;
|
|
96
|
+
let dragging = false;
|
|
97
|
+
el.addEventListener('pointerdown', (e) => {
|
|
98
|
+
if (e.button !== 0) return;
|
|
99
|
+
start = { x: e.clientX, y: e.clientY, t: e.timeStamp, id: e.pointerId };
|
|
100
|
+
dx = 0;
|
|
101
|
+
dragging = false;
|
|
102
|
+
hold();
|
|
103
|
+
});
|
|
104
|
+
el.addEventListener('pointermove', (e) => {
|
|
105
|
+
if (!start || e.pointerId !== start.id) return;
|
|
106
|
+
dx = e.clientX - start.x;
|
|
107
|
+
if (!dragging) {
|
|
108
|
+
if (Math.abs(dx) < 8 || Math.abs(dx) < Math.abs(e.clientY - start.y)) return;
|
|
109
|
+
dragging = true;
|
|
110
|
+
el.setPointerCapture(e.pointerId);
|
|
111
|
+
el.getAnimations().forEach((a) => a.finish());
|
|
112
|
+
}
|
|
113
|
+
el.style.transform = `translateX(${dx}px)`;
|
|
114
|
+
el.style.opacity = String(Math.max(0.2, 1 - Math.abs(dx) / el.offsetWidth));
|
|
115
|
+
});
|
|
116
|
+
const up = (e: PointerEvent) => {
|
|
117
|
+
if (!start || e.pointerId !== start.id) return;
|
|
118
|
+
const speed = Math.abs(dx) / Math.max(1, e.timeStamp - start.t);
|
|
119
|
+
start = null;
|
|
120
|
+
resume();
|
|
121
|
+
if (!dragging) return;
|
|
122
|
+
const from = { transform: el.style.transform, opacity: el.style.opacity };
|
|
123
|
+
const duration = reduce() ? 0 : 200;
|
|
124
|
+
if (e.type === 'pointerup' && (Math.abs(dx) > el.offsetWidth / 3 || speed > 0.6)) {
|
|
125
|
+
const to = { transform: `translateX(${Math.sign(dx) * (el.offsetWidth + 32)}px)`, opacity: 0 };
|
|
126
|
+
el.animate([from, to], { duration, easing: 'ease-out', fill: 'forwards' }).finished.then(remove);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
el.animate([from, { transform: 'none', opacity: 1 }], { duration, easing: 'ease-out' });
|
|
130
|
+
el.style.transform = '';
|
|
131
|
+
el.style.opacity = '';
|
|
132
|
+
};
|
|
133
|
+
el.addEventListener('pointerup', up);
|
|
134
|
+
el.addEventListener('pointercancel', up);
|
|
135
|
+
// With the mouse, a link would otherwise be dragged instead of the message.
|
|
136
|
+
el.addEventListener('dragstart', (e) => e.preventDefault());
|
|
137
|
+
// A tap takes it away (a tap on a link or an action also follows it, and on the close button only takes it
|
|
138
|
+
// away); the click at the end of a swipe does nothing.
|
|
139
|
+
el.addEventListener(
|
|
140
|
+
'click',
|
|
141
|
+
(e) => {
|
|
142
|
+
if (!dragging) return remove();
|
|
143
|
+
e.preventDefault();
|
|
144
|
+
e.stopImmediatePropagation();
|
|
145
|
+
dragging = false;
|
|
146
|
+
},
|
|
147
|
+
true,
|
|
148
|
+
);
|
|
149
|
+
}
|
package/lib/status.d.mts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** What a page or post is on a site built at `now`: 'published', 'draft' or 'unlisted'.
|
|
2
|
+
* @param {{ status?: unknown; publishAt?: unknown }} data
|
|
3
|
+
* @returns {'published' | 'draft' | 'unlisted'} */
|
|
4
|
+
export function stateOf(data: {
|
|
5
|
+
status?: unknown;
|
|
6
|
+
publishAt?: unknown;
|
|
7
|
+
}, now?: number): "published" | "draft" | "unlisted";
|
package/lib/status.mjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// The status of a page or blog post: `status` in its front matter, "Status" at the top of it in the
|
|
2
|
+
// editor (packages/editor/defaults/collections.ts).
|
|
3
|
+
// (none) Udgivet: on the site.
|
|
4
|
+
// draft Kladde: not on the site (in dev, and on the editor's preview, it opens on its address).
|
|
5
|
+
// unlisted Skjult: opens on its address, but is not on the blog, in the sitemap or in Google.
|
|
6
|
+
// scheduled Planlagt: a draft until `publishAt` (Danish time, "2026-11-01T08:00"), then published.
|
|
7
|
+
// A build after that time has it; each hour the site's Worker makes it Udgivet in the file
|
|
8
|
+
// (packages/editor/worker/publish.js, packages/editor/lib/scheduled.mjs), which builds the site.
|
|
9
|
+
// No dependencies, so the Worker can use it.
|
|
10
|
+
import { isOver } from './notice.mjs';
|
|
11
|
+
|
|
12
|
+
/** What a page or post is on a site built at `now`: 'published', 'draft' or 'unlisted'.
|
|
13
|
+
* @param {{ status?: unknown; publishAt?: unknown }} data
|
|
14
|
+
* @returns {'published' | 'draft' | 'unlisted'} */
|
|
15
|
+
export function stateOf(data, now = Date.now()) {
|
|
16
|
+
if (data.status === 'scheduled') return isOver(String(data.publishAt ?? ''), now) ? 'published' : 'draft';
|
|
17
|
+
return data.status === 'draft' || data.status === 'unlisted' ? data.status : 'published';
|
|
18
|
+
}
|
package/lib/svg.d.mts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** An SVG file with only what draws (see above), or null when it is not one well-formed <svg>. `style`: keep
|
|
2
|
+
* <style> elements, for a file shown on its own (the logo); an icon drawn inside a page has none, as its CSS would
|
|
3
|
+
* apply to the whole page. `svg` is the cleaned file, `viewBox` and `inner` its viewBox (only four numbers) and what is
|
|
4
|
+
* inside its <svg>, and `removed` what was left out (`<script>`, `onload`, …), for check:content.
|
|
5
|
+
* @param {string | undefined} file @param {{ style?: boolean }} [options]
|
|
6
|
+
* @returns {{ svg: string, viewBox: string | undefined, inner: string, removed: string[] } | null} */
|
|
7
|
+
export function cleanSvg(file: string | undefined, { style }?: {
|
|
8
|
+
style?: boolean;
|
|
9
|
+
}): {
|
|
10
|
+
svg: string;
|
|
11
|
+
viewBox: string | undefined;
|
|
12
|
+
inner: string;
|
|
13
|
+
removed: string[];
|
|
14
|
+
} | null;
|
|
15
|
+
/** An SVG file's viewBox and what is inside its <svg>, cleaned (cleanSvg), or null when it is not one <svg>.
|
|
16
|
+
* @param {string | undefined} file @returns {{ viewBox: string | undefined, inner: string } | null} */
|
|
17
|
+
export function svgParts(file: string | undefined): {
|
|
18
|
+
viewBox: string | undefined;
|
|
19
|
+
inner: string;
|
|
20
|
+
} | null;
|
|
21
|
+
/** The icon as HTML, as <Svg> draws it. @param {string | undefined} file @param {number} size */
|
|
22
|
+
export function svgHtml(file: string | undefined, size: number): string;
|