@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
|
@@ -11,6 +11,8 @@ const TEST_COLLECTION_ID = "col_test00000000000000000000001";
|
|
|
11
11
|
const TEST_COLLECTION_ID_2 = "col_test00000000000000000000002";
|
|
12
12
|
const TEST_POST_ID = "pst_test00000000000000000000001";
|
|
13
13
|
const TEST_POST_ID_2 = "pst_test00000000000000000000002";
|
|
14
|
+
const TEST_POST_ID_3 = "pst_test00000000000000000000003";
|
|
15
|
+
const TEST_POST_ID_4 = "pst_test00000000000000000000004";
|
|
14
16
|
|
|
15
17
|
function insertTestPath(
|
|
16
18
|
sqlite: ReturnType<typeof createTestDatabase>["sqlite"],
|
|
@@ -76,6 +78,7 @@ function insertTestPost(
|
|
|
76
78
|
id: string;
|
|
77
79
|
slug: string;
|
|
78
80
|
title: string | null;
|
|
81
|
+
format?: "note" | "link" | "quote";
|
|
79
82
|
status?: "draft" | "published";
|
|
80
83
|
visibility?: "public" | "latest_hidden" | "private";
|
|
81
84
|
},
|
|
@@ -87,11 +90,12 @@ function insertTestPost(
|
|
|
87
90
|
id, site_id, format, status, visibility, title, thread_id,
|
|
88
91
|
published_at, last_activity_at, created_at, updated_at
|
|
89
92
|
)
|
|
90
|
-
VALUES (?, ?,
|
|
93
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
91
94
|
)
|
|
92
95
|
.run(
|
|
93
96
|
input.id,
|
|
94
97
|
DEFAULT_TEST_SITE_ID,
|
|
98
|
+
input.format ?? "note",
|
|
95
99
|
input.status ?? "published",
|
|
96
100
|
input.visibility ?? "latest_hidden",
|
|
97
101
|
input.title,
|
|
@@ -232,15 +236,71 @@ describe("NavItemService", () => {
|
|
|
232
236
|
}),
|
|
233
237
|
).rejects.toThrow("Built-in navigation item already exists");
|
|
234
238
|
});
|
|
239
|
+
|
|
240
|
+
it("creates a page nav item from an eligible titled note", async () => {
|
|
241
|
+
insertTestPost(sqlite, {
|
|
242
|
+
id: TEST_POST_ID,
|
|
243
|
+
slug: "about-me",
|
|
244
|
+
title: "About me",
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const item = await navItemService.create({
|
|
248
|
+
type: "page",
|
|
249
|
+
postId: TEST_POST_ID,
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
expect(item).toMatchObject({
|
|
253
|
+
type: "page",
|
|
254
|
+
postId: TEST_POST_ID,
|
|
255
|
+
label: "About me",
|
|
256
|
+
url: "/about-me",
|
|
257
|
+
placement: "header",
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it("rejects duplicate and ineligible page nav items", async () => {
|
|
262
|
+
insertTestPost(sqlite, {
|
|
263
|
+
id: TEST_POST_ID,
|
|
264
|
+
slug: "about",
|
|
265
|
+
title: "About",
|
|
266
|
+
});
|
|
267
|
+
insertTestPost(sqlite, {
|
|
268
|
+
id: TEST_POST_ID_2,
|
|
269
|
+
slug: "private-page",
|
|
270
|
+
title: "Private page",
|
|
271
|
+
visibility: "private",
|
|
272
|
+
});
|
|
273
|
+
await navItemService.create({ type: "page", postId: TEST_POST_ID });
|
|
274
|
+
|
|
275
|
+
await expect(
|
|
276
|
+
navItemService.create({ type: "page", postId: TEST_POST_ID }),
|
|
277
|
+
).rejects.toThrow("Page already added to navigation");
|
|
278
|
+
await expect(
|
|
279
|
+
navItemService.create({ type: "page", postId: TEST_POST_ID_2 }),
|
|
280
|
+
).rejects.toThrow("Page must be a published, non-private titled note");
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it("truncates a page's default navigation label", async () => {
|
|
284
|
+
insertTestPost(sqlite, {
|
|
285
|
+
id: TEST_POST_ID,
|
|
286
|
+
slug: "long-title",
|
|
287
|
+
title: "A".repeat(150),
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const item = await navItemService.create({
|
|
291
|
+
type: "page",
|
|
292
|
+
postId: TEST_POST_ID,
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
expect(item.label).toBe("A".repeat(100));
|
|
296
|
+
});
|
|
235
297
|
});
|
|
236
298
|
|
|
237
|
-
describe("
|
|
238
|
-
it("creates the
|
|
239
|
-
const created = await navItemService.
|
|
299
|
+
describe("materializeDefaultNavigation", () => {
|
|
300
|
+
it("creates the five-item default profile without Latest", async () => {
|
|
301
|
+
const created = await navItemService.materializeDefaultNavigation();
|
|
240
302
|
|
|
241
|
-
expect(created).toHaveLength(6);
|
|
242
303
|
expect(created.map((item) => item.systemKey)).toEqual([
|
|
243
|
-
"latest",
|
|
244
304
|
"featured",
|
|
245
305
|
"collections",
|
|
246
306
|
"archive",
|
|
@@ -251,39 +311,86 @@ describe("NavItemService", () => {
|
|
|
251
311
|
"header",
|
|
252
312
|
"header",
|
|
253
313
|
"header",
|
|
254
|
-
"header",
|
|
255
314
|
"more",
|
|
256
315
|
"more",
|
|
257
316
|
]);
|
|
317
|
+
expect(created.map((item) => item.systemKey)).not.toContain("latest");
|
|
258
318
|
});
|
|
259
319
|
|
|
260
|
-
it("
|
|
261
|
-
await navItemService.create({
|
|
320
|
+
it("preserves an existing optional Latest item", async () => {
|
|
321
|
+
const latest = await navItemService.create({
|
|
262
322
|
type: "system",
|
|
263
|
-
systemKey: "
|
|
323
|
+
systemKey: "latest",
|
|
324
|
+
});
|
|
325
|
+
const customizedLatest = await navItemService.update(latest.id, {
|
|
326
|
+
label: "Recent writing",
|
|
327
|
+
placement: "more",
|
|
328
|
+
position: "a3",
|
|
264
329
|
});
|
|
265
330
|
|
|
266
|
-
const created = await navItemService.
|
|
331
|
+
const created = await navItemService.materializeDefaultNavigation();
|
|
267
332
|
const items = await navItemService.list();
|
|
268
333
|
|
|
269
334
|
expect(created.map((item) => item.systemKey)).toEqual([
|
|
270
|
-
"latest",
|
|
271
335
|
"featured",
|
|
272
336
|
"collections",
|
|
337
|
+
"archive",
|
|
273
338
|
"rss",
|
|
274
339
|
"settings",
|
|
275
340
|
]);
|
|
341
|
+
expect(items.find((item) => item.id === latest.id)).toEqual(
|
|
342
|
+
customizedLatest,
|
|
343
|
+
);
|
|
276
344
|
expect(items.filter((item) => item.type === "system")).toHaveLength(6);
|
|
277
345
|
});
|
|
278
346
|
|
|
279
|
-
it("
|
|
280
|
-
await navItemService.
|
|
347
|
+
it("only appends missing profile items during recovery", async () => {
|
|
348
|
+
const archive = await navItemService.create({
|
|
349
|
+
type: "system",
|
|
350
|
+
systemKey: "archive",
|
|
351
|
+
});
|
|
352
|
+
const customizedArchive = await navItemService.update(archive.id, {
|
|
353
|
+
label: "All posts",
|
|
354
|
+
placement: "more",
|
|
355
|
+
position: "a2",
|
|
356
|
+
});
|
|
357
|
+
const customLink = await navItemService.create({
|
|
358
|
+
type: "link",
|
|
359
|
+
label: "Elsewhere",
|
|
360
|
+
url: "https://example.com",
|
|
361
|
+
position: "a3",
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
const created = await navItemService.materializeDefaultNavigation();
|
|
365
|
+
const items = await navItemService.list();
|
|
366
|
+
|
|
367
|
+
expect(created.map((item) => item.systemKey)).toEqual([
|
|
368
|
+
"featured",
|
|
369
|
+
"collections",
|
|
370
|
+
"rss",
|
|
371
|
+
"settings",
|
|
372
|
+
]);
|
|
373
|
+
expect(items.slice(0, 2).map((item) => item.id)).toEqual([
|
|
374
|
+
archive.id,
|
|
375
|
+
customLink.id,
|
|
376
|
+
]);
|
|
377
|
+
expect(items.find((item) => item.id === archive.id)).toEqual(
|
|
378
|
+
customizedArchive,
|
|
379
|
+
);
|
|
380
|
+
expect(items.find((item) => item.id === customLink.id)).toEqual(
|
|
381
|
+
customLink,
|
|
382
|
+
);
|
|
383
|
+
expect(items.map((item) => item.systemKey)).not.toContain("latest");
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
it("is idempotent when the current profile already exists", async () => {
|
|
387
|
+
await navItemService.materializeDefaultNavigation();
|
|
281
388
|
|
|
282
|
-
const created = await navItemService.
|
|
389
|
+
const created = await navItemService.materializeDefaultNavigation();
|
|
283
390
|
const items = await navItemService.list();
|
|
284
391
|
|
|
285
392
|
expect(created).toEqual([]);
|
|
286
|
-
expect(items.filter((item) => item.type === "system")).toHaveLength(
|
|
393
|
+
expect(items.filter((item) => item.type === "system")).toHaveLength(5);
|
|
287
394
|
});
|
|
288
395
|
});
|
|
289
396
|
|
|
@@ -361,8 +468,53 @@ describe("NavItemService", () => {
|
|
|
361
468
|
});
|
|
362
469
|
});
|
|
363
470
|
|
|
471
|
+
describe("listPageCandidates", () => {
|
|
472
|
+
it("returns eligible notes by title and excludes added pages", async () => {
|
|
473
|
+
insertTestPost(sqlite, {
|
|
474
|
+
id: TEST_POST_ID,
|
|
475
|
+
slug: "about",
|
|
476
|
+
title: "About this site",
|
|
477
|
+
visibility: "latest_hidden",
|
|
478
|
+
});
|
|
479
|
+
insertTestPost(sqlite, {
|
|
480
|
+
id: TEST_POST_ID_2,
|
|
481
|
+
slug: "another-note",
|
|
482
|
+
title: "Another note",
|
|
483
|
+
visibility: "public",
|
|
484
|
+
});
|
|
485
|
+
insertTestPost(sqlite, {
|
|
486
|
+
id: TEST_POST_ID_3,
|
|
487
|
+
slug: "about-link",
|
|
488
|
+
title: "About link",
|
|
489
|
+
format: "link",
|
|
490
|
+
});
|
|
491
|
+
insertTestPost(sqlite, {
|
|
492
|
+
id: TEST_POST_ID_4,
|
|
493
|
+
slug: "about-draft",
|
|
494
|
+
title: "About draft",
|
|
495
|
+
status: "draft",
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
expect(
|
|
499
|
+
await navItemService.listPageCandidates({ query: "ABOUT" }),
|
|
500
|
+
).toEqual([
|
|
501
|
+
{
|
|
502
|
+
id: TEST_POST_ID,
|
|
503
|
+
title: "About this site",
|
|
504
|
+
slug: "about",
|
|
505
|
+
updatedAt: expect.any(Number),
|
|
506
|
+
},
|
|
507
|
+
]);
|
|
508
|
+
|
|
509
|
+
await navItemService.create({ type: "page", postId: TEST_POST_ID });
|
|
510
|
+
expect(
|
|
511
|
+
await navItemService.listPageCandidates({ query: "about" }),
|
|
512
|
+
).toEqual([]);
|
|
513
|
+
});
|
|
514
|
+
});
|
|
515
|
+
|
|
364
516
|
describe("listSuggestedLinks", () => {
|
|
365
|
-
it("suggests a published /about page as a
|
|
517
|
+
it("suggests a published /about page as a page nav item", async () => {
|
|
366
518
|
insertTestPost(sqlite, {
|
|
367
519
|
id: TEST_POST_ID,
|
|
368
520
|
slug: "about",
|
|
@@ -377,7 +529,8 @@ describe("NavItemService", () => {
|
|
|
377
529
|
label: "About me",
|
|
378
530
|
url: "/about",
|
|
379
531
|
targetType: "page",
|
|
380
|
-
navItemType: "
|
|
532
|
+
navItemType: "page",
|
|
533
|
+
postId: TEST_POST_ID,
|
|
381
534
|
},
|
|
382
535
|
]);
|
|
383
536
|
});
|
|
@@ -786,6 +939,32 @@ describe("NavItemService", () => {
|
|
|
786
939
|
});
|
|
787
940
|
});
|
|
788
941
|
|
|
942
|
+
describe("page nav items", () => {
|
|
943
|
+
beforeEach(() => {
|
|
944
|
+
insertTestPost(sqlite, {
|
|
945
|
+
id: TEST_POST_ID,
|
|
946
|
+
slug: "about",
|
|
947
|
+
title: "About",
|
|
948
|
+
});
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
it("allows label updates but keeps the page URL managed", async () => {
|
|
952
|
+
const item = await navItemService.create({
|
|
953
|
+
type: "page",
|
|
954
|
+
postId: TEST_POST_ID,
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
const updated = await navItemService.update(item.id, {
|
|
958
|
+
label: "Start here",
|
|
959
|
+
});
|
|
960
|
+
expect(updated?.label).toBe("Start here");
|
|
961
|
+
|
|
962
|
+
await expect(
|
|
963
|
+
navItemService.update(item.id, { url: "/other" }),
|
|
964
|
+
).rejects.toThrow("Page navigation URLs are managed automatically");
|
|
965
|
+
});
|
|
966
|
+
});
|
|
967
|
+
|
|
789
968
|
describe("getCollectionFreshness", () => {
|
|
790
969
|
beforeEach(() => {
|
|
791
970
|
insertTestCollection(sqlite, TEST_COLLECTION_ID, "design", "Design");
|
|
@@ -810,7 +989,7 @@ describe("NavItemService", () => {
|
|
|
810
989
|
// Add it to the collection recently
|
|
811
990
|
sqlite
|
|
812
991
|
.prepare(
|
|
813
|
-
`INSERT INTO
|
|
992
|
+
`INSERT INTO thread_collection (site_id, thread_id, collection_id, created_at, position)
|
|
814
993
|
VALUES (?, ?, ?, ?, 0)`,
|
|
815
994
|
)
|
|
816
995
|
.run(DEFAULT_TEST_SITE_ID, "pst_test001", TEST_COLLECTION_ID, ts);
|
|
@@ -838,7 +1017,7 @@ describe("NavItemService", () => {
|
|
|
838
1017
|
);
|
|
839
1018
|
sqlite
|
|
840
1019
|
.prepare(
|
|
841
|
-
`INSERT INTO
|
|
1020
|
+
`INSERT INTO thread_collection (site_id, thread_id, collection_id, created_at, position)
|
|
842
1021
|
VALUES (?, ?, ?, ?, 0)`,
|
|
843
1022
|
)
|
|
844
1023
|
.run(DEFAULT_TEST_SITE_ID, "pst_test002", TEST_COLLECTION_ID, oldTs);
|
|
@@ -849,6 +1028,35 @@ describe("NavItemService", () => {
|
|
|
849
1028
|
expect(result.has(TEST_COLLECTION_ID)).toBe(false);
|
|
850
1029
|
});
|
|
851
1030
|
|
|
1031
|
+
it("detects freshness from a recent root edit even when Thread activity is old", async () => {
|
|
1032
|
+
const oldTs = now() - 60 * 60 * 72;
|
|
1033
|
+
const recentTs = now();
|
|
1034
|
+
sqlite
|
|
1035
|
+
.prepare(
|
|
1036
|
+
`INSERT INTO post (id, site_id, thread_id, format, status, visibility, created_at, updated_at, last_activity_at)
|
|
1037
|
+
VALUES (?, ?, ?, 'note', 'published', 'public', ?, ?, ?)`,
|
|
1038
|
+
)
|
|
1039
|
+
.run(
|
|
1040
|
+
"pst_edited",
|
|
1041
|
+
DEFAULT_TEST_SITE_ID,
|
|
1042
|
+
"pst_edited",
|
|
1043
|
+
oldTs,
|
|
1044
|
+
recentTs,
|
|
1045
|
+
oldTs,
|
|
1046
|
+
);
|
|
1047
|
+
sqlite
|
|
1048
|
+
.prepare(
|
|
1049
|
+
`INSERT INTO thread_collection (site_id, thread_id, collection_id, created_at, position)
|
|
1050
|
+
VALUES (?, ?, ?, ?, 0)`,
|
|
1051
|
+
)
|
|
1052
|
+
.run(DEFAULT_TEST_SITE_ID, "pst_edited", TEST_COLLECTION_ID, oldTs);
|
|
1053
|
+
|
|
1054
|
+
const result = await navItemService.getCollectionFreshness([
|
|
1055
|
+
TEST_COLLECTION_ID,
|
|
1056
|
+
]);
|
|
1057
|
+
expect(result.get(TEST_COLLECTION_ID)).toBe(recentTs);
|
|
1058
|
+
});
|
|
1059
|
+
|
|
852
1060
|
it("detects freshness from recent thread replies", async () => {
|
|
853
1061
|
const oldTs = now() - 60 * 60 * 72; // 72 hours ago
|
|
854
1062
|
const recentTs = now();
|
|
@@ -871,7 +1079,7 @@ describe("NavItemService", () => {
|
|
|
871
1079
|
// Add the root to the collection (old)
|
|
872
1080
|
sqlite
|
|
873
1081
|
.prepare(
|
|
874
|
-
`INSERT INTO
|
|
1082
|
+
`INSERT INTO thread_collection (site_id, thread_id, collection_id, created_at, position)
|
|
875
1083
|
VALUES (?, ?, ?, ?, 0)`,
|
|
876
1084
|
)
|
|
877
1085
|
.run(DEFAULT_TEST_SITE_ID, "pst_root", TEST_COLLECTION_ID, oldTs);
|