@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
|
@@ -1,30 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Collection Form
|
|
2
|
+
* Collection Quick-Create Form
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* A title and an address, nothing else — the two things a collection cannot be
|
|
5
|
+
* created without. It exists for the places where creating a collection is a
|
|
6
|
+
* step inside another task: picking one while composing, or putting one in the
|
|
7
|
+
* navigation. Everything a collection *can* have is decided in the collection
|
|
8
|
+
* dialog, which is where an author who came to make a collection already is.
|
|
9
|
+
*
|
|
10
|
+
* Submitting dispatches `jant:collection-submit`; the surrounding dialog owns
|
|
11
|
+
* the request and what happens after it.
|
|
8
12
|
*
|
|
9
13
|
* Light DOM only — BaseCoat and Tailwind classes apply directly.
|
|
10
14
|
*/
|
|
11
15
|
|
|
12
16
|
import { LitElement, html, nothing } from "lit";
|
|
13
17
|
import type { PropertyValueMap } from "lit";
|
|
14
|
-
import type { Editor } from "@tiptap/core";
|
|
15
18
|
import {
|
|
16
19
|
MAX_COLLECTION_SLUG_LENGTH,
|
|
17
20
|
MAX_COLLECTION_TITLE_LENGTH,
|
|
18
|
-
type CollectionSortOrder,
|
|
19
21
|
} from "../../types.js";
|
|
20
22
|
import { getCollectionPagePath } from "../../lib/collection-paths.js";
|
|
21
23
|
import { getSlugValidationIssue, truncateSlug } from "../../lib/slug-format.js";
|
|
22
24
|
import { slugify } from "../lazy-slugify.js";
|
|
23
25
|
import { publicPath } from "../runtime-paths.js";
|
|
24
|
-
import {
|
|
25
|
-
createSettingsEditor,
|
|
26
|
-
jsonToMarkdown,
|
|
27
|
-
} from "../tiptap/create-editor.js";
|
|
28
26
|
import type {
|
|
29
27
|
CollectionFormInitial,
|
|
30
28
|
CollectionFormLabels,
|
|
@@ -36,14 +34,9 @@ export class JantCollectionForm extends LitElement {
|
|
|
36
34
|
labels: { type: Object },
|
|
37
35
|
initial: { type: Object },
|
|
38
36
|
action: { type: String },
|
|
39
|
-
cancelHref: { type: String, attribute: "cancel-href" },
|
|
40
|
-
isEdit: { type: Boolean, attribute: "is-edit" },
|
|
41
|
-
variant: { type: String },
|
|
42
37
|
|
|
43
38
|
_title: { state: true },
|
|
44
39
|
_slug: { state: true },
|
|
45
|
-
_description: { state: true },
|
|
46
|
-
_sortOrder: { state: true },
|
|
47
40
|
_showSlugEditor: { state: true },
|
|
48
41
|
_slugEdited: { state: true },
|
|
49
42
|
_suggestedSlug: { state: true },
|
|
@@ -53,21 +46,15 @@ export class JantCollectionForm extends LitElement {
|
|
|
53
46
|
declare labels: CollectionFormLabels;
|
|
54
47
|
declare initial: CollectionFormInitial;
|
|
55
48
|
declare action: string;
|
|
56
|
-
declare cancelHref: string;
|
|
57
|
-
declare isEdit: boolean;
|
|
58
|
-
declare variant: "full" | "quick";
|
|
59
49
|
|
|
60
50
|
declare _title: string;
|
|
61
51
|
declare _slug: string;
|
|
62
|
-
declare _description: string;
|
|
63
|
-
declare _sortOrder: CollectionSortOrder;
|
|
64
52
|
declare _showSlugEditor: boolean;
|
|
65
53
|
declare _slugEdited: boolean;
|
|
66
54
|
declare _suggestedSlug: string;
|
|
67
55
|
declare _loading: boolean;
|
|
68
56
|
|
|
69
57
|
#initialized = false;
|
|
70
|
-
private _descEditor: Editor | null = null;
|
|
71
58
|
#boundKeydown: ((e: KeyboardEvent) => void) | null = null;
|
|
72
59
|
|
|
73
60
|
createRenderRoot() {
|
|
@@ -78,21 +65,11 @@ export class JantCollectionForm extends LitElement {
|
|
|
78
65
|
constructor() {
|
|
79
66
|
super();
|
|
80
67
|
this.labels = {} as CollectionFormLabels;
|
|
81
|
-
this.initial = {
|
|
82
|
-
title: "",
|
|
83
|
-
slug: "",
|
|
84
|
-
description: "",
|
|
85
|
-
sortOrder: "newest",
|
|
86
|
-
};
|
|
68
|
+
this.initial = { title: "", slug: "" };
|
|
87
69
|
this.action = "";
|
|
88
|
-
this.cancelHref = "/";
|
|
89
|
-
this.isEdit = false;
|
|
90
|
-
this.variant = "full";
|
|
91
70
|
|
|
92
71
|
this._title = "";
|
|
93
72
|
this._slug = "";
|
|
94
|
-
this._description = "";
|
|
95
|
-
this._sortOrder = "newest";
|
|
96
73
|
this._showSlugEditor = false;
|
|
97
74
|
this._slugEdited = false;
|
|
98
75
|
this._suggestedSlug = "";
|
|
@@ -117,8 +94,6 @@ export class JantCollectionForm extends LitElement {
|
|
|
117
94
|
this.#boundKeydown = null;
|
|
118
95
|
}
|
|
119
96
|
super.disconnectedCallback();
|
|
120
|
-
this._descEditor?.destroy();
|
|
121
|
-
this._descEditor = null;
|
|
122
97
|
}
|
|
123
98
|
|
|
124
99
|
protected update(
|
|
@@ -144,46 +119,15 @@ export class JantCollectionForm extends LitElement {
|
|
|
144
119
|
this._title = this.initial.title ?? "";
|
|
145
120
|
this._slug = this.initial.slug ?? "";
|
|
146
121
|
this._suggestedSlug = this.initial.slug ?? "";
|
|
147
|
-
this.
|
|
148
|
-
this.
|
|
149
|
-
this._slugEdited = this.isEdit || Boolean(this._slug.trim());
|
|
150
|
-
this._showSlugEditor = this.variant !== "quick";
|
|
151
|
-
|
|
152
|
-
if (this.variant !== "quick") {
|
|
153
|
-
this.updateComplete.then(() => this.#initDescEditor());
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
#initDescEditor() {
|
|
158
|
-
const container = this.querySelector<HTMLElement>(
|
|
159
|
-
"[data-collection-desc-editor]",
|
|
160
|
-
);
|
|
161
|
-
if (!container || this._descEditor) return;
|
|
162
|
-
|
|
163
|
-
this._descEditor = createSettingsEditor({
|
|
164
|
-
element: container,
|
|
165
|
-
placeholder: this.isEdit ? undefined : this.labels.descriptionPlaceholder,
|
|
166
|
-
content: this._description || undefined,
|
|
167
|
-
onUpdate: (markdown) => {
|
|
168
|
-
this._description = markdown;
|
|
169
|
-
},
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// Normalize initial markdown through the editor round-trip
|
|
173
|
-
this._description = jsonToMarkdown(this._descEditor.getJSON());
|
|
174
|
-
|
|
175
|
-
const pm = container.querySelector<HTMLElement>(".ProseMirror");
|
|
176
|
-
if (pm) {
|
|
177
|
-
pm.style.outline = "none";
|
|
178
|
-
pm.style.minHeight = "5rem";
|
|
179
|
-
}
|
|
122
|
+
this._slugEdited = Boolean(this._slug.trim());
|
|
123
|
+
this._showSlugEditor = false;
|
|
180
124
|
}
|
|
181
125
|
|
|
182
126
|
async #handleTitleInput(event: Event) {
|
|
183
127
|
const target = event.target as HTMLInputElement;
|
|
184
128
|
this._title = target.value;
|
|
185
129
|
|
|
186
|
-
if (this.
|
|
130
|
+
if (this._slugEdited) {
|
|
187
131
|
return;
|
|
188
132
|
}
|
|
189
133
|
|
|
@@ -237,9 +181,7 @@ export class JantCollectionForm extends LitElement {
|
|
|
237
181
|
if (!this._suggestedSlug) return;
|
|
238
182
|
this._slug = this._suggestedSlug;
|
|
239
183
|
this._slugEdited = false;
|
|
240
|
-
|
|
241
|
-
this._showSlugEditor = false;
|
|
242
|
-
}
|
|
184
|
+
this._showSlugEditor = false;
|
|
243
185
|
}
|
|
244
186
|
|
|
245
187
|
#getCollectionLinkPreview(): string {
|
|
@@ -276,7 +218,7 @@ export class JantCollectionForm extends LitElement {
|
|
|
276
218
|
</p>`;
|
|
277
219
|
}
|
|
278
220
|
|
|
279
|
-
#
|
|
221
|
+
#renderSlugControls() {
|
|
280
222
|
const hasPreview = Boolean(this._slug.trim());
|
|
281
223
|
const canResetToTitle =
|
|
282
224
|
this._showSlugEditor &&
|
|
@@ -293,17 +235,19 @@ export class JantCollectionForm extends LitElement {
|
|
|
293
235
|
<div class="field">
|
|
294
236
|
<div class="collection-quick-link-row">
|
|
295
237
|
<label class="label mb-0">${this.labels.slugLabel}</label>
|
|
296
|
-
${
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
238
|
+
${
|
|
239
|
+
canResetToTitle
|
|
240
|
+
? html`
|
|
241
|
+
<button
|
|
242
|
+
type="button"
|
|
243
|
+
class="collection-quick-link-action"
|
|
244
|
+
@click=${() => this.#resetSlugToSuggested()}
|
|
245
|
+
>
|
|
246
|
+
${this.labels.resetSlugLabel}
|
|
247
|
+
</button>
|
|
248
|
+
`
|
|
249
|
+
: nothing
|
|
250
|
+
}
|
|
307
251
|
</div>
|
|
308
252
|
<input
|
|
309
253
|
type="text"
|
|
@@ -313,9 +257,9 @@ export class JantCollectionForm extends LitElement {
|
|
|
313
257
|
pattern="[a-z0-9]+(?:-[a-z0-9]+)*"
|
|
314
258
|
maxlength=${MAX_COLLECTION_SLUG_LENGTH}
|
|
315
259
|
.value=${this._slug}
|
|
316
|
-
aria-invalid=${
|
|
317
|
-
? "true"
|
|
318
|
-
|
|
260
|
+
aria-invalid=${
|
|
261
|
+
this.#getSlugValidationMessage() ? "true" : "false"
|
|
262
|
+
}
|
|
319
263
|
placeholder="my-collection"
|
|
320
264
|
@input=${(event: Event) => this.#handleSlugInput(event)}
|
|
321
265
|
/>
|
|
@@ -369,9 +313,7 @@ export class JantCollectionForm extends LitElement {
|
|
|
369
313
|
}
|
|
370
314
|
|
|
371
315
|
if (!slug || this.#getSlugValidationMessage()) {
|
|
372
|
-
|
|
373
|
-
this.#showSlugEditor();
|
|
374
|
-
}
|
|
316
|
+
this.#showSlugEditor();
|
|
375
317
|
this.updateComplete.then(() => {
|
|
376
318
|
this.querySelector<HTMLInputElement>(
|
|
377
319
|
"[data-collection-slug-input]",
|
|
@@ -382,17 +324,7 @@ export class JantCollectionForm extends LitElement {
|
|
|
382
324
|
|
|
383
325
|
const detail: CollectionSubmitDetail = {
|
|
384
326
|
endpoint: this.action,
|
|
385
|
-
|
|
386
|
-
data: {
|
|
387
|
-
title,
|
|
388
|
-
slug,
|
|
389
|
-
description:
|
|
390
|
-
this.variant === "quick"
|
|
391
|
-
? undefined
|
|
392
|
-
: this._description.trim() || undefined,
|
|
393
|
-
sortOrder:
|
|
394
|
-
this.variant === "quick" ? undefined : this._sortOrder || undefined,
|
|
395
|
-
},
|
|
327
|
+
data: { title, slug },
|
|
396
328
|
};
|
|
397
329
|
|
|
398
330
|
this.dispatchEvent(
|
|
@@ -404,141 +336,30 @@ export class JantCollectionForm extends LitElement {
|
|
|
404
336
|
}
|
|
405
337
|
|
|
406
338
|
render() {
|
|
407
|
-
const isQuick = this.variant === "quick";
|
|
408
|
-
const formClass = isQuick
|
|
409
|
-
? "flex flex-col gap-4"
|
|
410
|
-
: "collection-editor-form";
|
|
411
|
-
|
|
412
339
|
return html`
|
|
413
340
|
<form
|
|
414
|
-
class
|
|
341
|
+
class="flex flex-col gap-4"
|
|
415
342
|
@submit=${(event: Event) => void this.#handleSubmit(event)}
|
|
416
343
|
>
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
`
|
|
437
|
-
: html`
|
|
438
|
-
<div class="collection-editor-primary-grid">
|
|
439
|
-
<div class="field collection-editor-title-field">
|
|
440
|
-
<label class="label">${this.labels.titleLabel}</label>
|
|
441
|
-
<input
|
|
442
|
-
type="text"
|
|
443
|
-
class="input"
|
|
444
|
-
data-collection-title-input
|
|
445
|
-
required
|
|
446
|
-
maxlength=${MAX_COLLECTION_TITLE_LENGTH}
|
|
447
|
-
.value=${this._title}
|
|
448
|
-
placeholder=${this.isEdit
|
|
449
|
-
? nothing
|
|
450
|
-
: this.labels.titlePlaceholder}
|
|
451
|
-
@input=${(event: Event) =>
|
|
452
|
-
void this.#handleTitleInput(event)}
|
|
453
|
-
/>
|
|
454
|
-
</div>
|
|
455
|
-
|
|
456
|
-
<div class="field collection-editor-slug-field">
|
|
457
|
-
<label class="label">${this.labels.slugLabel}</label>
|
|
458
|
-
<input
|
|
459
|
-
type="text"
|
|
460
|
-
class="input"
|
|
461
|
-
data-collection-slug-input
|
|
462
|
-
required
|
|
463
|
-
pattern="[a-z0-9]+(?:-[a-z0-9]+)*"
|
|
464
|
-
maxlength=${MAX_COLLECTION_SLUG_LENGTH}
|
|
465
|
-
.value=${this._slug}
|
|
466
|
-
aria-invalid=${this.#getSlugValidationMessage()
|
|
467
|
-
? "true"
|
|
468
|
-
: "false"}
|
|
469
|
-
placeholder=${this.isEdit ? nothing : "my-collection"}
|
|
470
|
-
@input=${(event: Event) => this.#handleSlugInput(event)}
|
|
471
|
-
/>
|
|
472
|
-
${this.#renderSlugHelper()}
|
|
473
|
-
</div>
|
|
474
|
-
</div>
|
|
475
|
-
|
|
476
|
-
<div class="collection-editor-secondary-grid">
|
|
477
|
-
<div class="field collection-editor-description-field">
|
|
478
|
-
<label class="label">${this.labels.descriptionLabel}</label>
|
|
479
|
-
<div
|
|
480
|
-
class="settings-tiptap-editor"
|
|
481
|
-
data-collection-desc-editor
|
|
482
|
-
></div>
|
|
483
|
-
</div>
|
|
484
|
-
|
|
485
|
-
<div class="field collection-editor-sort-field">
|
|
486
|
-
<label class="label">${this.labels.sortOrderLabel}</label>
|
|
487
|
-
<select
|
|
488
|
-
class="select"
|
|
489
|
-
.value=${this._sortOrder}
|
|
490
|
-
@change=${(event: Event) => {
|
|
491
|
-
const target = event.target as HTMLSelectElement;
|
|
492
|
-
this._sortOrder = target.value as CollectionSortOrder;
|
|
493
|
-
}}
|
|
494
|
-
>
|
|
495
|
-
<option value="newest">${this.labels.sortNewest}</option>
|
|
496
|
-
<option value="oldest">${this.labels.sortOldest}</option>
|
|
497
|
-
<option value="rating_desc">
|
|
498
|
-
${this.labels.sortRatingDesc}
|
|
499
|
-
</option>
|
|
500
|
-
</select>
|
|
501
|
-
</div>
|
|
502
|
-
</div>
|
|
503
|
-
`}
|
|
504
|
-
${isQuick
|
|
505
|
-
? html`
|
|
506
|
-
<button type="submit" class="sr-only">
|
|
507
|
-
${this.labels.quickSubmitLabel}
|
|
508
|
-
</button>
|
|
509
|
-
`
|
|
510
|
-
: html`
|
|
511
|
-
<div class="collection-editor-actions">
|
|
512
|
-
<button
|
|
513
|
-
type="submit"
|
|
514
|
-
class="btn collection-editor-submit"
|
|
515
|
-
?disabled=${this._loading}
|
|
516
|
-
>
|
|
517
|
-
${this._loading
|
|
518
|
-
? html`<svg
|
|
519
|
-
class="animate-spin size-4"
|
|
520
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
521
|
-
viewBox="0 0 24 24"
|
|
522
|
-
fill="none"
|
|
523
|
-
stroke="currentColor"
|
|
524
|
-
stroke-width="2"
|
|
525
|
-
stroke-linecap="round"
|
|
526
|
-
stroke-linejoin="round"
|
|
527
|
-
role="status"
|
|
528
|
-
>
|
|
529
|
-
<path d="M21 12a9 9 0 1 1-6.219-8.56" />
|
|
530
|
-
</svg>`
|
|
531
|
-
: nothing}
|
|
532
|
-
${this.labels.submitLabel}
|
|
533
|
-
</button>
|
|
534
|
-
<a
|
|
535
|
-
href=${this.cancelHref}
|
|
536
|
-
class="btn-outline collection-editor-cancel"
|
|
537
|
-
>
|
|
538
|
-
${this.labels.cancelLabel}
|
|
539
|
-
</a>
|
|
540
|
-
</div>
|
|
541
|
-
`}
|
|
344
|
+
<div class="field">
|
|
345
|
+
<label class="label">${this.labels.titleLabel}</label>
|
|
346
|
+
<input
|
|
347
|
+
type="text"
|
|
348
|
+
class="input"
|
|
349
|
+
data-collection-title-input
|
|
350
|
+
required
|
|
351
|
+
maxlength=${MAX_COLLECTION_TITLE_LENGTH}
|
|
352
|
+
.value=${this._title}
|
|
353
|
+
placeholder=${this.labels.titlePlaceholder}
|
|
354
|
+
@input=${(event: Event) => void this.#handleTitleInput(event)}
|
|
355
|
+
/>
|
|
356
|
+
</div>
|
|
357
|
+
|
|
358
|
+
${this.#renderSlugControls()}
|
|
359
|
+
|
|
360
|
+
<button type="submit" class="sr-only">
|
|
361
|
+
${this.labels.quickSubmitLabel}
|
|
362
|
+
</button>
|
|
542
363
|
</form>
|
|
543
364
|
`;
|
|
544
365
|
}
|
|
@@ -13,7 +13,8 @@ import { classMap } from "lit/directives/class-map.js";
|
|
|
13
13
|
import { unsafeSVG } from "lit/directives/unsafe-svg.js";
|
|
14
14
|
import { NAVIGATION_SETTINGS_PATH } from "../../lib/settings-paths.js";
|
|
15
15
|
import { openNewCompose } from "../compose-launch.js";
|
|
16
|
-
import {
|
|
16
|
+
import { isFullUrl, toInternalPath } from "../../lib/url.js";
|
|
17
|
+
import { navPath, sitePathPrefix } from "../runtime-paths.js";
|
|
17
18
|
import { getBestFieldSearchRank, normalizeSearch } from "../search-rank.js";
|
|
18
19
|
|
|
19
20
|
// ---------------------------------------------------------------------------
|
|
@@ -23,7 +24,7 @@ import { getBestFieldSearchRank, normalizeSearch } from "../search-rank.js";
|
|
|
23
24
|
interface PaletteItem {
|
|
24
25
|
title: string;
|
|
25
26
|
path: string;
|
|
26
|
-
type: "post" | "collection" | "system";
|
|
27
|
+
type: "post" | "collection" | "smart_collection" | "system";
|
|
27
28
|
status?: "draft" | "published";
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -58,6 +59,9 @@ const ICONS = {
|
|
|
58
59
|
post: `<svg ${ICON_ATTRS}><path d="M8 2v4"/><path d="M12 2v4"/><path d="M16 2v4"/><rect width="16" height="18" x="4" y="4" rx="2"/><path d="M8 10h6"/><path d="M8 14h8"/><path d="M8 18h5"/></svg>`,
|
|
59
60
|
// clipboard/collection icon from PostFooter
|
|
60
61
|
collection: `<svg ${ICON_ATTRS} viewBox="0 0 16 16" stroke-width="1.35"><rect x="3" y="5.05" width="10" height="8.15" rx="2.2"/><path d="M5.1 5.05V4.2a1.1 1.1 0 0 1 1.1-1.1h3.6a1.1 1.1 0 0 1 1.1 1.1v.85"/></svg>`,
|
|
62
|
+
// funnel — the same icon the directory and the page use, so a smart
|
|
63
|
+
// collection reads as a collection with a rule behind it everywhere at once.
|
|
64
|
+
smart_collection: `<svg ${ICON_ATTRS}><path d="M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z"/></svg>`,
|
|
61
65
|
// settings gear from SettingsRootContent
|
|
62
66
|
system: `<svg ${ICON_ATTRS}><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>`,
|
|
63
67
|
// zap/lightning for commands
|
|
@@ -73,6 +77,29 @@ export function getPathCommandTarget(query: string): string {
|
|
|
73
77
|
return stripped ? `/${stripped}` : "/";
|
|
74
78
|
}
|
|
75
79
|
|
|
80
|
+
/**
|
|
81
|
+
* The local path a pasted full URL points at, when it points at this site.
|
|
82
|
+
*
|
|
83
|
+
* Copying an address out of the browser bar and dropping it in the palette
|
|
84
|
+
* should go there, the same as typing `/`. Someone else's URL is left to
|
|
85
|
+
* navigate mode, where it falls through to a full-text search — looking for
|
|
86
|
+
* the post where you linked something is the likelier intent.
|
|
87
|
+
*
|
|
88
|
+
* @param query - Raw palette query
|
|
89
|
+
* @returns Internal path with its query string, or null when not our URL
|
|
90
|
+
*/
|
|
91
|
+
export function getPastedAddressTarget(query: string): string | null {
|
|
92
|
+
const trimmed = query.trim();
|
|
93
|
+
if (!isFullUrl(trimmed)) return null;
|
|
94
|
+
|
|
95
|
+
return toInternalPath(trimmed, {
|
|
96
|
+
siteOrigins: [window.location.origin],
|
|
97
|
+
sitePathPrefix: sitePathPrefix(),
|
|
98
|
+
// A pasted `/en/about` was copied from that view and belongs there.
|
|
99
|
+
keepQuery: true,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
76
103
|
export function getPathCommandSearchQuery(query: string): string {
|
|
77
104
|
return query
|
|
78
105
|
.trim()
|
|
@@ -246,6 +273,7 @@ export class JantCommandPalette extends LitElement {
|
|
|
246
273
|
if (first === ">" || first === ">") return "command";
|
|
247
274
|
if (first === "?" || first === "?") return "search";
|
|
248
275
|
if (first === "/" || first === "/") return "path";
|
|
276
|
+
if (getPastedAddressTarget(this._query)) return "path";
|
|
249
277
|
return "navigate";
|
|
250
278
|
}
|
|
251
279
|
|
|
@@ -326,8 +354,11 @@ export class JantCommandPalette extends LitElement {
|
|
|
326
354
|
}
|
|
327
355
|
|
|
328
356
|
if (mode === "path") {
|
|
329
|
-
const
|
|
330
|
-
const
|
|
357
|
+
const pasted = getPastedAddressTarget(this._query);
|
|
358
|
+
const target = pasted ?? getPathCommandTarget(this._query);
|
|
359
|
+
// A pasted URL is already an answer; only a typed path is also plausible
|
|
360
|
+
// as search words.
|
|
361
|
+
const searchQuery = pasted ? "" : getPathCommandSearchQuery(this._query);
|
|
331
362
|
const items: DisplayItem[] = [
|
|
332
363
|
{
|
|
333
364
|
label: `Go to ${target}`,
|
|
@@ -380,7 +411,11 @@ export class JantCommandPalette extends LitElement {
|
|
|
380
411
|
#executeSearch(query: string) {
|
|
381
412
|
saveHistory(SEARCH_HISTORY_KEY, query);
|
|
382
413
|
this.close();
|
|
383
|
-
|
|
414
|
+
// navPath, not publicPath: a search run from inside /en belongs in /en.
|
|
415
|
+
// The palette jumps to settings pages and posts through this same code
|
|
416
|
+
// path, so it cannot assert the kind of any one target — navPath decides
|
|
417
|
+
// per target and leaves the site-wide ones alone.
|
|
418
|
+
window.location.href = navPath(`/search?q=${encodeURIComponent(query)}`);
|
|
384
419
|
}
|
|
385
420
|
|
|
386
421
|
#executeItem(index: number) {
|
|
@@ -409,7 +444,7 @@ export class JantCommandPalette extends LitElement {
|
|
|
409
444
|
if (displayItem?.pathTarget) {
|
|
410
445
|
saveHistory(NAV_HISTORY_KEY, displayItem.pathTarget);
|
|
411
446
|
this.close();
|
|
412
|
-
window.location.href =
|
|
447
|
+
window.location.href = navPath(displayItem.pathTarget);
|
|
413
448
|
return;
|
|
414
449
|
}
|
|
415
450
|
|
|
@@ -431,11 +466,15 @@ export class JantCommandPalette extends LitElement {
|
|
|
431
466
|
saveHistory(NAV_HISTORY_KEY, item.path);
|
|
432
467
|
this.close();
|
|
433
468
|
if (item.type === "system") {
|
|
434
|
-
window.location.href =
|
|
469
|
+
window.location.href = navPath(item.path);
|
|
435
470
|
} else if (item.type === "collection") {
|
|
436
|
-
window.location.href =
|
|
471
|
+
window.location.href = navPath(`/collections/${item.path}`);
|
|
472
|
+
} else if (item.type === "smart_collection") {
|
|
473
|
+
// Straight to its address. `/collections/{slug}` redirects for a
|
|
474
|
+
// collection but names nothing for a smart collection.
|
|
475
|
+
window.location.href = navPath(`/${item.path}`);
|
|
437
476
|
} else {
|
|
438
|
-
window.location.href =
|
|
477
|
+
window.location.href = navPath(
|
|
439
478
|
item.status === "draft"
|
|
440
479
|
? `/preview/${item.path}?edit=1`
|
|
441
480
|
: `/${item.path}`,
|
|
@@ -554,19 +593,23 @@ export class JantCommandPalette extends LitElement {
|
|
|
554
593
|
<span class="command-palette-result-icon">${unsafeSVG(item.icon)}</span>
|
|
555
594
|
<span class="command-palette-result-body">
|
|
556
595
|
<span class="command-palette-result-title">${item.label}</span>
|
|
557
|
-
${
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
596
|
+
${
|
|
597
|
+
item.secondary
|
|
598
|
+
? html`<span class="command-palette-result-path"
|
|
599
|
+
>${item.secondary}</span
|
|
600
|
+
>`
|
|
601
|
+
: nothing
|
|
602
|
+
}
|
|
562
603
|
</span>
|
|
563
|
-
${
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
604
|
+
${
|
|
605
|
+
item.shortcut
|
|
606
|
+
? html`<kbd
|
|
607
|
+
class="command-palette-result-shortcut"
|
|
608
|
+
aria-label="Command or Control plus Enter"
|
|
609
|
+
>${item.shortcut}</kbd
|
|
610
|
+
>`
|
|
611
|
+
: nothing
|
|
612
|
+
}
|
|
570
613
|
</div>
|
|
571
614
|
`;
|
|
572
615
|
}
|
|
@@ -606,39 +649,47 @@ export class JantCommandPalette extends LitElement {
|
|
|
606
649
|
role="combobox"
|
|
607
650
|
aria-expanded="true"
|
|
608
651
|
aria-controls="command-palette-results"
|
|
609
|
-
aria-activedescendant=${
|
|
610
|
-
|
|
611
|
-
|
|
652
|
+
aria-activedescendant=${
|
|
653
|
+
items.length > 0
|
|
654
|
+
? `command-palette-item-${this._selectedIndex}`
|
|
655
|
+
: ""
|
|
656
|
+
}
|
|
612
657
|
autocomplete="off"
|
|
613
658
|
spellcheck="false"
|
|
614
659
|
/>
|
|
615
|
-
${
|
|
616
|
-
|
|
617
|
-
|
|
660
|
+
${
|
|
661
|
+
this._loading
|
|
662
|
+
? html`<span class="command-palette-spinner"></span>`
|
|
663
|
+
: nothing
|
|
664
|
+
}
|
|
618
665
|
</div>
|
|
619
666
|
|
|
620
|
-
${
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
667
|
+
${
|
|
668
|
+
items.length > 0
|
|
669
|
+
? html`
|
|
670
|
+
<div
|
|
671
|
+
id="command-palette-results"
|
|
672
|
+
class="command-palette-results-container"
|
|
673
|
+
role="listbox"
|
|
674
|
+
>
|
|
675
|
+
${
|
|
676
|
+
resultItems.length > 0
|
|
677
|
+
? html`<div class="command-palette-results">
|
|
678
|
+
${resultItems.map(({ item, index }) =>
|
|
679
|
+
this.#renderItem(item, index),
|
|
680
|
+
)}
|
|
681
|
+
</div>`
|
|
682
|
+
: nothing
|
|
683
|
+
}
|
|
684
|
+
${footerItems.map(({ item, index }) =>
|
|
685
|
+
this.#renderItem(item, index, true),
|
|
686
|
+
)}
|
|
687
|
+
</div>
|
|
688
|
+
`
|
|
689
|
+
: this._query.trim() && !this._loading
|
|
690
|
+
? html`<div class="command-palette-empty">No results</div>`
|
|
691
|
+
: nothing
|
|
692
|
+
}
|
|
642
693
|
</div>
|
|
643
694
|
</dialog>
|
|
644
695
|
`;
|