@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/site/icons.mjs
CHANGED
|
@@ -1,605 +1,605 @@
|
|
|
1
|
-
// The icons the site and the editor draw, by Phosphor's names (usedIcons), and the icon packs that draw them (the
|
|
2
|
-
// folders, packages/editor/site/iconPacks.mjs): which packs there are (installedPacks), each one's icons (packIcons) and what is
|
|
3
|
-
// wrong with one (packProblems). The system's own packs (SYSTEM_PACKS: Material Symbols, Phosphor and Lucide, in
|
|
4
|
-
// packages/editor/icons/<pack>/) are written by packages/editor/scripts/icon-packs.mjs (`npm run icons`) from their sets' packages at the versions in
|
|
5
|
-
// PACK_SOURCES, by the maps here: Phosphor's name → the set's icon, chosen for what it means where it is used (by its own
|
|
6
|
-
// name in the set, else by what it shows: Phosphor's `browser`, a window with a bar at the top, is Material Symbols'
|
|
7
|
-
// `web`). An icon a set has none of (a brand's logo; Lucide has none) is Pictogrammers' Material Design Icons'
|
|
8
|
-
// (MATERIAL_DESIGN_ICONS), with its licence beside the pack's own. check:content stops at a pack without an icon the
|
|
9
|
-
// site or the editor draws (themeProblems and iconPackProblems in packages/editor/site/theme.mjs).
|
|
10
|
-
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
11
|
-
import { join, relative } from 'node:path';
|
|
12
|
-
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
13
|
-
import { cleanSvg } from '@morphemecms/cms/lib/svg.mjs';
|
|
14
|
-
import { ICON_PACK_FILE, ICON_PACK_LICENSE, SYSTEM_PACKS, THEME_PACKS_FOLDER, themePackId } from './iconPacks.mjs';
|
|
15
|
-
|
|
16
|
-
// The site's root (the working directory) and this package's.
|
|
17
|
-
const root = pathToFileURL(`${process.cwd()}/`);
|
|
18
|
-
const pkg = new URL('../', import.meta.url);
|
|
19
|
-
/** Whether the system packs are written here (`npm run icons`, where the CMS is made: this package is the site's own
|
|
20
|
-
* packages/editor/, not in node_modules/ and not outside the site, as for the CMS's demo): only there can it be said that
|
|
21
|
-
* a pack has icons nothing draws, since the apps of the store and the site that makes the CMS draw them too. */
|
|
22
|
-
const packsWrittenHere = (() => {
|
|
23
|
-
const path = relative(fileURLToPath(root), fileURLToPath(pkg));
|
|
24
|
-
return !path.startsWith('..') && !path.split(/[\\/]/).includes('node_modules');
|
|
25
|
-
})();
|
|
26
|
-
|
|
27
|
-
/** Where the system's own packs are, one folder each (this package's icons/), from the site's root. */
|
|
28
|
-
export const SYSTEM_PACKS_FOLDER = relative(process.cwd(), fileURLToPath(new URL('icons', pkg)));
|
|
29
|
-
|
|
30
|
-
/** A pack's folder, from its id, from the site's root: a system pack's in this package, a theme's in its folder. */
|
|
31
|
-
export const packFolder = (id) => {
|
|
32
|
-
const [theme, pack] = id.split('/');
|
|
33
|
-
return pack ? `src/themes/${theme}/${THEME_PACKS_FOLDER}/${pack}` : `${SYSTEM_PACKS_FOLDER}/${theme}`;
|
|
34
|
-
};
|
|
35
|
-
const PHOSPHOR = 'node_modules/@phosphor-icons/core/assets/';
|
|
36
|
-
const has = (path) => existsSync(new URL(path, root));
|
|
37
|
-
|
|
38
|
-
/** The packages the system's packs are written from, at the versions they are (not in package.json, so neither an
|
|
39
|
-
* install nor the site's build fetches them; packages/editor/scripts/icon-packs.mjs fetches them into node_modules/.cache/), and what
|
|
40
|
-
* their packs' manifests say of them. Phosphor's is the site's own dependency (the names, and its React icons), at the
|
|
41
|
-
* version package-lock.json has; check:content stops when it is another. */
|
|
42
|
-
export const PACK_SOURCES = {
|
|
43
|
-
'material-symbols': {
|
|
44
|
-
package: '@material-symbols/svg-400@0.48.2',
|
|
45
|
-
name: 'Material Symbols',
|
|
46
|
-
author: 'Google',
|
|
47
|
-
license: 'Apache-2.0',
|
|
48
|
-
url: 'https://fonts.google.com/icons',
|
|
49
|
-
},
|
|
50
|
-
phosphor: {
|
|
51
|
-
package: '@phosphor-icons/core@2.1.1',
|
|
52
|
-
name: 'Phosphor',
|
|
53
|
-
author: 'Phosphor Icons',
|
|
54
|
-
license: 'MIT',
|
|
55
|
-
url: 'https://phosphoricons.com',
|
|
56
|
-
},
|
|
57
|
-
lucide: {
|
|
58
|
-
package: 'lucide-static@1.63.0',
|
|
59
|
-
name: 'Lucide',
|
|
60
|
-
author: 'Lucide Contributors',
|
|
61
|
-
license: 'ISC',
|
|
62
|
-
url: 'https://lucide.dev',
|
|
63
|
-
},
|
|
64
|
-
'material-design-icons': {
|
|
65
|
-
package: '@mdi/svg@7.4.47',
|
|
66
|
-
name: 'Material Design Icons',
|
|
67
|
-
author: 'Pictogrammers',
|
|
68
|
-
license: 'Apache-2.0',
|
|
69
|
-
url: 'https://pictogrammers.com/library/mdi/',
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
/** For each system pack but Phosphor's (whose names they are): Phosphor's name → Material Design Icons' (the package in
|
|
74
|
-
* PACK_SOURCES), for an icon the site or the editor draws that its set has none of. Material Symbols: a brand's logo (the
|
|
75
|
-
* account logged in at GitHub, the SEO choices' Google) and the
|
|
76
|
-
* things it has nothing that shows (binoculars, a hard disk, swatches, a scan frame, the arrows that widen and narrow
|
|
77
|
-
* the Hero). Lucide, which draws no brands: the logos. */
|
|
78
|
-
export const MATERIAL_DESIGN_ICONS = {
|
|
79
|
-
'material-symbols': {
|
|
80
|
-
'arrows-in-line-horizontal': 'arrow-collapse-horizontal',
|
|
81
|
-
'arrows-out-line-horizontal': 'arrow-expand-horizontal',
|
|
82
|
-
binoculars: 'binoculars',
|
|
83
|
-
'github-logo': 'github',
|
|
84
|
-
'google-logo': 'google',
|
|
85
|
-
'hard-drives': 'harddisk',
|
|
86
|
-
scan: 'scan-helper',
|
|
87
|
-
swatches: 'palette-swatch',
|
|
88
|
-
},
|
|
89
|
-
lucide: {
|
|
90
|
-
'github-logo': 'github',
|
|
91
|
-
'google-logo': 'google',
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
/** Phosphor's name → Material Symbols' (Outlined, weight 400; `-fill` the filled one), for every icon the site and the
|
|
96
|
-
* editor draw (usedIcons) but those in MATERIAL_DESIGN_ICONS['material-symbols']. */
|
|
97
|
-
export const MATERIAL_SYMBOLS = {
|
|
98
|
-
'address-book': 'contacts',
|
|
99
|
-
'app-window': 'web_asset',
|
|
100
|
-
'arrow-counter-clockwise': 'replay',
|
|
101
|
-
'arrow-down': 'arrow_downward',
|
|
102
|
-
'arrow-left': 'arrow_back',
|
|
103
|
-
'arrow-right': 'arrow_forward',
|
|
104
|
-
'arrow-square-out': 'open_in_new',
|
|
105
|
-
'arrow-u-up-left': 'undo',
|
|
106
|
-
'arrow-u-up-right': 'redo',
|
|
107
|
-
'arrow-up': 'arrow_upward',
|
|
108
|
-
'arrow-up-right': 'arrow_outward',
|
|
109
|
-
'arrows-down-up': 'swap_vert',
|
|
110
|
-
article: 'article',
|
|
111
|
-
bank: 'account_balance',
|
|
112
|
-
bell: 'notifications',
|
|
113
|
-
bicycle: 'pedal_bike',
|
|
114
|
-
'book-open': 'import_contacts',
|
|
115
|
-
'book-open-text': 'menu_book',
|
|
116
|
-
browser: 'web',
|
|
117
|
-
buildings: 'domain',
|
|
118
|
-
bus: 'directions_bus',
|
|
119
|
-
'calendar-blank': 'calendar_today',
|
|
120
|
-
'calendar-check': 'event_available',
|
|
121
|
-
car: 'directions_car',
|
|
122
|
-
cards: 'cards_stack',
|
|
123
|
-
'caret-down': 'keyboard_arrow_down',
|
|
124
|
-
'caret-left': 'chevron_left',
|
|
125
|
-
'caret-right': 'chevron_right',
|
|
126
|
-
'caret-up': 'keyboard_arrow_up',
|
|
127
|
-
certificate: 'license',
|
|
128
|
-
'chart-line-up': 'monitoring',
|
|
129
|
-
chats: 'forum',
|
|
130
|
-
check: 'check',
|
|
131
|
-
'check-circle': 'check_circle',
|
|
132
|
-
circle: 'circle',
|
|
133
|
-
'circle-half': 'contrast',
|
|
134
|
-
clock: 'schedule',
|
|
135
|
-
'clock-counter-clockwise': 'history',
|
|
136
|
-
code: 'code',
|
|
137
|
-
coffee: 'local_cafe',
|
|
138
|
-
columns: 'view_column_2',
|
|
139
|
-
cookie: 'cookie',
|
|
140
|
-
copy: 'content_copy',
|
|
141
|
-
'credit-card': 'credit_card',
|
|
142
|
-
'currency-circle-dollar': 'paid',
|
|
143
|
-
'cursor-click': 'ads_click',
|
|
144
|
-
database: 'database',
|
|
145
|
-
desktop: 'desktop_windows',
|
|
146
|
-
'device-mobile': 'mobile',
|
|
147
|
-
'door-open': 'door_open',
|
|
148
|
-
'download-simple': 'download',
|
|
149
|
-
'envelope-simple': 'mail',
|
|
150
|
-
eye: 'visibility',
|
|
151
|
-
'eye-slash': 'visibility_off',
|
|
152
|
-
'file-pdf': 'picture_as_pdf',
|
|
153
|
-
'file-text': 'description',
|
|
154
|
-
'file-video': 'video_file',
|
|
155
|
-
'file-zip': 'folder_zip',
|
|
156
|
-
'flower-lotus': 'spa',
|
|
157
|
-
'folder-simple': 'folder',
|
|
158
|
-
funnel: 'filter_alt',
|
|
159
|
-
gauge: 'speed',
|
|
160
|
-
gear: 'settings',
|
|
161
|
-
globe: 'language',
|
|
162
|
-
'graduation-cap': 'school',
|
|
163
|
-
hammer: 'hardware',
|
|
164
|
-
'hand-heart': 'volunteer_activism',
|
|
165
|
-
handshake: 'handshake',
|
|
166
|
-
heart: 'favorite',
|
|
167
|
-
house: 'home',
|
|
168
|
-
image: 'image',
|
|
169
|
-
'image-square': 'image',
|
|
170
|
-
info: 'info',
|
|
171
|
-
keyboard: 'keyboard',
|
|
172
|
-
leaf: 'eco',
|
|
173
|
-
lifebuoy: 'support',
|
|
174
|
-
lightbulb: 'lightbulb',
|
|
175
|
-
'link-break': 'link_off',
|
|
176
|
-
'link-simple': 'link',
|
|
177
|
-
list: 'menu',
|
|
178
|
-
'list-bullets': 'format_list_bulleted',
|
|
179
|
-
'list-checks': 'checklist',
|
|
180
|
-
'list-numbers': 'format_list_numbered',
|
|
181
|
-
'lock-simple': 'lock',
|
|
182
|
-
'lock-simple-open': 'lock_open',
|
|
183
|
-
'magnifying-glass': 'search',
|
|
184
|
-
'map-pin': 'location_on',
|
|
185
|
-
'map-trifold': 'map',
|
|
186
|
-
medal: 'military_tech',
|
|
187
|
-
megaphone: 'campaign',
|
|
188
|
-
minus: 'remove',
|
|
189
|
-
moon: 'dark_mode',
|
|
190
|
-
newspaper: 'newspaper',
|
|
191
|
-
'paint-brush-broad': 'brush',
|
|
192
|
-
palette: 'palette',
|
|
193
|
-
'paper-plane-tilt': 'send',
|
|
194
|
-
'pencil-simple': 'edit',
|
|
195
|
-
phone: 'call',
|
|
196
|
-
'play-fill': 'play_arrow-fill',
|
|
197
|
-
plus: 'add',
|
|
198
|
-
prohibit: 'block',
|
|
199
|
-
'puzzle-piece': 'extension',
|
|
200
|
-
question: 'help',
|
|
201
|
-
quotes: 'format_quote',
|
|
202
|
-
rows: 'view_agenda',
|
|
203
|
-
ruler: 'straighten',
|
|
204
|
-
shapes: 'shapes',
|
|
205
|
-
'share-network': 'share',
|
|
206
|
-
'shield-check': 'verified_user',
|
|
207
|
-
'sidebar-simple': 'side_navigation',
|
|
208
|
-
'sign-out': 'logout',
|
|
209
|
-
signpost: 'signpost',
|
|
210
|
-
'sliders-horizontal': 'tune',
|
|
211
|
-
smiley: 'mood',
|
|
212
|
-
sparkle: 'star_shine',
|
|
213
|
-
square: 'square',
|
|
214
|
-
'square-half-bottom': 'call_to_action',
|
|
215
|
-
'squares-four': 'grid_view',
|
|
216
|
-
sticker: 'brand_family',
|
|
217
|
-
storefront: 'storefront',
|
|
218
|
-
sun: 'light_mode',
|
|
219
|
-
tag: 'sell',
|
|
220
|
-
'text-aa': 'match_case',
|
|
221
|
-
'text-align-left': 'format_align_left',
|
|
222
|
-
'text-b': 'format_bold',
|
|
223
|
-
'text-h-one': 'format_h1',
|
|
224
|
-
'text-h-three': 'format_h3',
|
|
225
|
-
'text-h-two': 'format_h2',
|
|
226
|
-
'text-italic': 'format_italic',
|
|
227
|
-
'text-t': 'title',
|
|
228
|
-
ticket: 'confirmation_number',
|
|
229
|
-
'toggle-right': 'toggle_on',
|
|
230
|
-
train: 'train',
|
|
231
|
-
trash: 'delete',
|
|
232
|
-
'upload-simple': 'upload',
|
|
233
|
-
user: 'person',
|
|
234
|
-
'user-circle': 'account_circle',
|
|
235
|
-
users: 'group',
|
|
236
|
-
'users-three': 'groups',
|
|
237
|
-
'video-camera': 'videocam',
|
|
238
|
-
warning: 'warning',
|
|
239
|
-
'warning-circle': 'error',
|
|
240
|
-
'wave-sine': 'animation',
|
|
241
|
-
wheelchair: 'accessible',
|
|
242
|
-
wrench: 'build',
|
|
243
|
-
x: 'close',
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
/** Phosphor's name → Lucide's, for every icon the site and the editor draw (usedIcons) but those in
|
|
247
|
-
* MATERIAL_DESIGN_ICONS.lucide. `-fill`: Lucide's outline filled in (Lucide has no filled icons). */
|
|
248
|
-
export const LUCIDE = {
|
|
249
|
-
'address-book': 'book-user',
|
|
250
|
-
'app-window': 'app-window',
|
|
251
|
-
'arrow-counter-clockwise': 'rotate-ccw',
|
|
252
|
-
'arrow-down': 'arrow-down',
|
|
253
|
-
'arrow-left': 'arrow-left',
|
|
254
|
-
'arrow-right': 'arrow-right',
|
|
255
|
-
'arrow-square-out': 'external-link',
|
|
256
|
-
'arrow-u-up-left': 'undo-2',
|
|
257
|
-
'arrow-u-up-right': 'redo-2',
|
|
258
|
-
'arrow-up': 'arrow-up',
|
|
259
|
-
'arrow-up-right': 'arrow-up-right',
|
|
260
|
-
'arrows-down-up': 'arrow-down-up',
|
|
261
|
-
'arrows-in-line-horizontal': 'fold-horizontal',
|
|
262
|
-
'arrows-out-line-horizontal': 'unfold-horizontal',
|
|
263
|
-
article: 'file-text',
|
|
264
|
-
bank: 'landmark',
|
|
265
|
-
bell: 'bell',
|
|
266
|
-
bicycle: 'bike',
|
|
267
|
-
binoculars: 'binoculars',
|
|
268
|
-
'book-open': 'book-open',
|
|
269
|
-
'book-open-text': 'book-open-text',
|
|
270
|
-
browser: 'panel-top',
|
|
271
|
-
buildings: 'building-2',
|
|
272
|
-
bus: 'bus',
|
|
273
|
-
'calendar-blank': 'calendar',
|
|
274
|
-
'calendar-check': 'calendar-check',
|
|
275
|
-
car: 'car',
|
|
276
|
-
cards: 'gallery-vertical-end',
|
|
277
|
-
'caret-down': 'chevron-down',
|
|
278
|
-
'caret-left': 'chevron-left',
|
|
279
|
-
'caret-right': 'chevron-right',
|
|
280
|
-
'caret-up': 'chevron-up',
|
|
281
|
-
certificate: 'award',
|
|
282
|
-
'chart-line-up': 'chart-line',
|
|
283
|
-
chats: 'messages-square',
|
|
284
|
-
check: 'check',
|
|
285
|
-
'check-circle': 'circle-check',
|
|
286
|
-
circle: 'circle',
|
|
287
|
-
'circle-half': 'contrast',
|
|
288
|
-
clock: 'clock',
|
|
289
|
-
'clock-counter-clockwise': 'history',
|
|
290
|
-
code: 'code',
|
|
291
|
-
coffee: 'coffee',
|
|
292
|
-
columns: 'columns-2',
|
|
293
|
-
cookie: 'cookie',
|
|
294
|
-
copy: 'copy',
|
|
295
|
-
'credit-card': 'credit-card',
|
|
296
|
-
'currency-circle-dollar': 'circle-dollar-sign',
|
|
297
|
-
'cursor-click': 'mouse-pointer-click',
|
|
298
|
-
database: 'database',
|
|
299
|
-
desktop: 'monitor',
|
|
300
|
-
'device-mobile': 'smartphone',
|
|
301
|
-
'door-open': 'door-open',
|
|
302
|
-
'download-simple': 'download',
|
|
303
|
-
'envelope-simple': 'mail',
|
|
304
|
-
eye: 'eye',
|
|
305
|
-
'eye-slash': 'eye-off',
|
|
306
|
-
'file-pdf': 'file-text',
|
|
307
|
-
'file-text': 'file-text',
|
|
308
|
-
'file-video': 'file-video-camera',
|
|
309
|
-
'file-zip': 'file-archive',
|
|
310
|
-
'flower-lotus': 'flower-2',
|
|
311
|
-
'folder-simple': 'folder',
|
|
312
|
-
funnel: 'funnel',
|
|
313
|
-
gauge: 'gauge',
|
|
314
|
-
gear: 'settings',
|
|
315
|
-
globe: 'globe',
|
|
316
|
-
'graduation-cap': 'graduation-cap',
|
|
317
|
-
hammer: 'hammer',
|
|
318
|
-
'hand-heart': 'hand-heart',
|
|
319
|
-
handshake: 'handshake',
|
|
320
|
-
'hard-drives': 'server',
|
|
321
|
-
heart: 'heart',
|
|
322
|
-
house: 'house',
|
|
323
|
-
image: 'image',
|
|
324
|
-
'image-square': 'image',
|
|
325
|
-
info: 'info',
|
|
326
|
-
keyboard: 'keyboard',
|
|
327
|
-
leaf: 'leaf',
|
|
328
|
-
lifebuoy: 'life-buoy',
|
|
329
|
-
lightbulb: 'lightbulb',
|
|
330
|
-
'link-break': 'unlink',
|
|
331
|
-
'link-simple': 'link',
|
|
332
|
-
list: 'menu',
|
|
333
|
-
'list-bullets': 'list',
|
|
334
|
-
'list-checks': 'list-checks',
|
|
335
|
-
'list-numbers': 'list-ordered',
|
|
336
|
-
'lock-simple': 'lock',
|
|
337
|
-
'lock-simple-open': 'lock-open',
|
|
338
|
-
'magnifying-glass': 'search',
|
|
339
|
-
'map-pin': 'map-pin',
|
|
340
|
-
'map-trifold': 'map',
|
|
341
|
-
medal: 'medal',
|
|
342
|
-
megaphone: 'megaphone',
|
|
343
|
-
minus: 'minus',
|
|
344
|
-
moon: 'moon',
|
|
345
|
-
newspaper: 'newspaper',
|
|
346
|
-
'paint-brush-broad': 'paintbrush',
|
|
347
|
-
palette: 'palette',
|
|
348
|
-
'paper-plane-tilt': 'send',
|
|
349
|
-
'pencil-simple': 'pencil',
|
|
350
|
-
phone: 'phone',
|
|
351
|
-
'play-fill': 'play-fill',
|
|
352
|
-
plus: 'plus',
|
|
353
|
-
prohibit: 'ban',
|
|
354
|
-
'puzzle-piece': 'puzzle',
|
|
355
|
-
question: 'circle-question-mark',
|
|
356
|
-
quotes: 'quote',
|
|
357
|
-
rows: 'rows-2',
|
|
358
|
-
ruler: 'ruler',
|
|
359
|
-
scan: 'scan',
|
|
360
|
-
shapes: 'shapes',
|
|
361
|
-
'share-network': 'share-2',
|
|
362
|
-
'shield-check': 'shield-check',
|
|
363
|
-
'sidebar-simple': 'panel-left',
|
|
364
|
-
'sign-out': 'log-out',
|
|
365
|
-
signpost: 'signpost',
|
|
366
|
-
'sliders-horizontal': 'sliders-horizontal',
|
|
367
|
-
smiley: 'smile',
|
|
368
|
-
sparkle: 'sparkle',
|
|
369
|
-
square: 'square',
|
|
370
|
-
'square-half-bottom': 'panel-bottom',
|
|
371
|
-
'squares-four': 'layout-grid',
|
|
372
|
-
sticker: 'sticker',
|
|
373
|
-
storefront: 'store',
|
|
374
|
-
sun: 'sun',
|
|
375
|
-
swatches: 'swatch-book',
|
|
376
|
-
tag: 'tag',
|
|
377
|
-
'text-aa': 'case-sensitive',
|
|
378
|
-
'text-align-left': 'text-align-start',
|
|
379
|
-
'text-b': 'bold',
|
|
380
|
-
'text-h-one': 'heading-1',
|
|
381
|
-
'text-h-three': 'heading-3',
|
|
382
|
-
'text-h-two': 'heading-2',
|
|
383
|
-
'text-italic': 'italic',
|
|
384
|
-
'text-t': 'type',
|
|
385
|
-
ticket: 'ticket',
|
|
386
|
-
'toggle-right': 'toggle-right',
|
|
387
|
-
train: 'train-front',
|
|
388
|
-
trash: 'trash-2',
|
|
389
|
-
'upload-simple': 'upload',
|
|
390
|
-
user: 'user',
|
|
391
|
-
'user-circle': 'circle-user',
|
|
392
|
-
users: 'users',
|
|
393
|
-
'users-three': 'users-round',
|
|
394
|
-
'video-camera': 'video',
|
|
395
|
-
warning: 'triangle-alert',
|
|
396
|
-
'warning-circle': 'circle-alert',
|
|
397
|
-
'wave-sine': 'spline',
|
|
398
|
-
wheelchair: 'accessibility',
|
|
399
|
-
wrench: 'wrench',
|
|
400
|
-
x: 'x',
|
|
401
|
-
};
|
|
402
|
-
|
|
403
|
-
/** Each system pack's map: Phosphor's name → its set's icon (Phosphor's: its own names, no map). */
|
|
404
|
-
export const PACK_MAPS = { 'material-symbols': MATERIAL_SYMBOLS, lucide: LUCIDE };
|
|
405
|
-
|
|
406
|
-
/** The names the system's pack has an icon by in its maps (its set's and Material Design Icons'); all for Phosphor's. */
|
|
407
|
-
const mapped = (pack) => (PACK_MAPS[pack] ? [...Object.keys(PACK_MAPS[pack]), ...Object.keys(MATERIAL_DESIGN_ICONS[pack] ?? {})] : null);
|
|
408
|
-
|
|
409
|
-
/** Whether a name is one the site and the editor draw an icon by: Phosphor's (regular, and the filled ones as
|
|
410
|
-
* `<name>-fill`). A pack's file and a theme's own icon have one of them. */
|
|
411
|
-
export const isIconName = (name) =>
|
|
412
|
-
/^[a-z0-9-]+$/.test(name) && (has(`${PHOSPHOR}regular/${name}.svg`) || (name.endsWith('-fill') && has(`${PHOSPHOR}fill/${name}.svg`)));
|
|
413
|
-
|
|
414
|
-
/** What is wrong with an icon's SVG file (`file` its path, for the message): one <svg> with a viewBox, with only what
|
|
415
|
-
* draws in it (what cleanSvg keeps; the rest is left out where it is drawn). */
|
|
416
|
-
export function svgProblems(file, svg) {
|
|
417
|
-
const clean = cleanSvg(svg);
|
|
418
|
-
if (!clean || svg.match(/<svg\b/gi).length > 1 || !clean.viewBox)
|
|
419
|
-
return [`${file}: et ikon er ét <svg> med en viewBox og intet før eller efter.`];
|
|
420
|
-
if (clean.removed.length)
|
|
421
|
-
return [
|
|
422
|
-
`${file}: ${clean.removed.join(', ')} tegner ikke og bliver ikke vist. Et ikon har kun tegning: ingen scripts, stil, hændelser (on…) eller noget, der hentes udefra.`,
|
|
423
|
-
];
|
|
424
|
-
return [];
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
const folders = (dir) =>
|
|
428
|
-
has(dir)
|
|
429
|
-
? readdirSync(new URL(dir, root), { withFileTypes: true })
|
|
430
|
-
.filter((e) => e.isDirectory())
|
|
431
|
-
.map((e) => e.name)
|
|
432
|
-
: [];
|
|
433
|
-
|
|
434
|
-
/** The icon packs there are, by id: the system's (packages/editor/icons/<pack>/) and those the themes installed bring
|
|
435
|
-
* (src/themes/<theme>/icon-packs/<pack>/, as `<theme>/<pack>`), each a folder with its pack.json. */
|
|
436
|
-
export function installedPacks() {
|
|
437
|
-
const system = folders(`${SYSTEM_PACKS_FOLDER}/`).filter((p) => has(`${SYSTEM_PACKS_FOLDER}/${p}/${ICON_PACK_FILE}`));
|
|
438
|
-
const themes = folders('src/themes/').flatMap((theme) =>
|
|
439
|
-
folders(`src/themes/${theme}/${THEME_PACKS_FOLDER}/`)
|
|
440
|
-
.filter((p) => has(`src/themes/${theme}/${THEME_PACKS_FOLDER}/${p}/${ICON_PACK_FILE}`))
|
|
441
|
-
.map((p) => themePackId(theme, p)),
|
|
442
|
-
);
|
|
443
|
-
return [...system, ...themes];
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/** A pack's icons as their files' text, by name (its <name>.svg). */
|
|
447
|
-
export function packIcons(id) {
|
|
448
|
-
const dir = `${packFolder(id)}/`;
|
|
449
|
-
const icons = {};
|
|
450
|
-
if (has(dir))
|
|
451
|
-
for (const f of readdirSync(new URL(dir, root)))
|
|
452
|
-
if (f.endsWith('.svg')) icons[f.slice(0, -'.svg'.length)] = readFileSync(new URL(dir + f, root), 'utf8');
|
|
453
|
-
return icons;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
/** Phosphor's own file of an icon by its name (regular, or `<name>-fill` filled), as its package has it; null for one it
|
|
457
|
-
* does not have. */
|
|
458
|
-
export function phosphorFile(name) {
|
|
459
|
-
const file =
|
|
460
|
-
name.endsWith('-fill') && has(`${PHOSPHOR}fill/${name}.svg`) ? `${PHOSPHOR}fill/${name}.svg` : `${PHOSPHOR}regular/${name}.svg`;
|
|
461
|
-
return has(file) ? readFileSync(new URL(file, root), 'utf8') : null;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
const isText = (x) => typeof x === 'string' && x.trim() !== '';
|
|
465
|
-
|
|
466
|
-
/** What is wrong with an icon pack (`id`, as installedPacks gives it): its manifest (pack.json: name, author, license;
|
|
467
|
-
* and for each set it takes icons from besides its own, `includes`, its name, author, license, licence file and icons),
|
|
468
|
-
* its licences (LICENSE, and each `includes`' licenseFile), an icon the site or the editor draws (usedIcons) it has no
|
|
469
|
-
* file for, a file that is not an icon by a name the site draws, and each icon's SVG (svgProblems). For a system pack,
|
|
470
|
-
* also that it is written as its maps say (systemPackProblems). */
|
|
471
|
-
export function packProblems(id, used = usedIcons()) {
|
|
472
|
-
const dir = packFolder(id);
|
|
473
|
-
const problems = [];
|
|
474
|
-
let manifest = {};
|
|
475
|
-
try {
|
|
476
|
-
manifest = JSON.parse(readFileSync(new URL(`${dir}/${ICON_PACK_FILE}`, root), 'utf8'));
|
|
477
|
-
} catch (e) {
|
|
478
|
-
return [`${dir}/${ICON_PACK_FILE}: ${e.message}`];
|
|
479
|
-
}
|
|
480
|
-
for (const key of ['name', 'author', 'license'])
|
|
481
|
-
if (!isText(manifest[key]))
|
|
482
|
-
problems.push(`${dir}/${ICON_PACK_FILE}: "${key}" mangler (ikonpakkens navn, hvem der har lavet den, og dens licens).`);
|
|
483
|
-
if (!has(`${dir}/${ICON_PACK_LICENSE}`)) problems.push(`${dir}/${ICON_PACK_LICENSE} mangler: ikonpakkens licens.`);
|
|
484
|
-
const licences = new Set([ICON_PACK_LICENSE]);
|
|
485
|
-
if (manifest.includes !== undefined && !Array.isArray(manifest.includes))
|
|
486
|
-
problems.push(`${dir}/${ICON_PACK_FILE}: "includes" er en liste med de sæt, pakken har ikoner fra ud over sit eget.`);
|
|
487
|
-
for (const x of Array.isArray(manifest.includes) ? manifest.includes : []) {
|
|
488
|
-
const named = isText(x?.name) ? x.name : '?';
|
|
489
|
-
if (!['name', 'author', 'license', 'licenseFile'].every((k) => isText(x?.[k])) || !Array.isArray(x.icons) || !x.icons.every(isText))
|
|
490
|
-
problems.push(`${dir}/${ICON_PACK_FILE}: "includes" (${named}) skal have "name", "author", "license", "licenseFile" og "icons".`);
|
|
491
|
-
else if (!/^LICENSE-[a-z0-9-]+$/.test(x.licenseFile) || !has(`${dir}/${x.licenseFile}`))
|
|
492
|
-
problems.push(`${dir}/${x.licenseFile ?? ICON_PACK_LICENSE}: licensen for ${named} mangler (LICENSE-<sæt> i pakkens mappe).`);
|
|
493
|
-
else licences.add(x.licenseFile);
|
|
494
|
-
for (const name of Array.isArray(x?.icons) ? x.icons : [])
|
|
495
|
-
if (!has(`${dir}/${name}.svg`)) problems.push(`${dir}/${ICON_PACK_FILE}: "includes" (${named}) nævner ${name}, som pakken ikke har.`);
|
|
496
|
-
}
|
|
497
|
-
const files = has(dir) ? readdirSync(new URL(`${dir}/`, root), { withFileTypes: true }) : [];
|
|
498
|
-
for (const entry of files) {
|
|
499
|
-
const file = `${dir}/${entry.name}`;
|
|
500
|
-
if (entry.name === ICON_PACK_FILE || licences.has(entry.name)) continue;
|
|
501
|
-
if (!entry.isFile() || !entry.name.endsWith('.svg')) {
|
|
502
|
-
problems.push(`${file}: en ikonpakke har kun ${ICON_PACK_FILE}, sine licenser og ikoner (${dir}/<navn>.svg).`);
|
|
503
|
-
continue;
|
|
504
|
-
}
|
|
505
|
-
const name = entry.name.slice(0, -'.svg'.length);
|
|
506
|
-
if (!isIconName(name))
|
|
507
|
-
problems.push(`${file}: sitet tegner intet ikon, der hedder "${name}". Et ikon hedder som i Phosphor (fx map-pin, play-fill).`);
|
|
508
|
-
problems.push(...svgProblems(file, readFileSync(new URL(file, root), 'utf8')));
|
|
509
|
-
}
|
|
510
|
-
const missing = [...used].sort().filter((name) => !has(`${dir}/${name}.svg`));
|
|
511
|
-
if (missing.length)
|
|
512
|
-
problems.push(
|
|
513
|
-
`Ikonpakken ${isText(manifest.name) ? manifest.name : id} (${dir}/) har intet ikon for ${missing.join(', ')}: ${
|
|
514
|
-
SYSTEM_PACKS.includes(id)
|
|
515
|
-
? 'skriv det, der passer, i packages/editor/site/icons.mjs, og kør npm run icons.'
|
|
516
|
-
: 'giv den et ikon ved hvert navn.'
|
|
517
|
-
}`,
|
|
518
|
-
);
|
|
519
|
-
return [...problems, ...(SYSTEM_PACKS.includes(id) ? systemPackProblems(id, used) : [])];
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
/** What is wrong with a system pack beyond what every pack must be (packProblems): an icon the site or the editor draws
|
|
523
|
-
* that its maps have none for (Phosphor's: one its package has none of), and where the packs are written, one they name
|
|
524
|
-
* that is not written or a file they do not name (`npm run icons` writes it again), and Phosphor's package at another
|
|
525
|
-
* version than its pack's. */
|
|
526
|
-
function systemPackProblems(id, used) {
|
|
527
|
-
const dir = packFolder(id);
|
|
528
|
-
const problems = [];
|
|
529
|
-
const names = mapped(id);
|
|
530
|
-
if (!packsWrittenHere) {
|
|
531
|
-
const unnamed = names ? [...used].sort().filter((name) => !names.includes(name)) : [];
|
|
532
|
-
return unnamed.length ? [`${PACK_SOURCES[id].name} har intet ikon for ${unnamed.join(', ')}.`] : [];
|
|
533
|
-
}
|
|
534
|
-
if (names) {
|
|
535
|
-
const map = id === 'material-symbols' ? 'MATERIAL_SYMBOLS' : 'LUCIDE';
|
|
536
|
-
const unnamed = [...used].sort().filter((name) => !names.includes(name));
|
|
537
|
-
if (unnamed.length)
|
|
538
|
-
problems.push(
|
|
539
|
-
`${PACK_SOURCES[id].name} har intet ikon for ${unnamed.join(', ')}: skriv det, der passer, i ${map} i packages/editor/site/icons.mjs (et, ${PACK_SOURCES[id].name} intet har af, i MATERIAL_DESIGN_ICONS), og kør npm run icons.`,
|
|
540
|
-
);
|
|
541
|
-
} else {
|
|
542
|
-
const version = JSON.parse(readFileSync(new URL('node_modules/@phosphor-icons/core/package.json', root), 'utf8')).version;
|
|
543
|
-
if (`@phosphor-icons/core@${version}` !== PACK_SOURCES.phosphor.package)
|
|
544
|
-
problems.push(
|
|
545
|
-
`@phosphor-icons/core er ${version}, men ikonpakken Phosphor er skrevet fra ${PACK_SOURCES.phosphor.package}: ret versionen i PACK_SOURCES i packages/editor/site/icons.mjs, og kør npm run icons.`,
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
if (names) {
|
|
549
|
-
const unused = names.filter((name) => !used.has(name)).sort();
|
|
550
|
-
if (unused.length)
|
|
551
|
-
problems.push(
|
|
552
|
-
`packages/editor/site/icons.mjs: ${PACK_SOURCES[id].name}s kort har ${unused.join(', ')}, som sitet og editoren ikke tegner: tag dem ud, og kør npm run icons.`,
|
|
553
|
-
);
|
|
554
|
-
}
|
|
555
|
-
const written = Object.keys(packIcons(id));
|
|
556
|
-
const wanted = names ?? [...used];
|
|
557
|
-
const unwritten = wanted.filter((name) => !written.includes(name)).sort();
|
|
558
|
-
const stray = written.filter((name) => !wanted.includes(name)).sort();
|
|
559
|
-
if (unwritten.length) problems.push(`${dir}/ mangler ${unwritten.join(', ')}: kør npm run icons.`);
|
|
560
|
-
if (stray.length)
|
|
561
|
-
problems.push(`${dir}/: ${stray.join(', ')} bruges ikke (eller står ikke i packages/editor/site/icons.mjs): kør npm run icons.`);
|
|
562
|
-
return problems;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
/** The Phosphor icons the site and the editor draw, by their file's name: the site's (Svg's import.meta.glob in
|
|
566
|
-
* packages/editor/src/icon.tsx), the React icons imported from @phosphor-icons/react (`CaretRight` → caret-right) and
|
|
567
|
-
* the SVG files imported as text (`…/core/assets/regular/eye.svg` with `?raw`), in packages/editor/ and src/; and the
|
|
568
|
-
* icons of the apps in the app store and what they add (`icon` in store/catalog.json, drawn by AnyIcon in icon.tsx
|
|
569
|
-
* before they are installed). */
|
|
570
|
-
export function usedIcons() {
|
|
571
|
-
const used = new Set();
|
|
572
|
-
const has = (name) => existsSync(new URL(`${PHOSPHOR}regular/${name}.svg`, root));
|
|
573
|
-
// The CMS's code (also when it is in node_modules/) and the site's, without the packages inside either.
|
|
574
|
-
const files = [pkg, new URL('src/', root)].flatMap((dir) =>
|
|
575
|
-
readdirSync(fileURLToPath(dir), { recursive: true, withFileTypes: true })
|
|
576
|
-
.filter(
|
|
577
|
-
(e) => e.isFile() && /\.(tsx?|mjs|astro)$/.test(e.name) && !relative(fileURLToPath(dir), e.parentPath).includes('node_modules'),
|
|
578
|
-
)
|
|
579
|
-
.map((e) => join(e.parentPath, e.name)),
|
|
580
|
-
);
|
|
581
|
-
for (const file of files) {
|
|
582
|
-
const code = readFileSync(file, 'utf8');
|
|
583
|
-
for (const [, names] of code.matchAll(/import\s*\{([^}]*)\}\s*from\s*'@phosphor-icons\/react'/g))
|
|
584
|
-
for (const part of names.split(',')) {
|
|
585
|
-
const name = part
|
|
586
|
-
.trim()
|
|
587
|
-
.split(/\s+as\s+/)[0]
|
|
588
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
589
|
-
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
|
|
590
|
-
.toLowerCase();
|
|
591
|
-
if (has(name)) used.add(name);
|
|
592
|
-
}
|
|
593
|
-
for (const [, name] of code.matchAll(/@phosphor-icons\/core\/assets\/(?:regular|fill)\/([a-z0-9-]+)\.svg\?raw/g)) used.add(name);
|
|
594
|
-
for (const [, names] of code.matchAll(/\/node_modules\/@phosphor-icons\/core\/assets\/(?:regular|fill)\/\{([^}]*)\}\.svg/g))
|
|
595
|
-
for (const name of names.split(',')) used.add(name);
|
|
596
|
-
}
|
|
597
|
-
// The store's catalog (until the real store exists, this repository's own: `store` in src/site/config.ts).
|
|
598
|
-
const catalog = new URL('store/catalog.json', root);
|
|
599
|
-
if (existsSync(catalog))
|
|
600
|
-
JSON.parse(readFileSync(catalog, 'utf8'), (key, value) => {
|
|
601
|
-
if (key === 'icon' && typeof value === 'string' && /^[a-z0-9-]+$/.test(value) && has(value)) used.add(value);
|
|
602
|
-
return value;
|
|
603
|
-
});
|
|
604
|
-
return used;
|
|
605
|
-
}
|
|
1
|
+
// The icons the site and the editor draw, by Phosphor's names (usedIcons), and the icon packs that draw them (the
|
|
2
|
+
// folders, packages/editor/site/iconPacks.mjs): which packs there are (installedPacks), each one's icons (packIcons) and what is
|
|
3
|
+
// wrong with one (packProblems). The system's own packs (SYSTEM_PACKS: Material Symbols, Phosphor and Lucide, in
|
|
4
|
+
// packages/editor/icons/<pack>/) are written by packages/editor/scripts/icon-packs.mjs (`npm run icons`) from their sets' packages at the versions in
|
|
5
|
+
// PACK_SOURCES, by the maps here: Phosphor's name → the set's icon, chosen for what it means where it is used (by its own
|
|
6
|
+
// name in the set, else by what it shows: Phosphor's `browser`, a window with a bar at the top, is Material Symbols'
|
|
7
|
+
// `web`). An icon a set has none of (a brand's logo; Lucide has none) is Pictogrammers' Material Design Icons'
|
|
8
|
+
// (MATERIAL_DESIGN_ICONS), with its licence beside the pack's own. check:content stops at a pack without an icon the
|
|
9
|
+
// site or the editor draws (themeProblems and iconPackProblems in packages/editor/site/theme.mjs).
|
|
10
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
11
|
+
import { join, relative } from 'node:path';
|
|
12
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
13
|
+
import { cleanSvg } from '@morphemecms/cms/lib/svg.mjs';
|
|
14
|
+
import { ICON_PACK_FILE, ICON_PACK_LICENSE, SYSTEM_PACKS, THEME_PACKS_FOLDER, themePackId } from './iconPacks.mjs';
|
|
15
|
+
|
|
16
|
+
// The site's root (the working directory) and this package's.
|
|
17
|
+
const root = pathToFileURL(`${process.cwd()}/`);
|
|
18
|
+
const pkg = new URL('../', import.meta.url);
|
|
19
|
+
/** Whether the system packs are written here (`npm run icons`, where the CMS is made: this package is the site's own
|
|
20
|
+
* packages/editor/, not in node_modules/ and not outside the site, as for the CMS's demo): only there can it be said that
|
|
21
|
+
* a pack has icons nothing draws, since the apps of the store and the site that makes the CMS draw them too. */
|
|
22
|
+
const packsWrittenHere = (() => {
|
|
23
|
+
const path = relative(fileURLToPath(root), fileURLToPath(pkg));
|
|
24
|
+
return !path.startsWith('..') && !path.split(/[\\/]/).includes('node_modules');
|
|
25
|
+
})();
|
|
26
|
+
|
|
27
|
+
/** Where the system's own packs are, one folder each (this package's icons/), from the site's root. */
|
|
28
|
+
export const SYSTEM_PACKS_FOLDER = relative(process.cwd(), fileURLToPath(new URL('icons', pkg)));
|
|
29
|
+
|
|
30
|
+
/** A pack's folder, from its id, from the site's root: a system pack's in this package, a theme's in its folder. */
|
|
31
|
+
export const packFolder = (id) => {
|
|
32
|
+
const [theme, pack] = id.split('/');
|
|
33
|
+
return pack ? `src/themes/${theme}/${THEME_PACKS_FOLDER}/${pack}` : `${SYSTEM_PACKS_FOLDER}/${theme}`;
|
|
34
|
+
};
|
|
35
|
+
const PHOSPHOR = 'node_modules/@phosphor-icons/core/assets/';
|
|
36
|
+
const has = (path) => existsSync(new URL(path, root));
|
|
37
|
+
|
|
38
|
+
/** The packages the system's packs are written from, at the versions they are (not in package.json, so neither an
|
|
39
|
+
* install nor the site's build fetches them; packages/editor/scripts/icon-packs.mjs fetches them into node_modules/.cache/), and what
|
|
40
|
+
* their packs' manifests say of them. Phosphor's is the site's own dependency (the names, and its React icons), at the
|
|
41
|
+
* version package-lock.json has; check:content stops when it is another. */
|
|
42
|
+
export const PACK_SOURCES = {
|
|
43
|
+
'material-symbols': {
|
|
44
|
+
package: '@material-symbols/svg-400@0.48.2',
|
|
45
|
+
name: 'Material Symbols',
|
|
46
|
+
author: 'Google',
|
|
47
|
+
license: 'Apache-2.0',
|
|
48
|
+
url: 'https://fonts.google.com/icons',
|
|
49
|
+
},
|
|
50
|
+
phosphor: {
|
|
51
|
+
package: '@phosphor-icons/core@2.1.1',
|
|
52
|
+
name: 'Phosphor',
|
|
53
|
+
author: 'Phosphor Icons',
|
|
54
|
+
license: 'MIT',
|
|
55
|
+
url: 'https://phosphoricons.com',
|
|
56
|
+
},
|
|
57
|
+
lucide: {
|
|
58
|
+
package: 'lucide-static@1.63.0',
|
|
59
|
+
name: 'Lucide',
|
|
60
|
+
author: 'Lucide Contributors',
|
|
61
|
+
license: 'ISC',
|
|
62
|
+
url: 'https://lucide.dev',
|
|
63
|
+
},
|
|
64
|
+
'material-design-icons': {
|
|
65
|
+
package: '@mdi/svg@7.4.47',
|
|
66
|
+
name: 'Material Design Icons',
|
|
67
|
+
author: 'Pictogrammers',
|
|
68
|
+
license: 'Apache-2.0',
|
|
69
|
+
url: 'https://pictogrammers.com/library/mdi/',
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/** For each system pack but Phosphor's (whose names they are): Phosphor's name → Material Design Icons' (the package in
|
|
74
|
+
* PACK_SOURCES), for an icon the site or the editor draws that its set has none of. Material Symbols: a brand's logo (the
|
|
75
|
+
* account logged in at GitHub, the SEO choices' Google) and the
|
|
76
|
+
* things it has nothing that shows (binoculars, a hard disk, swatches, a scan frame, the arrows that widen and narrow
|
|
77
|
+
* the Hero). Lucide, which draws no brands: the logos. */
|
|
78
|
+
export const MATERIAL_DESIGN_ICONS = {
|
|
79
|
+
'material-symbols': {
|
|
80
|
+
'arrows-in-line-horizontal': 'arrow-collapse-horizontal',
|
|
81
|
+
'arrows-out-line-horizontal': 'arrow-expand-horizontal',
|
|
82
|
+
binoculars: 'binoculars',
|
|
83
|
+
'github-logo': 'github',
|
|
84
|
+
'google-logo': 'google',
|
|
85
|
+
'hard-drives': 'harddisk',
|
|
86
|
+
scan: 'scan-helper',
|
|
87
|
+
swatches: 'palette-swatch',
|
|
88
|
+
},
|
|
89
|
+
lucide: {
|
|
90
|
+
'github-logo': 'github',
|
|
91
|
+
'google-logo': 'google',
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/** Phosphor's name → Material Symbols' (Outlined, weight 400; `-fill` the filled one), for every icon the site and the
|
|
96
|
+
* editor draw (usedIcons) but those in MATERIAL_DESIGN_ICONS['material-symbols']. */
|
|
97
|
+
export const MATERIAL_SYMBOLS = {
|
|
98
|
+
'address-book': 'contacts',
|
|
99
|
+
'app-window': 'web_asset',
|
|
100
|
+
'arrow-counter-clockwise': 'replay',
|
|
101
|
+
'arrow-down': 'arrow_downward',
|
|
102
|
+
'arrow-left': 'arrow_back',
|
|
103
|
+
'arrow-right': 'arrow_forward',
|
|
104
|
+
'arrow-square-out': 'open_in_new',
|
|
105
|
+
'arrow-u-up-left': 'undo',
|
|
106
|
+
'arrow-u-up-right': 'redo',
|
|
107
|
+
'arrow-up': 'arrow_upward',
|
|
108
|
+
'arrow-up-right': 'arrow_outward',
|
|
109
|
+
'arrows-down-up': 'swap_vert',
|
|
110
|
+
article: 'article',
|
|
111
|
+
bank: 'account_balance',
|
|
112
|
+
bell: 'notifications',
|
|
113
|
+
bicycle: 'pedal_bike',
|
|
114
|
+
'book-open': 'import_contacts',
|
|
115
|
+
'book-open-text': 'menu_book',
|
|
116
|
+
browser: 'web',
|
|
117
|
+
buildings: 'domain',
|
|
118
|
+
bus: 'directions_bus',
|
|
119
|
+
'calendar-blank': 'calendar_today',
|
|
120
|
+
'calendar-check': 'event_available',
|
|
121
|
+
car: 'directions_car',
|
|
122
|
+
cards: 'cards_stack',
|
|
123
|
+
'caret-down': 'keyboard_arrow_down',
|
|
124
|
+
'caret-left': 'chevron_left',
|
|
125
|
+
'caret-right': 'chevron_right',
|
|
126
|
+
'caret-up': 'keyboard_arrow_up',
|
|
127
|
+
certificate: 'license',
|
|
128
|
+
'chart-line-up': 'monitoring',
|
|
129
|
+
chats: 'forum',
|
|
130
|
+
check: 'check',
|
|
131
|
+
'check-circle': 'check_circle',
|
|
132
|
+
circle: 'circle',
|
|
133
|
+
'circle-half': 'contrast',
|
|
134
|
+
clock: 'schedule',
|
|
135
|
+
'clock-counter-clockwise': 'history',
|
|
136
|
+
code: 'code',
|
|
137
|
+
coffee: 'local_cafe',
|
|
138
|
+
columns: 'view_column_2',
|
|
139
|
+
cookie: 'cookie',
|
|
140
|
+
copy: 'content_copy',
|
|
141
|
+
'credit-card': 'credit_card',
|
|
142
|
+
'currency-circle-dollar': 'paid',
|
|
143
|
+
'cursor-click': 'ads_click',
|
|
144
|
+
database: 'database',
|
|
145
|
+
desktop: 'desktop_windows',
|
|
146
|
+
'device-mobile': 'mobile',
|
|
147
|
+
'door-open': 'door_open',
|
|
148
|
+
'download-simple': 'download',
|
|
149
|
+
'envelope-simple': 'mail',
|
|
150
|
+
eye: 'visibility',
|
|
151
|
+
'eye-slash': 'visibility_off',
|
|
152
|
+
'file-pdf': 'picture_as_pdf',
|
|
153
|
+
'file-text': 'description',
|
|
154
|
+
'file-video': 'video_file',
|
|
155
|
+
'file-zip': 'folder_zip',
|
|
156
|
+
'flower-lotus': 'spa',
|
|
157
|
+
'folder-simple': 'folder',
|
|
158
|
+
funnel: 'filter_alt',
|
|
159
|
+
gauge: 'speed',
|
|
160
|
+
gear: 'settings',
|
|
161
|
+
globe: 'language',
|
|
162
|
+
'graduation-cap': 'school',
|
|
163
|
+
hammer: 'hardware',
|
|
164
|
+
'hand-heart': 'volunteer_activism',
|
|
165
|
+
handshake: 'handshake',
|
|
166
|
+
heart: 'favorite',
|
|
167
|
+
house: 'home',
|
|
168
|
+
image: 'image',
|
|
169
|
+
'image-square': 'image',
|
|
170
|
+
info: 'info',
|
|
171
|
+
keyboard: 'keyboard',
|
|
172
|
+
leaf: 'eco',
|
|
173
|
+
lifebuoy: 'support',
|
|
174
|
+
lightbulb: 'lightbulb',
|
|
175
|
+
'link-break': 'link_off',
|
|
176
|
+
'link-simple': 'link',
|
|
177
|
+
list: 'menu',
|
|
178
|
+
'list-bullets': 'format_list_bulleted',
|
|
179
|
+
'list-checks': 'checklist',
|
|
180
|
+
'list-numbers': 'format_list_numbered',
|
|
181
|
+
'lock-simple': 'lock',
|
|
182
|
+
'lock-simple-open': 'lock_open',
|
|
183
|
+
'magnifying-glass': 'search',
|
|
184
|
+
'map-pin': 'location_on',
|
|
185
|
+
'map-trifold': 'map',
|
|
186
|
+
medal: 'military_tech',
|
|
187
|
+
megaphone: 'campaign',
|
|
188
|
+
minus: 'remove',
|
|
189
|
+
moon: 'dark_mode',
|
|
190
|
+
newspaper: 'newspaper',
|
|
191
|
+
'paint-brush-broad': 'brush',
|
|
192
|
+
palette: 'palette',
|
|
193
|
+
'paper-plane-tilt': 'send',
|
|
194
|
+
'pencil-simple': 'edit',
|
|
195
|
+
phone: 'call',
|
|
196
|
+
'play-fill': 'play_arrow-fill',
|
|
197
|
+
plus: 'add',
|
|
198
|
+
prohibit: 'block',
|
|
199
|
+
'puzzle-piece': 'extension',
|
|
200
|
+
question: 'help',
|
|
201
|
+
quotes: 'format_quote',
|
|
202
|
+
rows: 'view_agenda',
|
|
203
|
+
ruler: 'straighten',
|
|
204
|
+
shapes: 'shapes',
|
|
205
|
+
'share-network': 'share',
|
|
206
|
+
'shield-check': 'verified_user',
|
|
207
|
+
'sidebar-simple': 'side_navigation',
|
|
208
|
+
'sign-out': 'logout',
|
|
209
|
+
signpost: 'signpost',
|
|
210
|
+
'sliders-horizontal': 'tune',
|
|
211
|
+
smiley: 'mood',
|
|
212
|
+
sparkle: 'star_shine',
|
|
213
|
+
square: 'square',
|
|
214
|
+
'square-half-bottom': 'call_to_action',
|
|
215
|
+
'squares-four': 'grid_view',
|
|
216
|
+
sticker: 'brand_family',
|
|
217
|
+
storefront: 'storefront',
|
|
218
|
+
sun: 'light_mode',
|
|
219
|
+
tag: 'sell',
|
|
220
|
+
'text-aa': 'match_case',
|
|
221
|
+
'text-align-left': 'format_align_left',
|
|
222
|
+
'text-b': 'format_bold',
|
|
223
|
+
'text-h-one': 'format_h1',
|
|
224
|
+
'text-h-three': 'format_h3',
|
|
225
|
+
'text-h-two': 'format_h2',
|
|
226
|
+
'text-italic': 'format_italic',
|
|
227
|
+
'text-t': 'title',
|
|
228
|
+
ticket: 'confirmation_number',
|
|
229
|
+
'toggle-right': 'toggle_on',
|
|
230
|
+
train: 'train',
|
|
231
|
+
trash: 'delete',
|
|
232
|
+
'upload-simple': 'upload',
|
|
233
|
+
user: 'person',
|
|
234
|
+
'user-circle': 'account_circle',
|
|
235
|
+
users: 'group',
|
|
236
|
+
'users-three': 'groups',
|
|
237
|
+
'video-camera': 'videocam',
|
|
238
|
+
warning: 'warning',
|
|
239
|
+
'warning-circle': 'error',
|
|
240
|
+
'wave-sine': 'animation',
|
|
241
|
+
wheelchair: 'accessible',
|
|
242
|
+
wrench: 'build',
|
|
243
|
+
x: 'close',
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
/** Phosphor's name → Lucide's, for every icon the site and the editor draw (usedIcons) but those in
|
|
247
|
+
* MATERIAL_DESIGN_ICONS.lucide. `-fill`: Lucide's outline filled in (Lucide has no filled icons). */
|
|
248
|
+
export const LUCIDE = {
|
|
249
|
+
'address-book': 'book-user',
|
|
250
|
+
'app-window': 'app-window',
|
|
251
|
+
'arrow-counter-clockwise': 'rotate-ccw',
|
|
252
|
+
'arrow-down': 'arrow-down',
|
|
253
|
+
'arrow-left': 'arrow-left',
|
|
254
|
+
'arrow-right': 'arrow-right',
|
|
255
|
+
'arrow-square-out': 'external-link',
|
|
256
|
+
'arrow-u-up-left': 'undo-2',
|
|
257
|
+
'arrow-u-up-right': 'redo-2',
|
|
258
|
+
'arrow-up': 'arrow-up',
|
|
259
|
+
'arrow-up-right': 'arrow-up-right',
|
|
260
|
+
'arrows-down-up': 'arrow-down-up',
|
|
261
|
+
'arrows-in-line-horizontal': 'fold-horizontal',
|
|
262
|
+
'arrows-out-line-horizontal': 'unfold-horizontal',
|
|
263
|
+
article: 'file-text',
|
|
264
|
+
bank: 'landmark',
|
|
265
|
+
bell: 'bell',
|
|
266
|
+
bicycle: 'bike',
|
|
267
|
+
binoculars: 'binoculars',
|
|
268
|
+
'book-open': 'book-open',
|
|
269
|
+
'book-open-text': 'book-open-text',
|
|
270
|
+
browser: 'panel-top',
|
|
271
|
+
buildings: 'building-2',
|
|
272
|
+
bus: 'bus',
|
|
273
|
+
'calendar-blank': 'calendar',
|
|
274
|
+
'calendar-check': 'calendar-check',
|
|
275
|
+
car: 'car',
|
|
276
|
+
cards: 'gallery-vertical-end',
|
|
277
|
+
'caret-down': 'chevron-down',
|
|
278
|
+
'caret-left': 'chevron-left',
|
|
279
|
+
'caret-right': 'chevron-right',
|
|
280
|
+
'caret-up': 'chevron-up',
|
|
281
|
+
certificate: 'award',
|
|
282
|
+
'chart-line-up': 'chart-line',
|
|
283
|
+
chats: 'messages-square',
|
|
284
|
+
check: 'check',
|
|
285
|
+
'check-circle': 'circle-check',
|
|
286
|
+
circle: 'circle',
|
|
287
|
+
'circle-half': 'contrast',
|
|
288
|
+
clock: 'clock',
|
|
289
|
+
'clock-counter-clockwise': 'history',
|
|
290
|
+
code: 'code',
|
|
291
|
+
coffee: 'coffee',
|
|
292
|
+
columns: 'columns-2',
|
|
293
|
+
cookie: 'cookie',
|
|
294
|
+
copy: 'copy',
|
|
295
|
+
'credit-card': 'credit-card',
|
|
296
|
+
'currency-circle-dollar': 'circle-dollar-sign',
|
|
297
|
+
'cursor-click': 'mouse-pointer-click',
|
|
298
|
+
database: 'database',
|
|
299
|
+
desktop: 'monitor',
|
|
300
|
+
'device-mobile': 'smartphone',
|
|
301
|
+
'door-open': 'door-open',
|
|
302
|
+
'download-simple': 'download',
|
|
303
|
+
'envelope-simple': 'mail',
|
|
304
|
+
eye: 'eye',
|
|
305
|
+
'eye-slash': 'eye-off',
|
|
306
|
+
'file-pdf': 'file-text',
|
|
307
|
+
'file-text': 'file-text',
|
|
308
|
+
'file-video': 'file-video-camera',
|
|
309
|
+
'file-zip': 'file-archive',
|
|
310
|
+
'flower-lotus': 'flower-2',
|
|
311
|
+
'folder-simple': 'folder',
|
|
312
|
+
funnel: 'funnel',
|
|
313
|
+
gauge: 'gauge',
|
|
314
|
+
gear: 'settings',
|
|
315
|
+
globe: 'globe',
|
|
316
|
+
'graduation-cap': 'graduation-cap',
|
|
317
|
+
hammer: 'hammer',
|
|
318
|
+
'hand-heart': 'hand-heart',
|
|
319
|
+
handshake: 'handshake',
|
|
320
|
+
'hard-drives': 'server',
|
|
321
|
+
heart: 'heart',
|
|
322
|
+
house: 'house',
|
|
323
|
+
image: 'image',
|
|
324
|
+
'image-square': 'image',
|
|
325
|
+
info: 'info',
|
|
326
|
+
keyboard: 'keyboard',
|
|
327
|
+
leaf: 'leaf',
|
|
328
|
+
lifebuoy: 'life-buoy',
|
|
329
|
+
lightbulb: 'lightbulb',
|
|
330
|
+
'link-break': 'unlink',
|
|
331
|
+
'link-simple': 'link',
|
|
332
|
+
list: 'menu',
|
|
333
|
+
'list-bullets': 'list',
|
|
334
|
+
'list-checks': 'list-checks',
|
|
335
|
+
'list-numbers': 'list-ordered',
|
|
336
|
+
'lock-simple': 'lock',
|
|
337
|
+
'lock-simple-open': 'lock-open',
|
|
338
|
+
'magnifying-glass': 'search',
|
|
339
|
+
'map-pin': 'map-pin',
|
|
340
|
+
'map-trifold': 'map',
|
|
341
|
+
medal: 'medal',
|
|
342
|
+
megaphone: 'megaphone',
|
|
343
|
+
minus: 'minus',
|
|
344
|
+
moon: 'moon',
|
|
345
|
+
newspaper: 'newspaper',
|
|
346
|
+
'paint-brush-broad': 'paintbrush',
|
|
347
|
+
palette: 'palette',
|
|
348
|
+
'paper-plane-tilt': 'send',
|
|
349
|
+
'pencil-simple': 'pencil',
|
|
350
|
+
phone: 'phone',
|
|
351
|
+
'play-fill': 'play-fill',
|
|
352
|
+
plus: 'plus',
|
|
353
|
+
prohibit: 'ban',
|
|
354
|
+
'puzzle-piece': 'puzzle',
|
|
355
|
+
question: 'circle-question-mark',
|
|
356
|
+
quotes: 'quote',
|
|
357
|
+
rows: 'rows-2',
|
|
358
|
+
ruler: 'ruler',
|
|
359
|
+
scan: 'scan',
|
|
360
|
+
shapes: 'shapes',
|
|
361
|
+
'share-network': 'share-2',
|
|
362
|
+
'shield-check': 'shield-check',
|
|
363
|
+
'sidebar-simple': 'panel-left',
|
|
364
|
+
'sign-out': 'log-out',
|
|
365
|
+
signpost: 'signpost',
|
|
366
|
+
'sliders-horizontal': 'sliders-horizontal',
|
|
367
|
+
smiley: 'smile',
|
|
368
|
+
sparkle: 'sparkle',
|
|
369
|
+
square: 'square',
|
|
370
|
+
'square-half-bottom': 'panel-bottom',
|
|
371
|
+
'squares-four': 'layout-grid',
|
|
372
|
+
sticker: 'sticker',
|
|
373
|
+
storefront: 'store',
|
|
374
|
+
sun: 'sun',
|
|
375
|
+
swatches: 'swatch-book',
|
|
376
|
+
tag: 'tag',
|
|
377
|
+
'text-aa': 'case-sensitive',
|
|
378
|
+
'text-align-left': 'text-align-start',
|
|
379
|
+
'text-b': 'bold',
|
|
380
|
+
'text-h-one': 'heading-1',
|
|
381
|
+
'text-h-three': 'heading-3',
|
|
382
|
+
'text-h-two': 'heading-2',
|
|
383
|
+
'text-italic': 'italic',
|
|
384
|
+
'text-t': 'type',
|
|
385
|
+
ticket: 'ticket',
|
|
386
|
+
'toggle-right': 'toggle-right',
|
|
387
|
+
train: 'train-front',
|
|
388
|
+
trash: 'trash-2',
|
|
389
|
+
'upload-simple': 'upload',
|
|
390
|
+
user: 'user',
|
|
391
|
+
'user-circle': 'circle-user',
|
|
392
|
+
users: 'users',
|
|
393
|
+
'users-three': 'users-round',
|
|
394
|
+
'video-camera': 'video',
|
|
395
|
+
warning: 'triangle-alert',
|
|
396
|
+
'warning-circle': 'circle-alert',
|
|
397
|
+
'wave-sine': 'spline',
|
|
398
|
+
wheelchair: 'accessibility',
|
|
399
|
+
wrench: 'wrench',
|
|
400
|
+
x: 'x',
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
/** Each system pack's map: Phosphor's name → its set's icon (Phosphor's: its own names, no map). */
|
|
404
|
+
export const PACK_MAPS = { 'material-symbols': MATERIAL_SYMBOLS, lucide: LUCIDE };
|
|
405
|
+
|
|
406
|
+
/** The names the system's pack has an icon by in its maps (its set's and Material Design Icons'); all for Phosphor's. */
|
|
407
|
+
const mapped = (pack) => (PACK_MAPS[pack] ? [...Object.keys(PACK_MAPS[pack]), ...Object.keys(MATERIAL_DESIGN_ICONS[pack] ?? {})] : null);
|
|
408
|
+
|
|
409
|
+
/** Whether a name is one the site and the editor draw an icon by: Phosphor's (regular, and the filled ones as
|
|
410
|
+
* `<name>-fill`). A pack's file and a theme's own icon have one of them. */
|
|
411
|
+
export const isIconName = (name) =>
|
|
412
|
+
/^[a-z0-9-]+$/.test(name) && (has(`${PHOSPHOR}regular/${name}.svg`) || (name.endsWith('-fill') && has(`${PHOSPHOR}fill/${name}.svg`)));
|
|
413
|
+
|
|
414
|
+
/** What is wrong with an icon's SVG file (`file` its path, for the message): one <svg> with a viewBox, with only what
|
|
415
|
+
* draws in it (what cleanSvg keeps; the rest is left out where it is drawn). */
|
|
416
|
+
export function svgProblems(file, svg) {
|
|
417
|
+
const clean = cleanSvg(svg);
|
|
418
|
+
if (!clean || svg.match(/<svg\b/gi).length > 1 || !clean.viewBox)
|
|
419
|
+
return [`${file}: et ikon er ét <svg> med en viewBox og intet før eller efter.`];
|
|
420
|
+
if (clean.removed.length)
|
|
421
|
+
return [
|
|
422
|
+
`${file}: ${clean.removed.join(', ')} tegner ikke og bliver ikke vist. Et ikon har kun tegning: ingen scripts, stil, hændelser (on…) eller noget, der hentes udefra.`,
|
|
423
|
+
];
|
|
424
|
+
return [];
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const folders = (dir) =>
|
|
428
|
+
has(dir)
|
|
429
|
+
? readdirSync(new URL(dir, root), { withFileTypes: true })
|
|
430
|
+
.filter((e) => e.isDirectory())
|
|
431
|
+
.map((e) => e.name)
|
|
432
|
+
: [];
|
|
433
|
+
|
|
434
|
+
/** The icon packs there are, by id: the system's (packages/editor/icons/<pack>/) and those the themes installed bring
|
|
435
|
+
* (src/themes/<theme>/icon-packs/<pack>/, as `<theme>/<pack>`), each a folder with its pack.json. */
|
|
436
|
+
export function installedPacks() {
|
|
437
|
+
const system = folders(`${SYSTEM_PACKS_FOLDER}/`).filter((p) => has(`${SYSTEM_PACKS_FOLDER}/${p}/${ICON_PACK_FILE}`));
|
|
438
|
+
const themes = folders('src/themes/').flatMap((theme) =>
|
|
439
|
+
folders(`src/themes/${theme}/${THEME_PACKS_FOLDER}/`)
|
|
440
|
+
.filter((p) => has(`src/themes/${theme}/${THEME_PACKS_FOLDER}/${p}/${ICON_PACK_FILE}`))
|
|
441
|
+
.map((p) => themePackId(theme, p)),
|
|
442
|
+
);
|
|
443
|
+
return [...system, ...themes];
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/** A pack's icons as their files' text, by name (its <name>.svg). */
|
|
447
|
+
export function packIcons(id) {
|
|
448
|
+
const dir = `${packFolder(id)}/`;
|
|
449
|
+
const icons = {};
|
|
450
|
+
if (has(dir))
|
|
451
|
+
for (const f of readdirSync(new URL(dir, root)))
|
|
452
|
+
if (f.endsWith('.svg')) icons[f.slice(0, -'.svg'.length)] = readFileSync(new URL(dir + f, root), 'utf8');
|
|
453
|
+
return icons;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/** Phosphor's own file of an icon by its name (regular, or `<name>-fill` filled), as its package has it; null for one it
|
|
457
|
+
* does not have. */
|
|
458
|
+
export function phosphorFile(name) {
|
|
459
|
+
const file =
|
|
460
|
+
name.endsWith('-fill') && has(`${PHOSPHOR}fill/${name}.svg`) ? `${PHOSPHOR}fill/${name}.svg` : `${PHOSPHOR}regular/${name}.svg`;
|
|
461
|
+
return has(file) ? readFileSync(new URL(file, root), 'utf8') : null;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const isText = (x) => typeof x === 'string' && x.trim() !== '';
|
|
465
|
+
|
|
466
|
+
/** What is wrong with an icon pack (`id`, as installedPacks gives it): its manifest (pack.json: name, author, license;
|
|
467
|
+
* and for each set it takes icons from besides its own, `includes`, its name, author, license, licence file and icons),
|
|
468
|
+
* its licences (LICENSE, and each `includes`' licenseFile), an icon the site or the editor draws (usedIcons) it has no
|
|
469
|
+
* file for, a file that is not an icon by a name the site draws, and each icon's SVG (svgProblems). For a system pack,
|
|
470
|
+
* also that it is written as its maps say (systemPackProblems). */
|
|
471
|
+
export function packProblems(id, used = usedIcons()) {
|
|
472
|
+
const dir = packFolder(id);
|
|
473
|
+
const problems = [];
|
|
474
|
+
let manifest = {};
|
|
475
|
+
try {
|
|
476
|
+
manifest = JSON.parse(readFileSync(new URL(`${dir}/${ICON_PACK_FILE}`, root), 'utf8'));
|
|
477
|
+
} catch (e) {
|
|
478
|
+
return [`${dir}/${ICON_PACK_FILE}: ${e.message}`];
|
|
479
|
+
}
|
|
480
|
+
for (const key of ['name', 'author', 'license'])
|
|
481
|
+
if (!isText(manifest[key]))
|
|
482
|
+
problems.push(`${dir}/${ICON_PACK_FILE}: "${key}" mangler (ikonpakkens navn, hvem der har lavet den, og dens licens).`);
|
|
483
|
+
if (!has(`${dir}/${ICON_PACK_LICENSE}`)) problems.push(`${dir}/${ICON_PACK_LICENSE} mangler: ikonpakkens licens.`);
|
|
484
|
+
const licences = new Set([ICON_PACK_LICENSE]);
|
|
485
|
+
if (manifest.includes !== undefined && !Array.isArray(manifest.includes))
|
|
486
|
+
problems.push(`${dir}/${ICON_PACK_FILE}: "includes" er en liste med de sæt, pakken har ikoner fra ud over sit eget.`);
|
|
487
|
+
for (const x of Array.isArray(manifest.includes) ? manifest.includes : []) {
|
|
488
|
+
const named = isText(x?.name) ? x.name : '?';
|
|
489
|
+
if (!['name', 'author', 'license', 'licenseFile'].every((k) => isText(x?.[k])) || !Array.isArray(x.icons) || !x.icons.every(isText))
|
|
490
|
+
problems.push(`${dir}/${ICON_PACK_FILE}: "includes" (${named}) skal have "name", "author", "license", "licenseFile" og "icons".`);
|
|
491
|
+
else if (!/^LICENSE-[a-z0-9-]+$/.test(x.licenseFile) || !has(`${dir}/${x.licenseFile}`))
|
|
492
|
+
problems.push(`${dir}/${x.licenseFile ?? ICON_PACK_LICENSE}: licensen for ${named} mangler (LICENSE-<sæt> i pakkens mappe).`);
|
|
493
|
+
else licences.add(x.licenseFile);
|
|
494
|
+
for (const name of Array.isArray(x?.icons) ? x.icons : [])
|
|
495
|
+
if (!has(`${dir}/${name}.svg`)) problems.push(`${dir}/${ICON_PACK_FILE}: "includes" (${named}) nævner ${name}, som pakken ikke har.`);
|
|
496
|
+
}
|
|
497
|
+
const files = has(dir) ? readdirSync(new URL(`${dir}/`, root), { withFileTypes: true }) : [];
|
|
498
|
+
for (const entry of files) {
|
|
499
|
+
const file = `${dir}/${entry.name}`;
|
|
500
|
+
if (entry.name === ICON_PACK_FILE || licences.has(entry.name)) continue;
|
|
501
|
+
if (!entry.isFile() || !entry.name.endsWith('.svg')) {
|
|
502
|
+
problems.push(`${file}: en ikonpakke har kun ${ICON_PACK_FILE}, sine licenser og ikoner (${dir}/<navn>.svg).`);
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
const name = entry.name.slice(0, -'.svg'.length);
|
|
506
|
+
if (!isIconName(name))
|
|
507
|
+
problems.push(`${file}: sitet tegner intet ikon, der hedder "${name}". Et ikon hedder som i Phosphor (fx map-pin, play-fill).`);
|
|
508
|
+
problems.push(...svgProblems(file, readFileSync(new URL(file, root), 'utf8')));
|
|
509
|
+
}
|
|
510
|
+
const missing = [...used].sort().filter((name) => !has(`${dir}/${name}.svg`));
|
|
511
|
+
if (missing.length)
|
|
512
|
+
problems.push(
|
|
513
|
+
`Ikonpakken ${isText(manifest.name) ? manifest.name : id} (${dir}/) har intet ikon for ${missing.join(', ')}: ${
|
|
514
|
+
SYSTEM_PACKS.includes(id)
|
|
515
|
+
? 'skriv det, der passer, i packages/editor/site/icons.mjs, og kør npm run icons.'
|
|
516
|
+
: 'giv den et ikon ved hvert navn.'
|
|
517
|
+
}`,
|
|
518
|
+
);
|
|
519
|
+
return [...problems, ...(SYSTEM_PACKS.includes(id) ? systemPackProblems(id, used) : [])];
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/** What is wrong with a system pack beyond what every pack must be (packProblems): an icon the site or the editor draws
|
|
523
|
+
* that its maps have none for (Phosphor's: one its package has none of), and where the packs are written, one they name
|
|
524
|
+
* that is not written or a file they do not name (`npm run icons` writes it again), and Phosphor's package at another
|
|
525
|
+
* version than its pack's. */
|
|
526
|
+
function systemPackProblems(id, used) {
|
|
527
|
+
const dir = packFolder(id);
|
|
528
|
+
const problems = [];
|
|
529
|
+
const names = mapped(id);
|
|
530
|
+
if (!packsWrittenHere) {
|
|
531
|
+
const unnamed = names ? [...used].sort().filter((name) => !names.includes(name)) : [];
|
|
532
|
+
return unnamed.length ? [`${PACK_SOURCES[id].name} har intet ikon for ${unnamed.join(', ')}.`] : [];
|
|
533
|
+
}
|
|
534
|
+
if (names) {
|
|
535
|
+
const map = id === 'material-symbols' ? 'MATERIAL_SYMBOLS' : 'LUCIDE';
|
|
536
|
+
const unnamed = [...used].sort().filter((name) => !names.includes(name));
|
|
537
|
+
if (unnamed.length)
|
|
538
|
+
problems.push(
|
|
539
|
+
`${PACK_SOURCES[id].name} har intet ikon for ${unnamed.join(', ')}: skriv det, der passer, i ${map} i packages/editor/site/icons.mjs (et, ${PACK_SOURCES[id].name} intet har af, i MATERIAL_DESIGN_ICONS), og kør npm run icons.`,
|
|
540
|
+
);
|
|
541
|
+
} else {
|
|
542
|
+
const version = JSON.parse(readFileSync(new URL('node_modules/@phosphor-icons/core/package.json', root), 'utf8')).version;
|
|
543
|
+
if (`@phosphor-icons/core@${version}` !== PACK_SOURCES.phosphor.package)
|
|
544
|
+
problems.push(
|
|
545
|
+
`@phosphor-icons/core er ${version}, men ikonpakken Phosphor er skrevet fra ${PACK_SOURCES.phosphor.package}: ret versionen i PACK_SOURCES i packages/editor/site/icons.mjs, og kør npm run icons.`,
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
if (names) {
|
|
549
|
+
const unused = names.filter((name) => !used.has(name)).sort();
|
|
550
|
+
if (unused.length)
|
|
551
|
+
problems.push(
|
|
552
|
+
`packages/editor/site/icons.mjs: ${PACK_SOURCES[id].name}s kort har ${unused.join(', ')}, som sitet og editoren ikke tegner: tag dem ud, og kør npm run icons.`,
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
const written = Object.keys(packIcons(id));
|
|
556
|
+
const wanted = names ?? [...used];
|
|
557
|
+
const unwritten = wanted.filter((name) => !written.includes(name)).sort();
|
|
558
|
+
const stray = written.filter((name) => !wanted.includes(name)).sort();
|
|
559
|
+
if (unwritten.length) problems.push(`${dir}/ mangler ${unwritten.join(', ')}: kør npm run icons.`);
|
|
560
|
+
if (stray.length)
|
|
561
|
+
problems.push(`${dir}/: ${stray.join(', ')} bruges ikke (eller står ikke i packages/editor/site/icons.mjs): kør npm run icons.`);
|
|
562
|
+
return problems;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/** The Phosphor icons the site and the editor draw, by their file's name: the site's (Svg's import.meta.glob in
|
|
566
|
+
* packages/editor/src/icon.tsx), the React icons imported from @phosphor-icons/react (`CaretRight` → caret-right) and
|
|
567
|
+
* the SVG files imported as text (`…/core/assets/regular/eye.svg` with `?raw`), in packages/editor/ and src/; and the
|
|
568
|
+
* icons of the apps in the app store and what they add (`icon` in store/catalog.json, drawn by AnyIcon in icon.tsx
|
|
569
|
+
* before they are installed). */
|
|
570
|
+
export function usedIcons() {
|
|
571
|
+
const used = new Set();
|
|
572
|
+
const has = (name) => existsSync(new URL(`${PHOSPHOR}regular/${name}.svg`, root));
|
|
573
|
+
// The CMS's code (also when it is in node_modules/) and the site's, without the packages inside either.
|
|
574
|
+
const files = [pkg, new URL('src/', root)].flatMap((dir) =>
|
|
575
|
+
readdirSync(fileURLToPath(dir), { recursive: true, withFileTypes: true })
|
|
576
|
+
.filter(
|
|
577
|
+
(e) => e.isFile() && /\.(tsx?|mjs|astro)$/.test(e.name) && !relative(fileURLToPath(dir), e.parentPath).includes('node_modules'),
|
|
578
|
+
)
|
|
579
|
+
.map((e) => join(e.parentPath, e.name)),
|
|
580
|
+
);
|
|
581
|
+
for (const file of files) {
|
|
582
|
+
const code = readFileSync(file, 'utf8');
|
|
583
|
+
for (const [, names] of code.matchAll(/import\s*\{([^}]*)\}\s*from\s*'@phosphor-icons\/react'/g))
|
|
584
|
+
for (const part of names.split(',')) {
|
|
585
|
+
const name = part
|
|
586
|
+
.trim()
|
|
587
|
+
.split(/\s+as\s+/)[0]
|
|
588
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
589
|
+
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
|
|
590
|
+
.toLowerCase();
|
|
591
|
+
if (has(name)) used.add(name);
|
|
592
|
+
}
|
|
593
|
+
for (const [, name] of code.matchAll(/@phosphor-icons\/core\/assets\/(?:regular|fill)\/([a-z0-9-]+)\.svg\?raw/g)) used.add(name);
|
|
594
|
+
for (const [, names] of code.matchAll(/\/node_modules\/@phosphor-icons\/core\/assets\/(?:regular|fill)\/\{([^}]*)\}\.svg/g))
|
|
595
|
+
for (const name of names.split(',')) used.add(name);
|
|
596
|
+
}
|
|
597
|
+
// The store's catalog (until the real store exists, this repository's own: `store` in src/site/config.ts).
|
|
598
|
+
const catalog = new URL('store/catalog.json', root);
|
|
599
|
+
if (existsSync(catalog))
|
|
600
|
+
JSON.parse(readFileSync(catalog, 'utf8'), (key, value) => {
|
|
601
|
+
if (key === 'icon' && typeof value === 'string' && /^[a-z0-9-]+$/.test(value) && has(value)) used.add(value);
|
|
602
|
+
return value;
|
|
603
|
+
});
|
|
604
|
+
return used;
|
|
605
|
+
}
|