@jant/core 0.6.16 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/bin/commands/assets/upload.js +192 -15
- package/bin/commands/import-site.js +60 -4
- package/bin/commands/reset-password.js +21 -8
- package/bin/commands/site/snapshot/export.js +1 -1
- package/bin/commands/site/snapshot/import.js +1 -1
- package/bin/lib/d1-query.js +5 -16
- package/bin/lib/node-env.js +40 -4
- package/bin/lib/site-selection.js +85 -29
- package/bin/lib/wrangler-cli.js +28 -2
- package/bin/lib/wrangler-json.js +35 -0
- package/dist/{app-C7_4oab9.js → app-K_Aa1MMn.js} +52476 -13330
- package/dist/client/.vite/manifest.json +255 -90
- package/dist/client/_assets/chunks/confirm-D7GrwsCN.js +45 -0
- package/dist/client/_assets/chunks/create-editor-CD3FhrOB.js +257 -0
- package/dist/client/_assets/chunks/{native-DpcrFAPh.js → emoji-mart-C4RpRKcU.js} +716 -1
- package/dist/client/_assets/chunks/footnote-rail-CmeoVtnU.js +1 -0
- package/dist/client/_assets/chunks/heic-to-CuP2Qlsw.js +1 -0
- package/dist/client/_assets/chunks/jant-locale-picker-DL6mIOT5.js +69 -0
- package/dist/client/_assets/chunks/lit-DW8VmJAT.js +2 -0
- package/dist/client/_assets/chunks/mediabunny-DRaCQ1r-.js +31 -0
- package/dist/client/_assets/chunks/rolldown-runtime-hePW80VL.js +1 -0
- package/dist/client/_assets/chunks/settings-paths-BcdySNx6.js +84 -0
- package/dist/client/_assets/chunks/site-header-nav-DzXsFk05.js +1 -0
- package/dist/client/_assets/chunks/slug-format-CRXO1AL5.js +1 -0
- package/dist/client/_assets/chunks/slugify-373citbs.js +1 -0
- package/dist/client/_assets/chunks/sortable-list-CgaL2jCs.js +2 -0
- package/dist/client/_assets/chunks/types-D5iF3H1a.js +1 -0
- package/dist/client/_assets/chunks/unsafe-html-B5ZEXaxg.js +1 -0
- package/dist/client/_assets/chunks/unsafe-svg-0QCkP0vZ.js +2 -0
- package/dist/client/_assets/client-GiYENVw8.css +2 -0
- package/dist/client/_assets/client-VnFxJN7G.js +295 -0
- package/dist/client/_assets/client-auth-k8gJ6QJj.js +828 -0
- package/dist/client/_assets/client-author-DQ8R-8KR.css +2 -0
- package/dist/client/_assets/client-compose-B_kDtWkW.js +2004 -0
- package/dist/client/_assets/client-manage-M90aSTOk.js +2170 -0
- package/dist/client/_assets/client-settings-DfYs9n1F.js +1112 -0
- package/dist/{export-Dl5KCiEs.js → github-sync-BPAvT999.js} +2254 -107
- package/dist/index.js +2 -5
- package/dist/node.js +5 -7
- package/package.json +3 -3
- package/src/__tests__/auth-session-freshness.test.ts +57 -0
- package/src/__tests__/basecoat-variants.test.ts +121 -0
- package/src/__tests__/bin/assets-upload.test.ts +68 -0
- package/src/__tests__/export-hugo-build.test.ts +260 -0
- package/src/__tests__/export-service.test.ts +231 -0
- package/src/__tests__/helpers/component-css.ts +91 -0
- package/src/__tests__/helpers/db.ts +33 -0
- package/src/__tests__/helpers/export-fixtures.ts +3 -0
- package/src/__tests__/stylesheet-audience.test.ts +159 -0
- package/src/__tests__/stylesheet-breakpoints.test.ts +183 -0
- package/src/app.tsx +71 -16
- package/src/auth.ts +18 -1
- package/src/client/__tests__/collection-page-actions.test.ts +51 -2
- package/src/client/__tests__/compose-bridge-image-upload.test.ts +196 -0
- package/src/client/__tests__/compose-bridge-video-poster.test.ts +159 -0
- package/src/client/__tests__/compose-bridge.test.ts +272 -0
- package/src/client/__tests__/compose-launch.test.ts +62 -1
- package/src/client/__tests__/compose-shortcuts.test.ts +38 -9
- package/src/client/__tests__/compose-triggers.test.ts +90 -0
- package/src/client/__tests__/copy-field.test.ts +162 -0
- package/src/client/__tests__/custom-url-menu.test.ts +127 -6
- package/src/client/__tests__/image-processor.test.ts +324 -2
- package/src/client/__tests__/lazy-entries.test.ts +92 -0
- package/src/client/__tests__/media-scroll-hint.test.ts +155 -0
- package/src/client/__tests__/runtime-paths.test.ts +84 -0
- package/src/client/__tests__/smart-collection-page-actions.test.ts +158 -0
- package/src/client/__tests__/toast.test.ts +23 -0
- package/src/client/__tests__/video-processor-probe.test.ts +175 -0
- package/src/client/__tests__/video-processor.test.ts +181 -0
- package/src/client/audio-processor.ts +24 -15
- package/src/client/audio-waveform.ts +49 -0
- package/src/client/collection-dialog-host.ts +72 -0
- package/src/client/collection-navigation.ts +51 -16
- package/src/client/collection-page-actions.ts +26 -0
- package/src/client/components/__tests__/jant-collection-dialog.test.ts +329 -0
- package/src/client/components/__tests__/jant-collection-directory.test.ts +274 -10
- package/src/client/components/__tests__/jant-collection-form.test.ts +59 -178
- package/src/client/components/__tests__/jant-command-palette.test.ts +28 -0
- package/src/client/components/__tests__/jant-compose-dialog-draft-storage.test.ts +340 -0
- package/src/client/components/__tests__/jant-compose-dialog.test.ts +1250 -53
- package/src/client/components/__tests__/jant-compose-editor.test.ts +544 -40
- package/src/client/components/__tests__/jant-compose-fullscreen.test.ts +0 -1
- package/src/client/components/__tests__/jant-locale-picker.test.ts +207 -0
- package/src/client/components/__tests__/jant-nav-manager.test.ts +234 -15
- package/src/client/components/__tests__/jant-post-menu.test.ts +413 -2
- package/src/client/components/__tests__/jant-post-picker.test.ts +197 -0
- package/src/client/components/__tests__/jant-settings-avatar.test.ts +15 -12
- package/src/client/components/__tests__/jant-settings-general.test.ts +541 -172
- package/src/client/components/__tests__/jant-settings-language.test.ts +851 -0
- package/src/client/components/__tests__/jant-smart-collection-dialog.test.ts +665 -0
- package/src/client/components/collection-dialog-types.ts +49 -0
- package/src/client/components/collection-manager-types.ts +32 -1
- package/src/client/components/collection-types.ts +1 -15
- package/src/client/components/compose-types.ts +75 -1
- package/src/client/components/jant-collection-dialog.ts +722 -0
- package/src/client/components/jant-collection-directory.ts +567 -182
- package/src/client/components/jant-collection-form.ts +53 -232
- package/src/client/components/jant-command-palette.ts +100 -49
- package/src/client/components/jant-compose-dialog.ts +1486 -707
- package/src/client/components/jant-compose-editor.ts +673 -336
- package/src/client/components/jant-compose-fullscreen.ts +51 -43
- package/src/client/components/jant-config-editor.ts +65 -53
- package/src/client/components/jant-confirm-dialog.ts +13 -11
- package/src/client/components/jant-locale-picker.ts +418 -0
- package/src/client/components/jant-media-lightbox.ts +146 -136
- package/src/client/components/jant-nav-manager.ts +690 -366
- package/src/client/components/jant-post-menu.ts +1086 -282
- package/src/client/components/jant-post-picker.ts +324 -0
- package/src/client/components/jant-repo-picker.ts +138 -106
- package/src/client/components/jant-settings-avatar.ts +31 -27
- package/src/client/components/jant-settings-general.ts +617 -543
- package/src/client/components/jant-settings-language.ts +1087 -0
- package/src/client/components/jant-smart-collection-dialog.ts +1021 -0
- package/src/client/components/jant-text-preview.ts +94 -86
- package/src/client/components/nav-manager-types.ts +62 -1
- package/src/client/components/settings-types.ts +14 -29
- package/src/client/components/smart-collection-conditions.ts +285 -0
- package/src/client/components/smart-collection-dialog-types.ts +68 -0
- package/src/client/compose-bridge.ts +214 -141
- package/src/client/compose-launch.ts +76 -2
- package/src/client/compose-shortcuts.ts +6 -8
- package/src/client/compose-triggers.ts +50 -0
- package/src/client/copy-field.ts +108 -0
- package/src/client/custom-url-menu.ts +60 -4
- package/src/client/icons.ts +14 -0
- package/src/client/image-plan.ts +165 -0
- package/src/client/image-processor.ts +195 -117
- package/src/client/image-worker-client.ts +45 -0
- package/src/client/image-worker.ts +135 -0
- package/src/client/lazy-entries.ts +95 -0
- package/src/client/lazy-slugify.ts +2 -2
- package/src/client/media-scroll-hint.ts +43 -2
- package/src/client/mediabunny.ts +29 -0
- package/src/client/post-picker.ts +41 -0
- package/src/client/runtime-paths.ts +74 -1
- package/src/client/settings-bridge.ts +4 -10
- package/src/client/site-header-nav.js +18 -6
- package/src/client/smart-collection-dialog-host.ts +116 -0
- package/src/client/smart-collection-page-actions.ts +208 -0
- package/src/client/tiptap/__tests__/bubble-menu.test.ts +110 -0
- package/src/client/tiptap/__tests__/floating-position.test.ts +136 -1
- package/src/client/tiptap/__tests__/inline-image-upload.test.ts +37 -0
- package/src/client/tiptap/bubble-menu.ts +47 -16
- package/src/client/tiptap/floating-position.ts +216 -2
- package/src/client/tiptap/inline-image-upload.ts +7 -3
- package/src/client/tiptap/link-toolbar.ts +22 -9
- package/src/client/toast.ts +13 -0
- package/src/client/types/vite-worker.d.ts +12 -0
- package/src/client/upload-with-metadata.ts +3 -13
- package/src/client/video-processor.ts +351 -107
- package/src/client-auth.ts +14 -31
- package/src/client-compose.ts +19 -0
- package/src/client-manage.ts +13 -0
- package/src/client-settings.ts +14 -0
- package/src/client-site.ts +10 -3
- package/src/client.ts +4 -0
- package/src/db/__tests__/backfill-nav-label-mirrors.test.ts +149 -0
- package/src/db/__tests__/schema-enum-sources.test.ts +33 -0
- package/src/db/__tests__/smart-collection-placement.test.ts +402 -0
- package/src/db/backfills/0006_clear_mirrored_page_nav_labels.sql +31 -0
- package/src/db/migrations/0032_married_tomas.sql +3 -0
- package/src/db/migrations/0033_busy_johnny_storm.sql +198 -0
- package/src/db/migrations/0034_cheerful_rumiko_fujikawa.sql +35 -0
- package/src/db/migrations/meta/0032_snapshot.json +2582 -0
- package/src/db/migrations/meta/0033_snapshot.json +2816 -0
- package/src/db/migrations/meta/0034_snapshot.json +2816 -0
- package/src/db/migrations/meta/_journal.json +21 -0
- package/src/db/migrations/pg/0030_abandoned_nighthawk.sql +3 -0
- package/src/db/migrations/pg/0031_strong_ultimatum.sql +128 -0
- package/src/db/migrations/pg/0032_furry_multiple_man.sql +6 -0
- package/src/db/migrations/pg/meta/0030_snapshot.json +3329 -0
- package/src/db/migrations/pg/meta/0031_snapshot.json +3660 -0
- package/src/db/migrations/pg/meta/0032_snapshot.json +3660 -0
- package/src/db/migrations/pg/meta/_journal.json +21 -0
- package/src/db/pg/schema.ts +195 -27
- package/src/db/post-visibility.ts +117 -0
- package/src/db/schema.ts +222 -27
- package/src/i18n/__tests__/detect.test.ts +26 -81
- package/src/i18n/__tests__/supported-locales.test.ts +83 -0
- package/src/i18n/context.tsx +12 -2
- package/src/i18n/detect.ts +7 -66
- package/src/i18n/locales/glossary.zh-Hans.yml +44 -4
- package/src/i18n/locales/glossary.zh-Hant.yml +44 -4
- package/src/i18n/locales/public/en.po +490 -158
- package/src/i18n/locales/public/en.ts +1 -1
- package/src/i18n/locales/public/zh-Hans.po +487 -155
- package/src/i18n/locales/public/zh-Hans.ts +1 -1
- package/src/i18n/locales/public/zh-Hant.po +487 -155
- package/src/i18n/locales/public/zh-Hant.ts +1 -1
- package/src/i18n/locales/settings/en.po +551 -69
- package/src/i18n/locales/settings/en.ts +1 -1
- package/src/i18n/locales/settings/zh-Hans.po +597 -115
- package/src/i18n/locales/settings/zh-Hans.ts +1 -1
- package/src/i18n/locales/settings/zh-Hant.po +610 -128
- package/src/i18n/locales/settings/zh-Hant.ts +1 -1
- package/src/i18n/locales.ts +94 -0
- package/src/i18n/middleware.ts +12 -2
- package/src/i18n/supported-locales.ts +80 -0
- package/src/lib/__tests__/api-settings.test.ts +11 -2
- package/src/lib/__tests__/asset-path.test.ts +92 -0
- package/src/lib/__tests__/deferred.test.ts +90 -0
- package/src/lib/__tests__/discover-ping.test.ts +89 -0
- package/src/lib/__tests__/discover.test.ts +410 -0
- package/src/lib/__tests__/feed-policy.test.ts +26 -0
- package/src/lib/__tests__/feed.test.ts +1526 -15
- package/src/lib/__tests__/filter-dimensions.test.ts +341 -0
- package/src/lib/__tests__/hosted-signin.test.ts +1 -1
- package/src/lib/__tests__/http-cache.test.ts +162 -0
- package/src/lib/__tests__/jant-docs-dev.test.ts +21 -0
- package/src/lib/__tests__/jant-docs.test.ts +23 -0
- package/src/lib/__tests__/lang-detect.test.ts +231 -0
- package/src/lib/__tests__/media-helpers.test.ts +81 -0
- package/src/lib/__tests__/navigation.test.ts +135 -1
- package/src/lib/__tests__/resolve-config.test.ts +64 -3
- package/src/lib/__tests__/schemas.test.ts +42 -4
- package/src/lib/__tests__/site-unavailable-page.test.ts +25 -0
- package/src/lib/__tests__/slug.test.ts +70 -0
- package/src/lib/__tests__/slugify.test.ts +85 -0
- package/src/lib/__tests__/storage.test.ts +32 -0
- package/src/lib/__tests__/thread-fold.test.ts +113 -0
- package/src/lib/__tests__/upload-sideload.test.ts +14 -0
- package/src/lib/__tests__/url-fetch.test.ts +1 -2
- package/src/lib/__tests__/url.test.ts +78 -72
- package/src/lib/__tests__/view-language.test.ts +413 -0
- package/src/lib/__tests__/worker-response-cache.test.ts +90 -0
- package/src/lib/address.ts +57 -0
- package/src/lib/api-posts.ts +12 -0
- package/src/lib/asset-path.ts +98 -1
- package/src/lib/build-env.ts +16 -0
- package/src/lib/collection-groups.ts +5 -1
- package/src/lib/collection-paths.ts +3 -10
- package/src/lib/constants.ts +28 -3
- package/src/lib/copy-field.ts +36 -0
- package/src/lib/crypto.ts +40 -0
- package/src/lib/csp-builder.ts +2 -1
- package/src/lib/deferred.ts +79 -0
- package/src/lib/discover-ping.ts +141 -0
- package/src/lib/discover.ts +437 -0
- package/src/lib/env.ts +134 -0
- package/src/lib/errors.ts +33 -0
- package/src/lib/feed-policy.ts +236 -2
- package/src/lib/feed.ts +926 -73
- package/src/lib/filter-dimensions.ts +1349 -0
- package/src/lib/github-sync-site-config.ts +3 -0
- package/src/lib/hosted-signin.ts +1 -1
- package/src/lib/http-cache.ts +148 -0
- package/src/lib/hugo-markdown.ts +16 -0
- package/src/lib/icons.ts +9 -2
- package/src/lib/ids.ts +3 -0
- package/src/lib/jant-docs.ts +42 -0
- package/src/lib/lang-detect.ts +308 -0
- package/src/lib/media-helpers.ts +13 -1
- package/src/lib/navigation.ts +78 -11
- package/src/lib/pagination.ts +28 -24
- package/src/lib/per-language-surfaces.ts +67 -0
- package/src/lib/post-meta.ts +19 -0
- package/src/lib/render.tsx +55 -7
- package/src/lib/resolve-config.ts +53 -5
- package/src/lib/schemas.ts +201 -10
- package/src/lib/site-header-fragment.tsx +2 -1
- package/src/lib/site-unavailable-page.ts +47 -0
- package/src/lib/slug.ts +51 -7
- package/src/lib/slugify.ts +113 -0
- package/src/lib/startup-config.ts +4 -6
- package/src/lib/storage.ts +7 -0
- package/src/lib/summary.ts +50 -0
- package/src/lib/thread-fold.ts +161 -0
- package/src/lib/time.ts +32 -0
- package/src/lib/timeline.ts +42 -1
- package/src/lib/tiptap-render.ts +1 -2
- package/src/lib/upload.ts +16 -13
- package/src/lib/url.ts +139 -86
- package/src/lib/version.ts +10 -8
- package/src/lib/view-language.ts +436 -0
- package/src/lib/view.ts +51 -23
- package/src/lib/viewer-context.ts +62 -0
- package/src/middleware/__tests__/auth.test.ts +70 -2
- package/src/middleware/__tests__/cache-control.test.ts +71 -3
- package/src/middleware/__tests__/onboarding.test.ts +76 -5
- package/src/middleware/__tests__/secure-headers.test.ts +1 -1
- package/src/middleware/__tests__/session.test.ts +181 -33
- package/src/middleware/auth.ts +50 -31
- package/src/middleware/cache-control.ts +75 -10
- package/src/middleware/config.ts +6 -6
- package/src/middleware/error-handler.ts +12 -0
- package/src/middleware/onboarding.ts +32 -10
- package/src/middleware/secure-headers.ts +1 -1
- package/src/middleware/session.ts +96 -8
- package/src/node/__tests__/cli-migrate.test.ts +21 -19
- package/src/node/__tests__/cli-reset-password.test.ts +81 -8
- package/src/node/__tests__/cli-runtime-target.test.ts +48 -1
- package/src/node/__tests__/cli-site-selection.test.ts +128 -38
- package/src/node/__tests__/runtime.test.ts +37 -0
- package/src/node/index.ts +1 -0
- package/src/preset.css +76 -22
- package/src/routes/__tests__/feed-validator.test.ts +156 -0
- package/src/routes/api/__tests__/collections.test.ts +114 -0
- package/src/routes/api/__tests__/discover.test.ts +222 -0
- package/src/routes/api/__tests__/nav-items.test.ts +212 -2
- package/src/routes/api/__tests__/post-translations.test.ts +829 -0
- package/src/routes/api/__tests__/settings.test.ts +24 -3
- package/src/routes/api/__tests__/telegram.test.ts +6 -5
- package/src/routes/api/collections.ts +49 -6
- package/src/routes/api/custom-urls.ts +0 -1
- package/src/routes/api/discover.ts +95 -0
- package/src/routes/api/export.ts +3 -0
- package/src/routes/api/internal/__tests__/sites.test.ts +42 -2
- package/src/routes/api/nav-items.ts +55 -8
- package/src/routes/api/posts.ts +159 -0
- package/src/routes/api/public/__tests__/archive.test.ts +111 -0
- package/src/routes/api/public/archive.ts +77 -81
- package/src/routes/api/public/posts.ts +23 -6
- package/src/routes/api/smart-collections.ts +132 -0
- package/src/routes/api/telegram.ts +2 -40
- package/src/routes/api/uploads.ts +1 -2
- package/src/routes/auth/__tests__/setup-auth.test.ts +137 -0
- package/src/routes/auth/__tests__/setup-discover.test.ts +204 -0
- package/src/routes/auth/__tests__/setup-flow.test.ts +270 -0
- package/src/routes/auth/__tests__/setup-page.test.tsx +329 -0
- package/src/routes/auth/__tests__/setup-steps.test.ts +310 -0
- package/src/routes/auth/__tests__/setup.test.ts +278 -26
- package/src/routes/auth/__tests__/signin.test.ts +135 -0
- package/src/routes/auth/setup.tsx +934 -186
- package/src/routes/auth/signin.tsx +10 -8
- package/src/routes/compose.tsx +5 -0
- package/src/routes/dash/__tests__/custom-urls-archive.test.ts +44 -0
- package/src/routes/dash/__tests__/custom-urls-page.test.ts +49 -0
- package/src/routes/dash/__tests__/delete-account.test.ts +106 -0
- package/src/routes/dash/__tests__/settings-discover.test.ts +213 -0
- package/src/routes/dash/custom-urls.tsx +1 -37
- package/src/routes/dash/settings.tsx +502 -41
- package/src/routes/discover-announce.ts +96 -0
- package/src/routes/feed/__tests__/feed.test.ts +165 -2
- package/src/routes/feed/feed.ts +69 -40
- package/src/routes/feed/sitemap.ts +95 -11
- package/src/routes/pages/__tests__/archive-indexing.test.ts +200 -0
- package/src/routes/pages/__tests__/archive-params.test.ts +370 -6
- package/src/routes/pages/__tests__/collection-routing.test.ts +16 -0
- package/src/routes/pages/__tests__/collections-feed-links.test.ts +72 -0
- package/src/routes/pages/__tests__/collections.test.ts +9 -3
- package/src/routes/pages/__tests__/custom-archive-url.test.ts +119 -0
- package/src/routes/pages/__tests__/feed-autodiscovery.test.ts +148 -0
- package/src/routes/pages/__tests__/language-routing.test.ts +679 -0
- package/src/routes/pages/__tests__/post-preview-partial.test.ts +96 -0
- package/src/routes/pages/__tests__/smart-collection.test.ts +298 -0
- package/src/routes/pages/__tests__/subscribe.test.ts +248 -0
- package/src/routes/pages/archive.tsx +471 -369
- package/src/routes/pages/collection.tsx +94 -96
- package/src/routes/pages/collections.tsx +38 -50
- package/src/routes/pages/featured.tsx +32 -13
- package/src/routes/pages/home.tsx +25 -6
- package/src/routes/pages/language.tsx +113 -0
- package/src/routes/pages/latest.tsx +26 -16
- package/src/routes/pages/new.tsx +3 -0
- package/src/routes/pages/page.tsx +178 -17
- package/src/routes/pages/partials.tsx +41 -0
- package/src/routes/pages/search.tsx +18 -3
- package/src/routes/pages/smart-collection.tsx +340 -0
- package/src/routes/pages/subscribe.tsx +182 -0
- package/src/runtime/__tests__/index.test.ts +19 -0
- package/src/runtime/__tests__/node.test.ts +129 -4
- package/src/runtime/cloudflare.ts +21 -2
- package/src/runtime/index.ts +27 -1
- package/src/runtime/node.ts +18 -1
- package/src/runtime/site.ts +95 -24
- package/src/services/__tests__/auth.test.ts +116 -7
- package/src/services/__tests__/collection.test.ts +108 -4
- package/src/services/__tests__/language.test.ts +495 -0
- package/src/services/__tests__/navigation.test.ts +213 -10
- package/src/services/__tests__/path.test.ts +180 -0
- package/src/services/__tests__/post-language.test.ts +830 -0
- package/src/services/__tests__/post.test.ts +46 -9
- package/src/services/__tests__/settings.test.ts +228 -17
- package/src/services/__tests__/site-admin.test.ts +5 -5
- package/src/services/__tests__/smart-collection.test.ts +651 -0
- package/src/services/about-page.ts +22 -1
- package/src/services/auth.ts +51 -49
- package/src/services/bootstrap.ts +188 -38
- package/src/services/collection-directory-position.ts +76 -0
- package/src/services/collection.ts +331 -46
- package/src/services/custom-url.ts +27 -22
- package/src/services/export-theme/assets/client-site.css +1 -1
- package/src/services/export-theme/assets/client-site.js +123 -123
- package/src/services/export-theme/layouts/_default/rss.xml +77 -1
- package/src/services/export-theme/layouts/partials/feed-post-content.xml +105 -2
- package/src/services/export-theme/layouts/partials/media-gallery.html +35 -21
- package/src/services/export-theme/layouts/partials/pagination.html +14 -13
- package/src/services/export-theme/layouts/partials/post-card.html +8 -4
- package/src/services/export-theme/layouts/partials/reply.html +2 -1
- package/src/services/export-theme/layouts/partials/thread-preview.html +40 -30
- package/src/services/export-theme/styles/main.css +13 -1
- package/src/services/export.ts +278 -19
- package/src/services/index.ts +34 -3
- package/src/services/language.ts +412 -0
- package/src/services/mcp.ts +3 -1
- package/src/services/media.ts +14 -6
- package/src/services/navigation.ts +429 -67
- package/src/services/path.ts +221 -6
- package/src/services/post.ts +1021 -152
- package/src/services/search.ts +39 -2
- package/src/services/settings.ts +238 -43
- package/src/services/site-admin.ts +24 -7
- package/src/services/site.ts +77 -1
- package/src/services/smart-collection.ts +636 -0
- package/src/services/telegram.ts +20 -22
- package/src/services/upload-session.ts +1 -3
- package/src/style-author.css +27 -0
- package/src/styles/components-author.css +1622 -0
- package/src/styles/components.css +24 -1571
- package/src/styles/site-media.css +16 -2
- package/src/styles/tokens.css +82 -12
- package/src/styles/ui-author.css +7602 -0
- package/src/styles/ui.css +1087 -7219
- package/src/types/app-context.ts +7 -0
- package/src/types/bindings.ts +3 -0
- package/src/types/config.ts +94 -15
- package/src/types/constants.ts +188 -16
- package/src/types/entities.ts +87 -1
- package/src/types/operations.ts +64 -2
- package/src/types/props.ts +157 -31
- package/src/types/views.ts +55 -1
- package/src/ui/__tests__/font-themes.test.ts +52 -12
- package/src/ui/compose/ComposeDialog.tsx +201 -7
- package/src/ui/compose/ComposePrompt.tsx +1 -5
- package/src/ui/compose/__tests__/ComposeDialog.test.tsx +125 -0
- package/src/ui/dash/appearance/AdvancedContent.tsx +2 -2
- package/src/ui/dash/appearance/CodeInjectionContent.tsx +12 -16
- package/src/ui/dash/appearance/NavigationContent.tsx +117 -16
- package/src/ui/dash/appearance/__tests__/NavigationContent.test.tsx +33 -11
- package/src/ui/dash/appearance/__tests__/system-nav-descriptions.test.ts +44 -0
- package/src/ui/dash/appearance/system-nav-descriptions.ts +75 -0
- package/src/ui/dash/settings/AccountMenuContent.tsx +2 -2
- package/src/ui/dash/settings/ApiTokensContent.tsx +2 -1
- package/src/ui/dash/settings/ConfigEditorContent.tsx +35 -16
- package/src/ui/dash/settings/GeneralContent.tsx +275 -113
- package/src/ui/dash/settings/LanguageContent.tsx +409 -0
- package/src/ui/dash/settings/SettingsRootContent.tsx +19 -1
- package/src/ui/dash/settings/__tests__/GeneralContent.test.tsx +324 -4
- package/src/ui/dash/settings/__tests__/LanguageContent.test.tsx +144 -0
- package/src/ui/dash/settings/__tests__/discover-copy.test.ts +66 -0
- package/src/ui/dash/settings/discover-copy.ts +116 -0
- package/src/ui/feed/LinkCard.tsx +55 -45
- package/src/ui/feed/NoteCard.tsx +9 -4
- package/src/ui/feed/PostStatusBadges.tsx +90 -43
- package/src/ui/feed/QuoteCard.tsx +55 -30
- package/src/ui/feed/ThreadPreview.tsx +6 -2
- package/src/ui/feed/__tests__/thread-preview.test.ts +13 -16
- package/src/ui/feed/__tests__/timeline-cards.test.ts +314 -49
- package/src/ui/feed/thread-preview-state.ts +20 -6
- package/src/ui/font-themes.ts +39 -29
- package/src/ui/layouts/BaseLayout.tsx +155 -10
- package/src/ui/layouts/SiteLayout.tsx +192 -34
- package/src/ui/layouts/__tests__/BaseLayout.test.tsx +196 -17
- package/src/ui/layouts/__tests__/SiteLayout.test.tsx +109 -85
- package/src/ui/pages/ArchivePage.tsx +282 -289
- package/src/ui/pages/CollectionPage.tsx +86 -76
- package/src/ui/pages/CollectionsPage.tsx +5 -0
- package/src/ui/pages/ComposePage.tsx +8 -0
- package/src/ui/pages/PostPage.tsx +47 -0
- package/src/ui/pages/SearchPage.tsx +3 -3
- package/src/ui/pages/SmartCollectionPage.tsx +434 -0
- package/src/ui/pages/SubscribePage.tsx +236 -0
- package/src/ui/pages/__tests__/ArchivePage.test.tsx +65 -9
- package/src/ui/pages/__tests__/collections-directory-rows.test.tsx +92 -0
- package/src/ui/pages/__tests__/collections-view-links.test.tsx +81 -0
- package/src/ui/shared/CollectionDirectory.tsx +178 -3
- package/src/ui/shared/CollectionsManager.tsx +70 -17
- package/src/ui/shared/CopyField.tsx +127 -0
- package/src/ui/shared/EmptyPostContent.tsx +23 -0
- package/src/ui/shared/MediaGallery.tsx +125 -46
- package/src/ui/shared/Pagination.tsx +20 -5
- package/src/ui/shared/PostFooter.tsx +20 -11
- package/src/ui/shared/__tests__/archive-labels.test.ts +100 -0
- package/src/ui/shared/__tests__/media-gallery.test.ts +210 -2
- package/src/ui/shared/__tests__/navigation-labels.test.ts +16 -22
- package/src/ui/shared/__tests__/pagination.test.ts +38 -24
- package/src/ui/shared/__tests__/post-footer.test.ts +32 -0
- package/src/ui/shared/archive-labels.ts +98 -0
- package/src/ui/shared/collection-management-labels.ts +94 -16
- package/src/ui/shared/navigation-labels.ts +45 -71
- package/src/ui/shared/post-article-attributes.ts +2 -0
- package/src/ui/shared/smart-collection-labels.ts +343 -0
- package/dist/app-C75Zc8dD.js +0 -6
- package/dist/client/_assets/chunks/heic-to-DUUaO23q.js +0 -1
- package/dist/client/_assets/chunks/module-DcsAZQZ_.js +0 -716
- package/dist/client/_assets/chunks/url-CU9pEbk5.js +0 -1
- package/dist/client/_assets/client-Bq0vre8Y.js +0 -296
- package/dist/client/_assets/client-D3VZyG4L.css +0 -2
- package/dist/client/_assets/client-auth-F2rb9WfF.js +0 -5571
- package/dist/env-BPYViDJJ.js +0 -281
- package/dist/github-api-BNF35Lkx.js +0 -176
- package/dist/github-app-DdiD-bC4.js +0 -275
- package/dist/github-sync-Bqg62IvV.js +0 -4
- package/dist/github-sync-HdK2EgvJ.js +0 -431
- package/dist/url-CbLAtlZe.js +0 -900
- package/src/client/__tests__/collection-created-notice.test.ts +0 -36
- package/src/client/__tests__/collection-form-bridge.test.ts +0 -216
- package/src/client/__tests__/post-form-bridge.test.ts +0 -82
- package/src/client/collection-created-notice.ts +0 -66
- package/src/client/collection-form-bridge.ts +0 -191
- package/src/client/components/__tests__/jant-post-form.test.ts +0 -193
- package/src/client/components/jant-post-form.ts +0 -422
- package/src/client/components/post-form-template.ts +0 -352
- package/src/client/components/post-form-types.ts +0 -96
- package/src/client/media-metadata.ts +0 -247
- package/src/client/post-form-bridge.ts +0 -193
- package/src/ui/pages/CollectionEditorPage.tsx +0 -175
|
@@ -13,12 +13,27 @@ import type { FC } from "hono/jsx";
|
|
|
13
13
|
import { MAX_THREAD_POSTS, type Collection } from "../../types.js";
|
|
14
14
|
import { useLingui } from "../../i18n/context.js";
|
|
15
15
|
import { getCollectionFormLabels } from "../shared/collection-management-labels.js";
|
|
16
|
-
import type {
|
|
16
|
+
import type {
|
|
17
|
+
ComposeLabels,
|
|
18
|
+
ComposeLanguage,
|
|
19
|
+
} from "../../client/components/compose-types.js";
|
|
17
20
|
|
|
18
21
|
export interface ComposeDialogProps {
|
|
19
22
|
collections?: Collection[];
|
|
20
23
|
uploadMaxFileSize?: number;
|
|
21
24
|
slashCommandDiscovered?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Languages the site publishes. Empty on a single-language site, and the
|
|
27
|
+
* composer then shows no language UI at all — an author who never turned
|
|
28
|
+
* multilingual content on should not meet it.
|
|
29
|
+
*/
|
|
30
|
+
languages?: ComposeLanguage[];
|
|
31
|
+
/**
|
|
32
|
+
* Content language of the page the composer opens from. A post left on
|
|
33
|
+
* automatic publishes in this language until detection reads the writing as
|
|
34
|
+
* another one, which the composer says on the button beside Post.
|
|
35
|
+
*/
|
|
36
|
+
contextLanguage?: string | null;
|
|
22
37
|
}
|
|
23
38
|
|
|
24
39
|
export interface ComposeFormProps extends ComposeDialogProps {
|
|
@@ -31,6 +46,8 @@ export const ComposeForm: FC<ComposeFormProps> = ({
|
|
|
31
46
|
collections,
|
|
32
47
|
uploadMaxFileSize,
|
|
33
48
|
slashCommandDiscovered = false,
|
|
49
|
+
languages,
|
|
50
|
+
contextLanguage,
|
|
34
51
|
pageMode = false,
|
|
35
52
|
closeHref,
|
|
36
53
|
autoRestoreDraft = false,
|
|
@@ -41,7 +58,15 @@ export const ComposeForm: FC<ComposeFormProps> = ({
|
|
|
41
58
|
cancel: i18n._(
|
|
42
59
|
msg({
|
|
43
60
|
message: "Cancel",
|
|
44
|
-
comment:
|
|
61
|
+
comment:
|
|
62
|
+
"@context: Back out of the attached-text sub-editor, paired with Done. Leaving the composer itself says Close instead — it may keep the work as a draft, so nothing is being cancelled.",
|
|
63
|
+
}),
|
|
64
|
+
),
|
|
65
|
+
close: i18n._(
|
|
66
|
+
msg({
|
|
67
|
+
message: "Close",
|
|
68
|
+
comment:
|
|
69
|
+
"@context: Leaves the composer — the × on a single post, and the button in a thread. Prompts to save a draft first if there is unsaved work.",
|
|
45
70
|
}),
|
|
46
71
|
),
|
|
47
72
|
imageNotRehosted: i18n._(
|
|
@@ -322,12 +347,39 @@ export const ComposeForm: FC<ComposeFormProps> = ({
|
|
|
322
347
|
comment: "@context: Button to remove an uploaded attachment in compose",
|
|
323
348
|
}),
|
|
324
349
|
),
|
|
350
|
+
moveAttachmentEarlier: i18n._(
|
|
351
|
+
msg({
|
|
352
|
+
message: "Move attachment earlier",
|
|
353
|
+
comment:
|
|
354
|
+
"@context: Button that moves an attachment one place toward the start in compose",
|
|
355
|
+
}),
|
|
356
|
+
),
|
|
357
|
+
moveAttachmentLater: i18n._(
|
|
358
|
+
msg({
|
|
359
|
+
message: "Move attachment later",
|
|
360
|
+
comment:
|
|
361
|
+
"@context: Button that moves an attachment one place toward the end in compose",
|
|
362
|
+
}),
|
|
363
|
+
),
|
|
325
364
|
uploading: i18n._(
|
|
326
365
|
msg({
|
|
327
366
|
message: "Uploading...",
|
|
328
367
|
comment: "@context: Toast shown during background upload",
|
|
329
368
|
}),
|
|
330
369
|
),
|
|
370
|
+
publishing: i18n._(
|
|
371
|
+
msg({
|
|
372
|
+
message: "Publishing...",
|
|
373
|
+
comment: "@context: Toast shown while a post is being published",
|
|
374
|
+
}),
|
|
375
|
+
),
|
|
376
|
+
saving: i18n._(
|
|
377
|
+
msg({
|
|
378
|
+
message: "Saving...",
|
|
379
|
+
comment:
|
|
380
|
+
"@context: Toast shown while a draft or an edited post is being saved",
|
|
381
|
+
}),
|
|
382
|
+
),
|
|
331
383
|
loadingPost: i18n._(
|
|
332
384
|
msg({
|
|
333
385
|
message: "Loading post...",
|
|
@@ -391,9 +443,9 @@ export const ComposeForm: FC<ComposeFormProps> = ({
|
|
|
391
443
|
),
|
|
392
444
|
confirmCloseCancel: i18n._(
|
|
393
445
|
msg({
|
|
394
|
-
message: "
|
|
446
|
+
message: "Keep editing",
|
|
395
447
|
comment:
|
|
396
|
-
"@context: Confirm close action sheet -
|
|
448
|
+
"@context: Confirm close action sheet - dismiss the sheet and return to the editor. Says what it does rather than 'Cancel', which the composer already spends on leaving.",
|
|
397
449
|
}),
|
|
398
450
|
),
|
|
399
451
|
confirmCloseDiscard: i18n._(
|
|
@@ -510,6 +562,20 @@ export const ComposeForm: FC<ComposeFormProps> = ({
|
|
|
510
562
|
"@context: Toast when publish fails and post is auto-saved as draft",
|
|
511
563
|
}),
|
|
512
564
|
),
|
|
565
|
+
publishFailed: i18n._(
|
|
566
|
+
msg({
|
|
567
|
+
message: "Couldn't publish. Try again.",
|
|
568
|
+
comment:
|
|
569
|
+
"@context: Toast when publish fails and the server gave no reason",
|
|
570
|
+
}),
|
|
571
|
+
),
|
|
572
|
+
publishFailedOffline: i18n._(
|
|
573
|
+
msg({
|
|
574
|
+
message: "Couldn't reach the server. Try again.",
|
|
575
|
+
comment:
|
|
576
|
+
"@context: Toast when a publish request never reached the server",
|
|
577
|
+
}),
|
|
578
|
+
),
|
|
513
579
|
uploadFailedDraft: i18n._(
|
|
514
580
|
msg({
|
|
515
581
|
message: "Some uploads failed. Saved as draft.",
|
|
@@ -795,11 +861,11 @@ export const ComposeForm: FC<ComposeFormProps> = ({
|
|
|
795
861
|
"@context: Toast shown when a local draft is restored on compose open",
|
|
796
862
|
}),
|
|
797
863
|
),
|
|
798
|
-
|
|
864
|
+
draftStoreFailed: i18n._(
|
|
799
865
|
msg({
|
|
800
|
-
message: "
|
|
866
|
+
message: "This browser can't keep a local copy. Save as a draft.",
|
|
801
867
|
comment:
|
|
802
|
-
"@context:
|
|
868
|
+
"@context: Toast shown when the composer cannot write its local draft to browser storage",
|
|
803
869
|
}),
|
|
804
870
|
),
|
|
805
871
|
editing: i18n._(
|
|
@@ -897,10 +963,132 @@ export const ComposeForm: FC<ComposeFormProps> = ({
|
|
|
897
963
|
}),
|
|
898
964
|
),
|
|
899
965
|
},
|
|
966
|
+
languageLabel: i18n._(
|
|
967
|
+
msg({
|
|
968
|
+
message: "Language",
|
|
969
|
+
comment: "@context: Compose field for the post's content language",
|
|
970
|
+
}),
|
|
971
|
+
),
|
|
972
|
+
languageAuto: i18n._(
|
|
973
|
+
msg({
|
|
974
|
+
message: "Detect",
|
|
975
|
+
comment:
|
|
976
|
+
"@context: Compose language option that leaves detection to Jant",
|
|
977
|
+
}),
|
|
978
|
+
),
|
|
979
|
+
languageAutoHint: i18n._(
|
|
980
|
+
msg({
|
|
981
|
+
message: "Read from what you write",
|
|
982
|
+
comment: "@context: Help text under the compose language field",
|
|
983
|
+
}),
|
|
984
|
+
),
|
|
985
|
+
languageAutoDetected: i18n._(
|
|
986
|
+
msg({
|
|
987
|
+
message: "Read from what you write — looks like {language}",
|
|
988
|
+
comment:
|
|
989
|
+
"@context: Help text under the compose language field once a language has been detected",
|
|
990
|
+
}),
|
|
991
|
+
// Detected in the browser from the current text; see `translationOf`.
|
|
992
|
+
{ language: "{language}" },
|
|
993
|
+
),
|
|
994
|
+
languageAutoPending: i18n._(
|
|
995
|
+
msg({
|
|
996
|
+
message: "Not enough text to tell yet — publishes in {language}",
|
|
997
|
+
comment:
|
|
998
|
+
"@context: Help text under the compose language field before there is enough writing to read a language out of; {language} is the one it would publish in meanwhile, which is the language of the page the composer was opened from",
|
|
999
|
+
}),
|
|
1000
|
+
// Only known in the browser; see `translationOf`.
|
|
1001
|
+
{ language: "{language}" },
|
|
1002
|
+
),
|
|
1003
|
+
languageTriggerLabel: i18n._(
|
|
1004
|
+
msg({
|
|
1005
|
+
message: "Language: {language}",
|
|
1006
|
+
comment:
|
|
1007
|
+
"@context: Accessible name of the composer's language button, which sits beside Post and names the language this post would publish in",
|
|
1008
|
+
}),
|
|
1009
|
+
// Filled in the browser with whichever language that is; see
|
|
1010
|
+
// `translationOf`.
|
|
1011
|
+
{ language: "{language}" },
|
|
1012
|
+
),
|
|
1013
|
+
translationOf: i18n._(
|
|
1014
|
+
msg({
|
|
1015
|
+
message: "Translation of “{title}”",
|
|
1016
|
+
comment:
|
|
1017
|
+
"@context: Compose banner shown while writing a translation of an existing post",
|
|
1018
|
+
}),
|
|
1019
|
+
// The post being translated is only known in the browser, and Lingui
|
|
1020
|
+
// resolves an ICU message completely at `i18n._()` time — formatted with
|
|
1021
|
+
// no value, this slot would come out empty. Passing the placeholder back
|
|
1022
|
+
// as the value leaves it intact for the component to fill.
|
|
1023
|
+
{ title: "{title}" },
|
|
1024
|
+
),
|
|
1025
|
+
translationContext: i18n._(
|
|
1026
|
+
msg({
|
|
1027
|
+
message: "Translating",
|
|
1028
|
+
comment:
|
|
1029
|
+
"@context: Divider between the original post and the editor writing its translation, when the target language is not known yet",
|
|
1030
|
+
}),
|
|
1031
|
+
),
|
|
1032
|
+
translationContextInLanguage: i18n._(
|
|
1033
|
+
msg({
|
|
1034
|
+
message: "Translating into {language}",
|
|
1035
|
+
comment:
|
|
1036
|
+
"@context: Divider between the original post above and the editor below, naming the language being written",
|
|
1037
|
+
}),
|
|
1038
|
+
// Filled in the browser from the chosen language; see `translationOf`.
|
|
1039
|
+
{ language: "{language}" },
|
|
1040
|
+
),
|
|
1041
|
+
translationContextOpen: i18n._(
|
|
1042
|
+
msg({
|
|
1043
|
+
message: "Open the original in a new tab",
|
|
1044
|
+
comment:
|
|
1045
|
+
"@context: Tooltip on the source post link above the compose editor while writing a translation",
|
|
1046
|
+
}),
|
|
1047
|
+
),
|
|
1048
|
+
translationContextOriginal: i18n._(
|
|
1049
|
+
msg({
|
|
1050
|
+
message: "The original",
|
|
1051
|
+
comment:
|
|
1052
|
+
"@context: Accessible name of the scrollable panel holding the post being translated",
|
|
1053
|
+
}),
|
|
1054
|
+
),
|
|
1055
|
+
translationContextHide: i18n._(
|
|
1056
|
+
msg({
|
|
1057
|
+
message: "Hide",
|
|
1058
|
+
comment:
|
|
1059
|
+
"@context: Button that folds away the original while writing its translation. Sits right after the words “Translating into …”, which is what makes it clear what gets hidden — the accessible name spells it out",
|
|
1060
|
+
}),
|
|
1061
|
+
),
|
|
1062
|
+
translationContextHideLong: i18n._(
|
|
1063
|
+
msg({
|
|
1064
|
+
message: "Hide the original",
|
|
1065
|
+
comment:
|
|
1066
|
+
"@context: Accessible name of the button that folds away the post being translated",
|
|
1067
|
+
}),
|
|
1068
|
+
),
|
|
1069
|
+
translationContextShow: i18n._(
|
|
1070
|
+
msg({
|
|
1071
|
+
message: "Show",
|
|
1072
|
+
comment:
|
|
1073
|
+
"@context: Button that brings back the folded-away original while writing its translation",
|
|
1074
|
+
}),
|
|
1075
|
+
),
|
|
1076
|
+
translationContextShowLong: i18n._(
|
|
1077
|
+
msg({
|
|
1078
|
+
message: "Show the original",
|
|
1079
|
+
comment:
|
|
1080
|
+
"@context: Accessible name of the button that brings back the folded-away post being translated",
|
|
1081
|
+
}),
|
|
1082
|
+
),
|
|
900
1083
|
collectionFormLabels: getCollectionFormLabels(i18n),
|
|
901
1084
|
} satisfies ComposeLabels;
|
|
902
1085
|
const labels = JSON.stringify(labelsObject).replace(/</g, "\\u003c");
|
|
903
1086
|
|
|
1087
|
+
const languagesJson = JSON.stringify(languages ?? []).replace(
|
|
1088
|
+
/</g,
|
|
1089
|
+
"\\u003c",
|
|
1090
|
+
);
|
|
1091
|
+
|
|
904
1092
|
const collectionsJson = JSON.stringify(
|
|
905
1093
|
(collections ?? []).map((c) => ({
|
|
906
1094
|
id: c.id,
|
|
@@ -912,6 +1100,8 @@ export const ComposeForm: FC<ComposeFormProps> = ({
|
|
|
912
1100
|
return (
|
|
913
1101
|
<jant-compose-dialog
|
|
914
1102
|
collections={collectionsJson}
|
|
1103
|
+
languages={languagesJson}
|
|
1104
|
+
{...(contextLanguage ? { "context-language": contextLanguage } : {})}
|
|
915
1105
|
labels={labels}
|
|
916
1106
|
upload-max-file-size={uploadMaxFileSize ?? 500}
|
|
917
1107
|
{...(pageMode ? { "page-mode": "" } : {})}
|
|
@@ -931,6 +1121,8 @@ export const ComposeDialog: FC<ComposeDialogProps> = ({
|
|
|
931
1121
|
collections,
|
|
932
1122
|
uploadMaxFileSize,
|
|
933
1123
|
slashCommandDiscovered = false,
|
|
1124
|
+
languages,
|
|
1125
|
+
contextLanguage,
|
|
934
1126
|
}) => {
|
|
935
1127
|
return (
|
|
936
1128
|
<dialog id="compose-dialog" class="compose-dialog">
|
|
@@ -938,6 +1130,8 @@ export const ComposeDialog: FC<ComposeDialogProps> = ({
|
|
|
938
1130
|
collections={collections}
|
|
939
1131
|
uploadMaxFileSize={uploadMaxFileSize}
|
|
940
1132
|
slashCommandDiscovered={slashCommandDiscovered}
|
|
1133
|
+
languages={languages}
|
|
1134
|
+
contextLanguage={contextLanguage}
|
|
941
1135
|
/>
|
|
942
1136
|
</dialog>
|
|
943
1137
|
);
|
|
@@ -25,11 +25,7 @@ export const ComposePrompt: FC<ComposePromptProps> = ({
|
|
|
25
25
|
composeOpenShortcutDiscovered ? "true" : "false"
|
|
26
26
|
}
|
|
27
27
|
>
|
|
28
|
-
<button
|
|
29
|
-
type="button"
|
|
30
|
-
class="compose-prompt-trigger"
|
|
31
|
-
data-on:click="document.getElementById('compose-dialog')?.querySelector('jant-compose-dialog')?.openNew()"
|
|
32
|
-
>
|
|
28
|
+
<button type="button" class="compose-prompt-trigger" data-compose-open>
|
|
33
29
|
<span class="compose-prompt-avatar">
|
|
34
30
|
<svg
|
|
35
31
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compose dialog labels.
|
|
3
|
+
*
|
|
4
|
+
* The composer fills two labels in the browser, from values only it knows: the
|
|
5
|
+
* post being translated and the detected language. Lingui resolves an ICU
|
|
6
|
+
* message completely at `i18n._()` time, so those slots have to be carried
|
|
7
|
+
* through deliberately — a label formatted with no value renders as an empty
|
|
8
|
+
* string, which reads as a missing title rather than as a bug.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { Context } from "hono";
|
|
12
|
+
import { renderToString } from "hono/jsx/dom/server";
|
|
13
|
+
import { describe, expect, it } from "vitest";
|
|
14
|
+
import { I18nProvider } from "../../../i18n/context.js";
|
|
15
|
+
import { createI18n } from "../../../i18n/i18n.js";
|
|
16
|
+
import { ComposeForm } from "../ComposeDialog.js";
|
|
17
|
+
|
|
18
|
+
function renderComposeLabels(): Record<string, string> {
|
|
19
|
+
const i18n = createI18n("en");
|
|
20
|
+
const c = {
|
|
21
|
+
get(key: string) {
|
|
22
|
+
return key === "i18n" ? i18n : undefined;
|
|
23
|
+
},
|
|
24
|
+
} as unknown as Context;
|
|
25
|
+
I18nProvider({ c, children: "" });
|
|
26
|
+
|
|
27
|
+
const html = renderToString(
|
|
28
|
+
ComposeForm({
|
|
29
|
+
languages: [
|
|
30
|
+
{ tag: "zh-Hans", label: "简体中文" },
|
|
31
|
+
{ tag: "en", label: "English" },
|
|
32
|
+
],
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const match = /labels="([^"]*)"/.exec(html);
|
|
37
|
+
if (!match?.[1]) throw new Error("expected a labels attribute");
|
|
38
|
+
const decoded = match[1]
|
|
39
|
+
.replace(/"/g, '"')
|
|
40
|
+
.replace(/&/g, "&")
|
|
41
|
+
.replace(/</g, "<")
|
|
42
|
+
.replace(/>/g, ">")
|
|
43
|
+
.replace(/'/g, "'");
|
|
44
|
+
return JSON.parse(decoded) as Record<string, string>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
describe("ComposeForm labels", () => {
|
|
48
|
+
it("leaves the slots the browser fills", () => {
|
|
49
|
+
const labels = renderComposeLabels();
|
|
50
|
+
|
|
51
|
+
expect(labels.translationOf).toContain("{title}");
|
|
52
|
+
expect(labels.translationContextInLanguage).toContain("{language}");
|
|
53
|
+
expect(labels.languageAutoDetected).toContain("{language}");
|
|
54
|
+
expect(labels.languageAutoPending).toContain("{language}");
|
|
55
|
+
expect(labels.languageTriggerLabel).toContain("{language}");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("never ships an unresolved ICU construct", () => {
|
|
59
|
+
for (const [key, value] of Object.entries(renderComposeLabels())) {
|
|
60
|
+
if (typeof value !== "string") continue;
|
|
61
|
+
expect(value, key).not.toContain("plural,");
|
|
62
|
+
expect(value, key).not.toContain("NaN");
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("passes the site's languages to the component", () => {
|
|
67
|
+
const i18n = createI18n("en");
|
|
68
|
+
const c = {
|
|
69
|
+
get(key: string) {
|
|
70
|
+
return key === "i18n" ? i18n : undefined;
|
|
71
|
+
},
|
|
72
|
+
} as unknown as Context;
|
|
73
|
+
I18nProvider({ c, children: "" });
|
|
74
|
+
|
|
75
|
+
const html = renderToString(
|
|
76
|
+
ComposeForm({
|
|
77
|
+
languages: [{ tag: "en", label: "English" }],
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
80
|
+
expect(html).toContain("languages=");
|
|
81
|
+
expect(html).toContain("English");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("hands the component the page's language as the automatic default", () => {
|
|
85
|
+
const i18n = createI18n("en");
|
|
86
|
+
const c = {
|
|
87
|
+
get(key: string) {
|
|
88
|
+
return key === "i18n" ? i18n : undefined;
|
|
89
|
+
},
|
|
90
|
+
} as unknown as Context;
|
|
91
|
+
I18nProvider({ c, children: "" });
|
|
92
|
+
|
|
93
|
+
const html = renderToString(
|
|
94
|
+
ComposeForm({
|
|
95
|
+
languages: [
|
|
96
|
+
{ tag: "zh-Hans", label: "简体中文" },
|
|
97
|
+
{ tag: "ja", label: "日本語" },
|
|
98
|
+
],
|
|
99
|
+
contextLanguage: "ja",
|
|
100
|
+
}),
|
|
101
|
+
);
|
|
102
|
+
expect(html).toContain('context-language="ja"');
|
|
103
|
+
|
|
104
|
+
// Without a page language the attribute stays off, and the component
|
|
105
|
+
// falls back to the primary language on its own.
|
|
106
|
+
expect(
|
|
107
|
+
renderToString(
|
|
108
|
+
ComposeForm({ languages: [{ tag: "en", label: "English" }] }),
|
|
109
|
+
),
|
|
110
|
+
).not.toContain("context-language");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("sends an empty list on a single-language site", () => {
|
|
114
|
+
const i18n = createI18n("en");
|
|
115
|
+
const c = {
|
|
116
|
+
get(key: string) {
|
|
117
|
+
return key === "i18n" ? i18n : undefined;
|
|
118
|
+
},
|
|
119
|
+
} as unknown as Context;
|
|
120
|
+
I18nProvider({ c, children: "" });
|
|
121
|
+
|
|
122
|
+
// The composer renders no language UI at all in that case.
|
|
123
|
+
expect(renderToString(ComposeForm({}))).toContain('languages="[]"');
|
|
124
|
+
});
|
|
125
|
+
});
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
import { msg } from "@lingui/core/macro";
|
|
6
6
|
import { useLingui } from "../../../i18n/context.js";
|
|
7
|
+
import { getJantDocsUrl } from "../../../lib/jant-docs.js";
|
|
7
8
|
import { toPublicPath } from "../../../lib/url.js";
|
|
8
9
|
|
|
9
|
-
const THEMING_DOCS_URL =
|
|
10
|
-
"https://github.com/jant-me/jant/blob/main/docs/theming.md";
|
|
10
|
+
const THEMING_DOCS_URL = getJantDocsUrl("theming");
|
|
11
11
|
|
|
12
12
|
export function AdvancedContent({
|
|
13
13
|
customCSS,
|
|
@@ -33,11 +33,7 @@ export function CodeInjectionContent({
|
|
|
33
33
|
data-indicator="_codeLoading"
|
|
34
34
|
class="max-w-form"
|
|
35
35
|
>
|
|
36
|
-
<div
|
|
37
|
-
role="note"
|
|
38
|
-
class="alert alert-destructive mb-6"
|
|
39
|
-
style="display:flex;gap:.75rem;align-items:flex-start"
|
|
40
|
-
>
|
|
36
|
+
<div role="note" class="alert-destructive mb-6">
|
|
41
37
|
<svg
|
|
42
38
|
xmlns="http://www.w3.org/2000/svg"
|
|
43
39
|
width="20"
|
|
@@ -54,16 +50,16 @@ export function CodeInjectionContent({
|
|
|
54
50
|
<path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" />
|
|
55
51
|
<path d="M12 17h.01" />
|
|
56
52
|
</svg>
|
|
57
|
-
<
|
|
58
|
-
|
|
59
|
-
{
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<p
|
|
53
|
+
<strong>
|
|
54
|
+
{i18n._(
|
|
55
|
+
msg({
|
|
56
|
+
message: "This code runs on every page of your site.",
|
|
57
|
+
comment: "@context: Code Injection security warning headline",
|
|
58
|
+
}),
|
|
59
|
+
)}
|
|
60
|
+
</strong>
|
|
61
|
+
<section>
|
|
62
|
+
<p>
|
|
67
63
|
{i18n._(
|
|
68
64
|
msg({
|
|
69
65
|
message:
|
|
@@ -72,7 +68,7 @@ export function CodeInjectionContent({
|
|
|
72
68
|
}),
|
|
73
69
|
)}
|
|
74
70
|
</p>
|
|
75
|
-
</
|
|
71
|
+
</section>
|
|
76
72
|
</div>
|
|
77
73
|
|
|
78
74
|
<fieldset class="mb-6">
|