@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/Versions.tsx
CHANGED
|
@@ -1,214 +1,214 @@
|
|
|
1
|
-
// "Tidligere versioner": the commits that changed a form's file (github.ts versionsOf), newest first, with when and by
|
|
2
|
-
// whom, 20 at a time: the last section of a page's or a post's form (VersionList), and in the other forms a sheet
|
|
3
|
-
// opened by the clock in the top bar (VersionsButton). The newest is the
|
|
4
|
-
// version saved now. Tapping an earlier one opens it in the form as changes that are not saved yet
|
|
5
|
-
// (EntryForm.tsx, DataForm.tsx, with a Notice at the top): "Gem ændringer" makes it the current
|
|
6
|
-
// version, in a new commit, so nothing is lost and every version can always be found here again.
|
|
7
|
-
import { Component, Fragment, useEffect, useRef, useState, type ReactNode } from 'react';
|
|
8
|
-
import { ClockCounterClockwise } from '@phosphor-icons/react';
|
|
9
|
-
import {
|
|
10
|
-
Button,
|
|
11
|
-
EmptyNote,
|
|
12
|
-
IconButton,
|
|
13
|
-
listClass,
|
|
14
|
-
Notice,
|
|
15
|
-
LoadingIndicator,
|
|
16
|
-
BottomSheet,
|
|
17
|
-
SheetTitle,
|
|
18
|
-
SheetBody,
|
|
19
|
-
ProblemNote,
|
|
20
|
-
ListItem,
|
|
21
|
-
} from './ui';
|
|
22
|
-
import { mayLeave } from './FormFrame';
|
|
23
|
-
import { when } from './when';
|
|
24
|
-
import type { Env } from './App';
|
|
25
|
-
import type { Version } from './github';
|
|
26
|
-
import { locale, siteLocale, t } from './i18n';
|
|
27
|
-
|
|
28
|
-
/** An earlier version shown in a form: its text, and when it was saved. */
|
|
29
|
-
export type ShownVersion = { text: string; at: Date };
|
|
30
|
-
|
|
31
|
-
// "i dag kl. 13.42" as "I dag kl. 13.42", alone on its line.
|
|
32
|
-
const capital = (s: string) => s.charAt(0).toLocaleUpperCase(locale) + s.slice(1);
|
|
33
|
-
|
|
34
|
-
/** When a version was saved, in the site's language: for the commit that brings it back. */
|
|
35
|
-
export const savedOn = (v: ShownVersion) => v.at.toLocaleString(siteLocale, { dateStyle: 'medium', timeStyle: 'short' });
|
|
36
|
-
|
|
37
|
-
/** A form that can show an earlier version: started again with each version, and with the one saved
|
|
38
|
-
* now when it cannot show one (a file from before the form was changed): then it says so. */
|
|
39
|
-
export function WithVersions({
|
|
40
|
-
notify,
|
|
41
|
-
children,
|
|
42
|
-
}: {
|
|
43
|
-
notify: Env['notify'];
|
|
44
|
-
children: (version: ShownVersion | null, onVersion: (v: ShownVersion | null) => void) => ReactNode;
|
|
45
|
-
}) {
|
|
46
|
-
const [version, setVersion] = useState<ShownVersion | null>(null);
|
|
47
|
-
if (!version) return <Fragment key="now">{children(null, setVersion)}</Fragment>;
|
|
48
|
-
return (
|
|
49
|
-
<Unreadable
|
|
50
|
-
key={version.at.getTime()}
|
|
51
|
-
onError={() => {
|
|
52
|
-
setVersion(null);
|
|
53
|
-
notify({ text: t.history.cannotShow, error: true });
|
|
54
|
-
}}
|
|
55
|
-
>
|
|
56
|
-
{children(version, setVersion)}
|
|
57
|
-
</Unreadable>
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Catches an error while a version is shown, so the editor goes on (React needs a class for that).
|
|
62
|
-
class Unreadable extends Component<{ onError: () => void; children: ReactNode }, { failed: boolean }> {
|
|
63
|
-
state = { failed: false };
|
|
64
|
-
static getDerivedStateFromError() {
|
|
65
|
-
return { failed: true };
|
|
66
|
-
}
|
|
67
|
-
componentDidCatch() {
|
|
68
|
-
this.props.onError();
|
|
69
|
-
}
|
|
70
|
-
render() {
|
|
71
|
-
return this.state.failed ? null : this.props.children;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// The versions of a file, loaded 20 at a time (`load`, again from the newest without `after`), and how one is opened in
|
|
76
|
-
// the form (`pick`: asks first while something is unsaved, then fetches the file as it was; true when it was opened).
|
|
77
|
-
function useVersionList(env: Env, path: string, onPick: (v: ShownVersion) => void) {
|
|
78
|
-
const [versions, setVersions] = useState<Version[] | null>(null);
|
|
79
|
-
const [more, setMore] = useState<string | null>(null);
|
|
80
|
-
const [problem, setProblem] = useState('');
|
|
81
|
-
const [loading, setLoading] = useState(false);
|
|
82
|
-
|
|
83
|
-
async function load(after?: string) {
|
|
84
|
-
setLoading(true);
|
|
85
|
-
setProblem('');
|
|
86
|
-
try {
|
|
87
|
-
const page = await env.versions(path, after);
|
|
88
|
-
setVersions((was) => [...(after ? (was ?? []) : []), ...page.versions]);
|
|
89
|
-
setMore(page.more);
|
|
90
|
-
} catch (e) {
|
|
91
|
-
setProblem(t.history.notLoaded((e as Error).message));
|
|
92
|
-
} finally {
|
|
93
|
-
setLoading(false);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
async function pick(v: Version) {
|
|
98
|
-
if (!(await mayLeave())) return false;
|
|
99
|
-
env.notify({ text: t.history.opening });
|
|
100
|
-
try {
|
|
101
|
-
const text = await env.versionText(v, path);
|
|
102
|
-
if (text === null) {
|
|
103
|
-
env.notify({ text: t.history.notThere, error: true });
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
onPick({ text, at: v.at });
|
|
107
|
-
env.notify(null);
|
|
108
|
-
return true;
|
|
109
|
-
} catch (e) {
|
|
110
|
-
env.notify({ text: t.history.notOpened((e as Error).message), error: true });
|
|
111
|
-
return false;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return { versions, more, problem, loading, load, pick };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// The versions as rows, newest first: the one saved now first (it cannot be picked), each with when and by whom, and
|
|
119
|
-
// "Vis ældre versioner" under them while there are more.
|
|
120
|
-
function VersionRows({ list, onPick }: { list: ReturnType<typeof useVersionList>; onPick: (v: Version) => void }) {
|
|
121
|
-
const { versions, more, problem, loading, load } = list;
|
|
122
|
-
return (
|
|
123
|
-
<>
|
|
124
|
-
{problem && <ProblemNote>{problem}</ProblemNote>}
|
|
125
|
-
{!versions && !problem && <EmptyNote busy>{t.history.loading}</EmptyNote>}
|
|
126
|
-
{versions && versions.length < 2 && !more && <p className="text-muted">{t.history.none}</p>}
|
|
127
|
-
{versions && versions.length > 0 && (
|
|
128
|
-
<ul className={listClass}>
|
|
129
|
-
{versions.map((v, i) => (
|
|
130
|
-
<ListItem
|
|
131
|
-
key={v.commit}
|
|
132
|
-
onClick={i === 0 ? undefined : () => onPick(v)}
|
|
133
|
-
headline={capital(when(v.at))}
|
|
134
|
-
supporting={i === 0 ? t.history.current : v.by && t.history.by(v.by)}
|
|
135
|
-
truncate
|
|
136
|
-
/>
|
|
137
|
-
))}
|
|
138
|
-
</ul>
|
|
139
|
-
)}
|
|
140
|
-
{more && (
|
|
141
|
-
<Button kind="outlined" wide disabled={loading} onClick={() => load(more)}>
|
|
142
|
-
{loading ? <LoadingIndicator>{t.history.loading}</LoadingIndicator> : t.history.more}
|
|
143
|
-
</Button>
|
|
144
|
-
)}
|
|
145
|
-
</>
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** The clock in the top bar of a form (DataForm.tsx), and the sheet with the versions. `onPick` opens one in the form. */
|
|
150
|
-
export function VersionsButton({ env, path, onPick }: { env: Env; path: string; onPick: (v: ShownVersion) => void }) {
|
|
151
|
-
const dialog = useRef<HTMLDialogElement>(null);
|
|
152
|
-
const list = useVersionList(env, path, onPick);
|
|
153
|
-
|
|
154
|
-
function open() {
|
|
155
|
-
dialog.current?.showModal();
|
|
156
|
-
// Asked again each time, so a save since is among them.
|
|
157
|
-
void list.load();
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return (
|
|
161
|
-
<>
|
|
162
|
-
<IconButton icon={ClockCounterClockwise} label={t.history.versions} aria-haspopup="dialog" onClick={open} />
|
|
163
|
-
<BottomSheet ref={dialog} aria-label={t.history.versions} onClick={(e) => e.target === dialog.current && dialog.current?.close()}>
|
|
164
|
-
<SheetTitle title={t.history.versions} onClose={() => dialog.current?.close()} />
|
|
165
|
-
<SheetBody>
|
|
166
|
-
<VersionRows
|
|
167
|
-
list={list}
|
|
168
|
-
onPick={(v) => {
|
|
169
|
-
dialog.current?.close();
|
|
170
|
-
void list.pick(v);
|
|
171
|
-
}}
|
|
172
|
-
/>
|
|
173
|
-
</SheetBody>
|
|
174
|
-
</BottomSheet>
|
|
175
|
-
</>
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** The versions as the last section of a page's or a post's form (EntryForm.tsx), under its heading there: loaded when
|
|
180
|
-
* the form opens (so the page is as long as it will be when the drawer scrolls to them), and again after each save
|
|
181
|
-
* (`oid`, the file's version saved now). A version picked
|
|
182
|
-
* opens in the form, which goes up to its top, where it says which version it is (VersionNotice). */
|
|
183
|
-
export function VersionList({ env, path, oid, onPick }: { env: Env; path: string; oid: string; onPick: (v: ShownVersion) => void }) {
|
|
184
|
-
const list = useVersionList(env, path, onPick);
|
|
185
|
-
useEffect(() => {
|
|
186
|
-
void list.load();
|
|
187
|
-
}, [oid]);
|
|
188
|
-
const pick = async (v: Version) => {
|
|
189
|
-
if (!(await list.pick(v))) return;
|
|
190
|
-
requestAnimationFrame(() => scrollTo({ top: 0, behavior: matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth' }));
|
|
191
|
-
};
|
|
192
|
-
return (
|
|
193
|
-
<div className="space-y-4">
|
|
194
|
-
<VersionRows list={list} onPick={(v) => void pick(v)} />
|
|
195
|
-
</div>
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/** At the top of a form that shows an earlier version: when it is from, what saving does, and the way
|
|
200
|
-
* back to the version saved now. */
|
|
201
|
-
export function VersionNotice({ version, onCurrent }: { version: ShownVersion; onCurrent: () => void }) {
|
|
202
|
-
return (
|
|
203
|
-
<Notice
|
|
204
|
-
title={t.history.shownTitle(when(version.at))}
|
|
205
|
-
action={
|
|
206
|
-
<Button kind="outlined" size="small" onClick={onCurrent}>
|
|
207
|
-
{t.history.showCurrent}
|
|
208
|
-
</Button>
|
|
209
|
-
}
|
|
210
|
-
>
|
|
211
|
-
{t.history.shownText}
|
|
212
|
-
</Notice>
|
|
213
|
-
);
|
|
214
|
-
}
|
|
1
|
+
// "Tidligere versioner": the commits that changed a form's file (github.ts versionsOf), newest first, with when and by
|
|
2
|
+
// whom, 20 at a time: the last section of a page's or a post's form (VersionList), and in the other forms a sheet
|
|
3
|
+
// opened by the clock in the top bar (VersionsButton). The newest is the
|
|
4
|
+
// version saved now. Tapping an earlier one opens it in the form as changes that are not saved yet
|
|
5
|
+
// (EntryForm.tsx, DataForm.tsx, with a Notice at the top): "Gem ændringer" makes it the current
|
|
6
|
+
// version, in a new commit, so nothing is lost and every version can always be found here again.
|
|
7
|
+
import { Component, Fragment, useEffect, useRef, useState, type ReactNode } from 'react';
|
|
8
|
+
import { ClockCounterClockwise } from '@phosphor-icons/react';
|
|
9
|
+
import {
|
|
10
|
+
Button,
|
|
11
|
+
EmptyNote,
|
|
12
|
+
IconButton,
|
|
13
|
+
listClass,
|
|
14
|
+
Notice,
|
|
15
|
+
LoadingIndicator,
|
|
16
|
+
BottomSheet,
|
|
17
|
+
SheetTitle,
|
|
18
|
+
SheetBody,
|
|
19
|
+
ProblemNote,
|
|
20
|
+
ListItem,
|
|
21
|
+
} from './ui';
|
|
22
|
+
import { mayLeave } from './FormFrame';
|
|
23
|
+
import { when } from './when';
|
|
24
|
+
import type { Env } from './App';
|
|
25
|
+
import type { Version } from './github';
|
|
26
|
+
import { locale, siteLocale, t } from './i18n';
|
|
27
|
+
|
|
28
|
+
/** An earlier version shown in a form: its text, and when it was saved. */
|
|
29
|
+
export type ShownVersion = { text: string; at: Date };
|
|
30
|
+
|
|
31
|
+
// "i dag kl. 13.42" as "I dag kl. 13.42", alone on its line.
|
|
32
|
+
const capital = (s: string) => s.charAt(0).toLocaleUpperCase(locale) + s.slice(1);
|
|
33
|
+
|
|
34
|
+
/** When a version was saved, in the site's language: for the commit that brings it back. */
|
|
35
|
+
export const savedOn = (v: ShownVersion) => v.at.toLocaleString(siteLocale, { dateStyle: 'medium', timeStyle: 'short' });
|
|
36
|
+
|
|
37
|
+
/** A form that can show an earlier version: started again with each version, and with the one saved
|
|
38
|
+
* now when it cannot show one (a file from before the form was changed): then it says so. */
|
|
39
|
+
export function WithVersions({
|
|
40
|
+
notify,
|
|
41
|
+
children,
|
|
42
|
+
}: {
|
|
43
|
+
notify: Env['notify'];
|
|
44
|
+
children: (version: ShownVersion | null, onVersion: (v: ShownVersion | null) => void) => ReactNode;
|
|
45
|
+
}) {
|
|
46
|
+
const [version, setVersion] = useState<ShownVersion | null>(null);
|
|
47
|
+
if (!version) return <Fragment key="now">{children(null, setVersion)}</Fragment>;
|
|
48
|
+
return (
|
|
49
|
+
<Unreadable
|
|
50
|
+
key={version.at.getTime()}
|
|
51
|
+
onError={() => {
|
|
52
|
+
setVersion(null);
|
|
53
|
+
notify({ text: t.history.cannotShow, error: true });
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
{children(version, setVersion)}
|
|
57
|
+
</Unreadable>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Catches an error while a version is shown, so the editor goes on (React needs a class for that).
|
|
62
|
+
class Unreadable extends Component<{ onError: () => void; children: ReactNode }, { failed: boolean }> {
|
|
63
|
+
state = { failed: false };
|
|
64
|
+
static getDerivedStateFromError() {
|
|
65
|
+
return { failed: true };
|
|
66
|
+
}
|
|
67
|
+
componentDidCatch() {
|
|
68
|
+
this.props.onError();
|
|
69
|
+
}
|
|
70
|
+
render() {
|
|
71
|
+
return this.state.failed ? null : this.props.children;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// The versions of a file, loaded 20 at a time (`load`, again from the newest without `after`), and how one is opened in
|
|
76
|
+
// the form (`pick`: asks first while something is unsaved, then fetches the file as it was; true when it was opened).
|
|
77
|
+
function useVersionList(env: Env, path: string, onPick: (v: ShownVersion) => void) {
|
|
78
|
+
const [versions, setVersions] = useState<Version[] | null>(null);
|
|
79
|
+
const [more, setMore] = useState<string | null>(null);
|
|
80
|
+
const [problem, setProblem] = useState('');
|
|
81
|
+
const [loading, setLoading] = useState(false);
|
|
82
|
+
|
|
83
|
+
async function load(after?: string) {
|
|
84
|
+
setLoading(true);
|
|
85
|
+
setProblem('');
|
|
86
|
+
try {
|
|
87
|
+
const page = await env.versions(path, after);
|
|
88
|
+
setVersions((was) => [...(after ? (was ?? []) : []), ...page.versions]);
|
|
89
|
+
setMore(page.more);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
setProblem(t.history.notLoaded((e as Error).message));
|
|
92
|
+
} finally {
|
|
93
|
+
setLoading(false);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function pick(v: Version) {
|
|
98
|
+
if (!(await mayLeave())) return false;
|
|
99
|
+
env.notify({ text: t.history.opening });
|
|
100
|
+
try {
|
|
101
|
+
const text = await env.versionText(v, path);
|
|
102
|
+
if (text === null) {
|
|
103
|
+
env.notify({ text: t.history.notThere, error: true });
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
onPick({ text, at: v.at });
|
|
107
|
+
env.notify(null);
|
|
108
|
+
return true;
|
|
109
|
+
} catch (e) {
|
|
110
|
+
env.notify({ text: t.history.notOpened((e as Error).message), error: true });
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return { versions, more, problem, loading, load, pick };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// The versions as rows, newest first: the one saved now first (it cannot be picked), each with when and by whom, and
|
|
119
|
+
// "Vis ældre versioner" under them while there are more.
|
|
120
|
+
function VersionRows({ list, onPick }: { list: ReturnType<typeof useVersionList>; onPick: (v: Version) => void }) {
|
|
121
|
+
const { versions, more, problem, loading, load } = list;
|
|
122
|
+
return (
|
|
123
|
+
<>
|
|
124
|
+
{problem && <ProblemNote>{problem}</ProblemNote>}
|
|
125
|
+
{!versions && !problem && <EmptyNote busy>{t.history.loading}</EmptyNote>}
|
|
126
|
+
{versions && versions.length < 2 && !more && <p className="text-muted">{t.history.none}</p>}
|
|
127
|
+
{versions && versions.length > 0 && (
|
|
128
|
+
<ul className={listClass}>
|
|
129
|
+
{versions.map((v, i) => (
|
|
130
|
+
<ListItem
|
|
131
|
+
key={v.commit}
|
|
132
|
+
onClick={i === 0 ? undefined : () => onPick(v)}
|
|
133
|
+
headline={capital(when(v.at))}
|
|
134
|
+
supporting={i === 0 ? t.history.current : v.by && t.history.by(v.by)}
|
|
135
|
+
truncate
|
|
136
|
+
/>
|
|
137
|
+
))}
|
|
138
|
+
</ul>
|
|
139
|
+
)}
|
|
140
|
+
{more && (
|
|
141
|
+
<Button kind="outlined" wide disabled={loading} onClick={() => load(more)}>
|
|
142
|
+
{loading ? <LoadingIndicator>{t.history.loading}</LoadingIndicator> : t.history.more}
|
|
143
|
+
</Button>
|
|
144
|
+
)}
|
|
145
|
+
</>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** The clock in the top bar of a form (DataForm.tsx), and the sheet with the versions. `onPick` opens one in the form. */
|
|
150
|
+
export function VersionsButton({ env, path, onPick }: { env: Env; path: string; onPick: (v: ShownVersion) => void }) {
|
|
151
|
+
const dialog = useRef<HTMLDialogElement>(null);
|
|
152
|
+
const list = useVersionList(env, path, onPick);
|
|
153
|
+
|
|
154
|
+
function open() {
|
|
155
|
+
dialog.current?.showModal();
|
|
156
|
+
// Asked again each time, so a save since is among them.
|
|
157
|
+
void list.load();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<>
|
|
162
|
+
<IconButton icon={ClockCounterClockwise} label={t.history.versions} aria-haspopup="dialog" onClick={open} />
|
|
163
|
+
<BottomSheet ref={dialog} aria-label={t.history.versions} onClick={(e) => e.target === dialog.current && dialog.current?.close()}>
|
|
164
|
+
<SheetTitle title={t.history.versions} onClose={() => dialog.current?.close()} />
|
|
165
|
+
<SheetBody>
|
|
166
|
+
<VersionRows
|
|
167
|
+
list={list}
|
|
168
|
+
onPick={(v) => {
|
|
169
|
+
dialog.current?.close();
|
|
170
|
+
void list.pick(v);
|
|
171
|
+
}}
|
|
172
|
+
/>
|
|
173
|
+
</SheetBody>
|
|
174
|
+
</BottomSheet>
|
|
175
|
+
</>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** The versions as the last section of a page's or a post's form (EntryForm.tsx), under its heading there: loaded when
|
|
180
|
+
* the form opens (so the page is as long as it will be when the drawer scrolls to them), and again after each save
|
|
181
|
+
* (`oid`, the file's version saved now). A version picked
|
|
182
|
+
* opens in the form, which goes up to its top, where it says which version it is (VersionNotice). */
|
|
183
|
+
export function VersionList({ env, path, oid, onPick }: { env: Env; path: string; oid: string; onPick: (v: ShownVersion) => void }) {
|
|
184
|
+
const list = useVersionList(env, path, onPick);
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
void list.load();
|
|
187
|
+
}, [oid]);
|
|
188
|
+
const pick = async (v: Version) => {
|
|
189
|
+
if (!(await list.pick(v))) return;
|
|
190
|
+
requestAnimationFrame(() => scrollTo({ top: 0, behavior: matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth' }));
|
|
191
|
+
};
|
|
192
|
+
return (
|
|
193
|
+
<div className="space-y-4">
|
|
194
|
+
<VersionRows list={list} onPick={(v) => void pick(v)} />
|
|
195
|
+
</div>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** At the top of a form that shows an earlier version: when it is from, what saving does, and the way
|
|
200
|
+
* back to the version saved now. */
|
|
201
|
+
export function VersionNotice({ version, onCurrent }: { version: ShownVersion; onCurrent: () => void }) {
|
|
202
|
+
return (
|
|
203
|
+
<Notice
|
|
204
|
+
title={t.history.shownTitle(when(version.at))}
|
|
205
|
+
action={
|
|
206
|
+
<Button kind="outlined" size="small" onClick={onCurrent}>
|
|
207
|
+
{t.history.showCurrent}
|
|
208
|
+
</Button>
|
|
209
|
+
}
|
|
210
|
+
>
|
|
211
|
+
{t.history.shownText}
|
|
212
|
+
</Notice>
|
|
213
|
+
);
|
|
214
|
+
}
|
package/src/addresses.ts
CHANGED
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
// A page or blog post that gets a new address (Adresse under "Andre felter", EntryForm.tsx): the old
|
|
2
|
-
// address sends visitors on to the new one (301), from src/data/redirects.json, which the Worker reads
|
|
3
|
-
// (packages/editor/worker/index.js) and follows to where it ends, so there is one redirect and no chain. The links to
|
|
4
|
-
// the old address in the texts, the menu and the other files are changed to the new one in the same
|
|
5
|
-
// commit. Before it is saved, the redirects are checked for a loop.
|
|
6
|
-
import { slugify } from './schema';
|
|
7
|
-
import { config } from '@site/config';
|
|
8
|
-
import { t } from './i18n';
|
|
9
|
-
|
|
10
|
-
export const REDIRECTS = config.redirects;
|
|
11
|
-
|
|
12
|
-
/** Old address -> new address, e.g. "/om/" -> "/om-mig/". */
|
|
13
|
-
export type Redirects = Record<string, string>;
|
|
14
|
-
|
|
15
|
-
/** What is typed as an address, as one: "/ny-side/" (a page may have more parts, "/ydelser/raadgivning/";
|
|
16
|
-
* a blog post only one). With or without the slashes or the site's domain; '' when nothing is left. */
|
|
17
|
-
export function addressOf(typed: string, kind: 'page' | 'post'): string {
|
|
18
|
-
const parts = typed
|
|
19
|
-
.trim()
|
|
20
|
-
.replace(/^https?:\/\/[^/]+/i, '')
|
|
21
|
-
.split('/')
|
|
22
|
-
.map(slugify)
|
|
23
|
-
.filter(Boolean);
|
|
24
|
-
if (!parts.length) return '';
|
|
25
|
-
return kind === 'post' ? `/${parts.join('-')}/` : `/${parts.join('/')}/`;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** The redirects read from their file (an empty list without it). */
|
|
29
|
-
export const readRedirects = (text: string | undefined): Redirects => (text ? (JSON.parse(text) as Redirects) : {});
|
|
30
|
-
|
|
31
|
-
/** The redirects written as their file: by old address, one to a line. */
|
|
32
|
-
export const writeRedirects = (redirects: Redirects) =>
|
|
33
|
-
`${JSON.stringify(Object.fromEntries(Object.entries(redirects).sort(([a], [b]) => a.localeCompare(b))), null, 2)}\n`;
|
|
34
|
-
|
|
35
|
-
// Where an address ends when it is sent on, and a loop when it comes back to one it has been at.
|
|
36
|
-
function follow(redirects: Redirects, from: string): { end: string; loop: string[] | null } {
|
|
37
|
-
const seen = [from];
|
|
38
|
-
let at = from;
|
|
39
|
-
while (redirects[at.split('#')[0]] !== undefined) {
|
|
40
|
-
at = redirects[at.split('#')[0]];
|
|
41
|
-
if (seen.includes(at.split('#')[0])) return { end: at, loop: [...seen, at] };
|
|
42
|
-
seen.push(at);
|
|
43
|
-
}
|
|
44
|
-
return { end: at, loop: null };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** The redirects when a page moves from one address to another (from null: a new page at `to`): `to`
|
|
48
|
-
* is a page now, so it no longer sends on; `from` sends on to `to`, and so does every address that
|
|
49
|
-
* sent on to `from`. A message instead when they would send in a loop. */
|
|
50
|
-
export function moveRedirects(redirects: Redirects, from: string | null, to: string): Redirects | string {
|
|
51
|
-
const next: Redirects = {};
|
|
52
|
-
for (const [old, target] of Object.entries(redirects)) {
|
|
53
|
-
if (old === to) continue;
|
|
54
|
-
const [base, part] = target.split('#');
|
|
55
|
-
next[old] = from && base === from ? (part === undefined ? to : `${to}#${part}`) : target;
|
|
56
|
-
}
|
|
57
|
-
if (from && from !== to) next[from] = to;
|
|
58
|
-
for (const old of Object.keys(next)) {
|
|
59
|
-
const { end, loop } = follow(next, old);
|
|
60
|
-
if (loop) return t.app.addressLoop(loop.join(' → '));
|
|
61
|
-
// One redirect to where it ends, not a chain.
|
|
62
|
-
next[old] = end;
|
|
63
|
-
}
|
|
64
|
-
return next;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export const escape = (text: string) => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
68
|
-
|
|
69
|
-
/** A text with its links to an old address changed to the new one: in Markdown links, in HTML and in
|
|
70
|
-
* the JSON of the data files and of the blocks ("…"), also with the site's domain before it,
|
|
71
|
-
* and with a #part or ?query after it. Not an address that only starts with it (a page under it). */
|
|
72
|
-
export function retarget(text: string, from: string, to: string): string {
|
|
73
|
-
const at = new RegExp(`(?<=["'(]|"|${escape(config.domain)})${escape(from)}(?=["')#?\\s]|")`, 'g');
|
|
74
|
-
return text.replace(at, to);
|
|
75
|
-
}
|
|
1
|
+
// A page or blog post that gets a new address (Adresse under "Andre felter", EntryForm.tsx): the old
|
|
2
|
+
// address sends visitors on to the new one (301), from src/data/redirects.json, which the Worker reads
|
|
3
|
+
// (packages/editor/worker/index.js) and follows to where it ends, so there is one redirect and no chain. The links to
|
|
4
|
+
// the old address in the texts, the menu and the other files are changed to the new one in the same
|
|
5
|
+
// commit. Before it is saved, the redirects are checked for a loop.
|
|
6
|
+
import { slugify } from './schema';
|
|
7
|
+
import { config } from '@site/config';
|
|
8
|
+
import { t } from './i18n';
|
|
9
|
+
|
|
10
|
+
export const REDIRECTS = config.redirects;
|
|
11
|
+
|
|
12
|
+
/** Old address -> new address, e.g. "/om/" -> "/om-mig/". */
|
|
13
|
+
export type Redirects = Record<string, string>;
|
|
14
|
+
|
|
15
|
+
/** What is typed as an address, as one: "/ny-side/" (a page may have more parts, "/ydelser/raadgivning/";
|
|
16
|
+
* a blog post only one). With or without the slashes or the site's domain; '' when nothing is left. */
|
|
17
|
+
export function addressOf(typed: string, kind: 'page' | 'post'): string {
|
|
18
|
+
const parts = typed
|
|
19
|
+
.trim()
|
|
20
|
+
.replace(/^https?:\/\/[^/]+/i, '')
|
|
21
|
+
.split('/')
|
|
22
|
+
.map(slugify)
|
|
23
|
+
.filter(Boolean);
|
|
24
|
+
if (!parts.length) return '';
|
|
25
|
+
return kind === 'post' ? `/${parts.join('-')}/` : `/${parts.join('/')}/`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The redirects read from their file (an empty list without it). */
|
|
29
|
+
export const readRedirects = (text: string | undefined): Redirects => (text ? (JSON.parse(text) as Redirects) : {});
|
|
30
|
+
|
|
31
|
+
/** The redirects written as their file: by old address, one to a line. */
|
|
32
|
+
export const writeRedirects = (redirects: Redirects) =>
|
|
33
|
+
`${JSON.stringify(Object.fromEntries(Object.entries(redirects).sort(([a], [b]) => a.localeCompare(b))), null, 2)}\n`;
|
|
34
|
+
|
|
35
|
+
// Where an address ends when it is sent on, and a loop when it comes back to one it has been at.
|
|
36
|
+
function follow(redirects: Redirects, from: string): { end: string; loop: string[] | null } {
|
|
37
|
+
const seen = [from];
|
|
38
|
+
let at = from;
|
|
39
|
+
while (redirects[at.split('#')[0]] !== undefined) {
|
|
40
|
+
at = redirects[at.split('#')[0]];
|
|
41
|
+
if (seen.includes(at.split('#')[0])) return { end: at, loop: [...seen, at] };
|
|
42
|
+
seen.push(at);
|
|
43
|
+
}
|
|
44
|
+
return { end: at, loop: null };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The redirects when a page moves from one address to another (from null: a new page at `to`): `to`
|
|
48
|
+
* is a page now, so it no longer sends on; `from` sends on to `to`, and so does every address that
|
|
49
|
+
* sent on to `from`. A message instead when they would send in a loop. */
|
|
50
|
+
export function moveRedirects(redirects: Redirects, from: string | null, to: string): Redirects | string {
|
|
51
|
+
const next: Redirects = {};
|
|
52
|
+
for (const [old, target] of Object.entries(redirects)) {
|
|
53
|
+
if (old === to) continue;
|
|
54
|
+
const [base, part] = target.split('#');
|
|
55
|
+
next[old] = from && base === from ? (part === undefined ? to : `${to}#${part}`) : target;
|
|
56
|
+
}
|
|
57
|
+
if (from && from !== to) next[from] = to;
|
|
58
|
+
for (const old of Object.keys(next)) {
|
|
59
|
+
const { end, loop } = follow(next, old);
|
|
60
|
+
if (loop) return t.app.addressLoop(loop.join(' → '));
|
|
61
|
+
// One redirect to where it ends, not a chain.
|
|
62
|
+
next[old] = end;
|
|
63
|
+
}
|
|
64
|
+
return next;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const escape = (text: string) => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
68
|
+
|
|
69
|
+
/** A text with its links to an old address changed to the new one: in Markdown links, in HTML and in
|
|
70
|
+
* the JSON of the data files and of the blocks ("…"), also with the site's domain before it,
|
|
71
|
+
* and with a #part or ?query after it. Not an address that only starts with it (a page under it). */
|
|
72
|
+
export function retarget(text: string, from: string, to: string): string {
|
|
73
|
+
const at = new RegExp(`(?<=["'(]|"|${escape(config.domain)})${escape(from)}(?=["')#?\\s]|")`, 'g');
|
|
74
|
+
return text.replace(at, to);
|
|
75
|
+
}
|
package/src/allIcons.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// All Phosphor's icons (regular) as text, by their file, for AnyIcon (icon.tsx): loaded only when it draws one the site
|
|
2
|
-
// does not (an app's in the app store). The theme's are in their place, as for Svg (themePlugin, packages/editor/site/theme.mjs).
|
|
3
|
-
export const allIcons = import.meta.glob<string>('/node_modules/@phosphor-icons/core/assets/regular/*.svg', {
|
|
4
|
-
query: '?raw',
|
|
5
|
-
import: 'default',
|
|
6
|
-
eager: true,
|
|
7
|
-
});
|
|
1
|
+
// All Phosphor's icons (regular) as text, by their file, for AnyIcon (icon.tsx): loaded only when it draws one the site
|
|
2
|
+
// does not (an app's in the app store). The theme's are in their place, as for Svg (themePlugin, packages/editor/site/theme.mjs).
|
|
3
|
+
export const allIcons = import.meta.glob<string>('/node_modules/@phosphor-icons/core/assets/regular/*.svg', {
|
|
4
|
+
query: '?raw',
|
|
5
|
+
import: 'default',
|
|
6
|
+
eager: true,
|
|
7
|
+
});
|