@morphemecms/cms 0.1.0 → 0.2.0-next-20261104150211
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/CHANGELOG.md +12 -0
- package/LICENSE +21 -21
- package/README.md +51 -51
- package/astro.mjs +162 -162
- package/bin/morpheme.mjs +38 -38
- package/client.d.ts +10 -10
- package/defaults/blockTexts.ts +33 -33
- package/defaults/collections.ts +774 -774
- package/defaults/colors.ts +125 -125
- package/defaults/company.ts +20 -20
- package/defaults/editor.ts +178 -178
- package/defaults/internalLinks.ts +30 -30
- package/defaults/opens.ts +18 -18
- package/defaults/popup.tsx +93 -93
- package/defaults/privacy.ts +79 -79
- package/defaults/rules.ts +450 -450
- package/defaults/schema.ts +16 -16
- package/defaults/sitedata.ts +129 -129
- package/defaults/standard.ts +106 -106
- package/defaults/standardPages.ts +87 -87
- package/defaults/texts.ts +481 -481
- package/demo/README.md +26 -26
- package/demo/src/content/blog/build-a-page-from-blocks.md +19 -19
- package/demo/src/content/blog/colors-everyone-can-read.md +19 -19
- package/demo/src/content/blog/edit-your-website-from-your-phone.md +21 -21
- package/demo/src/content/blog/every-save-is-a-version.md +21 -21
- package/demo/src/content/blog/schedule-a-post.md +17 -17
- package/demo/src/content/blog/secure-from-day-one.md +17 -17
- package/demo/src/content/blog/seo-without-the-guesswork.md +23 -23
- package/demo/src/content/blog/switch-themes-without-losing-anything.md +23 -23
- package/demo/src/content/blog/the-app-store.md +21 -21
- package/demo/src/content/pages/about.md +22 -22
- package/demo/src/content/pages/app-store.md +30 -30
- package/demo/src/content/pages/blocks.md +98 -98
- package/demo/src/content/pages/blog-page.md +11 -11
- package/demo/src/content/pages/contact.md +16 -16
- package/demo/src/content/pages/get-started.md +20 -20
- package/demo/src/content/pages/home.md +26 -26
- package/demo/src/content/pages/page-not-found.md +11 -11
- package/demo/src/content/pages/privacy-policy.md +24 -24
- package/demo/src/data/blocks.json +25 -25
- package/demo/src/data/booking.json +6 -6
- package/demo/src/data/categories/apps.json +6 -6
- package/demo/src/data/categories/design.json +6 -6
- package/demo/src/data/categories/editing.json +6 -6
- package/demo/src/data/categories/security.json +6 -6
- package/demo/src/data/categories/seo.json +6 -6
- package/demo/src/data/colors.json +75 -75
- package/demo/src/data/contact.json +8 -8
- package/demo/src/data/cookies.json +21 -21
- package/demo/src/data/footer.json +27 -27
- package/demo/src/data/menu.json +35 -35
- package/demo/src/data/mobile-menu.json +25 -25
- package/demo/src/data/popups/booking-bar.json +13 -13
- package/demo/src/data/popups/try-the-editor.json +16 -16
- package/demo/src/data/standard-pages.json +8 -8
- package/demo/src/data/testimonials/sample-bakery.json +10 -10
- package/demo/src/data/testimonials/sample-clinic.json +10 -10
- package/demo/src/data/testimonials/sample-studio.json +10 -10
- package/demo/src/site/colors.ts +11 -11
- package/demo/src/site/config.ts +19 -19
- package/icons/lucide/LICENSE +43 -43
- package/icons/lucide/address-book.svg +1 -1
- package/icons/lucide/app-window.svg +1 -1
- package/icons/lucide/arrow-counter-clockwise.svg +1 -1
- package/icons/lucide/arrow-down.svg +1 -1
- package/icons/lucide/arrow-left.svg +1 -1
- package/icons/lucide/arrow-right.svg +1 -1
- package/icons/lucide/arrow-square-out.svg +1 -1
- package/icons/lucide/arrow-u-up-left.svg +1 -1
- package/icons/lucide/arrow-u-up-right.svg +1 -1
- package/icons/lucide/arrow-up-right.svg +1 -1
- package/icons/lucide/arrow-up.svg +1 -1
- package/icons/lucide/arrows-down-up.svg +1 -1
- package/icons/lucide/arrows-in-line-horizontal.svg +1 -1
- package/icons/lucide/arrows-out-line-horizontal.svg +1 -1
- package/icons/lucide/article.svg +1 -1
- package/icons/lucide/bank.svg +1 -1
- package/icons/lucide/bell.svg +1 -1
- package/icons/lucide/bicycle.svg +1 -1
- package/icons/lucide/binoculars.svg +1 -1
- package/icons/lucide/book-open-text.svg +1 -1
- package/icons/lucide/book-open.svg +1 -1
- package/icons/lucide/browser.svg +1 -1
- package/icons/lucide/buildings.svg +1 -1
- package/icons/lucide/bus.svg +1 -1
- package/icons/lucide/calendar-blank.svg +1 -1
- package/icons/lucide/calendar-check.svg +1 -1
- package/icons/lucide/car.svg +1 -1
- package/icons/lucide/cards.svg +1 -1
- package/icons/lucide/caret-down.svg +1 -1
- package/icons/lucide/caret-left.svg +1 -1
- package/icons/lucide/caret-right.svg +1 -1
- package/icons/lucide/caret-up.svg +1 -1
- package/icons/lucide/certificate.svg +1 -1
- package/icons/lucide/chart-line-up.svg +1 -1
- package/icons/lucide/chats.svg +1 -1
- package/icons/lucide/check-circle.svg +1 -1
- package/icons/lucide/check.svg +1 -1
- package/icons/lucide/circle-half.svg +1 -1
- package/icons/lucide/circle.svg +1 -1
- package/icons/lucide/clock-counter-clockwise.svg +1 -1
- package/icons/lucide/clock.svg +1 -1
- package/icons/lucide/code.svg +1 -1
- package/icons/lucide/coffee.svg +1 -1
- package/icons/lucide/columns.svg +1 -1
- package/icons/lucide/cookie.svg +1 -1
- package/icons/lucide/copy.svg +1 -1
- package/icons/lucide/credit-card.svg +1 -1
- package/icons/lucide/currency-circle-dollar.svg +1 -1
- package/icons/lucide/cursor-click.svg +1 -1
- package/icons/lucide/database.svg +1 -1
- package/icons/lucide/desktop.svg +1 -1
- package/icons/lucide/device-mobile.svg +1 -1
- package/icons/lucide/door-open.svg +1 -1
- package/icons/lucide/download-simple.svg +1 -1
- package/icons/lucide/envelope-simple.svg +1 -1
- package/icons/lucide/eye-slash.svg +1 -1
- package/icons/lucide/eye.svg +1 -1
- package/icons/lucide/file-pdf.svg +1 -1
- package/icons/lucide/file-text.svg +1 -1
- package/icons/lucide/file-video.svg +1 -1
- package/icons/lucide/file-zip.svg +1 -1
- package/icons/lucide/flower-lotus.svg +1 -1
- package/icons/lucide/folder-simple.svg +1 -1
- package/icons/lucide/funnel.svg +1 -1
- package/icons/lucide/gauge.svg +1 -1
- package/icons/lucide/gear.svg +1 -1
- package/icons/lucide/github-logo.svg +1 -1
- package/icons/lucide/globe.svg +1 -1
- package/icons/lucide/google-logo.svg +1 -1
- package/icons/lucide/graduation-cap.svg +1 -1
- package/icons/lucide/hammer.svg +1 -1
- package/icons/lucide/hand-heart.svg +1 -1
- package/icons/lucide/handshake.svg +1 -1
- package/icons/lucide/hard-drives.svg +1 -1
- package/icons/lucide/heart.svg +1 -1
- package/icons/lucide/house.svg +1 -1
- package/icons/lucide/image-square.svg +1 -1
- package/icons/lucide/image.svg +1 -1
- package/icons/lucide/info.svg +1 -1
- package/icons/lucide/keyboard.svg +1 -1
- package/icons/lucide/leaf.svg +1 -1
- package/icons/lucide/lifebuoy.svg +1 -1
- package/icons/lucide/lightbulb.svg +1 -1
- package/icons/lucide/link-break.svg +1 -1
- package/icons/lucide/link-simple.svg +1 -1
- package/icons/lucide/list-bullets.svg +1 -1
- package/icons/lucide/list-checks.svg +1 -1
- package/icons/lucide/list-numbers.svg +1 -1
- package/icons/lucide/list.svg +1 -1
- package/icons/lucide/lock-simple-open.svg +1 -1
- package/icons/lucide/lock-simple.svg +1 -1
- package/icons/lucide/magnifying-glass.svg +1 -1
- package/icons/lucide/map-pin.svg +1 -1
- package/icons/lucide/map-trifold.svg +1 -1
- package/icons/lucide/medal.svg +1 -1
- package/icons/lucide/megaphone.svg +1 -1
- package/icons/lucide/minus.svg +1 -1
- package/icons/lucide/moon.svg +1 -1
- package/icons/lucide/newspaper.svg +1 -1
- package/icons/lucide/pack.json +23 -23
- package/icons/lucide/paint-brush-broad.svg +1 -1
- package/icons/lucide/palette.svg +1 -1
- package/icons/lucide/paper-plane-tilt.svg +1 -1
- package/icons/lucide/pencil-simple.svg +1 -1
- package/icons/lucide/phone.svg +1 -1
- package/icons/lucide/play-fill.svg +1 -1
- package/icons/lucide/plus.svg +1 -1
- package/icons/lucide/prohibit.svg +1 -1
- package/icons/lucide/puzzle-piece.svg +1 -1
- package/icons/lucide/question.svg +1 -1
- package/icons/lucide/quotes.svg +1 -1
- package/icons/lucide/rows.svg +1 -1
- package/icons/lucide/ruler.svg +1 -1
- package/icons/lucide/scan.svg +1 -1
- package/icons/lucide/shapes.svg +1 -1
- package/icons/lucide/share-network.svg +1 -1
- package/icons/lucide/shield-check.svg +1 -1
- package/icons/lucide/sidebar-simple.svg +1 -1
- package/icons/lucide/sign-out.svg +1 -1
- package/icons/lucide/signpost.svg +1 -1
- package/icons/lucide/sliders-horizontal.svg +1 -1
- package/icons/lucide/smiley.svg +1 -1
- package/icons/lucide/sparkle.svg +1 -1
- package/icons/lucide/square-half-bottom.svg +1 -1
- package/icons/lucide/square.svg +1 -1
- package/icons/lucide/squares-four.svg +1 -1
- package/icons/lucide/sticker.svg +1 -1
- package/icons/lucide/storefront.svg +1 -1
- package/icons/lucide/sun.svg +1 -1
- package/icons/lucide/swatches.svg +1 -1
- package/icons/lucide/tag.svg +1 -1
- package/icons/lucide/text-aa.svg +1 -1
- package/icons/lucide/text-align-left.svg +1 -1
- package/icons/lucide/text-b.svg +1 -1
- package/icons/lucide/text-h-one.svg +1 -1
- package/icons/lucide/text-h-three.svg +1 -1
- package/icons/lucide/text-h-two.svg +1 -1
- package/icons/lucide/text-italic.svg +1 -1
- package/icons/lucide/text-t.svg +1 -1
- package/icons/lucide/ticket.svg +1 -1
- package/icons/lucide/toggle-right.svg +1 -1
- package/icons/lucide/train.svg +1 -1
- package/icons/lucide/trash.svg +1 -1
- package/icons/lucide/upload-simple.svg +1 -1
- package/icons/lucide/user-circle.svg +1 -1
- package/icons/lucide/user.svg +1 -1
- package/icons/lucide/users-three.svg +1 -1
- package/icons/lucide/users.svg +1 -1
- package/icons/lucide/video-camera.svg +1 -1
- package/icons/lucide/warning-circle.svg +1 -1
- package/icons/lucide/warning.svg +1 -1
- package/icons/lucide/wave-sine.svg +1 -1
- package/icons/lucide/wheelchair.svg +1 -1
- package/icons/lucide/wrench.svg +1 -1
- package/icons/lucide/x.svg +1 -1
- package/icons/material-symbols/LICENSE +201 -201
- package/icons/material-symbols/address-book.svg +1 -1
- package/icons/material-symbols/app-window.svg +1 -1
- package/icons/material-symbols/arrow-counter-clockwise.svg +1 -1
- package/icons/material-symbols/arrow-down.svg +1 -1
- package/icons/material-symbols/arrow-left.svg +1 -1
- package/icons/material-symbols/arrow-right.svg +1 -1
- package/icons/material-symbols/arrow-square-out.svg +1 -1
- package/icons/material-symbols/arrow-u-up-left.svg +1 -1
- package/icons/material-symbols/arrow-u-up-right.svg +1 -1
- package/icons/material-symbols/arrow-up-right.svg +1 -1
- package/icons/material-symbols/arrow-up.svg +1 -1
- package/icons/material-symbols/arrows-down-up.svg +1 -1
- package/icons/material-symbols/arrows-in-line-horizontal.svg +1 -1
- package/icons/material-symbols/arrows-out-line-horizontal.svg +1 -1
- package/icons/material-symbols/article.svg +1 -1
- package/icons/material-symbols/bank.svg +1 -1
- package/icons/material-symbols/bell.svg +1 -1
- package/icons/material-symbols/bicycle.svg +1 -1
- package/icons/material-symbols/binoculars.svg +1 -1
- package/icons/material-symbols/book-open-text.svg +1 -1
- package/icons/material-symbols/book-open.svg +1 -1
- package/icons/material-symbols/browser.svg +1 -1
- package/icons/material-symbols/buildings.svg +1 -1
- package/icons/material-symbols/bus.svg +1 -1
- package/icons/material-symbols/calendar-blank.svg +1 -1
- package/icons/material-symbols/calendar-check.svg +1 -1
- package/icons/material-symbols/car.svg +1 -1
- package/icons/material-symbols/cards.svg +1 -1
- package/icons/material-symbols/caret-down.svg +1 -1
- package/icons/material-symbols/caret-left.svg +1 -1
- package/icons/material-symbols/caret-right.svg +1 -1
- package/icons/material-symbols/caret-up.svg +1 -1
- package/icons/material-symbols/certificate.svg +1 -1
- package/icons/material-symbols/chart-line-up.svg +1 -1
- package/icons/material-symbols/chats.svg +1 -1
- package/icons/material-symbols/check-circle.svg +1 -1
- package/icons/material-symbols/check.svg +1 -1
- package/icons/material-symbols/circle-half.svg +1 -1
- package/icons/material-symbols/circle.svg +1 -1
- package/icons/material-symbols/clock-counter-clockwise.svg +1 -1
- package/icons/material-symbols/clock.svg +1 -1
- package/icons/material-symbols/code.svg +1 -1
- package/icons/material-symbols/coffee.svg +1 -1
- package/icons/material-symbols/columns.svg +1 -1
- package/icons/material-symbols/cookie.svg +1 -1
- package/icons/material-symbols/copy.svg +1 -1
- package/icons/material-symbols/credit-card.svg +1 -1
- package/icons/material-symbols/currency-circle-dollar.svg +1 -1
- package/icons/material-symbols/cursor-click.svg +1 -1
- package/icons/material-symbols/database.svg +1 -1
- package/icons/material-symbols/desktop.svg +1 -1
- package/icons/material-symbols/device-mobile.svg +1 -1
- package/icons/material-symbols/door-open.svg +1 -1
- package/icons/material-symbols/download-simple.svg +1 -1
- package/icons/material-symbols/envelope-simple.svg +1 -1
- package/icons/material-symbols/eye-slash.svg +1 -1
- package/icons/material-symbols/eye.svg +1 -1
- package/icons/material-symbols/file-pdf.svg +1 -1
- package/icons/material-symbols/file-text.svg +1 -1
- package/icons/material-symbols/file-video.svg +1 -1
- package/icons/material-symbols/file-zip.svg +1 -1
- package/icons/material-symbols/flower-lotus.svg +1 -1
- package/icons/material-symbols/folder-simple.svg +1 -1
- package/icons/material-symbols/funnel.svg +1 -1
- package/icons/material-symbols/gauge.svg +1 -1
- package/icons/material-symbols/gear.svg +1 -1
- package/icons/material-symbols/github-logo.svg +1 -1
- package/icons/material-symbols/globe.svg +1 -1
- package/icons/material-symbols/google-logo.svg +1 -1
- package/icons/material-symbols/graduation-cap.svg +1 -1
- package/icons/material-symbols/hammer.svg +1 -1
- package/icons/material-symbols/hand-heart.svg +1 -1
- package/icons/material-symbols/handshake.svg +1 -1
- package/icons/material-symbols/hard-drives.svg +1 -1
- package/icons/material-symbols/heart.svg +1 -1
- package/icons/material-symbols/house.svg +1 -1
- package/icons/material-symbols/image-square.svg +1 -1
- package/icons/material-symbols/image.svg +1 -1
- package/icons/material-symbols/info.svg +1 -1
- package/icons/material-symbols/keyboard.svg +1 -1
- package/icons/material-symbols/leaf.svg +1 -1
- package/icons/material-symbols/lifebuoy.svg +1 -1
- package/icons/material-symbols/lightbulb.svg +1 -1
- package/icons/material-symbols/link-break.svg +1 -1
- package/icons/material-symbols/link-simple.svg +1 -1
- package/icons/material-symbols/list-bullets.svg +1 -1
- package/icons/material-symbols/list-checks.svg +1 -1
- package/icons/material-symbols/list-numbers.svg +1 -1
- package/icons/material-symbols/list.svg +1 -1
- package/icons/material-symbols/lock-simple-open.svg +1 -1
- package/icons/material-symbols/lock-simple.svg +1 -1
- package/icons/material-symbols/magnifying-glass.svg +1 -1
- package/icons/material-symbols/map-pin.svg +1 -1
- package/icons/material-symbols/map-trifold.svg +1 -1
- package/icons/material-symbols/medal.svg +1 -1
- package/icons/material-symbols/megaphone.svg +1 -1
- package/icons/material-symbols/minus.svg +1 -1
- package/icons/material-symbols/moon.svg +1 -1
- package/icons/material-symbols/newspaper.svg +1 -1
- package/icons/material-symbols/pack.json +29 -29
- package/icons/material-symbols/paint-brush-broad.svg +1 -1
- package/icons/material-symbols/palette.svg +1 -1
- package/icons/material-symbols/paper-plane-tilt.svg +1 -1
- package/icons/material-symbols/pencil-simple.svg +1 -1
- package/icons/material-symbols/phone.svg +1 -1
- package/icons/material-symbols/play-fill.svg +1 -1
- package/icons/material-symbols/plus.svg +1 -1
- package/icons/material-symbols/prohibit.svg +1 -1
- package/icons/material-symbols/puzzle-piece.svg +1 -1
- package/icons/material-symbols/question.svg +1 -1
- package/icons/material-symbols/quotes.svg +1 -1
- package/icons/material-symbols/rows.svg +1 -1
- package/icons/material-symbols/ruler.svg +1 -1
- package/icons/material-symbols/scan.svg +1 -1
- package/icons/material-symbols/shapes.svg +1 -1
- package/icons/material-symbols/share-network.svg +1 -1
- package/icons/material-symbols/shield-check.svg +1 -1
- package/icons/material-symbols/sidebar-simple.svg +1 -1
- package/icons/material-symbols/sign-out.svg +1 -1
- package/icons/material-symbols/signpost.svg +1 -1
- package/icons/material-symbols/sliders-horizontal.svg +1 -1
- package/icons/material-symbols/smiley.svg +1 -1
- package/icons/material-symbols/sparkle.svg +1 -1
- package/icons/material-symbols/square-half-bottom.svg +1 -1
- package/icons/material-symbols/square.svg +1 -1
- package/icons/material-symbols/squares-four.svg +1 -1
- package/icons/material-symbols/sticker.svg +1 -1
- package/icons/material-symbols/storefront.svg +1 -1
- package/icons/material-symbols/sun.svg +1 -1
- package/icons/material-symbols/swatches.svg +1 -1
- package/icons/material-symbols/tag.svg +1 -1
- package/icons/material-symbols/text-aa.svg +1 -1
- package/icons/material-symbols/text-align-left.svg +1 -1
- package/icons/material-symbols/text-b.svg +1 -1
- package/icons/material-symbols/text-h-one.svg +1 -1
- package/icons/material-symbols/text-h-three.svg +1 -1
- package/icons/material-symbols/text-h-two.svg +1 -1
- package/icons/material-symbols/text-italic.svg +1 -1
- package/icons/material-symbols/text-t.svg +1 -1
- package/icons/material-symbols/ticket.svg +1 -1
- package/icons/material-symbols/toggle-right.svg +1 -1
- package/icons/material-symbols/train.svg +1 -1
- package/icons/material-symbols/trash.svg +1 -1
- package/icons/material-symbols/upload-simple.svg +1 -1
- package/icons/material-symbols/user-circle.svg +1 -1
- package/icons/material-symbols/user.svg +1 -1
- package/icons/material-symbols/users-three.svg +1 -1
- package/icons/material-symbols/users.svg +1 -1
- package/icons/material-symbols/video-camera.svg +1 -1
- package/icons/material-symbols/warning-circle.svg +1 -1
- package/icons/material-symbols/warning.svg +1 -1
- package/icons/material-symbols/wave-sine.svg +1 -1
- package/icons/material-symbols/wheelchair.svg +1 -1
- package/icons/material-symbols/wrench.svg +1 -1
- package/icons/material-symbols/x.svg +1 -1
- package/icons/phosphor/pack.json +8 -8
- package/lib/apps.mjs +142 -139
- package/lib/apps.test.d.mts +1 -0
- package/lib/apps.test.mjs +50 -0
- package/lib/blocks.mjs +90 -90
- package/lib/caseCollisions.d.mts +4 -0
- package/lib/caseCollisions.mjs +62 -0
- package/lib/caseCollisions.test.d.mts +1 -0
- package/lib/caseCollisions.test.mjs +74 -0
- package/lib/colors.ts +86 -86
- package/lib/contactBar.ts +18 -18
- package/lib/contracts.d.mts +15 -0
- package/lib/contracts.mjs +17 -0
- package/lib/cookieCategories.mjs +28 -28
- package/lib/crop.mjs +83 -83
- package/lib/csp.mjs +130 -130
- package/lib/cspSources.mjs +60 -60
- package/lib/dynamic-colors.ts +426 -426
- package/lib/git.mjs +64 -64
- package/lib/hooks.ts +51 -51
- package/lib/inline.ts +20 -20
- package/lib/license-texts/Apache-2.0.txt +190 -190
- package/lib/license-texts/BSD-2-Clause.txt +24 -24
- package/lib/license-texts/BSD-3-Clause.txt +28 -28
- package/lib/license-texts/ISC.txt +15 -15
- package/lib/license-texts/MIT.txt +21 -21
- package/lib/licenses.d.mts +1 -1
- package/lib/licenses.mjs +683 -683
- package/lib/markdown.ts +42 -42
- package/lib/motion-schemes.mjs +5 -5
- package/lib/motion.ts +131 -131
- package/lib/notice.mjs +34 -34
- package/lib/scheduled.mjs +37 -37
- package/lib/snackbar.ts +149 -149
- package/lib/status.mjs +18 -18
- package/lib/storeEntries.d.mts +18 -0
- package/lib/storeEntries.mjs +64 -0
- package/lib/storeEntries.test.d.mts +1 -0
- package/lib/storeEntries.test.mjs +71 -0
- package/lib/svg.mjs +231 -231
- package/lib/text-colors.mjs +43 -43
- package/lib/video-id.mjs +72 -72
- package/lib/video.mjs +91 -91
- package/package.json +136 -131
- package/pages/404.astro +10 -10
- package/pages/[...slug].astro +51 -51
- package/pages/_headers.txt +31 -31
- package/pages/blog/index.astro +10 -10
- package/pages/blog/kategori/[category].astro +18 -18
- package/pages/editor/code-images.json.js +25 -25
- package/pages/editor/index.astro +75 -75
- package/pages/editor/manifest.webmanifest.js +23 -23
- package/pages/editor/sw.js +33 -33
- package/pages/editor/sw.js.js +4 -4
- package/pages/editor/thumbnails.json.js +21 -21
- package/pages/editor/version.json.js +22 -22
- package/pages/headers.js +4 -4
- package/pages/index.astro +10 -10
- package/pages/ny.astro +6 -6
- package/pages/robots.txt.js +3 -3
- package/pages/rss.xml.js +20 -20
- package/scripts/app-screenshots.mjs +164 -164
- package/scripts/app-workers.mjs +6 -6
- package/scripts/bin.mjs +12 -12
- package/scripts/built-site.mjs +134 -99
- package/scripts/check-consent.mjs +113 -113
- package/scripts/check-content.mjs +151 -149
- package/scripts/check-demo.mjs +24 -24
- package/scripts/check-store.mjs +160 -0
- package/scripts/check-themes.mjs +45 -45
- package/scripts/check-worker.mjs +569 -569
- package/scripts/compare-html.mjs +81 -81
- package/scripts/declarations.mjs +10 -0
- package/scripts/declarations.test.mjs +32 -0
- package/scripts/demo-site.mjs +42 -42
- package/scripts/editor-icons.mjs +56 -56
- package/scripts/editor-roundtrip.mjs +134 -134
- package/scripts/editor-screens.mjs +101 -101
- package/scripts/git-env.mjs +9 -9
- package/scripts/icon-packs.mjs +151 -151
- package/scripts/link-counts.mjs +22 -22
- package/scripts/page-colors.mjs +42 -42
- package/scripts/releases.mjs +80 -80
- package/scripts/responsive-images.mjs +94 -94
- package/scripts/scheduled-list.mjs +15 -15
- package/scripts/theme-screenshots.mjs +88 -88
- package/scripts/types.mjs +17 -21
- package/scripts/video-thumbnails.mjs +89 -89
- package/scripts/worker-modules.mjs +34 -34
- package/site/appCookies.mjs +74 -74
- package/site/apps.ts +21 -21
- package/site/autolinks.mjs +200 -200
- package/site/blockScripts.ts +31 -31
- package/site/categories.ts +16 -16
- package/site/consent.ts +26 -26
- package/site/content.config.ts +84 -84
- package/site/content.ts +104 -104
- package/site/cookieList.ts +17 -17
- package/site/defineSite.d.mts +2 -14
- package/site/defineSite.mjs +131 -136
- package/site/directives/interact.mjs +31 -31
- package/site/editor-version.mjs +26 -26
- package/site/fill.ts +13 -13
- package/site/format.ts +11 -11
- package/site/home.ts +66 -66
- package/site/iconPacks.mjs +43 -43
- package/site/icons.mjs +605 -605
- package/site/images.mjs +157 -157
- package/site/motion.ts +13 -13
- package/site/noindex.mjs +21 -21
- package/site/pageColors.ts +110 -110
- package/site/popups.ts +98 -98
- package/site/schema.ts +189 -189
- package/site/sections.ts +3 -3
- package/site/seo.ts +28 -28
- package/site/site.ts +76 -76
- package/site/siteConfig.mjs +8 -8
- package/site/siteCsp.mjs +75 -75
- package/site/siteModules.mjs +27 -27
- package/site/standardPages.ts +59 -59
- package/site/storeTheme.d.mts +6 -0
- package/site/storeTheme.mjs +29 -0
- package/site/storeTheme.test.d.mts +1 -0
- package/site/storeTheme.test.mjs +53 -0
- package/site/testimonials.ts +48 -48
- package/site/text.ts +43 -43
- package/site/theme.mjs +483 -472
- package/site/tracking.client.ts +225 -225
- package/site/tracking.ts +9 -9
- package/src/ActionParts.tsx +205 -205
- package/src/Advanced.tsx +152 -152
- package/src/App.tsx +901 -904
- package/src/AppList.tsx +1362 -1345
- package/src/BlockDialog.tsx +360 -360
- package/src/BlockParts.tsx +652 -652
- package/src/BlockSettings.tsx +533 -533
- package/src/BrandForm.tsx +164 -164
- package/src/Colors.tsx +476 -476
- package/src/CommunicationParts.tsx +199 -199
- package/src/CompanyForm.tsx +209 -209
- package/src/Consents.tsx +175 -175
- package/src/ContainmentParts.tsx +185 -185
- package/src/Crop.tsx +152 -152
- package/src/DataForm.tsx +434 -434
- package/src/Deleted.tsx +177 -177
- package/src/EntryForm.tsx +740 -740
- package/src/FileView.tsx +30 -30
- package/src/FormFrame.tsx +237 -237
- package/src/Keywords.tsx +225 -225
- package/src/Library.tsx +1563 -1563
- package/src/Licenses.tsx +336 -336
- package/src/LinkSheet.tsx +138 -138
- package/src/MarkdownEditor.tsx +1075 -1075
- package/src/Media.tsx +677 -677
- package/src/NavigationParts.tsx +350 -350
- package/src/NavigationRestParts.tsx +247 -247
- package/src/Notifications.tsx +59 -59
- package/src/PagePicker.tsx +136 -136
- package/src/Parts.tsx +991 -991
- package/src/PartsShown.tsx +168 -168
- package/src/PickerParts.tsx +183 -183
- package/src/Redirects.tsx +450 -450
- package/src/Screen.tsx +184 -184
- package/src/SectionsField.tsx +65 -65
- package/src/SelectionParts.tsx +134 -134
- package/src/SeoScores.tsx +184 -184
- package/src/Sheet.tsx +35 -35
- package/src/ThemeStore.tsx +376 -376
- package/src/Tokens.tsx +346 -346
- package/src/Versions.tsx +214 -214
- package/src/addresses.ts +75 -75
- package/src/allIcons.ts +7 -7
- package/src/appFiles.ts +29 -29
- package/src/apps.ts +281 -281
- package/src/ask.tsx +123 -123
- package/src/blocks.ts +251 -251
- package/src/brand.ts +153 -153
- package/src/cache.ts +42 -42
- package/src/check.ts +285 -285
- package/src/checkSite.ts +256 -256
- package/src/{consents.ts → consentData.ts} +26 -26
- package/src/cookieList.ts +70 -70
- package/src/countries.ts +59 -59
- package/src/deploy.ts +155 -155
- package/src/editor.css +602 -602
- package/src/examples.ts +85 -85
- package/src/fields.tsx +942 -942
- package/src/frontmatter.mjs +42 -42
- package/src/github.ts +376 -376
- package/src/i18n/da-DK/advanced.ts +28 -28
- package/src/i18n/da-DK/app.ts +71 -71
- package/src/i18n/da-DK/apps.ts +90 -90
- package/src/i18n/da-DK/blockSettings.ts +38 -38
- package/src/i18n/da-DK/blocks.ts +408 -408
- package/src/i18n/da-DK/check.ts +25 -25
- package/src/i18n/da-DK/colors.ts +64 -64
- package/src/i18n/da-DK/common.ts +118 -118
- package/src/i18n/da-DK/company.ts +24 -24
- package/src/i18n/da-DK/consents.ts +23 -23
- package/src/i18n/da-DK/forms.ts +116 -116
- package/src/i18n/da-DK/history.ts +35 -35
- package/src/i18n/da-DK/index.ts +49 -49
- package/src/i18n/da-DK/keywords.ts +19 -19
- package/src/i18n/da-DK/library.ts +135 -135
- package/src/i18n/da-DK/licenses.ts +25 -25
- package/src/i18n/da-DK/media.ts +79 -79
- package/src/i18n/da-DK/parts.ts +696 -696
- package/src/i18n/da-DK/preview.ts +13 -13
- package/src/i18n/da-DK/redirects.ts +51 -51
- package/src/i18n/da-DK/seo.ts +20 -20
- package/src/i18n/da-DK/text.ts +35 -35
- package/src/i18n/da-DK/theme.ts +41 -41
- package/src/i18n/en-US/advanced.ts +32 -32
- package/src/i18n/en-US/app.ts +84 -84
- package/src/i18n/en-US/apps.ts +134 -134
- package/src/i18n/en-US/blockSettings.ts +48 -48
- package/src/i18n/en-US/blocks.ts +441 -441
- package/src/i18n/en-US/check.ts +31 -31
- package/src/i18n/en-US/colors.ts +82 -82
- package/src/i18n/en-US/common.ts +144 -144
- package/src/i18n/en-US/company.ts +25 -25
- package/src/i18n/en-US/consents.ts +25 -25
- package/src/i18n/en-US/forms.ts +145 -145
- package/src/i18n/en-US/history.ts +43 -43
- package/src/i18n/en-US/index.ts +51 -51
- package/src/i18n/en-US/keywords.ts +24 -24
- package/src/i18n/en-US/library.ts +176 -176
- package/src/i18n/en-US/licenses.ts +36 -36
- package/src/i18n/en-US/media.ts +80 -80
- package/src/i18n/en-US/parts.ts +718 -718
- package/src/i18n/en-US/preview.ts +15 -15
- package/src/i18n/en-US/redirects.ts +66 -66
- package/src/i18n/en-US/seo.ts +26 -26
- package/src/i18n/en-US/text.ts +41 -41
- package/src/i18n/en-US/theme.ts +41 -41
- package/src/i18n/index.ts +124 -124
- package/src/icon.tsx +160 -160
- package/src/iconPacks.ts +89 -89
- package/src/images.ts +163 -163
- package/src/{licenses.ts → licenseData.ts} +79 -79
- package/src/markdown.mjs +204 -204
- package/src/nav.ts +68 -68
- package/src/notFound.ts +28 -28
- package/src/{notifications.ts → notificationData.ts} +223 -223
- package/src/pagePreview.tsx +204 -204
- package/src/r2Caching.ts +55 -55
- package/src/{redirects.ts → redirectData.ts} +149 -149
- package/src/registry.tsx +188 -188
- package/src/schema.ts +417 -417
- package/src/sections.mjs +303 -303
- package/src/seo.ts +333 -333
- package/src/shared.ts +44 -44
- package/src/sidebar.ts +31 -31
- package/src/site.ts +317 -317
- package/src/standard/Block.astro +19 -19
- package/src/standard/BlockSite.astro +18 -18
- package/src/standard/accordion/index.tsx +47 -47
- package/src/standard/accordion/load.ts +23 -23
- package/src/standard/accordion/shared.ts +15 -15
- package/src/standard/accordion/view.ts +32 -32
- package/src/standard/buttons/fields.ts +98 -98
- package/src/standard/buttons/index.tsx +23 -23
- package/src/standard/buttons/load.ts +34 -34
- package/src/standard/buttons/shared.ts +12 -12
- package/src/standard/buttons/view.ts +30 -30
- package/src/standard/cards/index.tsx +71 -71
- package/src/standard/cards/load.ts +17 -17
- package/src/standard/cards/shared.ts +27 -27
- package/src/standard/cards/view.ts +29 -29
- package/src/standard/checklist/index.tsx +27 -27
- package/src/standard/checklist/load.ts +5 -5
- package/src/standard/checklist/view.ts +13 -13
- package/src/standard/cookies/index.tsx +17 -17
- package/src/standard/cookies/list.ts +56 -56
- package/src/standard/cookies/load.ts +11 -11
- package/src/standard/cookies/shared.ts +20 -20
- package/src/standard/cookies/view.ts +28 -28
- package/src/standard/faq/index.tsx +29 -29
- package/src/standard/faq/load.ts +14 -14
- package/src/standard/faq/view.ts +21 -21
- package/src/standard/head.ts +23 -23
- package/src/standard/hero/fields.ts +48 -48
- package/src/standard/hero/index.tsx +57 -57
- package/src/standard/hero/load.ts +23 -23
- package/src/standard/hero/view.ts +38 -38
- package/src/standard/links/index.tsx +41 -41
- package/src/standard/links/load.ts +17 -17
- package/src/standard/links/view.ts +25 -25
- package/src/standard/list/index.tsx +50 -50
- package/src/standard/list/load.ts +5 -5
- package/src/standard/list/view.ts +18 -18
- package/src/standard/load.ts +7 -7
- package/src/standard/notice/index.tsx +30 -30
- package/src/standard/notice/load.ts +16 -16
- package/src/standard/notice/view.ts +10 -10
- package/src/standard/points/index.tsx +42 -42
- package/src/standard/points/load.ts +5 -5
- package/src/standard/points/view.ts +12 -12
- package/src/standard/posts/index.tsx +132 -132
- package/src/standard/posts/load.ts +36 -36
- package/src/standard/posts/shared.ts +21 -21
- package/src/standard/posts/view.ts +63 -63
- package/src/standard/pricecards/index.tsx +57 -57
- package/src/standard/pricecards/load.ts +11 -11
- package/src/standard/pricecards/view.ts +50 -50
- package/src/standard/sharedTexts.ts +6 -6
- package/src/standard/site.ts +124 -124
- package/src/standard/siteLooks.ts +19 -19
- package/src/standard/sites.ts +13 -13
- package/src/standard/steps/index.tsx +28 -28
- package/src/standard/steps/load.ts +5 -5
- package/src/standard/steps/view.ts +11 -11
- package/src/standard/testimonials/index.tsx +87 -87
- package/src/standard/testimonials/list.ts +43 -43
- package/src/standard/testimonials/load.ts +58 -58
- package/src/standard/testimonials/shared.ts +13 -13
- package/src/standard/testimonials/view.ts +76 -76
- package/src/standard/themeBlocks.ts +13 -13
- package/src/standard/video/index.tsx +23 -23
- package/src/standard/video/load.ts +10 -10
- package/src/standard/video/view.ts +42 -42
- package/src/standard/view.tsx +105 -105
- package/src/standard/views.ts +37 -37
- package/src/store.ts +479 -499
- package/src/theme.ts +90 -90
- package/src/themeUi.ts +97 -97
- package/src/themes.ts +91 -91
- package/src/ui.tsx +3402 -3402
- package/src/virtual.d.ts +5 -5
- package/src/when.ts +22 -22
- package/starter/.githooks/pre-push +4 -4
- package/starter/.nvmrc +1 -1
- package/starter/.prettierignore +11 -11
- package/starter/.prettierrc.json +7 -7
- package/starter/README.md +27 -26
- package/starter/astro.config.mjs +5 -5
- package/starter/package.json +67 -67
- package/starter/public/_redirects +1 -1
- package/starter/public/favicon.svg +1 -1
- package/starter/public/logo.svg +1 -1
- package/starter/src/content/pages/blog.md +8 -8
- package/starter/src/content/pages/forside.md +9 -9
- package/starter/src/content/pages/kontakt.md +7 -7
- package/starter/src/content/pages/privatlivspolitik.md +9 -9
- package/starter/src/content/pages/siden-findes-ikke.md +7 -7
- package/starter/src/content.config.ts +2 -2
- package/starter/src/data/apps.json +1 -1
- package/starter/src/data/block-settings.json +3 -3
- package/starter/src/data/blocks.json +1 -1
- package/starter/src/data/booking.json +6 -6
- package/starter/src/data/colors.json +70 -70
- package/starter/src/data/contact.json +8 -8
- package/starter/src/data/cookies.json +21 -21
- package/starter/src/data/csp.json +1 -1
- package/starter/src/data/footer.json +15 -15
- package/starter/src/data/internal-links.json +4 -4
- package/starter/src/data/menu.json +4 -4
- package/starter/src/data/mobile-menu.json +4 -4
- package/starter/src/data/old-addresses.json +1 -1
- package/starter/src/data/redirects.json +1 -1
- package/starter/src/data/standard-pages.json +8 -8
- package/starter/src/data/theme.json +1 -1
- package/starter/src/env.d.ts +2 -2
- package/starter/src/site/config.ts +13 -13
- package/starter/src/site/worker.js +14 -14
- package/starter/tsconfig.json +17 -17
- package/starter/worker/apps.js +6 -6
- package/starter/wrangler.jsonc +39 -39
- package/theme/LICENSE +21 -21
- package/theme/blocks/ArrowLink.tsx +14 -14
- package/theme/blocks/BlockHead.tsx +26 -26
- package/theme/blocks/Panel.tsx +32 -32
- package/theme/blocks/Person.tsx +26 -26
- package/theme/blocks/accordion/PageRow.tsx +25 -25
- package/theme/blocks/accordion/View.tsx +17 -17
- package/theme/blocks/buttons/Buttons.tsx +28 -28
- package/theme/blocks/buttons/View.tsx +12 -12
- package/theme/blocks/cards/LinkCards.tsx +72 -72
- package/theme/blocks/cards/View.tsx +20 -20
- package/theme/blocks/checklist/Checks.tsx +15 -15
- package/theme/blocks/checklist/View.tsx +14 -14
- package/theme/blocks/cookies/View.tsx +36 -36
- package/theme/blocks/faq/Accordion.tsx +34 -34
- package/theme/blocks/faq/View.tsx +16 -16
- package/theme/blocks/faq/script.ts +56 -56
- package/theme/blocks/hero/View.tsx +44 -44
- package/theme/blocks/links/LinkGroups.tsx +24 -24
- package/theme/blocks/links/View.tsx +17 -17
- package/theme/blocks/list/Rows.tsx +24 -24
- package/theme/blocks/list/View.tsx +14 -14
- package/theme/blocks/notice/View.tsx +13 -13
- package/theme/blocks/points/PointList.tsx +34 -34
- package/theme/blocks/points/View.tsx +14 -14
- package/theme/blocks/posts/View.tsx +26 -26
- package/theme/blocks/pricecards/View.tsx +40 -40
- package/theme/blocks/steps/StepList.tsx +23 -23
- package/theme/blocks/steps/View.tsx +14 -14
- package/theme/blocks/testimonials/List.tsx +46 -46
- package/theme/blocks/testimonials/Slider.tsx +44 -44
- package/theme/blocks/testimonials/Testimonial.tsx +124 -124
- package/theme/blocks/testimonials/View.tsx +21 -21
- package/theme/blocks/testimonials/script.ts +52 -52
- package/theme/blocks/video/View.tsx +41 -41
- package/theme/components/ActionBar.astro +63 -63
- package/theme/components/AppSlot.astro +21 -21
- package/theme/components/ArrowLink.tsx +21 -21
- package/theme/components/BlogIndex.astro +48 -48
- package/theme/components/BlogPosts.astro +18 -18
- package/theme/components/BlogPosts.tsx +45 -45
- package/theme/components/BookButton.tsx +22 -22
- package/theme/components/Container.astro +11 -11
- package/theme/components/CookieConsent.astro +121 -121
- package/theme/components/EndBlock.astro +21 -21
- package/theme/components/FontPreload.astro +6 -6
- package/theme/components/Footer.astro +85 -85
- package/theme/components/Header.astro +186 -186
- package/theme/components/Icon.astro +16 -16
- package/theme/components/Img.astro +29 -29
- package/theme/components/Img.tsx +33 -33
- package/theme/components/Inline.astro +11 -11
- package/theme/components/Logo.astro +23 -23
- package/theme/components/LogoMark.astro +10 -10
- package/theme/components/Markdown.astro +17 -17
- package/theme/components/MobileMenu.tsx +224 -224
- package/theme/components/MobileNav.astro +33 -33
- package/theme/components/PageHeader.astro +22 -22
- package/theme/components/PageSection.astro +24 -24
- package/theme/components/PhoneButton.tsx +11 -11
- package/theme/components/Popup.astro +145 -145
- package/theme/components/PopupButton.tsx +24 -24
- package/theme/components/PopupView.tsx +48 -48
- package/theme/components/PostList.tsx +58 -58
- package/theme/components/PostMeta.tsx +17 -17
- package/theme/components/RichText.astro +28 -28
- package/theme/components/Section.astro +29 -29
- package/theme/components/SectionHeading.tsx +8 -8
- package/theme/components/TextSection.astro +16 -16
- package/theme/components/home/PageBlock.astro +19 -19
- package/theme/components/home/Text.astro +13 -13
- package/theme/components/loadPopup.ts +22 -22
- package/theme/components/loadPosts.ts +16 -16
- package/theme/components/posts.ts +15 -15
- package/theme/editor/looks.mjs +7 -7
- package/theme/editor/previews.tsx +56 -56
- package/theme/layouts/Base.astro +273 -273
- package/theme/layouts/PageLayout.astro +126 -126
- package/theme/layouts/PostLayout.astro +137 -137
- package/theme/scripts/motion.ts +29 -29
- package/theme/styles/base.css +320 -320
- package/theme/styles/blocks.css +1808 -1808
- package/theme/styles/components.css +206 -206
- package/theme/styles/global.css +1302 -1302
- package/theme/styles/ui.css +6544 -6544
- package/theme/templates/Blog.astro +38 -38
- package/theme/templates/Category.astro +19 -19
- package/theme/templates/Home.astro +36 -36
- package/theme/templates/New.astro +68 -68
- package/theme/templates/NotFound.astro +117 -117
- package/theme/theme.json +28 -28
- package/theme/ui/Badge.tsx +45 -45
- package/theme/ui/BottomSheet.tsx +148 -148
- package/theme/ui/Button.tsx +79 -79
- package/theme/ui/ButtonGroup.tsx +31 -31
- package/theme/ui/Card.tsx +45 -45
- package/theme/ui/Carousel.tsx +124 -124
- package/theme/ui/Checkbox.tsx +59 -59
- package/theme/ui/Chip.tsx +101 -101
- package/theme/ui/ChipSet.tsx +27 -27
- package/theme/ui/DatePicker.tsx +149 -149
- package/theme/ui/DatePickerContainer.tsx +316 -316
- package/theme/ui/Dialog.tsx +100 -100
- package/theme/ui/Divider.tsx +27 -27
- package/theme/ui/ExposedDropdownMenu.tsx +77 -77
- package/theme/ui/Fab.tsx +88 -88
- package/theme/ui/FabMenu.tsx +67 -67
- package/theme/ui/IconButton.tsx +78 -78
- package/theme/ui/List.tsx +287 -287
- package/theme/ui/LoadingIndicator.tsx +29 -29
- package/theme/ui/Menu.tsx +278 -278
- package/theme/ui/NavigationBar.tsx +62 -62
- package/theme/ui/NavigationDrawer.tsx +80 -80
- package/theme/ui/NavigationRail.tsx +154 -154
- package/theme/ui/ProgressIndicator.tsx +162 -162
- package/theme/ui/RadioButton.tsx +50 -50
- package/theme/ui/Search.tsx +129 -129
- package/theme/ui/SegmentedButton.tsx +49 -49
- package/theme/ui/SideSheet.tsx +54 -54
- package/theme/ui/Slider.tsx +155 -155
- package/theme/ui/Snackbar.tsx +67 -67
- package/theme/ui/SplitButton.tsx +67 -67
- package/theme/ui/Switch.tsx +60 -60
- package/theme/ui/Tabs.tsx +114 -114
- package/theme/ui/TextField.tsx +278 -278
- package/theme/ui/TimePicker.tsx +128 -128
- package/theme/ui/TimePickerContainer.tsx +234 -234
- package/theme/ui/Toolbar.tsx +67 -67
- package/theme/ui/Tooltip.tsx +58 -58
- package/theme/ui/TopAppBar.tsx +77 -77
- package/theme/ui/bottomSheet.script.ts +8 -8
- package/theme/ui/{bottomSheet.ts → bottomSheetControl.ts} +211 -211
- package/theme/ui/carousel.script.ts +28 -28
- package/theme/ui/carouselLayout.ts +229 -229
- package/theme/ui/checkbox.script.ts +8 -8
- package/theme/ui/datePicker.script.ts +302 -302
- package/theme/ui/dates.ts +185 -185
- package/theme/ui/{dialog.ts → dialogControl.ts} +48 -48
- package/theme/ui/dropdownMenu.script.ts +166 -166
- package/theme/ui/fabMenu.script.ts +57 -57
- package/theme/ui/navigationRail.script.ts +47 -47
- package/theme/ui/ripple.script.ts +159 -159
- package/theme/ui/search.script.ts +92 -92
- package/theme/ui/{sideSheet.ts → sideSheetControl.ts} +48 -48
- package/theme/ui/slider.script.ts +12 -12
- package/theme/ui/sliderUpdate.ts +52 -52
- package/theme/ui/snackbar.script.ts +16 -16
- package/theme/ui/splitButton.script.ts +63 -63
- package/theme/ui/tabs.script.ts +48 -48
- package/theme/ui/textField.script.ts +17 -17
- package/theme/ui/textFieldUpdate.ts +44 -44
- package/theme/ui/timePicker.script.ts +248 -248
- package/theme/ui/toolbar.script.ts +43 -43
- package/theme/ui/tooltip.script.ts +68 -68
- package/worker/consent.js +141 -141
- package/worker/editor-github.js +167 -167
- package/worker/editor-host.js +74 -74
- package/worker/files.js +401 -401
- package/worker/github.js +36 -36
- package/worker/index.js +188 -184
- package/worker/not-found.js +97 -97
- package/worker/oauth.js +95 -95
- package/worker/publish.js +52 -52
- package/worker/push.js +270 -270
- package/worker/r2-status.js +50 -50
- package/worker/session.js +58 -58
- package/worker/store.js +46 -0
package/src/cookieList.ts
CHANGED
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
// The site's cookie list, "Cookies" under "Lister" (the list the standard block "Cookieliste" brings,
|
|
2
|
-
// standard/cookies/list.ts): a file per cookie in config.cookieList, each with its name (`*` for the rest of it), who
|
|
3
|
-
// sets it, what for, how long it lasts and its category (necessary, or one the visitor says yes to in the cookie banner,
|
|
4
|
-
// lib/cookieCategories.mjs). An app's cookies (its
|
|
5
|
-
// cookies.json, those with a name) are added to it in the commit that installs the app, and those it added (`app`, its
|
|
6
|
-
// id, kept in the file but not shown) are taken out in the one that uninstalls it; an update adds its new ones and takes
|
|
7
|
-
// out those it no longer sets. One already in the list by its name and provider is left as it is, so what was written
|
|
8
|
-
// over an app's text stays. The app "Cookiescanner" adds those its scan finds besides (its worker.js), and more can be
|
|
9
|
-
// added by hand.
|
|
10
|
-
import { config } from '@site/config';
|
|
11
|
-
import type { Change, RepoFile } from './github';
|
|
12
|
-
import { slugify } from './schema';
|
|
13
|
-
import { categoryOf, type CookieCategory } from '../lib/cookieCategories.mjs';
|
|
14
|
-
import type { AppCookie } from './store';
|
|
15
|
-
|
|
16
|
-
/** A cookie in the list, as its file has it; `app`: the app that added it; `new`: added by the app "Cookiescanner" and not
|
|
17
|
-
* yet looked through (first in the list, marked, until it is saved: FolderCollection.fresh); `scanned`: added by it, kept
|
|
18
|
-
* when saved (its tab "Problemer" says when the site no longer sets it). */
|
|
19
|
-
export type CookieEntry = {
|
|
20
|
-
name: string;
|
|
21
|
-
provider: string;
|
|
22
|
-
purpose: string;
|
|
23
|
-
lasts?: string;
|
|
24
|
-
category: CookieCategory;
|
|
25
|
-
app?: string;
|
|
26
|
-
new?: boolean;
|
|
27
|
-
scanned?: boolean;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/** Whether a file is one of the list's. */
|
|
31
|
-
export const inCookieList = (path: string) => path.startsWith(`${config.cookieList}/`) && path.endsWith('.json');
|
|
32
|
-
|
|
33
|
-
function entryOf(file: RepoFile): Partial<CookieEntry> {
|
|
34
|
-
try {
|
|
35
|
-
return JSON.parse(file.text) ?? {};
|
|
36
|
-
} catch {
|
|
37
|
-
return {};
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const same = (a: { name?: string; provider?: string }, b: { name?: string; provider?: string }) =>
|
|
42
|
-
a.name === b.name && (a.provider ?? '') === (b.provider ?? '');
|
|
43
|
-
|
|
44
|
-
/** The changes to the list when an app is installed or updated with `cookies` (its cookies.json, in the site's
|
|
45
|
-
* language), or uninstalled (null), from the site's files now (see above). */
|
|
46
|
-
export function cookieChanges(app: string, cookies: AppCookie[] | null, files: RepoFile[]): Change[] {
|
|
47
|
-
const list = files.filter((f) => inCookieList(f.path)).map((file) => ({ file, entry: entryOf(file) }));
|
|
48
|
-
const wanted = (cookies ?? []).filter((c) => c.name?.trim());
|
|
49
|
-
const changes: Change[] = list
|
|
50
|
-
.filter(({ entry }) => entry.app === app && !wanted.some((c) => same(c, entry)))
|
|
51
|
-
.map(({ file }) => ({ path: file.path, content: null, oid: file.oid }));
|
|
52
|
-
const taken = new Set(list.map(({ file }) => file.path));
|
|
53
|
-
for (const c of wanted) {
|
|
54
|
-
if (list.some(({ entry }) => same(c, entry))) continue;
|
|
55
|
-
const slug = slugify(`${c.name!.replace(/\*/g, ' x ')} ${c.provider ?? ''}`) || 'cookie';
|
|
56
|
-
let path = `${config.cookieList}/${slug}.json`;
|
|
57
|
-
for (let n = 2; taken.has(path); n++) path = `${config.cookieList}/${slug}-${n}.json`;
|
|
58
|
-
taken.add(path);
|
|
59
|
-
const entry: CookieEntry = {
|
|
60
|
-
name: c.name!,
|
|
61
|
-
provider: c.provider ?? '',
|
|
62
|
-
purpose: c.purpose,
|
|
63
|
-
...(c.lasts ? { lasts: c.lasts } : {}),
|
|
64
|
-
category: categoryOf(c),
|
|
65
|
-
app,
|
|
66
|
-
};
|
|
67
|
-
changes.push({ path, content: `${JSON.stringify(entry, null, 2)}\n`, oid: null });
|
|
68
|
-
}
|
|
69
|
-
return changes;
|
|
70
|
-
}
|
|
1
|
+
// The site's cookie list, "Cookies" under "Lister" (the list the standard block "Cookieliste" brings,
|
|
2
|
+
// standard/cookies/list.ts): a file per cookie in config.cookieList, each with its name (`*` for the rest of it), who
|
|
3
|
+
// sets it, what for, how long it lasts and its category (necessary, or one the visitor says yes to in the cookie banner,
|
|
4
|
+
// lib/cookieCategories.mjs). An app's cookies (its
|
|
5
|
+
// cookies.json, those with a name) are added to it in the commit that installs the app, and those it added (`app`, its
|
|
6
|
+
// id, kept in the file but not shown) are taken out in the one that uninstalls it; an update adds its new ones and takes
|
|
7
|
+
// out those it no longer sets. One already in the list by its name and provider is left as it is, so what was written
|
|
8
|
+
// over an app's text stays. The app "Cookiescanner" adds those its scan finds besides (its worker.js), and more can be
|
|
9
|
+
// added by hand.
|
|
10
|
+
import { config } from '@site/config';
|
|
11
|
+
import type { Change, RepoFile } from './github';
|
|
12
|
+
import { slugify } from './schema';
|
|
13
|
+
import { categoryOf, type CookieCategory } from '../lib/cookieCategories.mjs';
|
|
14
|
+
import type { AppCookie } from './store';
|
|
15
|
+
|
|
16
|
+
/** A cookie in the list, as its file has it; `app`: the app that added it; `new`: added by the app "Cookiescanner" and not
|
|
17
|
+
* yet looked through (first in the list, marked, until it is saved: FolderCollection.fresh); `scanned`: added by it, kept
|
|
18
|
+
* when saved (its tab "Problemer" says when the site no longer sets it). */
|
|
19
|
+
export type CookieEntry = {
|
|
20
|
+
name: string;
|
|
21
|
+
provider: string;
|
|
22
|
+
purpose: string;
|
|
23
|
+
lasts?: string;
|
|
24
|
+
category: CookieCategory;
|
|
25
|
+
app?: string;
|
|
26
|
+
new?: boolean;
|
|
27
|
+
scanned?: boolean;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** Whether a file is one of the list's. */
|
|
31
|
+
export const inCookieList = (path: string) => path.startsWith(`${config.cookieList}/`) && path.endsWith('.json');
|
|
32
|
+
|
|
33
|
+
function entryOf(file: RepoFile): Partial<CookieEntry> {
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(file.text) ?? {};
|
|
36
|
+
} catch {
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const same = (a: { name?: string; provider?: string }, b: { name?: string; provider?: string }) =>
|
|
42
|
+
a.name === b.name && (a.provider ?? '') === (b.provider ?? '');
|
|
43
|
+
|
|
44
|
+
/** The changes to the list when an app is installed or updated with `cookies` (its cookies.json, in the site's
|
|
45
|
+
* language), or uninstalled (null), from the site's files now (see above). */
|
|
46
|
+
export function cookieChanges(app: string, cookies: AppCookie[] | null, files: RepoFile[]): Change[] {
|
|
47
|
+
const list = files.filter((f) => inCookieList(f.path)).map((file) => ({ file, entry: entryOf(file) }));
|
|
48
|
+
const wanted = (cookies ?? []).filter((c) => c.name?.trim());
|
|
49
|
+
const changes: Change[] = list
|
|
50
|
+
.filter(({ entry }) => entry.app === app && !wanted.some((c) => same(c, entry)))
|
|
51
|
+
.map(({ file }) => ({ path: file.path, content: null, oid: file.oid }));
|
|
52
|
+
const taken = new Set(list.map(({ file }) => file.path));
|
|
53
|
+
for (const c of wanted) {
|
|
54
|
+
if (list.some(({ entry }) => same(c, entry))) continue;
|
|
55
|
+
const slug = slugify(`${c.name!.replace(/\*/g, ' x ')} ${c.provider ?? ''}`) || 'cookie';
|
|
56
|
+
let path = `${config.cookieList}/${slug}.json`;
|
|
57
|
+
for (let n = 2; taken.has(path); n++) path = `${config.cookieList}/${slug}-${n}.json`;
|
|
58
|
+
taken.add(path);
|
|
59
|
+
const entry: CookieEntry = {
|
|
60
|
+
name: c.name!,
|
|
61
|
+
provider: c.provider ?? '',
|
|
62
|
+
purpose: c.purpose,
|
|
63
|
+
...(c.lasts ? { lasts: c.lasts } : {}),
|
|
64
|
+
category: categoryOf(c),
|
|
65
|
+
app,
|
|
66
|
+
};
|
|
67
|
+
changes.push({ path, content: `${JSON.stringify(entry, null, 2)}\n`, oid: null });
|
|
68
|
+
}
|
|
69
|
+
return changes;
|
|
70
|
+
}
|
package/src/countries.ts
CHANGED
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
// The countries a phone number can be in, by their code (ISO 3166, "DK") and their country code
|
|
2
|
-
// ("+45"), for the sheet the code is picked in (PhoneField in ui.tsx) and for reading a number typed
|
|
3
|
-
// with its code (phoneParts in check.ts). Their names are the browser's own, in the editor's language
|
|
4
|
-
// (Intl.DisplayNames). Countries that share a code (+1: the USA, Canada and the islands with an area
|
|
5
|
-
// code of their own) have it each; the first with a code is the one shown for it until another is picked.
|
|
6
|
-
import { locale } from './i18n';
|
|
7
|
-
|
|
8
|
-
const list =
|
|
9
|
-
'US1 CA1 AG1 AI1 AS1 BB1 BM1 BS1 DM1 DO1 GD1 GU1 JM1 KN1 KY1 LC1 MP1 MS1 PR1 SX1 TC1 TT1 VC1 VG1 VI1 RU7 KZ7 ' +
|
|
10
|
-
'EG20 ZA27 GR30 NL31 BE32 FR33 ES34 HU36 IT39 VA39 RO40 CH41 AT43 GB44 GG44 IM44 JE44 DK45 SE46 NO47 SJ47 PL48 ' +
|
|
11
|
-
'DE49 PE51 MX52 CU53 AR54 BR55 CL56 CO57 VE58 MY60 AU61 CX61 CC61 ID62 PH63 NZ64 SG65 TH66 JP81 KR82 VN84 CN86 ' +
|
|
12
|
-
'TR90 IN91 PK92 AF93 LK94 MM95 IR98 SS211 MA212 EH212 DZ213 TN216 LY218 GM220 SN221 MR222 ML223 GN224 CI225 ' +
|
|
13
|
-
'BF226 NE227 TG228 BJ229 MU230 LR231 SL232 GH233 NG234 TD235 CF236 CM237 CV238 ST239 GQ240 GA241 CG242 CD243 ' +
|
|
14
|
-
'AO244 GW245 IO246 SC248 SD249 RW250 ET251 SO252 DJ253 KE254 TZ255 UG256 BI257 MZ258 ZM260 MG261 RE262 YT262 ' +
|
|
15
|
-
'ZW263 NA264 MW265 LS266 BW267 SZ268 KM269 SH290 ER291 AW297 FO298 GL299 GI350 PT351 LU352 IE353 IS354 AL355 ' +
|
|
16
|
-
'MT356 CY357 FI358 AX358 BG359 LT370 LV371 EE372 MD373 AM374 BY375 AD376 MC377 SM378 UA380 RS381 ME382 XK383 ' +
|
|
17
|
-
'HR385 SI386 BA387 MK389 CZ420 SK421 LI423 FK500 BZ501 GT502 SV503 HN504 NI505 CR506 PA507 PM508 HT509 GP590 ' +
|
|
18
|
-
'BL590 MF590 BO591 GY592 EC593 GF594 PY595 MQ596 SR597 UY598 CW599 BQ599 TL670 NF672 BN673 NR674 PG675 TO676 ' +
|
|
19
|
-
'SB677 VU678 FJ679 PW680 WF681 CK682 NU683 WS685 KI686 NC687 TV688 PF689 TK690 FM691 MH692 KP850 HK852 MO853 ' +
|
|
20
|
-
'KH855 LA856 BD880 TW886 MV960 LB961 JO962 SY963 IQ964 KW965 SA966 YE967 OM968 PS970 AE971 IL972 BH973 QA974 ' +
|
|
21
|
-
'BT975 MN976 NP977 TJ992 TM993 AZ994 GE995 KG996 UZ998';
|
|
22
|
-
|
|
23
|
-
/** Each country's code and its country code, "+45". */
|
|
24
|
-
export const dialCodes: Record<string, string> = Object.fromEntries(list.split(' ').map((c) => [c.slice(0, 2), `+${c.slice(2)}`]));
|
|
25
|
-
|
|
26
|
-
/** The country shown for a country code: the first with it, or undefined when no country has it. */
|
|
27
|
-
export const regionOf = (code: string) => Object.keys(dialCodes).find((r) => dialCodes[r] === code);
|
|
28
|
-
|
|
29
|
-
const codes = new Set(Object.values(dialCodes));
|
|
30
|
-
|
|
31
|
-
/** The country code at the start of a number's digits, with digits after it (the longest that is one:
|
|
32
|
-
* +358 before +35), or undefined. */
|
|
33
|
-
export const codeAt = (digits: string) =>
|
|
34
|
-
[3, 2, 1]
|
|
35
|
-
.filter((n) => digits.length > n)
|
|
36
|
-
.map((n) => `+${digits.slice(0, n)}`)
|
|
37
|
-
.find((c) => codes.has(c));
|
|
38
|
-
|
|
39
|
-
/** A country's flag, of the two letters of its code. */
|
|
40
|
-
export const flagOf = (region: string) => String.fromCodePoint(...[...region].map((c) => 0x1f1e6 + c.charCodeAt(0) - 65));
|
|
41
|
-
|
|
42
|
-
const names = typeof Intl.DisplayNames === 'function' ? new Intl.DisplayNames([locale], { type: 'region' }) : null;
|
|
43
|
-
const english = typeof Intl.DisplayNames === 'function' ? new Intl.DisplayNames(['en'], { type: 'region' }) : null;
|
|
44
|
-
|
|
45
|
-
/** A country's name in the editor's language. */
|
|
46
|
-
export const countryName = (region: string) => names?.of(region) ?? region;
|
|
47
|
-
|
|
48
|
-
/** The countries in the order of their names, each with its name, its code and the words it is also
|
|
49
|
-
* found by in a search (its country code, its code, its name in English). */
|
|
50
|
-
export function countries() {
|
|
51
|
-
return Object.keys(dialCodes)
|
|
52
|
-
.map((region) => ({
|
|
53
|
-
region,
|
|
54
|
-
name: countryName(region),
|
|
55
|
-
code: dialCodes[region],
|
|
56
|
-
words: `${dialCodes[region]} ${region} ${english?.of(region) ?? ''}`,
|
|
57
|
-
}))
|
|
58
|
-
.sort((a, b) => a.name.localeCompare(b.name, locale));
|
|
59
|
-
}
|
|
1
|
+
// The countries a phone number can be in, by their code (ISO 3166, "DK") and their country code
|
|
2
|
+
// ("+45"), for the sheet the code is picked in (PhoneField in ui.tsx) and for reading a number typed
|
|
3
|
+
// with its code (phoneParts in check.ts). Their names are the browser's own, in the editor's language
|
|
4
|
+
// (Intl.DisplayNames). Countries that share a code (+1: the USA, Canada and the islands with an area
|
|
5
|
+
// code of their own) have it each; the first with a code is the one shown for it until another is picked.
|
|
6
|
+
import { locale } from './i18n';
|
|
7
|
+
|
|
8
|
+
const list =
|
|
9
|
+
'US1 CA1 AG1 AI1 AS1 BB1 BM1 BS1 DM1 DO1 GD1 GU1 JM1 KN1 KY1 LC1 MP1 MS1 PR1 SX1 TC1 TT1 VC1 VG1 VI1 RU7 KZ7 ' +
|
|
10
|
+
'EG20 ZA27 GR30 NL31 BE32 FR33 ES34 HU36 IT39 VA39 RO40 CH41 AT43 GB44 GG44 IM44 JE44 DK45 SE46 NO47 SJ47 PL48 ' +
|
|
11
|
+
'DE49 PE51 MX52 CU53 AR54 BR55 CL56 CO57 VE58 MY60 AU61 CX61 CC61 ID62 PH63 NZ64 SG65 TH66 JP81 KR82 VN84 CN86 ' +
|
|
12
|
+
'TR90 IN91 PK92 AF93 LK94 MM95 IR98 SS211 MA212 EH212 DZ213 TN216 LY218 GM220 SN221 MR222 ML223 GN224 CI225 ' +
|
|
13
|
+
'BF226 NE227 TG228 BJ229 MU230 LR231 SL232 GH233 NG234 TD235 CF236 CM237 CV238 ST239 GQ240 GA241 CG242 CD243 ' +
|
|
14
|
+
'AO244 GW245 IO246 SC248 SD249 RW250 ET251 SO252 DJ253 KE254 TZ255 UG256 BI257 MZ258 ZM260 MG261 RE262 YT262 ' +
|
|
15
|
+
'ZW263 NA264 MW265 LS266 BW267 SZ268 KM269 SH290 ER291 AW297 FO298 GL299 GI350 PT351 LU352 IE353 IS354 AL355 ' +
|
|
16
|
+
'MT356 CY357 FI358 AX358 BG359 LT370 LV371 EE372 MD373 AM374 BY375 AD376 MC377 SM378 UA380 RS381 ME382 XK383 ' +
|
|
17
|
+
'HR385 SI386 BA387 MK389 CZ420 SK421 LI423 FK500 BZ501 GT502 SV503 HN504 NI505 CR506 PA507 PM508 HT509 GP590 ' +
|
|
18
|
+
'BL590 MF590 BO591 GY592 EC593 GF594 PY595 MQ596 SR597 UY598 CW599 BQ599 TL670 NF672 BN673 NR674 PG675 TO676 ' +
|
|
19
|
+
'SB677 VU678 FJ679 PW680 WF681 CK682 NU683 WS685 KI686 NC687 TV688 PF689 TK690 FM691 MH692 KP850 HK852 MO853 ' +
|
|
20
|
+
'KH855 LA856 BD880 TW886 MV960 LB961 JO962 SY963 IQ964 KW965 SA966 YE967 OM968 PS970 AE971 IL972 BH973 QA974 ' +
|
|
21
|
+
'BT975 MN976 NP977 TJ992 TM993 AZ994 GE995 KG996 UZ998';
|
|
22
|
+
|
|
23
|
+
/** Each country's code and its country code, "+45". */
|
|
24
|
+
export const dialCodes: Record<string, string> = Object.fromEntries(list.split(' ').map((c) => [c.slice(0, 2), `+${c.slice(2)}`]));
|
|
25
|
+
|
|
26
|
+
/** The country shown for a country code: the first with it, or undefined when no country has it. */
|
|
27
|
+
export const regionOf = (code: string) => Object.keys(dialCodes).find((r) => dialCodes[r] === code);
|
|
28
|
+
|
|
29
|
+
const codes = new Set(Object.values(dialCodes));
|
|
30
|
+
|
|
31
|
+
/** The country code at the start of a number's digits, with digits after it (the longest that is one:
|
|
32
|
+
* +358 before +35), or undefined. */
|
|
33
|
+
export const codeAt = (digits: string) =>
|
|
34
|
+
[3, 2, 1]
|
|
35
|
+
.filter((n) => digits.length > n)
|
|
36
|
+
.map((n) => `+${digits.slice(0, n)}`)
|
|
37
|
+
.find((c) => codes.has(c));
|
|
38
|
+
|
|
39
|
+
/** A country's flag, of the two letters of its code. */
|
|
40
|
+
export const flagOf = (region: string) => String.fromCodePoint(...[...region].map((c) => 0x1f1e6 + c.charCodeAt(0) - 65));
|
|
41
|
+
|
|
42
|
+
const names = typeof Intl.DisplayNames === 'function' ? new Intl.DisplayNames([locale], { type: 'region' }) : null;
|
|
43
|
+
const english = typeof Intl.DisplayNames === 'function' ? new Intl.DisplayNames(['en'], { type: 'region' }) : null;
|
|
44
|
+
|
|
45
|
+
/** A country's name in the editor's language. */
|
|
46
|
+
export const countryName = (region: string) => names?.of(region) ?? region;
|
|
47
|
+
|
|
48
|
+
/** The countries in the order of their names, each with its name, its code and the words it is also
|
|
49
|
+
* found by in a search (its country code, its code, its name in English). */
|
|
50
|
+
export function countries() {
|
|
51
|
+
return Object.keys(dialCodes)
|
|
52
|
+
.map((region) => ({
|
|
53
|
+
region,
|
|
54
|
+
name: countryName(region),
|
|
55
|
+
code: dialCodes[region],
|
|
56
|
+
words: `${dialCodes[region]} ${region} ${english?.of(region) ?? ''}`,
|
|
57
|
+
}))
|
|
58
|
+
.sort((a, b) => a.name.localeCompare(b.name, locale));
|
|
59
|
+
}
|
package/src/deploy.ts
CHANGED
|
@@ -1,155 +1,155 @@
|
|
|
1
|
-
// After a save: tells when the site has been rebuilt with it. Each build writes the commit it was
|
|
2
|
-
// made from to /editor/version.json (packages/editor/pages/editor/version.json.js), and the editor asks for that
|
|
3
|
-
// until it is the saved commit or a later one. The message is a notification of the type `site` (
|
|
4
|
-
// which also comes on the phone or computer when the editor is not on screen.
|
|
5
|
-
// Each save says what it changed ("farver ændret", "side “Om” ændret", t.app.changes): right after it (savedText),
|
|
6
|
-
// and, with the other saves since, when the website has been updated with them (changesText, App.tsx save).
|
|
7
|
-
import { graphql, REPO } from './github';
|
|
8
|
-
import { entryName, type Collection } from './schema';
|
|
9
|
-
import { readFields, splitFrontmatter } from './frontmatter.mjs';
|
|
10
|
-
import { locale, t } from './i18n';
|
|
11
|
-
|
|
12
|
-
const fileName = (path: string) => path.split('/').pop() ?? path;
|
|
13
|
-
|
|
14
|
-
/** What a file of a list is called: a page's or post's title, an entry's name as its list shows it, else (a picture)
|
|
15
|
-
* its file name. */
|
|
16
|
-
export function nameOf(collection: Collection | undefined, file: { path: string; text: string }): string {
|
|
17
|
-
try {
|
|
18
|
-
if (collection?.kind === 'markdown') return String(readFields(splitFrontmatter(file.text).yaml).title ?? fileName(file.path));
|
|
19
|
-
if (collection?.kind === 'folder') return entryName(collection, JSON.parse(file.text)) || fileName(file.path);
|
|
20
|
-
} catch {}
|
|
21
|
-
return fileName(file.path);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** A kind or a label inside a sentence: "Side" as "side", but "SEO" as it is. */
|
|
25
|
-
export const lower = (s: string) => (/^\p{Lu}\p{Lu}/u.test(s) ? s : s.charAt(0).toLocaleLowerCase(locale) + s.slice(1));
|
|
26
|
-
const capital = (s: string) => s.charAt(0).toLocaleUpperCase(locale) + s.slice(1);
|
|
27
|
-
|
|
28
|
-
/** A thing by its kind and name, as a change says it: side “Om”. */
|
|
29
|
-
export const kindAndName = (kind: string, name: string) => t.app.changes.named(lower(kind), name);
|
|
30
|
-
|
|
31
|
-
/** The message right after a save, with what it changed; the site is rebuilt in 1-2 minutes. */
|
|
32
|
-
export const savedText = (change: string) => t.common.saved(capital(change));
|
|
33
|
-
|
|
34
|
-
/** What the saves since the last update changed, as a list: the first three and how many more. */
|
|
35
|
-
export function changesText(changes: string[]): string {
|
|
36
|
-
const shown = changes.slice(0, 3);
|
|
37
|
-
const rest = changes.length - shown.length;
|
|
38
|
-
return new Intl.ListFormat(locale, { type: 'conjunction' }).format(rest ? [...shown, t.app.changes.more(rest)] : shown);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const EVERY = 10_000;
|
|
42
|
-
const GIVE_UP = 10 * 60_000;
|
|
43
|
-
|
|
44
|
-
// What the site was last built from: the commit, the fingerprint of the editor's code and when.
|
|
45
|
-
type Version = { commit?: string; editor?: string; builtAt?: string };
|
|
46
|
-
async function version(): Promise<Version> {
|
|
47
|
-
try {
|
|
48
|
-
const res = await fetch('/editor/version.json', { cache: 'no-store' });
|
|
49
|
-
return res.ok ? await res.json() : {};
|
|
50
|
-
} catch {
|
|
51
|
-
return {};
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const built = async () => (await version()).commit ?? null;
|
|
56
|
-
|
|
57
|
-
// Whether `commit` is among the last commits up to `build` (the site may be built from a later one).
|
|
58
|
-
async function includes(build: string, commit: string): Promise<boolean> {
|
|
59
|
-
const data = await graphql<{ repository: { object: { history?: { nodes: { oid: string }[] } } | null } }>(
|
|
60
|
-
`
|
|
61
|
-
query ($owner: String!, $name: String!, $oid: GitObjectID!) {
|
|
62
|
-
repository(owner: $owner, name: $name) {
|
|
63
|
-
object(oid: $oid) {
|
|
64
|
-
... on Commit {
|
|
65
|
-
history(first: 50) {
|
|
66
|
-
nodes {
|
|
67
|
-
oid
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
`,
|
|
75
|
-
{ owner: REPO.owner, name: REPO.name, oid: build },
|
|
76
|
-
);
|
|
77
|
-
return data.repository.object?.history?.nodes.some((n) => n.oid === commit) ?? false;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Waits for `commit` to be on the site: done(true) when it is, done(false) when it is not after
|
|
81
|
-
// 10 minutes. Returns a function that stops waiting (a newer save takes over).
|
|
82
|
-
export function waitForSite(commit: string, done: (online: boolean) => void): () => void {
|
|
83
|
-
const until = Date.now() + GIVE_UP;
|
|
84
|
-
// The build last looked at, so GitHub is asked about each build once.
|
|
85
|
-
let seen: string | null = null;
|
|
86
|
-
let stopped = false;
|
|
87
|
-
let timer: ReturnType<typeof setTimeout>;
|
|
88
|
-
|
|
89
|
-
async function check() {
|
|
90
|
-
const build = await built();
|
|
91
|
-
if (stopped) return;
|
|
92
|
-
if (build && build !== seen) {
|
|
93
|
-
seen = build;
|
|
94
|
-
const online = build === commit || (await includes(build, commit).catch(() => false));
|
|
95
|
-
if (stopped) return;
|
|
96
|
-
if (online) return done(true);
|
|
97
|
-
}
|
|
98
|
-
if (Date.now() > until) {
|
|
99
|
-
// Without any version file (a build from before it existed) there is nothing to tell.
|
|
100
|
-
if (seen) done(false);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
timer = setTimeout(check, EVERY);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
timer = setTimeout(check, EVERY);
|
|
107
|
-
return () => {
|
|
108
|
-
stopped = true;
|
|
109
|
-
clearTimeout(timer);
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Whether a form has changes that are not saved (set by FormFrame).
|
|
114
|
-
let unsaved = false;
|
|
115
|
-
export const setUnsaved = (yes: boolean) => void (unsaved = yes);
|
|
116
|
-
export const hasUnsaved = () => unsaved;
|
|
117
|
-
|
|
118
|
-
// Keeps an open editor up to date. The installed app can stay open for days, and it reads the files
|
|
119
|
-
// straight from GitHub, so after a change to the editor and its files (like the front page becoming
|
|
120
|
-
// sections) an old editor would show them as empty forms. When the site has an editor with other
|
|
121
|
-
// code (the fingerprint in /editor/version.json is not the one in this page,
|
|
122
|
-
// packages/editor/site/editor-version.mjs), the page reloads, as soon as nothing is unsaved: checked when the
|
|
123
|
-
// editor opens, when it comes back on screen, and every minute while it is on screen. onSite: what the
|
|
124
|
-
// site was last built from, at each check (when it was updated, on the start screen).
|
|
125
|
-
export function keepCurrent(onSite?: (v: Version) => void) {
|
|
126
|
-
const own = document.querySelector<HTMLMetaElement>('meta[name="editor-version"]')?.content;
|
|
127
|
-
async function check() {
|
|
128
|
-
if (document.visibilityState !== 'visible') return;
|
|
129
|
-
const v = await version();
|
|
130
|
-
onSite?.(v);
|
|
131
|
-
const { editor } = v;
|
|
132
|
-
if (!own || unsaved || !editor || editor === own) return;
|
|
133
|
-
// Once for each newer editor, so a page that comes back old (from a cache) does not reload again
|
|
134
|
-
// and again.
|
|
135
|
-
try {
|
|
136
|
-
if (sessionStorage.getItem('editor-reloaded-for') === editor) return;
|
|
137
|
-
sessionStorage.setItem('editor-reloaded-for', editor);
|
|
138
|
-
} catch {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
location.reload();
|
|
142
|
-
}
|
|
143
|
-
check();
|
|
144
|
-
const timer = setInterval(check, 60_000);
|
|
145
|
-
document.addEventListener('visibilitychange', check);
|
|
146
|
-
return () => {
|
|
147
|
-
clearInterval(timer);
|
|
148
|
-
document.removeEventListener('visibilitychange', check);
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Notifications go through the service worker (packages/editor/pages/editor/sw.js); registered when the editor opens.
|
|
153
|
-
export function registerWorker() {
|
|
154
|
-
navigator.serviceWorker?.register('/editor/sw.js').catch(() => {});
|
|
155
|
-
}
|
|
1
|
+
// After a save: tells when the site has been rebuilt with it. Each build writes the commit it was
|
|
2
|
+
// made from to /editor/version.json (packages/editor/pages/editor/version.json.js), and the editor asks for that
|
|
3
|
+
// until it is the saved commit or a later one. The message is a notification of the type `site` (notificationData.ts),
|
|
4
|
+
// which also comes on the phone or computer when the editor is not on screen.
|
|
5
|
+
// Each save says what it changed ("farver ændret", "side “Om” ændret", t.app.changes): right after it (savedText),
|
|
6
|
+
// and, with the other saves since, when the website has been updated with them (changesText, App.tsx save).
|
|
7
|
+
import { graphql, REPO } from './github';
|
|
8
|
+
import { entryName, type Collection } from './schema';
|
|
9
|
+
import { readFields, splitFrontmatter } from './frontmatter.mjs';
|
|
10
|
+
import { locale, t } from './i18n';
|
|
11
|
+
|
|
12
|
+
const fileName = (path: string) => path.split('/').pop() ?? path;
|
|
13
|
+
|
|
14
|
+
/** What a file of a list is called: a page's or post's title, an entry's name as its list shows it, else (a picture)
|
|
15
|
+
* its file name. */
|
|
16
|
+
export function nameOf(collection: Collection | undefined, file: { path: string; text: string }): string {
|
|
17
|
+
try {
|
|
18
|
+
if (collection?.kind === 'markdown') return String(readFields(splitFrontmatter(file.text).yaml).title ?? fileName(file.path));
|
|
19
|
+
if (collection?.kind === 'folder') return entryName(collection, JSON.parse(file.text)) || fileName(file.path);
|
|
20
|
+
} catch {}
|
|
21
|
+
return fileName(file.path);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** A kind or a label inside a sentence: "Side" as "side", but "SEO" as it is. */
|
|
25
|
+
export const lower = (s: string) => (/^\p{Lu}\p{Lu}/u.test(s) ? s : s.charAt(0).toLocaleLowerCase(locale) + s.slice(1));
|
|
26
|
+
const capital = (s: string) => s.charAt(0).toLocaleUpperCase(locale) + s.slice(1);
|
|
27
|
+
|
|
28
|
+
/** A thing by its kind and name, as a change says it: side “Om”. */
|
|
29
|
+
export const kindAndName = (kind: string, name: string) => t.app.changes.named(lower(kind), name);
|
|
30
|
+
|
|
31
|
+
/** The message right after a save, with what it changed; the site is rebuilt in 1-2 minutes. */
|
|
32
|
+
export const savedText = (change: string) => t.common.saved(capital(change));
|
|
33
|
+
|
|
34
|
+
/** What the saves since the last update changed, as a list: the first three and how many more. */
|
|
35
|
+
export function changesText(changes: string[]): string {
|
|
36
|
+
const shown = changes.slice(0, 3);
|
|
37
|
+
const rest = changes.length - shown.length;
|
|
38
|
+
return new Intl.ListFormat(locale, { type: 'conjunction' }).format(rest ? [...shown, t.app.changes.more(rest)] : shown);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const EVERY = 10_000;
|
|
42
|
+
const GIVE_UP = 10 * 60_000;
|
|
43
|
+
|
|
44
|
+
// What the site was last built from: the commit, the fingerprint of the editor's code and when.
|
|
45
|
+
type Version = { commit?: string; editor?: string; builtAt?: string };
|
|
46
|
+
async function version(): Promise<Version> {
|
|
47
|
+
try {
|
|
48
|
+
const res = await fetch('/editor/version.json', { cache: 'no-store' });
|
|
49
|
+
return res.ok ? await res.json() : {};
|
|
50
|
+
} catch {
|
|
51
|
+
return {};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const built = async () => (await version()).commit ?? null;
|
|
56
|
+
|
|
57
|
+
// Whether `commit` is among the last commits up to `build` (the site may be built from a later one).
|
|
58
|
+
async function includes(build: string, commit: string): Promise<boolean> {
|
|
59
|
+
const data = await graphql<{ repository: { object: { history?: { nodes: { oid: string }[] } } | null } }>(
|
|
60
|
+
`
|
|
61
|
+
query ($owner: String!, $name: String!, $oid: GitObjectID!) {
|
|
62
|
+
repository(owner: $owner, name: $name) {
|
|
63
|
+
object(oid: $oid) {
|
|
64
|
+
... on Commit {
|
|
65
|
+
history(first: 50) {
|
|
66
|
+
nodes {
|
|
67
|
+
oid
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
`,
|
|
75
|
+
{ owner: REPO.owner, name: REPO.name, oid: build },
|
|
76
|
+
);
|
|
77
|
+
return data.repository.object?.history?.nodes.some((n) => n.oid === commit) ?? false;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Waits for `commit` to be on the site: done(true) when it is, done(false) when it is not after
|
|
81
|
+
// 10 minutes. Returns a function that stops waiting (a newer save takes over).
|
|
82
|
+
export function waitForSite(commit: string, done: (online: boolean) => void): () => void {
|
|
83
|
+
const until = Date.now() + GIVE_UP;
|
|
84
|
+
// The build last looked at, so GitHub is asked about each build once.
|
|
85
|
+
let seen: string | null = null;
|
|
86
|
+
let stopped = false;
|
|
87
|
+
let timer: ReturnType<typeof setTimeout>;
|
|
88
|
+
|
|
89
|
+
async function check() {
|
|
90
|
+
const build = await built();
|
|
91
|
+
if (stopped) return;
|
|
92
|
+
if (build && build !== seen) {
|
|
93
|
+
seen = build;
|
|
94
|
+
const online = build === commit || (await includes(build, commit).catch(() => false));
|
|
95
|
+
if (stopped) return;
|
|
96
|
+
if (online) return done(true);
|
|
97
|
+
}
|
|
98
|
+
if (Date.now() > until) {
|
|
99
|
+
// Without any version file (a build from before it existed) there is nothing to tell.
|
|
100
|
+
if (seen) done(false);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
timer = setTimeout(check, EVERY);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
timer = setTimeout(check, EVERY);
|
|
107
|
+
return () => {
|
|
108
|
+
stopped = true;
|
|
109
|
+
clearTimeout(timer);
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Whether a form has changes that are not saved (set by FormFrame).
|
|
114
|
+
let unsaved = false;
|
|
115
|
+
export const setUnsaved = (yes: boolean) => void (unsaved = yes);
|
|
116
|
+
export const hasUnsaved = () => unsaved;
|
|
117
|
+
|
|
118
|
+
// Keeps an open editor up to date. The installed app can stay open for days, and it reads the files
|
|
119
|
+
// straight from GitHub, so after a change to the editor and its files (like the front page becoming
|
|
120
|
+
// sections) an old editor would show them as empty forms. When the site has an editor with other
|
|
121
|
+
// code (the fingerprint in /editor/version.json is not the one in this page,
|
|
122
|
+
// packages/editor/site/editor-version.mjs), the page reloads, as soon as nothing is unsaved: checked when the
|
|
123
|
+
// editor opens, when it comes back on screen, and every minute while it is on screen. onSite: what the
|
|
124
|
+
// site was last built from, at each check (when it was updated, on the start screen).
|
|
125
|
+
export function keepCurrent(onSite?: (v: Version) => void) {
|
|
126
|
+
const own = document.querySelector<HTMLMetaElement>('meta[name="editor-version"]')?.content;
|
|
127
|
+
async function check() {
|
|
128
|
+
if (document.visibilityState !== 'visible') return;
|
|
129
|
+
const v = await version();
|
|
130
|
+
onSite?.(v);
|
|
131
|
+
const { editor } = v;
|
|
132
|
+
if (!own || unsaved || !editor || editor === own) return;
|
|
133
|
+
// Once for each newer editor, so a page that comes back old (from a cache) does not reload again
|
|
134
|
+
// and again.
|
|
135
|
+
try {
|
|
136
|
+
if (sessionStorage.getItem('editor-reloaded-for') === editor) return;
|
|
137
|
+
sessionStorage.setItem('editor-reloaded-for', editor);
|
|
138
|
+
} catch {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
location.reload();
|
|
142
|
+
}
|
|
143
|
+
check();
|
|
144
|
+
const timer = setInterval(check, 60_000);
|
|
145
|
+
document.addEventListener('visibilitychange', check);
|
|
146
|
+
return () => {
|
|
147
|
+
clearInterval(timer);
|
|
148
|
+
document.removeEventListener('visibilitychange', check);
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Notifications go through the service worker (packages/editor/pages/editor/sw.js); registered when the editor opens.
|
|
153
|
+
export function registerWorker() {
|
|
154
|
+
navigator.serviceWorker?.register('/editor/sw.js').catch(() => {});
|
|
155
|
+
}
|