@jant/core 0.6.14 → 0.6.16
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/bin/commands/import-site.js +88 -13
- package/bin/commands/migrate.js +55 -0
- package/bin/commands/posts/rebuild-html.js +184 -0
- package/bin/commands/site/snapshot/import.js +14 -10
- package/bin/lib/d1-query.js +23 -5
- package/bin/lib/migration-runner.js +29 -7
- package/bin/lib/node-database.js +32 -0
- package/bin/lib/site-snapshot.js +347 -46
- package/bin/lib/sql-export.js +1 -1
- package/bin/lib/thread-collection-migration.js +326 -0
- package/dist/app-C75Zc8dD.js +6 -0
- package/dist/{app-2i7-WQHg.js → app-C7_4oab9.js} +7774 -6425
- package/dist/client/.vite/manifest.json +8 -8
- package/dist/client/_assets/chunks/{url-pLre2DM_.js → url-CU9pEbk5.js} +1 -1
- package/dist/client/_assets/{client-BvID5ucz.js → client-Bq0vre8Y.js} +59 -38
- package/dist/client/_assets/client-D3VZyG4L.css +2 -0
- package/dist/client/_assets/client-auth-F2rb9WfF.js +5571 -0
- package/dist/{env-OHRKGcMj.js → env-BPYViDJJ.js} +1 -1
- package/dist/{export-DWn149b7.js → export-Dl5KCiEs.js} +1348 -128
- package/dist/{github-api-BgSiE71w.js → github-api-BNF35Lkx.js} +1 -1
- package/dist/{github-app-BbklkFmU.js → github-app-DdiD-bC4.js} +1 -1
- package/dist/{github-sync-C0zyF6XS.js → github-sync-Bqg62IvV.js} +3 -3
- package/dist/{github-sync-Ckk0sJxK.js → github-sync-HdK2EgvJ.js} +3 -3
- package/dist/index.js +5 -5
- package/dist/node.js +7 -7
- package/dist/{url-BMYO-Zlt.js → url-CbLAtlZe.js} +517 -12
- package/package.json +11 -10
- package/src/__tests__/bin/posts-rebuild-html.test.ts +137 -0
- package/src/__tests__/dev-navigation-defaults.test.ts +22 -0
- package/src/__tests__/export-hugo-build.test.ts +63 -4
- package/src/__tests__/export-import-roundtrip.test.ts +6 -4
- package/src/__tests__/export-service.test.ts +142 -9
- package/src/__tests__/helpers/app.ts +3 -0
- package/src/__tests__/helpers/export-fixtures.ts +2 -0
- package/src/__tests__/import-site-command.test.ts +65 -0
- package/src/__tests__/mise-config.test.ts +22 -0
- package/src/__tests__/vite-config.test.ts +45 -0
- package/src/app.tsx +16 -3
- package/src/client/__tests__/collection-created-notice.test.ts +36 -0
- package/src/client/__tests__/collection-form-bridge.test.ts +10 -1
- package/src/client/__tests__/collection-page-actions.test.ts +71 -2
- package/src/client/__tests__/compose-bridge.test.ts +316 -2
- package/src/client/__tests__/compose-shortcuts.test.ts +20 -0
- package/src/client/__tests__/feed-video-player.test.ts +16 -1
- package/src/client/__tests__/footnote-rail.test.ts +472 -0
- package/src/client/__tests__/hydrate-partial.test.ts +3 -0
- package/src/client/__tests__/toast.test.ts +82 -1
- package/src/client/collection-created-notice.ts +66 -0
- package/src/client/collection-form-bridge.ts +17 -0
- package/src/client/collection-navigation.ts +44 -0
- package/src/client/collection-page-actions.ts +57 -1
- package/src/client/components/__tests__/compose-format-convert.test.ts +0 -19
- package/src/client/components/__tests__/jant-collection-directory.test.ts +155 -6
- package/src/client/components/__tests__/jant-command-palette.test.ts +51 -0
- package/src/client/components/__tests__/jant-compose-dialog.test.ts +2268 -206
- package/src/client/components/__tests__/jant-compose-editor.test.ts +147 -59
- package/src/client/components/__tests__/jant-compose-fullscreen.test.ts +114 -64
- package/src/client/components/__tests__/jant-config-editor.test.ts +405 -0
- package/src/client/components/__tests__/jant-media-lightbox.test.ts +121 -0
- package/src/client/components/__tests__/jant-nav-manager.test.ts +538 -2
- package/src/client/components/__tests__/jant-post-form.test.ts +2 -2
- package/src/client/components/__tests__/jant-post-menu.test.ts +47 -5
- package/src/client/components/__tests__/jant-settings-avatar.test.ts +2 -2
- package/src/client/components/__tests__/jant-settings-general.test.ts +3 -3
- package/src/client/components/collection-manager-types.ts +9 -3
- package/src/client/components/compose-format-convert.ts +5 -1
- package/src/client/components/compose-types.ts +55 -3
- package/src/client/components/jant-collection-directory.ts +165 -30
- package/src/client/components/jant-command-palette.ts +14 -7
- package/src/client/components/jant-compose-dialog.ts +1542 -694
- package/src/client/components/jant-compose-editor.ts +237 -99
- package/src/client/components/jant-compose-fullscreen.ts +27 -9
- package/src/client/components/jant-config-editor.ts +722 -0
- package/src/client/components/jant-media-lightbox.ts +100 -18
- package/src/client/components/jant-nav-manager.ts +1283 -54
- package/src/client/components/jant-post-form.ts +3 -3
- package/src/client/components/jant-post-menu.ts +177 -95
- package/src/client/components/nav-manager-types.ts +51 -2
- package/src/client/components/post-form-types.ts +1 -1
- package/src/client/compose-bridge.ts +147 -123
- package/src/client/compose-launch.ts +13 -0
- package/src/client/compose-shortcuts.ts +5 -1
- package/src/client/feed-video-player.ts +62 -2
- package/src/client/footnote-rail.ts +478 -0
- package/src/client/hydrate-partial.ts +2 -0
- package/src/client/media-lightbox-events.ts +63 -0
- package/src/client/post-refresh.ts +135 -0
- package/src/client/site-header-fragment.ts +38 -0
- package/src/client/tiptap/__tests__/blockquote-editing.test.ts +201 -0
- package/src/client/tiptap/__tests__/clear-formatting.test.ts +168 -0
- package/src/client/tiptap/__tests__/link-input-rules.test.ts +121 -0
- package/src/client/tiptap/__tests__/list-editing.test.ts +447 -0
- package/src/client/tiptap/__tests__/markdown-clipboard.test.ts +727 -4
- package/src/client/tiptap/__tests__/table-controls.test.ts +263 -0
- package/src/client/tiptap/__tests__/table-size-picker.test.ts +179 -0
- package/src/client/tiptap/bubble-menu.ts +88 -10
- package/src/client/tiptap/continuous-lists.ts +102 -0
- package/src/client/tiptap/create-editor.ts +3 -0
- package/src/client/tiptap/extensions.ts +14 -5
- package/src/client/tiptap/link-input-rules.ts +4 -4
- package/src/client/tiptap/markdown-clipboard.ts +608 -11
- package/src/client/tiptap/slash-commands.ts +8 -1
- package/src/client/tiptap/structural-keymap.ts +211 -0
- package/src/client/tiptap/tab-indent.ts +8 -22
- package/src/client/tiptap/table-control-labels.ts +30 -0
- package/src/client/tiptap/table-controls.ts +537 -0
- package/src/client/tiptap/table-size-picker.ts +254 -0
- package/src/client/toast.ts +133 -39
- package/src/client-auth.ts +1 -0
- package/src/client.ts +1 -0
- package/src/db/__tests__/backfill-thread-activity.test.ts +234 -0
- package/src/db/__tests__/d1-query.test.ts +43 -1
- package/src/db/__tests__/migration-runner.test.ts +63 -0
- package/src/db/__tests__/migrations.test.ts +469 -0
- package/src/db/__tests__/thread-activity.test.ts +113 -0
- package/src/db/__tests__/thread-collection-migration.test.ts +364 -0
- package/src/db/backfills/0005_split_thread_activity_from_quiet_replies.sql +68 -0
- package/src/db/migrations/0027_old_blue_blade.sql +39 -0
- package/src/db/migrations/0028_superb_post.sql +2 -0
- package/src/db/migrations/0029_boring_magma.sql +1 -0
- package/src/db/migrations/0030_typical_vivisector.sql +50 -0
- package/src/db/migrations/0031_many_ego.sql +3 -0
- package/src/db/migrations/meta/0027_snapshot.json +2511 -0
- package/src/db/migrations/meta/0028_snapshot.json +2511 -0
- package/src/db/migrations/meta/0029_snapshot.json +2519 -0
- package/src/db/migrations/meta/0030_snapshot.json +2541 -0
- package/src/db/migrations/meta/0031_snapshot.json +2562 -0
- package/src/db/migrations/meta/_journal.json +35 -0
- package/src/db/migrations/pg/0025_moaning_epoch.sql +39 -0
- package/src/db/migrations/pg/0026_talented_killer_shrike.sql +2 -0
- package/src/db/migrations/pg/0027_short_cannonball.sql +1 -0
- package/src/db/migrations/pg/0028_perfect_sharon_carter.sql +27 -0
- package/src/db/migrations/pg/0029_rare_hairball.sql +3 -0
- package/src/db/migrations/pg/meta/0025_snapshot.json +3204 -0
- package/src/db/migrations/pg/meta/0026_snapshot.json +3204 -0
- package/src/db/migrations/pg/meta/0027_snapshot.json +3211 -0
- package/src/db/migrations/pg/meta/0028_snapshot.json +3248 -0
- package/src/db/migrations/pg/meta/0029_snapshot.json +3289 -0
- package/src/db/migrations/pg/meta/_journal.json +35 -0
- package/src/db/pg/schema.ts +46 -20
- package/src/db/rehearsal-fixtures/demo-current.json +39 -4
- package/src/db/rehearsal-fixtures/demo-current.sql +121 -6
- package/src/db/schema.ts +48 -20
- package/src/db/thread-activity.ts +101 -0
- package/src/i18n/__tests__/detect.test.ts +8 -2
- package/src/i18n/detect.ts +14 -5
- package/src/i18n/locales/public/en.po +222 -51
- package/src/i18n/locales/public/en.ts +1 -1
- package/src/i18n/locales/public/zh-Hans.po +216 -45
- package/src/i18n/locales/public/zh-Hans.ts +1 -1
- package/src/i18n/locales/public/zh-Hant.po +216 -45
- package/src/i18n/locales/public/zh-Hant.ts +1 -1
- package/src/i18n/locales/settings/en.po +513 -10
- package/src/i18n/locales/settings/en.ts +1 -1
- package/src/i18n/locales/settings/zh-Hans.po +515 -12
- package/src/i18n/locales/settings/zh-Hans.ts +1 -1
- package/src/i18n/locales/settings/zh-Hant.po +515 -12
- package/src/i18n/locales/settings/zh-Hant.ts +1 -1
- package/src/lib/__tests__/api-settings.test.ts +299 -0
- package/src/lib/__tests__/constants.test.ts +5 -0
- package/src/lib/__tests__/feed-policy.test.ts +25 -0
- package/src/lib/__tests__/feed.test.ts +168 -0
- package/src/lib/__tests__/footnotes-upgrade.test.ts +181 -0
- package/src/lib/__tests__/markdown-roundtrip-embed.test.ts +61 -0
- package/src/lib/__tests__/markdown-to-tiptap.test.ts +32 -4
- package/src/lib/__tests__/markdown.test.ts +24 -6
- package/src/lib/__tests__/navigation.test.ts +59 -2
- package/src/lib/__tests__/post-body-html.test.ts +176 -0
- package/src/lib/__tests__/post-display.test.ts +64 -0
- package/src/lib/__tests__/resolve-config.test.ts +113 -1
- package/src/lib/__tests__/slug.test.ts +18 -0
- package/src/lib/__tests__/summary.test.ts +82 -0
- package/src/lib/__tests__/timeline.test.ts +109 -70
- package/src/lib/__tests__/timezones.test.ts +31 -3
- package/src/lib/__tests__/tiptap-render.test.ts +268 -9
- package/src/lib/__tests__/tiptap-to-markdown.test.ts +6 -0
- package/src/lib/__tests__/translit.test.ts +87 -0
- package/src/lib/__tests__/url.test.ts +53 -0
- package/src/lib/__tests__/view.test.ts +53 -0
- package/src/lib/__tests__/worker-response-cache.test.ts +18 -1
- package/src/lib/api-settings.ts +239 -12
- package/src/lib/collection-sort.ts +7 -5
- package/src/lib/constants.ts +2 -0
- package/src/lib/feed-path.ts +25 -0
- package/src/lib/feed-policy.ts +64 -0
- package/src/lib/feed.ts +113 -11
- package/src/lib/footnotes.ts +264 -0
- package/src/lib/github-sync-site-config.ts +2 -0
- package/src/lib/hugo-markdown.ts +15 -3
- package/src/lib/jant-branding.ts +1 -0
- package/src/lib/link-preview.ts +25 -0
- package/src/lib/markdown-manager.ts +193 -5
- package/src/lib/markdown.ts +10 -3
- package/src/lib/navigation.ts +16 -3
- package/src/lib/post-body-html.ts +131 -0
- package/src/lib/post-display.ts +47 -8
- package/src/lib/render.tsx +9 -2
- package/src/lib/resolve-config.ts +100 -16
- package/src/lib/schemas.ts +133 -1
- package/src/lib/settings-paths.ts +5 -0
- package/src/lib/site-skill.ts +78 -0
- package/src/lib/summary.ts +16 -5
- package/src/lib/timeline.ts +137 -131
- package/src/lib/timezones.ts +54 -14
- package/src/lib/tiptap-render.ts +359 -83
- package/src/lib/translit.ts +288 -0
- package/src/lib/url.ts +123 -12
- package/src/lib/view.ts +58 -20
- package/src/lib/worker-response-cache.ts +11 -18
- package/src/middleware/__tests__/public-content-access.test.ts +91 -0
- package/src/middleware/config.ts +2 -2
- package/src/middleware/public-content-access.ts +87 -0
- package/src/node/__tests__/cli-export.test.ts +14 -0
- package/src/node/__tests__/cli-migrate.test.ts +6 -0
- package/src/node/__tests__/cli-site-snapshot.test.ts +205 -2
- package/src/node/__tests__/cli-snapshot-meta.test.ts +100 -0
- package/src/node/index.ts +2 -1
- package/src/preset.css +16 -2
- package/src/routes/__tests__/compose.test.ts +51 -0
- package/src/routes/__tests__/site-skill.test.ts +112 -0
- package/src/routes/api/__tests__/collections.test.ts +91 -19
- package/src/routes/api/__tests__/mcp.test.ts +65 -1
- package/src/routes/api/__tests__/nav-items.test.ts +91 -0
- package/src/routes/api/__tests__/palette.test.ts +44 -0
- package/src/routes/api/__tests__/public-access.test.ts +81 -0
- package/src/routes/api/__tests__/settings.test.ts +217 -0
- package/src/routes/api/collections.ts +22 -26
- package/src/routes/api/export.ts +2 -0
- package/src/routes/api/internal/__tests__/post-body-html.test.ts +163 -0
- package/src/routes/api/internal/__tests__/sites.test.ts +35 -2
- package/src/routes/api/internal/post-body-html.ts +43 -0
- package/src/routes/api/internal/sites.ts +24 -0
- package/src/routes/api/nav-items.ts +24 -1
- package/src/routes/api/posts.ts +14 -10
- package/src/routes/api/public/__tests__/archive.test.ts +35 -0
- package/src/routes/api/public/__tests__/posts.test.ts +246 -0
- package/src/routes/api/public/archive.ts +4 -0
- package/src/routes/api/public/posts.ts +48 -24
- package/src/routes/api/search.ts +3 -0
- package/src/routes/api/settings.ts +33 -0
- package/src/routes/auth/__tests__/setup.test.ts +7 -4
- package/src/routes/compose.tsx +8 -3
- package/src/routes/dash/settings.tsx +45 -2
- package/src/routes/feed/__tests__/feed.test.ts +210 -6
- package/src/routes/feed/__tests__/sitemap.test.ts +68 -1
- package/src/routes/feed/feed.ts +23 -14
- package/src/routes/pages/__tests__/archive-params.test.ts +384 -3
- package/src/routes/pages/__tests__/collection-routing.test.ts +63 -5
- package/src/routes/pages/__tests__/collections.test.ts +9 -9
- package/src/routes/pages/__tests__/featured.test.ts +6 -2
- package/src/routes/pages/__tests__/preview.test.ts +176 -0
- package/src/routes/pages/__tests__/search.test.ts +69 -0
- package/src/routes/pages/archive.tsx +90 -22
- package/src/routes/pages/collection.tsx +32 -19
- package/src/routes/pages/collections.tsx +6 -1
- package/src/routes/pages/page.tsx +86 -11
- package/src/routes/site-skill.ts +18 -0
- package/src/services/__tests__/auth.test.ts +7 -5
- package/src/services/__tests__/collection.test.ts +190 -44
- package/src/services/__tests__/navigation.test.ts +229 -21
- package/src/services/__tests__/post-timeline.test.ts +249 -39
- package/src/services/__tests__/post.test.ts +844 -5
- package/src/services/__tests__/search.test.ts +48 -1
- package/src/services/__tests__/settings.test.ts +8 -0
- package/src/services/__tests__/site-admin.test.ts +121 -1
- package/src/services/auth.ts +2 -2
- package/src/services/bootstrap.ts +3 -2
- package/src/services/collection.ts +224 -167
- package/src/services/export-theme/assets/client-site.css +1 -1
- package/src/services/export-theme/assets/client-site.js +46 -25
- package/src/services/export-theme/layouts/_default/list.html +18 -4
- package/src/services/export-theme/layouts/_default/rss.xml +8 -12
- package/src/services/export-theme/layouts/featured/list.html +5 -4
- package/src/services/export-theme/layouts/partials/featured-thread.html +56 -0
- package/src/services/export-theme/layouts/partials/footer.html +1 -1
- package/src/services/export-theme/layouts/partials/media-gallery.html +1 -0
- package/src/services/export-theme/styles/main.css +30 -2
- package/src/services/export.ts +94 -85
- package/src/services/mcp.ts +37 -27
- package/src/services/media.ts +1 -1
- package/src/services/navigation.ts +185 -46
- package/src/services/path.ts +4 -1
- package/src/services/post.ts +1142 -342
- package/src/services/search.ts +17 -2
- package/src/services/settings.ts +2 -10
- package/src/services/site-admin.ts +63 -43
- package/src/style-cjk-jp.css +1 -1
- package/src/style-cjk-kr.css +1 -1
- package/src/style-cjk-tc.css +1 -1
- package/src/style-cjk.css +1 -1
- package/src/styles/components.css +540 -14
- package/src/styles/site-media.css +111 -19
- package/src/styles/tokens.css +76 -10
- package/src/styles/ui.css +2227 -1347
- package/src/types/bindings.ts +3 -0
- package/src/types/config.ts +243 -12
- package/src/types/constants.ts +22 -1
- package/src/types/entities.ts +14 -8
- package/src/types/operations.ts +18 -10
- package/src/types/props.ts +20 -2
- package/src/types/raw-assets.d.ts +5 -0
- package/src/types/views.ts +22 -4
- package/src/ui/__tests__/font-themes.test.ts +42 -30
- package/src/ui/compose/ComposeDialog.tsx +109 -19
- package/src/ui/dash/appearance/NavigationContent.tsx +332 -4
- package/src/ui/dash/appearance/__tests__/NavigationContent.test.tsx +23 -0
- package/src/ui/dash/settings/ConfigEditorContent.tsx +578 -0
- package/src/ui/dash/settings/GeneralContent.tsx +15 -5
- package/src/ui/dash/settings/SettingsRootContent.tsx +21 -1
- package/src/ui/dash/settings/__tests__/ConfigEditorContent.test.tsx +98 -0
- package/src/ui/dash/settings/__tests__/SettingsRootContent.test.tsx +15 -0
- package/src/ui/feed/CuratedThreadPreview.tsx +16 -4
- package/src/ui/feed/LinkCard.tsx +2 -12
- package/src/ui/feed/LinkPreview.tsx +2 -7
- package/src/ui/feed/NoteCard.tsx +10 -20
- package/src/ui/feed/PostStatusBadges.tsx +42 -3
- package/src/ui/feed/QuoteCard.tsx +2 -12
- package/src/ui/feed/ThreadPreview.tsx +26 -34
- package/src/ui/feed/TimelineFeed.tsx +2 -2
- package/src/ui/feed/__tests__/thread-preview.test.ts +197 -56
- package/src/ui/feed/__tests__/timeline-cards.test.ts +178 -3
- package/src/ui/feed/thread-preview-state.ts +5 -7
- package/src/ui/font-themes.ts +74 -26
- package/src/ui/layouts/BaseLayout.tsx +22 -8
- package/src/ui/layouts/__tests__/BaseLayout.test.tsx +64 -1
- package/src/ui/pages/ArchivePage.tsx +131 -24
- package/src/ui/pages/CollectionPage.tsx +101 -22
- package/src/ui/pages/CollectionsPage.tsx +3 -1
- package/src/ui/pages/PostPage.tsx +39 -12
- package/src/ui/pages/SearchPage.tsx +6 -14
- package/src/ui/pages/__tests__/ArchivePage.test.tsx +70 -0
- package/src/ui/pages/__tests__/PostPage.test.tsx +88 -0
- package/src/ui/shared/CollectionDirectory.tsx +13 -9
- package/src/ui/shared/CollectionsManager.tsx +17 -7
- package/src/ui/shared/DraftPreviewBar.tsx +49 -0
- package/src/ui/shared/HomePageBranding.tsx +2 -2
- package/src/ui/shared/MediaGallery.tsx +1 -0
- package/src/ui/shared/PostFooter.tsx +38 -13
- package/src/ui/shared/__tests__/home-page-branding.test.tsx +1 -1
- package/src/ui/shared/__tests__/media-gallery.test.ts +1 -0
- package/src/ui/shared/__tests__/navigation-labels.test.ts +2 -2
- package/src/ui/shared/__tests__/post-footer.test.ts +15 -0
- package/src/ui/shared/collection-management-labels.ts +33 -2
- package/src/ui/shared/custom-icons.ts +5 -0
- package/src/ui/shared/navigation-labels.ts +2 -4
- package/src/ui/shared/post-article-attributes.ts +52 -0
- package/dist/app-DZDlmh7C.js +0 -6
- package/dist/client/_assets/client-Cevfpm8H.css +0 -2
- package/dist/client/_assets/client-auth-v3yvhbgZ.js +0 -4736
- package/src/client/tiptap/wrapping-input-rules.ts +0 -102
|
@@ -2,7 +2,7 @@ import type { FC } from "hono/jsx";
|
|
|
2
2
|
import {
|
|
3
3
|
HOME_BRANDING_LINK_LABEL,
|
|
4
4
|
HOME_BRANDING_PREFIX,
|
|
5
|
-
|
|
5
|
+
JANT_HOME_URL,
|
|
6
6
|
} from "../../lib/jant-branding.js";
|
|
7
7
|
|
|
8
8
|
export const HomePageBranding: FC = () => {
|
|
@@ -10,7 +10,7 @@ export const HomePageBranding: FC = () => {
|
|
|
10
10
|
<footer class="home-branding-credit">
|
|
11
11
|
{HOME_BRANDING_PREFIX}{" "}
|
|
12
12
|
<a
|
|
13
|
-
href={
|
|
13
|
+
href={JANT_HOME_URL}
|
|
14
14
|
target="_blank"
|
|
15
15
|
rel="noopener noreferrer"
|
|
16
16
|
class="home-branding-link"
|
|
@@ -97,7 +97,11 @@ export const CompactCollectionTags: FC<{
|
|
|
97
97
|
interface PostPublishedLinkProps {
|
|
98
98
|
post: Pick<
|
|
99
99
|
PostView,
|
|
100
|
-
|
|
100
|
+
| "permalink"
|
|
101
|
+
| "publishedAt"
|
|
102
|
+
| "publishedAtFormatted"
|
|
103
|
+
| "publishedAtTime"
|
|
104
|
+
| "status"
|
|
101
105
|
>;
|
|
102
106
|
className: string;
|
|
103
107
|
}
|
|
@@ -107,17 +111,33 @@ export const PostPublishedLink: FC<PostPublishedLinkProps> = ({
|
|
|
107
111
|
className,
|
|
108
112
|
}) => {
|
|
109
113
|
const { i18n } = useLingui();
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
114
|
+
// A draft has never been published; `publishedAt` is standing in for its
|
|
115
|
+
// last edit. The link still matters (it is how you open the post), so keep
|
|
116
|
+
// it and tell the truth about what the date means.
|
|
117
|
+
const publishedLabel =
|
|
118
|
+
post.status === "draft"
|
|
119
|
+
? i18n._(
|
|
120
|
+
msg({
|
|
121
|
+
message: "Last edited on {date} at {time}",
|
|
122
|
+
comment:
|
|
123
|
+
"@context: Tooltip text for the timestamp on an unpublished draft",
|
|
124
|
+
}),
|
|
125
|
+
{
|
|
126
|
+
date: post.publishedAtFormatted,
|
|
127
|
+
time: post.publishedAtTime,
|
|
128
|
+
},
|
|
129
|
+
)
|
|
130
|
+
: i18n._(
|
|
131
|
+
msg({
|
|
132
|
+
message: "Published on {date} at {time}",
|
|
133
|
+
comment:
|
|
134
|
+
"@context: Tooltip text for the published timestamp in post metadata",
|
|
135
|
+
}),
|
|
136
|
+
{
|
|
137
|
+
date: post.publishedAtFormatted,
|
|
138
|
+
time: post.publishedAtTime,
|
|
139
|
+
},
|
|
140
|
+
);
|
|
121
141
|
|
|
122
142
|
return (
|
|
123
143
|
<a href={post.permalink} class={className}>
|
|
@@ -180,12 +200,17 @@ export const PostFooter: FC<PostFooterProps> = ({ post, detail, display }) => {
|
|
|
180
200
|
);
|
|
181
201
|
const safeExternalUrl =
|
|
182
202
|
post.format === "link" && post.url ? sanitizeUrl(post.url) : "";
|
|
203
|
+
// Drafts get an ordinary footer — the Draft badge above already says what
|
|
204
|
+
// they are, and their lifecycle actions live in the post menu next to Edit
|
|
205
|
+
// and Delete rather than in a bespoke button row.
|
|
183
206
|
const showTimestamp = !display?.hideTimestamp;
|
|
184
207
|
const hideActions = !!display?.hideActions;
|
|
185
208
|
const hideReply = !!display?.hideReply;
|
|
186
209
|
const showReply = !hideReply && post.isLastInThread;
|
|
187
210
|
const showCollectionSeparator =
|
|
188
211
|
showTimestamp || !!safeExternalUrl || post.featured;
|
|
212
|
+
const visibleCollections =
|
|
213
|
+
post.replyToId || post.threadRootId ? [] : post.collections;
|
|
189
214
|
|
|
190
215
|
return (
|
|
191
216
|
<footer
|
|
@@ -224,7 +249,7 @@ export const PostFooter: FC<PostFooterProps> = ({ post, detail, display }) => {
|
|
|
224
249
|
</a>
|
|
225
250
|
)}
|
|
226
251
|
<CompactCollectionTags
|
|
227
|
-
collections={
|
|
252
|
+
collections={visibleCollections}
|
|
228
253
|
showSeparator={showCollectionSeparator}
|
|
229
254
|
showIcon={detail}
|
|
230
255
|
/>
|
|
@@ -7,7 +7,7 @@ describe("HomePageBranding", () => {
|
|
|
7
7
|
const html = renderToString(HomePageBranding({}));
|
|
8
8
|
|
|
9
9
|
expect(html).toContain("Build with");
|
|
10
|
-
expect(html).toContain("https://
|
|
10
|
+
expect(html).toContain('href="https://jant.me"');
|
|
11
11
|
expect(html).toContain(">Jant</span>");
|
|
12
12
|
expect(html).not.toContain("<svg");
|
|
13
13
|
});
|
|
@@ -104,6 +104,7 @@ describe("MediaGallery", () => {
|
|
|
104
104
|
|
|
105
105
|
expect(html).toContain("data-feed-short-video");
|
|
106
106
|
expect(html).toContain('data-video-src="/media/clip.mp4"');
|
|
107
|
+
expect(html).toContain(""id":"media-3"");
|
|
107
108
|
expect(html).toContain("data-feed-video-mute-toggle");
|
|
108
109
|
expect(html).not.toContain("media-video-play-overlay");
|
|
109
110
|
expect(html).not.toContain("media-short-video-progress");
|
|
@@ -139,10 +139,10 @@ describe("system nav labels", () => {
|
|
|
139
139
|
|
|
140
140
|
it("translates system nav descriptions", () => {
|
|
141
141
|
expect(getSystemNavDescription("latest", i18n)).toBe(
|
|
142
|
-
"translated:Link to your latest posts.
|
|
142
|
+
"translated:Link to your latest posts. Your homepage shows this feed.",
|
|
143
143
|
);
|
|
144
144
|
expect(getSystemNavDescription("featured", i18n)).toBe(
|
|
145
|
-
"translated:Link to
|
|
145
|
+
"translated:Link to posts you've marked as featured.",
|
|
146
146
|
);
|
|
147
147
|
expect(getSystemNavDescription("archive", i18n)).toBe(
|
|
148
148
|
"translated:Link to the post archive",
|
|
@@ -106,6 +106,21 @@ describe("PostFooter", () => {
|
|
|
106
106
|
expect(html.match(/href="\/studio"/g)).toHaveLength(1);
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
+
it("shows collection tags only on the thread root", () => {
|
|
110
|
+
const html = renderPostFooter(
|
|
111
|
+
createPostView({
|
|
112
|
+
id: "post-child",
|
|
113
|
+
replyToId: "post-root",
|
|
114
|
+
}),
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
expect(html).not.toContain('class="post-collection-tags"');
|
|
118
|
+
expect(html).not.toContain('href="/notes"');
|
|
119
|
+
expect(html).not.toContain("data-collection-popover-trigger");
|
|
120
|
+
expect(html).toContain('aria-label="More actions"');
|
|
121
|
+
expect(html).toContain("data-post-menu-trigger");
|
|
122
|
+
});
|
|
123
|
+
|
|
109
124
|
it("renders the featured icon before the timestamp for client-side toggles", () => {
|
|
110
125
|
const html = renderPostFooter(
|
|
111
126
|
createPostView({
|
|
@@ -53,7 +53,7 @@ const collectionFormMessages = {
|
|
|
53
53
|
}),
|
|
54
54
|
createdLabel: msg({
|
|
55
55
|
message: "Collection created.",
|
|
56
|
-
comment: "@context:
|
|
56
|
+
comment: "@context: Confirmation shown after creating a collection",
|
|
57
57
|
}),
|
|
58
58
|
descriptionLabel: msg({
|
|
59
59
|
message: "Description (optional)",
|
|
@@ -94,6 +94,30 @@ const collectionMutationMessages = {
|
|
|
94
94
|
message: "Edit",
|
|
95
95
|
comment: "@context: Per-collection edit action",
|
|
96
96
|
}),
|
|
97
|
+
addToNavigation: msg({
|
|
98
|
+
message: "Add to Navigation",
|
|
99
|
+
comment: "@context: Action that adds a Collection to site navigation",
|
|
100
|
+
}),
|
|
101
|
+
addingToNavigation: msg({
|
|
102
|
+
message: "Adding…",
|
|
103
|
+
comment:
|
|
104
|
+
"@context: Loading label while adding a Collection to site navigation",
|
|
105
|
+
}),
|
|
106
|
+
addedToNavigation: msg({
|
|
107
|
+
message: "Collection added to navigation.",
|
|
108
|
+
comment:
|
|
109
|
+
"@context: Confirmation after adding a Collection to site navigation",
|
|
110
|
+
}),
|
|
111
|
+
editNavigation: msg({
|
|
112
|
+
message: "Edit Navigation",
|
|
113
|
+
comment:
|
|
114
|
+
"@context: Action that opens Navigation settings for a Collection already in navigation",
|
|
115
|
+
}),
|
|
116
|
+
addToNavigationFailed: msg({
|
|
117
|
+
message: "Couldn't add this collection to navigation. Try again.",
|
|
118
|
+
comment:
|
|
119
|
+
"@context: Error after a Collection could not be added to site navigation",
|
|
120
|
+
}),
|
|
97
121
|
moreActions: msg({
|
|
98
122
|
message: "More actions",
|
|
99
123
|
comment: "@context: Aria-label for collections page more button",
|
|
@@ -112,7 +136,7 @@ const collectionMutationMessages = {
|
|
|
112
136
|
}),
|
|
113
137
|
confirmDelete: msg({
|
|
114
138
|
message:
|
|
115
|
-
"Delete this collection permanently?
|
|
139
|
+
"Delete this collection permanently? Threads inside won't be removed.",
|
|
116
140
|
comment: "@context: Confirm dialog for deleting a collection",
|
|
117
141
|
}),
|
|
118
142
|
cancel: msg({
|
|
@@ -210,6 +234,13 @@ export const getCollectionFormLabels = (i18n: Translator) => ({
|
|
|
210
234
|
|
|
211
235
|
export const getCollectionMutationLabels = (i18n: Translator) => ({
|
|
212
236
|
edit: i18n._(collectionMutationMessages.edit),
|
|
237
|
+
addToNavigation: i18n._(collectionMutationMessages.addToNavigation),
|
|
238
|
+
addingToNavigation: i18n._(collectionMutationMessages.addingToNavigation),
|
|
239
|
+
addedToNavigation: i18n._(collectionMutationMessages.addedToNavigation),
|
|
240
|
+
editNavigation: i18n._(collectionMutationMessages.editNavigation),
|
|
241
|
+
addToNavigationFailed: i18n._(
|
|
242
|
+
collectionMutationMessages.addToNavigationFailed,
|
|
243
|
+
),
|
|
213
244
|
moreActions: i18n._(collectionMutationMessages.moreActions),
|
|
214
245
|
label: i18n._(collectionMutationMessages.label),
|
|
215
246
|
url: i18n._(collectionMutationMessages.url),
|
|
@@ -106,6 +106,11 @@ export const CUSTOM_SYMBOLS: Record<string, CustomSymbol> = {
|
|
|
106
106
|
viewBox: "0 0 24 24",
|
|
107
107
|
inner: `<line ${STROKE_POST_BADGE} x1="12" x2="12" y1="17" y2="22" /><path ${STROKE_POST_BADGE} d="M5 17h14v-1.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V6h1a2 2 0 0 0 0-4H8a2 2 0 0 0 0 4h1v4.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24Z" />`,
|
|
108
108
|
},
|
|
109
|
+
// Post status badge: draft (lucide pencil-line, thin 1.75 stroke).
|
|
110
|
+
"post-status-draft": {
|
|
111
|
+
viewBox: "0 0 24 24",
|
|
112
|
+
inner: `<path ${STROKE_POST_BADGE} d="M12 20h9" /><path ${STROKE_POST_BADGE} d="M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z" />`,
|
|
113
|
+
},
|
|
109
114
|
// Post status badge: private (lucide eye-off, thin 1.75 stroke).
|
|
110
115
|
"post-status-private": {
|
|
111
116
|
viewBox: "0 0 24 24",
|
|
@@ -81,13 +81,11 @@ const SYSTEM_NAV_TITLES: Partial<Record<SystemNavKey, MessageDescriptor>> = {
|
|
|
81
81
|
|
|
82
82
|
const SYSTEM_NAV_DESCRIPTIONS: Record<SystemNavKey, MessageDescriptor> = {
|
|
83
83
|
latest: msg({
|
|
84
|
-
message:
|
|
85
|
-
"Link to your latest posts. If it comes before Featured, the homepage opens here.",
|
|
84
|
+
message: "Link to your latest posts. Your homepage shows this feed.",
|
|
86
85
|
comment: "@context: Description for the latest system navigation toggle",
|
|
87
86
|
}),
|
|
88
87
|
featured: msg({
|
|
89
|
-
message:
|
|
90
|
-
"Link to your featured posts. If it comes before Latest, the homepage opens here.",
|
|
88
|
+
message: "Link to posts you've marked as featured.",
|
|
91
89
|
comment: "@context: Description for the featured system navigation toggle",
|
|
92
90
|
}),
|
|
93
91
|
rss: msg({
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { PostView } from "../../types.js";
|
|
2
|
+
|
|
3
|
+
type PostArticleAttributeSource = Pick<
|
|
4
|
+
PostView,
|
|
5
|
+
| "id"
|
|
6
|
+
| "slug"
|
|
7
|
+
| "format"
|
|
8
|
+
| "status"
|
|
9
|
+
| "visibility"
|
|
10
|
+
| "replyToId"
|
|
11
|
+
| "threadRootId"
|
|
12
|
+
| "pinned"
|
|
13
|
+
| "pinnedInCollection"
|
|
14
|
+
| "featured"
|
|
15
|
+
| "draftTailId"
|
|
16
|
+
>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Builds the shared data-attribute contract for interactive Post articles.
|
|
20
|
+
* Child identity is content-derived and therefore stays stable across feed,
|
|
21
|
+
* detail, search, and partial-render modes.
|
|
22
|
+
*
|
|
23
|
+
* @param post - Render-ready Post identity and action state
|
|
24
|
+
* @returns Data attributes consumed by menus, shortcuts, themes, and scripts
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* <article {...getPostArticleAttributes(post)}>...</article>
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function getPostArticleAttributes(post: PostArticleAttributeSource) {
|
|
32
|
+
const isChildPost = Boolean(post.replyToId || post.threadRootId);
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
"data-post": "",
|
|
36
|
+
"data-format": post.format,
|
|
37
|
+
"data-post-id": post.id,
|
|
38
|
+
"data-post-slug": post.slug,
|
|
39
|
+
"data-thread-root-id": post.threadRootId ?? post.id,
|
|
40
|
+
...(post.pinned ? { "data-post-pinned": "" } : {}),
|
|
41
|
+
...(post.pinnedInCollection
|
|
42
|
+
? { "data-post-pinned-in-collection": "" }
|
|
43
|
+
: {}),
|
|
44
|
+
...(post.featured ? { "data-post-featured": "" } : {}),
|
|
45
|
+
...(post.status === "draft" ? { "data-post-draft": "" } : {}),
|
|
46
|
+
...(post.draftTailId
|
|
47
|
+
? { "data-thread-draft-tail-id": post.draftTailId }
|
|
48
|
+
: {}),
|
|
49
|
+
"data-post-visibility": post.visibility,
|
|
50
|
+
...(isChildPost ? { "data-post-reply": "" } : {}),
|
|
51
|
+
};
|
|
52
|
+
}
|