@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/site/theme.mjs
ADDED
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
// The site's theme: how it looks (src/themes/<theme>/, with its theme.json). Which one is in use is data,
|
|
2
|
+
// src/data/theme.json (`{ "theme": "<folder>" }`), changed with the swap button on "Tema" in the editor.
|
|
3
|
+
// Every theme builds on the standard theme (packages/editor/theme/): what a theme does not have itself, a file of the
|
|
4
|
+
// theme or the look of a block, is the standard theme's, styled by the theme in use's CSS. The site and the editor
|
|
5
|
+
// reach the theme as @theme (themePlugin: the theme in use's file, else the standard theme's), and the site's own
|
|
6
|
+
// parts (src/site/) as @site (aliases): for packages/editor/astro.mjs and packages/editor/scripts/check-content.mjs. Stops with what is
|
|
7
|
+
// wrong, when the theme named is not installed.
|
|
8
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
9
|
+
import { relative } from 'node:path';
|
|
10
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
11
|
+
import { svgParts } from '@morphemecms/cms/lib/svg.mjs';
|
|
12
|
+
import { declarationProblems, ownerId } from '@morphemecms/cms/lib/licenses.mjs';
|
|
13
|
+
import { installedPacks, isIconName, packFolder, packProblems, phosphorFile, svgProblems, usedIcons } from './icons.mjs';
|
|
14
|
+
import { ICON_PACK_FILE, ICON_PACK_LICENSE, SYSTEM_PACKS, THEME_PACKS_FOLDER, packInUse, packTheme, themePackId } from './iconPacks.mjs';
|
|
15
|
+
import { MOTION_SCHEMES } from '@morphemecms/cms/lib/motion-schemes.mjs';
|
|
16
|
+
|
|
17
|
+
/** The site's choice of icon pack, `{ "pack": "<id>" }` (config.icons in src/site/config.ts). */
|
|
18
|
+
const ICONS_FILE = 'src/data/icons.json';
|
|
19
|
+
|
|
20
|
+
// The site's root (the working directory) and this package's.
|
|
21
|
+
const root = pathToFileURL(`${process.cwd()}/`);
|
|
22
|
+
const pkg = new URL('../', import.meta.url);
|
|
23
|
+
|
|
24
|
+
/** The theme every theme builds on, Material (this package's theme/, id 'saturn'): it has all of THEME_FILES and the look of every
|
|
25
|
+
* standard block. */
|
|
26
|
+
export const STANDARD_THEME = 'saturn';
|
|
27
|
+
|
|
28
|
+
/** A theme's folder, from the site's root: the standard theme's is this package's theme/, another's src/themes/<theme>. */
|
|
29
|
+
export const themeFolder = (theme) =>
|
|
30
|
+
theme === STANDARD_THEME ? relative(process.cwd(), fileURLToPath(new URL('theme', pkg))) : `src/themes/${theme}`;
|
|
31
|
+
|
|
32
|
+
// What the standard theme has, as its folder in src/themes/: what the site's pages (packages/editor/pages/) and the editor
|
|
33
|
+
// (src/site/) take from it as @theme. Besides these, the look of its blocks (blocks/<type>/) and what they import.
|
|
34
|
+
// Another theme needs only theme.json and styles/global.css (OWN_FILES); the rest it may have, else it is the
|
|
35
|
+
// standard theme's.
|
|
36
|
+
export const THEME_FILES = [
|
|
37
|
+
'theme.json',
|
|
38
|
+
'styles/global.css',
|
|
39
|
+
'layouts/PageLayout.astro',
|
|
40
|
+
'layouts/PostLayout.astro',
|
|
41
|
+
...['Home', 'Blog', 'Category', 'New', 'NotFound'].map((t) => `templates/${t}.astro`),
|
|
42
|
+
'editor/previews.tsx',
|
|
43
|
+
'editor/looks.mjs',
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
/** The themes installed: the standard theme and the folders in src/themes/ with a theme.json. */
|
|
47
|
+
export const installedThemes = () => [
|
|
48
|
+
STANDARD_THEME,
|
|
49
|
+
...(existsSync(new URL('src/themes/', root)) ? readdirSync(new URL('src/themes/', root), { withFileTypes: true }) : [])
|
|
50
|
+
.filter((e) => e.isDirectory() && existsSync(new URL(`src/themes/${e.name}/theme.json`, root)))
|
|
51
|
+
.map((e) => e.name),
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
/** What every theme has itself. */
|
|
55
|
+
export const OWN_FILES = ['theme.json', 'styles/global.css'];
|
|
56
|
+
|
|
57
|
+
// A block's contract (its type, fields, rules, shared texts, list and what it shows), which is the editor's or an
|
|
58
|
+
// app's, never a theme's: a theme has only the look of the standard blocks (blocks/<type>/: View.tsx, components).
|
|
59
|
+
const CONTRACT_FILES = ['index.tsx', 'shared.ts', 'texts.ts', 'list.ts', 'fields.ts', 'view.ts', 'load.ts'];
|
|
60
|
+
|
|
61
|
+
// How a block looked before it was drawn from its view, once on the site and once in the editor: now View.tsx.
|
|
62
|
+
const OLD_LOOK = ['Site.astro', 'draw.tsx'];
|
|
63
|
+
|
|
64
|
+
// An import of the UI components (ui.css) or of the standard theme's CSS that has them (base.css, global.css); the
|
|
65
|
+
// standard theme's own global.css imports ./base.css.
|
|
66
|
+
const UI_IMPORT = /@import\s+['"](?:@morphemecms\/cms\/theme\/styles\/|\.\/)(?:ui|base|global)\.css['"]/;
|
|
67
|
+
|
|
68
|
+
const folders = (url) =>
|
|
69
|
+
existsSync(url)
|
|
70
|
+
? readdirSync(url, { withFileTypes: true })
|
|
71
|
+
.filter((e) => e.isDirectory())
|
|
72
|
+
.map((e) => e.name)
|
|
73
|
+
: [];
|
|
74
|
+
const has = (path) => existsSync(new URL(path, root));
|
|
75
|
+
|
|
76
|
+
/** The standard blocks' types: their contracts' folders in the editor (packages/editor/src/standard/<type>/). */
|
|
77
|
+
const standardTypes = () => folders(new URL('src/standard/', pkg)).filter((t) => existsSync(new URL(`src/standard/${t}/index.tsx`, pkg)));
|
|
78
|
+
|
|
79
|
+
/** What is wrong with a theme's own icons (icons/<name>.svg, drawn by Svg in packages/editor/src/icon.tsx, in place of
|
|
80
|
+
* its icon pack's): each is one <svg> with a viewBox, with only what draws in it (svgProblems), by a name the site
|
|
81
|
+
* draws. */
|
|
82
|
+
function iconProblems(theme) {
|
|
83
|
+
const dir = `${themeFolder(theme)}/icons`;
|
|
84
|
+
if (!has(dir)) return [];
|
|
85
|
+
const problems = [];
|
|
86
|
+
for (const entry of readdirSync(new URL(dir, root), { withFileTypes: true })) {
|
|
87
|
+
const file = `${dir}/${entry.name}`;
|
|
88
|
+
const name = entry.name.replace(/\.svg$/, '');
|
|
89
|
+
if (!entry.isFile() || !entry.name.endsWith('.svg')) {
|
|
90
|
+
problems.push(`${file}: et temas ikon er en SVG-fil, ${dir}/<navn>.svg.`);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (!isIconName(name))
|
|
94
|
+
problems.push(`${file}: sitet tegner intet ikon, der hedder "${name}". Et ikon hedder som i Phosphor (fx map-pin, play-fill).`);
|
|
95
|
+
problems.push(...svgProblems(file, readFileSync(new URL(file, root), 'utf8')));
|
|
96
|
+
}
|
|
97
|
+
return problems;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const manifestOf = (theme) => JSON.parse(readFileSync(new URL(`${themeFolder(theme)}/theme.json`, root), 'utf8'));
|
|
101
|
+
|
|
102
|
+
/** The icon packs a theme brings (src/themes/<theme>/icon-packs/<pack>/, with its pack.json), by their folders. */
|
|
103
|
+
const ownPacks = (theme) =>
|
|
104
|
+
folders(new URL(`${themeFolder(theme)}/${THEME_PACKS_FOLDER}/`, root)).filter((p) =>
|
|
105
|
+
has(`${themeFolder(theme)}/${THEME_PACKS_FOLDER}/${p}/${ICON_PACK_FILE}`),
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
/** The choice of icon pack made under "Indstillinger" › "Udseende" › "Ikonpakker" (src/data/icons.json, `{ "pack": "<id>"
|
|
109
|
+
* }`), or undefined while none is made (then the theme's is used). */
|
|
110
|
+
export function chosenPack() {
|
|
111
|
+
const file = new URL(ICONS_FILE, root);
|
|
112
|
+
if (!existsSync(file)) return undefined;
|
|
113
|
+
const { pack } = JSON.parse(readFileSync(file, 'utf8'));
|
|
114
|
+
return pack ?? undefined;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** The icon pack the site and the editor draw their icons with, by its id (packInUse in packages/editor/site/iconPacks.mjs): the one
|
|
118
|
+
* chosen, else the theme's ("icons" in its theme.json), else the standard theme's (Material Symbols). Stops with what is
|
|
119
|
+
* wrong when it is not installed. */
|
|
120
|
+
export function iconPack(theme = activeTheme()) {
|
|
121
|
+
const installed = installedPacks();
|
|
122
|
+
const chosen = chosenPack();
|
|
123
|
+
const id = packInUse({ chosen, theme, icons: manifestOf(theme).icons, standardIcons: manifestOf(STANDARD_THEME).icons, installed });
|
|
124
|
+
if (!installed.includes(id))
|
|
125
|
+
throw new Error(
|
|
126
|
+
chosen === id
|
|
127
|
+
? `${ICONS_FILE}: ikonpakken ${JSON.stringify(id)} er ikke installeret (${packFolder(id)}/${ICON_PACK_FILE}).`
|
|
128
|
+
: `${themeFolder(theme)}/theme.json: "icons" er ikonpakken ${JSON.stringify(id)}, som ikke er installeret.`,
|
|
129
|
+
);
|
|
130
|
+
return id;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** The icon packs there are with their licences, from their manifests, for "Licenser" under "Indstillinger" (IconPack
|
|
134
|
+
* in @morphemecms/cms/lib/licenses.mjs, licensesIntegration in packages/editor/astro.mjs): each pack's id, name, version, who made it,
|
|
135
|
+
* its licence's name and file (LICENSE in its folder), the theme it came with, whether the site draws with it, and each
|
|
136
|
+
* set it takes icons from besides its own (`includes`, with its `licenseFile`). packProblems checks the manifests. */
|
|
137
|
+
export function iconPackLicenses() {
|
|
138
|
+
const inUse = iconPack();
|
|
139
|
+
return installedPacks().map((id) => {
|
|
140
|
+
const dir = packFolder(id);
|
|
141
|
+
const manifest = JSON.parse(readFileSync(new URL(`${dir}/${ICON_PACK_FILE}`, root), 'utf8'));
|
|
142
|
+
const set = (x, file) => ({ name: x.name, version: x.version ?? null, author: x.author, license: x.license, file: `${dir}/${file}` });
|
|
143
|
+
return {
|
|
144
|
+
id,
|
|
145
|
+
...set(manifest, ICON_PACK_LICENSE),
|
|
146
|
+
...(packTheme(id) ? { theme: packTheme(id) } : {}),
|
|
147
|
+
inUse: id === inUse,
|
|
148
|
+
includes: (manifest.includes ?? []).map((x) => set(x, x.licenseFile)),
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** The folders a theme's icons come from, first the one that wins: its own icons/, then the standard theme's (it has
|
|
154
|
+
* none), then the icon pack in use's (iconPack). */
|
|
155
|
+
const iconFolders = (theme) =>
|
|
156
|
+
[...new Set([theme, STANDARD_THEME])].map((t) => `${themeFolder(t)}/icons/`).concat(`${packFolder(iconPack(theme))}/`);
|
|
157
|
+
|
|
158
|
+
/** Whether an icon's file is Phosphor's own (as its package has it, as Phosphor's pack has it): then it needs no
|
|
159
|
+
* putting in Phosphor's place. */
|
|
160
|
+
const isPhosphors = (name, svg) => svg.trim() === phosphorFile(name)?.trim();
|
|
161
|
+
|
|
162
|
+
/** The theme in use's icons as their files' text, by name: its own (icons/<name>.svg), else its icon pack's (iconPack);
|
|
163
|
+
* not those that are Phosphor's own, which the site and the editor draw as they are (all, with Phosphor's pack). */
|
|
164
|
+
function themeIcons() {
|
|
165
|
+
const icons = {};
|
|
166
|
+
for (const dir of iconFolders(activeTheme()).reverse())
|
|
167
|
+
if (has(dir))
|
|
168
|
+
for (const f of readdirSync(new URL(dir, root)))
|
|
169
|
+
if (f.endsWith('.svg')) icons[f.slice(0, -'.svg'.length)] = readFileSync(new URL(dir + f, root), 'utf8');
|
|
170
|
+
for (const [name, svg] of Object.entries(icons)) if (isPhosphors(name, svg)) delete icons[name];
|
|
171
|
+
return icons;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** An icon of a theme (the one in use, if none is given) as its file's text: its own (icons/<name>.svg), else its icon
|
|
175
|
+
* pack's; null when it is Phosphor's own, or neither has it (then it is Phosphor's). For what is drawn outside Vite: the
|
|
176
|
+
* play button of a video in the text (rehypeVideo, packages/editor/astro.mjs). In Vite, themePlugin puts them in Phosphor's place. */
|
|
177
|
+
export function themeIcon(name, theme = activeTheme()) {
|
|
178
|
+
for (const dir of iconFolders(theme))
|
|
179
|
+
if (has(`${dir}${name}.svg`)) {
|
|
180
|
+
const svg = readFileSync(new URL(`${dir}${name}.svg`, root), 'utf8');
|
|
181
|
+
return isPhosphors(name, svg) ? null : svg;
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** The site's choice of motion scheme, `{ "scheme": "<scheme>" }` (config.motion in src/site/config.ts). */
|
|
187
|
+
const MOTION_FILE = 'src/data/motion.json';
|
|
188
|
+
|
|
189
|
+
/** What is wrong with the choice of motion scheme made under "Udseende" › "Bevægelse" (src/data/motion.json): one that
|
|
190
|
+
* is not a scheme (lib/motion.ts). */
|
|
191
|
+
export function motionProblems() {
|
|
192
|
+
const file = new URL(MOTION_FILE, root);
|
|
193
|
+
if (!existsSync(file)) return [];
|
|
194
|
+
try {
|
|
195
|
+
const { scheme } = JSON.parse(readFileSync(file, 'utf8'));
|
|
196
|
+
if (MOTION_SCHEMES.includes(scheme)) return [];
|
|
197
|
+
return [`${MOTION_FILE}: bevægelsen ${JSON.stringify(scheme ?? null)} findes ikke. Vælg en under Udseende › Bevægelse.`];
|
|
198
|
+
} catch (e) {
|
|
199
|
+
return [`${MOTION_FILE}: ${e.message}`];
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** What is wrong with the system's icon packs (packProblems; a theme's own are its themeProblems) and the choice of one:
|
|
204
|
+
* src/data/icons.json naming one that is not there. */
|
|
205
|
+
export function iconPackProblems() {
|
|
206
|
+
const used = usedIcons();
|
|
207
|
+
const installed = installedPacks();
|
|
208
|
+
const problems = SYSTEM_PACKS.filter((id) => installed.includes(id)).flatMap((id) => packProblems(id, used));
|
|
209
|
+
for (const id of SYSTEM_PACKS)
|
|
210
|
+
if (!installed.includes(id)) problems.push(`${packFolder(id)}/${ICON_PACK_FILE} mangler: kør npm run icons.`);
|
|
211
|
+
try {
|
|
212
|
+
const chosen = chosenPack();
|
|
213
|
+
if (chosen !== undefined && (typeof chosen !== 'string' || !installed.includes(chosen)))
|
|
214
|
+
problems.push(`${ICONS_FILE}: ikonpakken ${JSON.stringify(chosen)} er ikke installeret. Vælg en anden under Udseende › Ikonpakker.`);
|
|
215
|
+
} catch (e) {
|
|
216
|
+
problems.push(`${ICONS_FILE}: ${e.message}`);
|
|
217
|
+
}
|
|
218
|
+
return problems;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Phosphor, as the site and the editor import it: its React icons (`import { CaretRight } from '@phosphor-icons/react'`)
|
|
222
|
+
// and its SVG files as text (`@phosphor-icons/core/assets/regular/caret-right.svg?raw`, `…/fill/play-fill.svg?raw`, also
|
|
223
|
+
// in the import.meta.glob of Svg, packages/editor/src/icon.tsx). themePlugin puts the theme's icons in their place.
|
|
224
|
+
const PHOSPHOR_REACT = '@phosphor-icons/react';
|
|
225
|
+
const PHOSPHOR_FILE = /@phosphor-icons\/core\/assets\/(?:regular|fill)\/([a-z0-9-]+)\.svg\?raw$/;
|
|
226
|
+
const REACT_ICONS = '\0site-theme-icons';
|
|
227
|
+
const FILE_ICON = '\0site-theme-icon:';
|
|
228
|
+
|
|
229
|
+
/** The React component's name of a Phosphor icon by its file's name (`caret-right` → CaretRight), when Phosphor has it. */
|
|
230
|
+
const reactName = (name) => {
|
|
231
|
+
const pascal = name.replace(/(^|-)([a-z0-9])/g, (_, __, c) => c.toUpperCase());
|
|
232
|
+
return has(`node_modules/@phosphor-icons/react/dist/csr/${pascal}.es.js`) ? pascal : null;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
/** `@phosphor-icons/react` with the theme's icons in place of Phosphor's, the rest Phosphor's: each one the theme has
|
|
236
|
+
* draws its SVG file in the file's viewBox, with the props of a Phosphor icon (size, color, weight, mirrored, alt, the
|
|
237
|
+
* svg's own; from IconContext as Phosphor's), through Phosphor's IconBase; `weight="fill"` its `<name>-fill`, if the
|
|
238
|
+
* theme has one, else the same as the others. */
|
|
239
|
+
function reactIcons(icons) {
|
|
240
|
+
const lines = [
|
|
241
|
+
"import { createElement, forwardRef, useContext } from 'react';",
|
|
242
|
+
`import { IconBase, IconContext } from '${PHOSPHOR_REACT}';`,
|
|
243
|
+
`export * from '${PHOSPHOR_REACT}';`,
|
|
244
|
+
'const draw = (regular, fill) =>',
|
|
245
|
+
' forwardRef((props, ref) => {',
|
|
246
|
+
' const context = useContext(IconContext);',
|
|
247
|
+
" const weight = props.weight ?? context.weight ?? 'regular';",
|
|
248
|
+
' const color = props.color ?? context.color;',
|
|
249
|
+
" const [viewBox, inner] = weight === 'fill' && fill ? fill : regular;",
|
|
250
|
+
// A colour of its own also for lines (a theme's own icon drawn with stroke="currentColor"), not only for what is filled.
|
|
251
|
+
" const drawn = createElement('g', { color: color === 'currentColor' ? undefined : color, dangerouslySetInnerHTML: { __html: inner } });",
|
|
252
|
+
' return createElement(IconBase, { ...props, ref, viewBox, weights: new Map([[weight, drawn]]) });',
|
|
253
|
+
' });',
|
|
254
|
+
];
|
|
255
|
+
const parts = (name) => {
|
|
256
|
+
const svg = svgParts(icons[name]);
|
|
257
|
+
return svg && JSON.stringify([svg.viewBox, svg.inner]);
|
|
258
|
+
};
|
|
259
|
+
for (const name of Object.keys(icons)) {
|
|
260
|
+
const component = reactName(name);
|
|
261
|
+
if (!component || !parts(name)) continue;
|
|
262
|
+
lines.push(
|
|
263
|
+
`export const ${component}Icon = /* @__PURE__ */ draw(${parts(name)}, ${parts(`${name}-fill`) ?? 'null'});`,
|
|
264
|
+
`export { ${component}Icon as ${component} };`,
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
return lines.join('\n');
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** An icon's SVG file as Phosphor's are (in the text's colour, `fill="currentColor"`), for an import of Phosphor's. */
|
|
271
|
+
const fileIcon = (svg) => {
|
|
272
|
+
const { viewBox, inner } = svgParts(svg);
|
|
273
|
+
const box = viewBox ? ` viewBox="${viewBox}"` : '';
|
|
274
|
+
return `export default ${JSON.stringify(`<svg xmlns="http://www.w3.org/2000/svg"${box} fill="currentColor">${inner}</svg>`)};`;
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
/** What a theme is missing (the standard theme: of THEME_FILES and the look of every standard block, another: of
|
|
278
|
+
* OWN_FILES), what is wrong in its theme.json (name, version, author, icon), a block of its own (a folder in its
|
|
279
|
+
* blocks/ that is not the look of a standard block, or with a block's contract in it), a part nothing uses (in a
|
|
280
|
+
* folder without its View.tsx, a file the standard theme does not have there), and what is wrong with its own icons
|
|
281
|
+
* (iconProblems). */
|
|
282
|
+
export function themeProblems(theme) {
|
|
283
|
+
const needed = theme === STANDARD_THEME ? THEME_FILES : OWN_FILES;
|
|
284
|
+
const problems = needed.filter((f) => !has(`${themeFolder(theme)}/${f}`)).map((f) => `${themeFolder(theme)}/${f} mangler.`);
|
|
285
|
+
const standard = new Set(standardTypes());
|
|
286
|
+
if (theme === STANDARD_THEME)
|
|
287
|
+
for (const type of standard)
|
|
288
|
+
if (!has(`${themeFolder(theme)}/blocks/${type}/View.tsx`)) problems.push(`${themeFolder(theme)}/blocks/${type}/View.tsx mangler.`);
|
|
289
|
+
// Every theme draws the UI components (styles/ui.css: the buttons and icon buttons): it imports them, itself or
|
|
290
|
+
// through the standard theme's base.css or global.css.
|
|
291
|
+
const css = `${themeFolder(theme)}/styles/global.css`;
|
|
292
|
+
if (has(css) && !UI_IMPORT.test(readFileSync(new URL(css, root), 'utf8')))
|
|
293
|
+
problems.push(
|
|
294
|
+
`${css}: importerer ikke temaets UI-dele (knapperne): @import '@morphemecms/cms/theme/styles/ui.css', eller standardtemaets base.css eller global.css, der gør det.`,
|
|
295
|
+
);
|
|
296
|
+
for (const type of folders(new URL(`${themeFolder(theme)}/blocks/`, root))) {
|
|
297
|
+
const dir = `${themeFolder(theme)}/blocks/${type}`;
|
|
298
|
+
if (!standard.has(type)) problems.push(`${dir}: et tema kan kun have udseendet af en standardblok, og "${type}" er ikke en.`);
|
|
299
|
+
for (const f of CONTRACT_FILES)
|
|
300
|
+
if (has(`${dir}/${f}`)) problems.push(`${dir}/${f}: en bloks kontrakt hører til editoren eller en app, ikke temaet.`);
|
|
301
|
+
// Without a View.tsx of its own, the standard theme's draws the block, and each file replaces one of its parts
|
|
302
|
+
// (faq/Accordion.tsx), which it imports as @theme/…; else nothing would use it. The standard theme draws them all.
|
|
303
|
+
if (theme === STANDARD_THEME || has(`${dir}/View.tsx`)) {
|
|
304
|
+
if (!has(`${dir}/View.tsx`)) problems.push(`${dir}/View.tsx mangler: den tegner blokken på sitet og i editoren.`);
|
|
305
|
+
} else
|
|
306
|
+
for (const entry of readdirSync(new URL(dir, root), { withFileTypes: true }))
|
|
307
|
+
if (
|
|
308
|
+
entry.name !== 'script.ts' &&
|
|
309
|
+
!CONTRACT_FILES.includes(entry.name) &&
|
|
310
|
+
!has(`${themeFolder(STANDARD_THEME)}/blocks/${type}/${entry.name}`)
|
|
311
|
+
)
|
|
312
|
+
problems.push(
|
|
313
|
+
`${dir}/${entry.name}: standardtemaet har ingen del med det navn, så intet bruger den. Giv den samme navn som den del, den erstatter, eller tegn blokken med en View.tsx.`,
|
|
314
|
+
);
|
|
315
|
+
for (const f of OLD_LOOK)
|
|
316
|
+
if (has(`${dir}/${f}`)) problems.push(`${dir}/${f}: blokken tegnes af View.tsx, både på sitet og i editoren.`);
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
const manifest = JSON.parse(readFileSync(new URL(`${themeFolder(theme)}/theme.json`, root), 'utf8'));
|
|
320
|
+
for (const key of ['name', 'version', 'author', 'icon'])
|
|
321
|
+
if (typeof manifest[key] !== 'string' || !manifest[key]) problems.push(`${themeFolder(theme)}/theme.json: "${key}" mangler.`);
|
|
322
|
+
const { description, highlights, releaseNotes } = manifest;
|
|
323
|
+
const byLanguage = (x, ok) => x && typeof x === 'object' && !Array.isArray(x) && Object.values(x).length && Object.values(x).every(ok);
|
|
324
|
+
if (description !== undefined && !byLanguage(description, (x) => typeof x === 'string' && x))
|
|
325
|
+
problems.push(`${themeFolder(theme)}/theme.json: "description" skal være teksten på hvert sprog, fx { "da-DK": "…" }.`);
|
|
326
|
+
if (
|
|
327
|
+
highlights !== undefined &&
|
|
328
|
+
!byLanguage(highlights, (x) => Array.isArray(x) && x.length && x.every((y) => typeof y === 'string' && y))
|
|
329
|
+
)
|
|
330
|
+
problems.push(`${themeFolder(theme)}/theme.json: "highlights" skal være punkterne på hvert sprog, fx { "da-DK": ["…"] }.`);
|
|
331
|
+
if (releaseNotes !== undefined && !byLanguage(releaseNotes, (x) => byLanguage(x, (y) => typeof y === 'string' && y)))
|
|
332
|
+
problems.push(
|
|
333
|
+
`${themeFolder(theme)}/theme.json: "releaseNotes" skal være det nye i hver version på hvert sprog, fx { "da-DK": { "1.1.0": "…" } }.`,
|
|
334
|
+
);
|
|
335
|
+
if ('store' in manifest && (manifest.store !== true || theme === STANDARD_THEME))
|
|
336
|
+
problems.push(
|
|
337
|
+
`${themeFolder(theme)}/theme.json: "store" kan kun være true (temaet står i Appstore, npm run store:release), og standardtemaet har det ikke.`,
|
|
338
|
+
);
|
|
339
|
+
// The icon pack it uses by default: a system pack, or one of its own by its folder; the standard theme's a system pack.
|
|
340
|
+
const own = ownPacks(theme);
|
|
341
|
+
if (
|
|
342
|
+
(manifest.icons !== undefined || theme === STANDARD_THEME) &&
|
|
343
|
+
!(SYSTEM_PACKS.includes(manifest.icons) || (theme !== STANDARD_THEME && own.includes(manifest.icons)))
|
|
344
|
+
)
|
|
345
|
+
problems.push(
|
|
346
|
+
`${themeFolder(theme)}/theme.json: "icons" er den ikonpakke, temaet bruger, når ingen er valgt: ${[...SYSTEM_PACKS, ...own].map((p) => `"${p}"`).join(', ')}.`,
|
|
347
|
+
);
|
|
348
|
+
// How it moves while the owner has chosen none (lib/motion.ts); without it, the standard theme's.
|
|
349
|
+
if (manifest.motion !== undefined && !MOTION_SCHEMES.includes(manifest.motion))
|
|
350
|
+
problems.push(
|
|
351
|
+
`${themeFolder(theme)}/theme.json: "motion" er den bevægelse, temaet bruger, når ingen er valgt: ${MOTION_SCHEMES.map((s) => `"${s}"`).join(', ')}.`,
|
|
352
|
+
);
|
|
353
|
+
// Its own licence and the licences of what it brings (fonts, code, pictures), for "Licenser" and the store.
|
|
354
|
+
problems.push(
|
|
355
|
+
...declarationProblems({
|
|
356
|
+
license: manifest.license,
|
|
357
|
+
thirdParty: manifest.thirdParty,
|
|
358
|
+
folder: fileURLToPath(new URL(`${themeFolder(theme)}/`, root)),
|
|
359
|
+
where: `${themeFolder(theme)}/theme.json`,
|
|
360
|
+
what: `temaet ${manifest.name || theme}`,
|
|
361
|
+
owner: ownerId('theme', theme),
|
|
362
|
+
root: fileURLToPath(root),
|
|
363
|
+
}),
|
|
364
|
+
);
|
|
365
|
+
} catch (e) {
|
|
366
|
+
problems.push(`${themeFolder(theme)}/theme.json: ${e.message}`);
|
|
367
|
+
}
|
|
368
|
+
// The icon packs it brings: each as every pack must be, and not by a system pack's name.
|
|
369
|
+
const packs = ownPacks(theme);
|
|
370
|
+
for (const p of packs)
|
|
371
|
+
if (SYSTEM_PACKS.includes(p))
|
|
372
|
+
problems.push(
|
|
373
|
+
`${themeFolder(theme)}/${THEME_PACKS_FOLDER}/${p}: en ikonpakke i et tema hedder ikke som systemets (${SYSTEM_PACKS.join(', ')}).`,
|
|
374
|
+
);
|
|
375
|
+
if (theme === STANDARD_THEME && packs.length)
|
|
376
|
+
problems.push(`${themeFolder(theme)}/${THEME_PACKS_FOLDER}: standardtemaets ikonpakker er systemets, i CMS'ets icons/.`);
|
|
377
|
+
for (const entry of has(`${themeFolder(theme)}/${THEME_PACKS_FOLDER}`)
|
|
378
|
+
? readdirSync(new URL(`${themeFolder(theme)}/${THEME_PACKS_FOLDER}/`, root))
|
|
379
|
+
: [])
|
|
380
|
+
if (!packs.includes(entry))
|
|
381
|
+
problems.push(`${themeFolder(theme)}/${THEME_PACKS_FOLDER}/${entry}: en ikonpakke er en mappe med sin ${ICON_PACK_FILE}.`);
|
|
382
|
+
const used = usedIcons();
|
|
383
|
+
return [...problems, ...iconProblems(theme), ...packs.flatMap((p) => packProblems(themePackId(theme, p), used))];
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// A site's own parts (src/site/<file>), else the package's standard ones (defaults/<file>): `@site/<file>`.
|
|
387
|
+
const SITE_DIRS = [fileURLToPath(new URL('src/site/', root)), fileURLToPath(new URL('defaults/', pkg))];
|
|
388
|
+
|
|
389
|
+
/** The file `@site/<file>` is: the site's src/site/<file>, else the package's defaults/<file>, with or without its
|
|
390
|
+
* extension (`@site/editor`, as TypeScript writes it), or null. */
|
|
391
|
+
export function siteFile(file) {
|
|
392
|
+
for (const dir of SITE_DIRS)
|
|
393
|
+
for (const ext of ['', '.ts', '.tsx', '.mjs', '.js'])
|
|
394
|
+
if (statSync(dir + file + ext, { throwIfNoEntry: false })?.isFile()) return dir + file + ext;
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/** The folder of the theme in use, under src/themes/. */
|
|
399
|
+
export function activeTheme() {
|
|
400
|
+
const { theme } = JSON.parse(readFileSync(new URL('src/data/theme.json', root), 'utf8'));
|
|
401
|
+
if (typeof theme !== 'string' || !/^[a-z0-9-]+$/.test(theme) || !existsSync(new URL(`${themeFolder(theme)}/theme.json`, root)))
|
|
402
|
+
throw new Error(`src/data/theme.json: temaet ${JSON.stringify(theme)} er ikke installeret (src/themes/<tema>/theme.json).`);
|
|
403
|
+
return theme;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/** @data (the site's data, src/data/), @saturn (the standard theme, this package's theme/) and @icons (the system's icon
|
|
407
|
+
* packs), as Vite's resolve.alias. @site is themePlugin's (siteFile). */
|
|
408
|
+
export const aliases = () => ({
|
|
409
|
+
'@data': fileURLToPath(new URL('src/data', root)),
|
|
410
|
+
'@saturn': fileURLToPath(new URL('theme', pkg)),
|
|
411
|
+
'@icons': fileURLToPath(new URL('icons', pkg)),
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
/** @theme and @site as a Vite plugin: `@site/<file>` is the site's own part, else the package's standard one
|
|
415
|
+
* (siteFile), and `@theme/<file>` is the theme in use's file, else the standard theme's. A glob
|
|
416
|
+
* (`import.meta.glob('@theme/blocks/*\/View.tsx')`) is the theme in use's; whoever globs puts the standard
|
|
417
|
+
* theme's under it (packages/editor/src/standard/siteLooks.ts, packages/editor/src/standard/themeBlocks.ts).
|
|
418
|
+
* And the theme's icons (themeIcons: its own, else the icon pack in use's, iconPack) in Phosphor's place, on the site
|
|
419
|
+
* and in the editor alike: an import of `@phosphor-icons/react` is Phosphor's with the theme's icons in place of its own
|
|
420
|
+
* (reactIcons), and an SVG file of Phosphor's as text (`?raw`) the theme's, when it has one. An icon neither has is
|
|
421
|
+
* Phosphor's (check:content stops at a pack without one the site or the editor draws: packProblems). With Phosphor's
|
|
422
|
+
* pack and no icons of its own nothing is changed. The pack is read when the site is built, so a new choice
|
|
423
|
+
* (src/data/icons.json) or theme is in the site and the editor after the next build. */
|
|
424
|
+
export function themePlugin() {
|
|
425
|
+
const themes = [activeTheme(), STANDARD_THEME].map((t) => fileURLToPath(new URL(`${themeFolder(t)}/`, root)));
|
|
426
|
+
const icons = themeIcons();
|
|
427
|
+
const own = Object.keys(icons).length > 0;
|
|
428
|
+
return {
|
|
429
|
+
name: 'site-theme',
|
|
430
|
+
enforce: 'pre',
|
|
431
|
+
// Phosphor's package bundled for the browser, also when the first import of it is the theme's icons'.
|
|
432
|
+
config: () => (own ? { optimizeDeps: { include: [PHOSPHOR_REACT] } } : {}),
|
|
433
|
+
resolveId(source, importer) {
|
|
434
|
+
// The theme's icons import Phosphor's own.
|
|
435
|
+
if (source === PHOSPHOR_REACT) return own && importer !== REACT_ICONS ? REACT_ICONS : null;
|
|
436
|
+
const icon = source.match(PHOSPHOR_FILE)?.[1];
|
|
437
|
+
if (icon) return svgParts(icons[icon]) ? FILE_ICON + icon : null;
|
|
438
|
+
if (source.startsWith('@site/')) return siteFile(source.slice('@site/'.length));
|
|
439
|
+
if (!source.startsWith('@theme/')) return null;
|
|
440
|
+
const file = source.slice('@theme/'.length);
|
|
441
|
+
if (file.includes('*')) return themes[0] + file;
|
|
442
|
+
// A file without its extension (`@theme/editor/previews`), as TypeScript writes it.
|
|
443
|
+
for (const dir of themes)
|
|
444
|
+
for (const ext of ['', '.ts', '.tsx', '.mjs', '.js'])
|
|
445
|
+
if (statSync(dir + file + ext, { throwIfNoEntry: false })?.isFile()) return dir + file + ext;
|
|
446
|
+
return null;
|
|
447
|
+
},
|
|
448
|
+
load(id) {
|
|
449
|
+
if (id === REACT_ICONS) return reactIcons(icons);
|
|
450
|
+
if (id.startsWith(FILE_ICON)) return fileIcon(icons[id.slice(FILE_ICON.length)]);
|
|
451
|
+
return null;
|
|
452
|
+
},
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/** What a block is missing to be drawn from its view (packages/editor/src/standard/view.tsx): a standard block's
|
|
457
|
+
* contract its view.ts and load.ts, an app's block (src/apps/<app>/blocks/<type>/) those and its View.tsx; and the
|
|
458
|
+
* files of how a block looked before (Site.astro, draw.tsx), which nothing uses now. */
|
|
459
|
+
export function blockProblems() {
|
|
460
|
+
const problems = [];
|
|
461
|
+
for (const type of standardTypes())
|
|
462
|
+
for (const f of ['view.ts', 'load.ts'])
|
|
463
|
+
if (!existsSync(new URL(`src/standard/${type}/${f}`, pkg))) problems.push(`packages/editor/src/standard/${type}/${f} mangler.`);
|
|
464
|
+
for (const app of folders(new URL('src/apps/', root)))
|
|
465
|
+
for (const type of folders(new URL(`src/apps/${app}/blocks/`, root))) {
|
|
466
|
+
const dir = `src/apps/${app}/blocks/${type}`;
|
|
467
|
+
for (const f of ['index.tsx', 'view.ts', 'load.ts', 'View.tsx']) if (!has(`${dir}/${f}`)) problems.push(`${dir}/${f} mangler.`);
|
|
468
|
+
for (const f of OLD_LOOK)
|
|
469
|
+
if (has(`${dir}/${f}`)) problems.push(`${dir}/${f}: blokken tegnes af View.tsx, både på sitet og i editoren.`);
|
|
470
|
+
}
|
|
471
|
+
return problems;
|
|
472
|
+
}
|