@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.
Files changed (350) hide show
  1. package/bin/commands/import-site.js +88 -13
  2. package/bin/commands/migrate.js +55 -0
  3. package/bin/commands/posts/rebuild-html.js +184 -0
  4. package/bin/commands/site/snapshot/import.js +14 -10
  5. package/bin/lib/d1-query.js +23 -5
  6. package/bin/lib/migration-runner.js +29 -7
  7. package/bin/lib/node-database.js +32 -0
  8. package/bin/lib/site-snapshot.js +347 -46
  9. package/bin/lib/sql-export.js +1 -1
  10. package/bin/lib/thread-collection-migration.js +326 -0
  11. package/dist/app-C75Zc8dD.js +6 -0
  12. package/dist/{app-2i7-WQHg.js → app-C7_4oab9.js} +7774 -6425
  13. package/dist/client/.vite/manifest.json +8 -8
  14. package/dist/client/_assets/chunks/{url-pLre2DM_.js → url-CU9pEbk5.js} +1 -1
  15. package/dist/client/_assets/{client-BvID5ucz.js → client-Bq0vre8Y.js} +59 -38
  16. package/dist/client/_assets/client-D3VZyG4L.css +2 -0
  17. package/dist/client/_assets/client-auth-F2rb9WfF.js +5571 -0
  18. package/dist/{env-OHRKGcMj.js → env-BPYViDJJ.js} +1 -1
  19. package/dist/{export-DWn149b7.js → export-Dl5KCiEs.js} +1348 -128
  20. package/dist/{github-api-BgSiE71w.js → github-api-BNF35Lkx.js} +1 -1
  21. package/dist/{github-app-BbklkFmU.js → github-app-DdiD-bC4.js} +1 -1
  22. package/dist/{github-sync-C0zyF6XS.js → github-sync-Bqg62IvV.js} +3 -3
  23. package/dist/{github-sync-Ckk0sJxK.js → github-sync-HdK2EgvJ.js} +3 -3
  24. package/dist/index.js +5 -5
  25. package/dist/node.js +7 -7
  26. package/dist/{url-BMYO-Zlt.js → url-CbLAtlZe.js} +517 -12
  27. package/package.json +11 -10
  28. package/src/__tests__/bin/posts-rebuild-html.test.ts +137 -0
  29. package/src/__tests__/dev-navigation-defaults.test.ts +22 -0
  30. package/src/__tests__/export-hugo-build.test.ts +63 -4
  31. package/src/__tests__/export-import-roundtrip.test.ts +6 -4
  32. package/src/__tests__/export-service.test.ts +142 -9
  33. package/src/__tests__/helpers/app.ts +3 -0
  34. package/src/__tests__/helpers/export-fixtures.ts +2 -0
  35. package/src/__tests__/import-site-command.test.ts +65 -0
  36. package/src/__tests__/mise-config.test.ts +22 -0
  37. package/src/__tests__/vite-config.test.ts +45 -0
  38. package/src/app.tsx +16 -3
  39. package/src/client/__tests__/collection-created-notice.test.ts +36 -0
  40. package/src/client/__tests__/collection-form-bridge.test.ts +10 -1
  41. package/src/client/__tests__/collection-page-actions.test.ts +71 -2
  42. package/src/client/__tests__/compose-bridge.test.ts +316 -2
  43. package/src/client/__tests__/compose-shortcuts.test.ts +20 -0
  44. package/src/client/__tests__/feed-video-player.test.ts +16 -1
  45. package/src/client/__tests__/footnote-rail.test.ts +472 -0
  46. package/src/client/__tests__/hydrate-partial.test.ts +3 -0
  47. package/src/client/__tests__/toast.test.ts +82 -1
  48. package/src/client/collection-created-notice.ts +66 -0
  49. package/src/client/collection-form-bridge.ts +17 -0
  50. package/src/client/collection-navigation.ts +44 -0
  51. package/src/client/collection-page-actions.ts +57 -1
  52. package/src/client/components/__tests__/compose-format-convert.test.ts +0 -19
  53. package/src/client/components/__tests__/jant-collection-directory.test.ts +155 -6
  54. package/src/client/components/__tests__/jant-command-palette.test.ts +51 -0
  55. package/src/client/components/__tests__/jant-compose-dialog.test.ts +2268 -206
  56. package/src/client/components/__tests__/jant-compose-editor.test.ts +147 -59
  57. package/src/client/components/__tests__/jant-compose-fullscreen.test.ts +114 -64
  58. package/src/client/components/__tests__/jant-config-editor.test.ts +405 -0
  59. package/src/client/components/__tests__/jant-media-lightbox.test.ts +121 -0
  60. package/src/client/components/__tests__/jant-nav-manager.test.ts +538 -2
  61. package/src/client/components/__tests__/jant-post-form.test.ts +2 -2
  62. package/src/client/components/__tests__/jant-post-menu.test.ts +47 -5
  63. package/src/client/components/__tests__/jant-settings-avatar.test.ts +2 -2
  64. package/src/client/components/__tests__/jant-settings-general.test.ts +3 -3
  65. package/src/client/components/collection-manager-types.ts +9 -3
  66. package/src/client/components/compose-format-convert.ts +5 -1
  67. package/src/client/components/compose-types.ts +55 -3
  68. package/src/client/components/jant-collection-directory.ts +165 -30
  69. package/src/client/components/jant-command-palette.ts +14 -7
  70. package/src/client/components/jant-compose-dialog.ts +1542 -694
  71. package/src/client/components/jant-compose-editor.ts +237 -99
  72. package/src/client/components/jant-compose-fullscreen.ts +27 -9
  73. package/src/client/components/jant-config-editor.ts +722 -0
  74. package/src/client/components/jant-media-lightbox.ts +100 -18
  75. package/src/client/components/jant-nav-manager.ts +1283 -54
  76. package/src/client/components/jant-post-form.ts +3 -3
  77. package/src/client/components/jant-post-menu.ts +177 -95
  78. package/src/client/components/nav-manager-types.ts +51 -2
  79. package/src/client/components/post-form-types.ts +1 -1
  80. package/src/client/compose-bridge.ts +147 -123
  81. package/src/client/compose-launch.ts +13 -0
  82. package/src/client/compose-shortcuts.ts +5 -1
  83. package/src/client/feed-video-player.ts +62 -2
  84. package/src/client/footnote-rail.ts +478 -0
  85. package/src/client/hydrate-partial.ts +2 -0
  86. package/src/client/media-lightbox-events.ts +63 -0
  87. package/src/client/post-refresh.ts +135 -0
  88. package/src/client/site-header-fragment.ts +38 -0
  89. package/src/client/tiptap/__tests__/blockquote-editing.test.ts +201 -0
  90. package/src/client/tiptap/__tests__/clear-formatting.test.ts +168 -0
  91. package/src/client/tiptap/__tests__/link-input-rules.test.ts +121 -0
  92. package/src/client/tiptap/__tests__/list-editing.test.ts +447 -0
  93. package/src/client/tiptap/__tests__/markdown-clipboard.test.ts +727 -4
  94. package/src/client/tiptap/__tests__/table-controls.test.ts +263 -0
  95. package/src/client/tiptap/__tests__/table-size-picker.test.ts +179 -0
  96. package/src/client/tiptap/bubble-menu.ts +88 -10
  97. package/src/client/tiptap/continuous-lists.ts +102 -0
  98. package/src/client/tiptap/create-editor.ts +3 -0
  99. package/src/client/tiptap/extensions.ts +14 -5
  100. package/src/client/tiptap/link-input-rules.ts +4 -4
  101. package/src/client/tiptap/markdown-clipboard.ts +608 -11
  102. package/src/client/tiptap/slash-commands.ts +8 -1
  103. package/src/client/tiptap/structural-keymap.ts +211 -0
  104. package/src/client/tiptap/tab-indent.ts +8 -22
  105. package/src/client/tiptap/table-control-labels.ts +30 -0
  106. package/src/client/tiptap/table-controls.ts +537 -0
  107. package/src/client/tiptap/table-size-picker.ts +254 -0
  108. package/src/client/toast.ts +133 -39
  109. package/src/client-auth.ts +1 -0
  110. package/src/client.ts +1 -0
  111. package/src/db/__tests__/backfill-thread-activity.test.ts +234 -0
  112. package/src/db/__tests__/d1-query.test.ts +43 -1
  113. package/src/db/__tests__/migration-runner.test.ts +63 -0
  114. package/src/db/__tests__/migrations.test.ts +469 -0
  115. package/src/db/__tests__/thread-activity.test.ts +113 -0
  116. package/src/db/__tests__/thread-collection-migration.test.ts +364 -0
  117. package/src/db/backfills/0005_split_thread_activity_from_quiet_replies.sql +68 -0
  118. package/src/db/migrations/0027_old_blue_blade.sql +39 -0
  119. package/src/db/migrations/0028_superb_post.sql +2 -0
  120. package/src/db/migrations/0029_boring_magma.sql +1 -0
  121. package/src/db/migrations/0030_typical_vivisector.sql +50 -0
  122. package/src/db/migrations/0031_many_ego.sql +3 -0
  123. package/src/db/migrations/meta/0027_snapshot.json +2511 -0
  124. package/src/db/migrations/meta/0028_snapshot.json +2511 -0
  125. package/src/db/migrations/meta/0029_snapshot.json +2519 -0
  126. package/src/db/migrations/meta/0030_snapshot.json +2541 -0
  127. package/src/db/migrations/meta/0031_snapshot.json +2562 -0
  128. package/src/db/migrations/meta/_journal.json +35 -0
  129. package/src/db/migrations/pg/0025_moaning_epoch.sql +39 -0
  130. package/src/db/migrations/pg/0026_talented_killer_shrike.sql +2 -0
  131. package/src/db/migrations/pg/0027_short_cannonball.sql +1 -0
  132. package/src/db/migrations/pg/0028_perfect_sharon_carter.sql +27 -0
  133. package/src/db/migrations/pg/0029_rare_hairball.sql +3 -0
  134. package/src/db/migrations/pg/meta/0025_snapshot.json +3204 -0
  135. package/src/db/migrations/pg/meta/0026_snapshot.json +3204 -0
  136. package/src/db/migrations/pg/meta/0027_snapshot.json +3211 -0
  137. package/src/db/migrations/pg/meta/0028_snapshot.json +3248 -0
  138. package/src/db/migrations/pg/meta/0029_snapshot.json +3289 -0
  139. package/src/db/migrations/pg/meta/_journal.json +35 -0
  140. package/src/db/pg/schema.ts +46 -20
  141. package/src/db/rehearsal-fixtures/demo-current.json +39 -4
  142. package/src/db/rehearsal-fixtures/demo-current.sql +121 -6
  143. package/src/db/schema.ts +48 -20
  144. package/src/db/thread-activity.ts +101 -0
  145. package/src/i18n/__tests__/detect.test.ts +8 -2
  146. package/src/i18n/detect.ts +14 -5
  147. package/src/i18n/locales/public/en.po +222 -51
  148. package/src/i18n/locales/public/en.ts +1 -1
  149. package/src/i18n/locales/public/zh-Hans.po +216 -45
  150. package/src/i18n/locales/public/zh-Hans.ts +1 -1
  151. package/src/i18n/locales/public/zh-Hant.po +216 -45
  152. package/src/i18n/locales/public/zh-Hant.ts +1 -1
  153. package/src/i18n/locales/settings/en.po +513 -10
  154. package/src/i18n/locales/settings/en.ts +1 -1
  155. package/src/i18n/locales/settings/zh-Hans.po +515 -12
  156. package/src/i18n/locales/settings/zh-Hans.ts +1 -1
  157. package/src/i18n/locales/settings/zh-Hant.po +515 -12
  158. package/src/i18n/locales/settings/zh-Hant.ts +1 -1
  159. package/src/lib/__tests__/api-settings.test.ts +299 -0
  160. package/src/lib/__tests__/constants.test.ts +5 -0
  161. package/src/lib/__tests__/feed-policy.test.ts +25 -0
  162. package/src/lib/__tests__/feed.test.ts +168 -0
  163. package/src/lib/__tests__/footnotes-upgrade.test.ts +181 -0
  164. package/src/lib/__tests__/markdown-roundtrip-embed.test.ts +61 -0
  165. package/src/lib/__tests__/markdown-to-tiptap.test.ts +32 -4
  166. package/src/lib/__tests__/markdown.test.ts +24 -6
  167. package/src/lib/__tests__/navigation.test.ts +59 -2
  168. package/src/lib/__tests__/post-body-html.test.ts +176 -0
  169. package/src/lib/__tests__/post-display.test.ts +64 -0
  170. package/src/lib/__tests__/resolve-config.test.ts +113 -1
  171. package/src/lib/__tests__/slug.test.ts +18 -0
  172. package/src/lib/__tests__/summary.test.ts +82 -0
  173. package/src/lib/__tests__/timeline.test.ts +109 -70
  174. package/src/lib/__tests__/timezones.test.ts +31 -3
  175. package/src/lib/__tests__/tiptap-render.test.ts +268 -9
  176. package/src/lib/__tests__/tiptap-to-markdown.test.ts +6 -0
  177. package/src/lib/__tests__/translit.test.ts +87 -0
  178. package/src/lib/__tests__/url.test.ts +53 -0
  179. package/src/lib/__tests__/view.test.ts +53 -0
  180. package/src/lib/__tests__/worker-response-cache.test.ts +18 -1
  181. package/src/lib/api-settings.ts +239 -12
  182. package/src/lib/collection-sort.ts +7 -5
  183. package/src/lib/constants.ts +2 -0
  184. package/src/lib/feed-path.ts +25 -0
  185. package/src/lib/feed-policy.ts +64 -0
  186. package/src/lib/feed.ts +113 -11
  187. package/src/lib/footnotes.ts +264 -0
  188. package/src/lib/github-sync-site-config.ts +2 -0
  189. package/src/lib/hugo-markdown.ts +15 -3
  190. package/src/lib/jant-branding.ts +1 -0
  191. package/src/lib/link-preview.ts +25 -0
  192. package/src/lib/markdown-manager.ts +193 -5
  193. package/src/lib/markdown.ts +10 -3
  194. package/src/lib/navigation.ts +16 -3
  195. package/src/lib/post-body-html.ts +131 -0
  196. package/src/lib/post-display.ts +47 -8
  197. package/src/lib/render.tsx +9 -2
  198. package/src/lib/resolve-config.ts +100 -16
  199. package/src/lib/schemas.ts +133 -1
  200. package/src/lib/settings-paths.ts +5 -0
  201. package/src/lib/site-skill.ts +78 -0
  202. package/src/lib/summary.ts +16 -5
  203. package/src/lib/timeline.ts +137 -131
  204. package/src/lib/timezones.ts +54 -14
  205. package/src/lib/tiptap-render.ts +359 -83
  206. package/src/lib/translit.ts +288 -0
  207. package/src/lib/url.ts +123 -12
  208. package/src/lib/view.ts +58 -20
  209. package/src/lib/worker-response-cache.ts +11 -18
  210. package/src/middleware/__tests__/public-content-access.test.ts +91 -0
  211. package/src/middleware/config.ts +2 -2
  212. package/src/middleware/public-content-access.ts +87 -0
  213. package/src/node/__tests__/cli-export.test.ts +14 -0
  214. package/src/node/__tests__/cli-migrate.test.ts +6 -0
  215. package/src/node/__tests__/cli-site-snapshot.test.ts +205 -2
  216. package/src/node/__tests__/cli-snapshot-meta.test.ts +100 -0
  217. package/src/node/index.ts +2 -1
  218. package/src/preset.css +16 -2
  219. package/src/routes/__tests__/compose.test.ts +51 -0
  220. package/src/routes/__tests__/site-skill.test.ts +112 -0
  221. package/src/routes/api/__tests__/collections.test.ts +91 -19
  222. package/src/routes/api/__tests__/mcp.test.ts +65 -1
  223. package/src/routes/api/__tests__/nav-items.test.ts +91 -0
  224. package/src/routes/api/__tests__/palette.test.ts +44 -0
  225. package/src/routes/api/__tests__/public-access.test.ts +81 -0
  226. package/src/routes/api/__tests__/settings.test.ts +217 -0
  227. package/src/routes/api/collections.ts +22 -26
  228. package/src/routes/api/export.ts +2 -0
  229. package/src/routes/api/internal/__tests__/post-body-html.test.ts +163 -0
  230. package/src/routes/api/internal/__tests__/sites.test.ts +35 -2
  231. package/src/routes/api/internal/post-body-html.ts +43 -0
  232. package/src/routes/api/internal/sites.ts +24 -0
  233. package/src/routes/api/nav-items.ts +24 -1
  234. package/src/routes/api/posts.ts +14 -10
  235. package/src/routes/api/public/__tests__/archive.test.ts +35 -0
  236. package/src/routes/api/public/__tests__/posts.test.ts +246 -0
  237. package/src/routes/api/public/archive.ts +4 -0
  238. package/src/routes/api/public/posts.ts +48 -24
  239. package/src/routes/api/search.ts +3 -0
  240. package/src/routes/api/settings.ts +33 -0
  241. package/src/routes/auth/__tests__/setup.test.ts +7 -4
  242. package/src/routes/compose.tsx +8 -3
  243. package/src/routes/dash/settings.tsx +45 -2
  244. package/src/routes/feed/__tests__/feed.test.ts +210 -6
  245. package/src/routes/feed/__tests__/sitemap.test.ts +68 -1
  246. package/src/routes/feed/feed.ts +23 -14
  247. package/src/routes/pages/__tests__/archive-params.test.ts +384 -3
  248. package/src/routes/pages/__tests__/collection-routing.test.ts +63 -5
  249. package/src/routes/pages/__tests__/collections.test.ts +9 -9
  250. package/src/routes/pages/__tests__/featured.test.ts +6 -2
  251. package/src/routes/pages/__tests__/preview.test.ts +176 -0
  252. package/src/routes/pages/__tests__/search.test.ts +69 -0
  253. package/src/routes/pages/archive.tsx +90 -22
  254. package/src/routes/pages/collection.tsx +32 -19
  255. package/src/routes/pages/collections.tsx +6 -1
  256. package/src/routes/pages/page.tsx +86 -11
  257. package/src/routes/site-skill.ts +18 -0
  258. package/src/services/__tests__/auth.test.ts +7 -5
  259. package/src/services/__tests__/collection.test.ts +190 -44
  260. package/src/services/__tests__/navigation.test.ts +229 -21
  261. package/src/services/__tests__/post-timeline.test.ts +249 -39
  262. package/src/services/__tests__/post.test.ts +844 -5
  263. package/src/services/__tests__/search.test.ts +48 -1
  264. package/src/services/__tests__/settings.test.ts +8 -0
  265. package/src/services/__tests__/site-admin.test.ts +121 -1
  266. package/src/services/auth.ts +2 -2
  267. package/src/services/bootstrap.ts +3 -2
  268. package/src/services/collection.ts +224 -167
  269. package/src/services/export-theme/assets/client-site.css +1 -1
  270. package/src/services/export-theme/assets/client-site.js +46 -25
  271. package/src/services/export-theme/layouts/_default/list.html +18 -4
  272. package/src/services/export-theme/layouts/_default/rss.xml +8 -12
  273. package/src/services/export-theme/layouts/featured/list.html +5 -4
  274. package/src/services/export-theme/layouts/partials/featured-thread.html +56 -0
  275. package/src/services/export-theme/layouts/partials/footer.html +1 -1
  276. package/src/services/export-theme/layouts/partials/media-gallery.html +1 -0
  277. package/src/services/export-theme/styles/main.css +30 -2
  278. package/src/services/export.ts +94 -85
  279. package/src/services/mcp.ts +37 -27
  280. package/src/services/media.ts +1 -1
  281. package/src/services/navigation.ts +185 -46
  282. package/src/services/path.ts +4 -1
  283. package/src/services/post.ts +1142 -342
  284. package/src/services/search.ts +17 -2
  285. package/src/services/settings.ts +2 -10
  286. package/src/services/site-admin.ts +63 -43
  287. package/src/style-cjk-jp.css +1 -1
  288. package/src/style-cjk-kr.css +1 -1
  289. package/src/style-cjk-tc.css +1 -1
  290. package/src/style-cjk.css +1 -1
  291. package/src/styles/components.css +540 -14
  292. package/src/styles/site-media.css +111 -19
  293. package/src/styles/tokens.css +76 -10
  294. package/src/styles/ui.css +2227 -1347
  295. package/src/types/bindings.ts +3 -0
  296. package/src/types/config.ts +243 -12
  297. package/src/types/constants.ts +22 -1
  298. package/src/types/entities.ts +14 -8
  299. package/src/types/operations.ts +18 -10
  300. package/src/types/props.ts +20 -2
  301. package/src/types/raw-assets.d.ts +5 -0
  302. package/src/types/views.ts +22 -4
  303. package/src/ui/__tests__/font-themes.test.ts +42 -30
  304. package/src/ui/compose/ComposeDialog.tsx +109 -19
  305. package/src/ui/dash/appearance/NavigationContent.tsx +332 -4
  306. package/src/ui/dash/appearance/__tests__/NavigationContent.test.tsx +23 -0
  307. package/src/ui/dash/settings/ConfigEditorContent.tsx +578 -0
  308. package/src/ui/dash/settings/GeneralContent.tsx +15 -5
  309. package/src/ui/dash/settings/SettingsRootContent.tsx +21 -1
  310. package/src/ui/dash/settings/__tests__/ConfigEditorContent.test.tsx +98 -0
  311. package/src/ui/dash/settings/__tests__/SettingsRootContent.test.tsx +15 -0
  312. package/src/ui/feed/CuratedThreadPreview.tsx +16 -4
  313. package/src/ui/feed/LinkCard.tsx +2 -12
  314. package/src/ui/feed/LinkPreview.tsx +2 -7
  315. package/src/ui/feed/NoteCard.tsx +10 -20
  316. package/src/ui/feed/PostStatusBadges.tsx +42 -3
  317. package/src/ui/feed/QuoteCard.tsx +2 -12
  318. package/src/ui/feed/ThreadPreview.tsx +26 -34
  319. package/src/ui/feed/TimelineFeed.tsx +2 -2
  320. package/src/ui/feed/__tests__/thread-preview.test.ts +197 -56
  321. package/src/ui/feed/__tests__/timeline-cards.test.ts +178 -3
  322. package/src/ui/feed/thread-preview-state.ts +5 -7
  323. package/src/ui/font-themes.ts +74 -26
  324. package/src/ui/layouts/BaseLayout.tsx +22 -8
  325. package/src/ui/layouts/__tests__/BaseLayout.test.tsx +64 -1
  326. package/src/ui/pages/ArchivePage.tsx +131 -24
  327. package/src/ui/pages/CollectionPage.tsx +101 -22
  328. package/src/ui/pages/CollectionsPage.tsx +3 -1
  329. package/src/ui/pages/PostPage.tsx +39 -12
  330. package/src/ui/pages/SearchPage.tsx +6 -14
  331. package/src/ui/pages/__tests__/ArchivePage.test.tsx +70 -0
  332. package/src/ui/pages/__tests__/PostPage.test.tsx +88 -0
  333. package/src/ui/shared/CollectionDirectory.tsx +13 -9
  334. package/src/ui/shared/CollectionsManager.tsx +17 -7
  335. package/src/ui/shared/DraftPreviewBar.tsx +49 -0
  336. package/src/ui/shared/HomePageBranding.tsx +2 -2
  337. package/src/ui/shared/MediaGallery.tsx +1 -0
  338. package/src/ui/shared/PostFooter.tsx +38 -13
  339. package/src/ui/shared/__tests__/home-page-branding.test.tsx +1 -1
  340. package/src/ui/shared/__tests__/media-gallery.test.ts +1 -0
  341. package/src/ui/shared/__tests__/navigation-labels.test.ts +2 -2
  342. package/src/ui/shared/__tests__/post-footer.test.ts +15 -0
  343. package/src/ui/shared/collection-management-labels.ts +33 -2
  344. package/src/ui/shared/custom-icons.ts +5 -0
  345. package/src/ui/shared/navigation-labels.ts +2 -4
  346. package/src/ui/shared/post-article-attributes.ts +52 -0
  347. package/dist/app-DZDlmh7C.js +0 -6
  348. package/dist/client/_assets/client-Cevfpm8H.css +0 -2
  349. package/dist/client/_assets/client-auth-v3yvhbgZ.js +0 -4736
  350. package/src/client/tiptap/wrapping-input-rules.ts +0 -102
@@ -17,7 +17,9 @@ import type {
17
17
  NavManagerSuggestedLink,
18
18
  SystemNavConfig,
19
19
  } from "../../../client/components/nav-manager-types.js";
20
+ import type { CollectionFormLabels } from "../../../client/components/collection-types.js";
20
21
  import { toPublicHref, toPublicPath } from "../../../lib/url.js";
22
+ import { getCollectionFormLabels } from "../../shared/collection-management-labels.js";
21
23
  import {
22
24
  getNavItemDisplayLabel,
23
25
  getSystemNavDescription,
@@ -34,6 +36,7 @@ export function NavigationContent({
34
36
  directoryData,
35
37
  suggestedLinks,
36
38
  mainRssFeed,
39
+ rssFeedsEnabled,
37
40
  siteName,
38
41
  sitePathPrefix = "",
39
42
  }: {
@@ -41,6 +44,7 @@ export function NavigationContent({
41
44
  directoryData: CollectionsDirectoryData;
42
45
  suggestedLinks: SuggestedNavLink[];
43
46
  mainRssFeed: string;
47
+ rssFeedsEnabled: boolean;
44
48
  siteName: string;
45
49
  sitePathPrefix?: string;
46
50
  }) {
@@ -64,6 +68,90 @@ export function NavigationContent({
64
68
  }),
65
69
  );
66
70
  const moreLabel = i18n._(NAV_MORE_LABEL);
71
+ const createCollectionLabel = i18n._(
72
+ msg({
73
+ message: "Create Collection",
74
+ comment:
75
+ "@context: Button and dialog title for quick collection creation in Navigation settings",
76
+ }),
77
+ );
78
+ const collectionFormLabels: CollectionFormLabels = {
79
+ ...getCollectionFormLabels(i18n),
80
+ titleLabel: i18n._(
81
+ msg({
82
+ message: "Title",
83
+ comment: "@context: Collection title field in Navigation settings",
84
+ }),
85
+ ),
86
+ titlePlaceholder: i18n._(
87
+ msg({
88
+ message: "My Collection",
89
+ comment:
90
+ "@context: Collection title placeholder in Navigation settings",
91
+ }),
92
+ ),
93
+ slugLabel: i18n._(
94
+ msg({
95
+ message: "Collection link",
96
+ comment: "@context: Collection slug field in Navigation settings",
97
+ }),
98
+ ),
99
+ slugHelp: i18n._(
100
+ msg({
101
+ message: "This is the last part of the collection link.",
102
+ comment: "@context: Collection slug help text in Navigation settings",
103
+ }),
104
+ ),
105
+ slugInvalidHelp: i18n._(
106
+ msg({
107
+ message: "Use lowercase letters, numbers, and hyphens only.",
108
+ comment:
109
+ "@context: Collection slug validation error in Navigation settings",
110
+ }),
111
+ ),
112
+ slugReservedHelp: i18n._(
113
+ msg({
114
+ message: "This link is reserved. Choose something else.",
115
+ comment:
116
+ "@context: Reserved collection slug error in Navigation settings",
117
+ }),
118
+ ),
119
+ slugTooLongHelp: i18n._(
120
+ msg({
121
+ message: "Keep this link under 200 characters.",
122
+ comment: "@context: Long collection slug error in Navigation settings",
123
+ }),
124
+ ),
125
+ editSlugLabel: i18n._(
126
+ msg({
127
+ message: "Edit link",
128
+ comment:
129
+ "@context: Button to edit the generated collection slug in Navigation settings",
130
+ }),
131
+ ),
132
+ resetSlugLabel: i18n._(
133
+ msg({
134
+ message: "Reset link",
135
+ comment:
136
+ "@context: Button to reset the collection slug in Navigation settings",
137
+ }),
138
+ ),
139
+ quickHint: i18n._(
140
+ msg({
141
+ message: "More options are available after you create it.",
142
+ comment:
143
+ "@context: Helper text in quick collection creation in Navigation settings",
144
+ }),
145
+ ),
146
+ quickSubmitLabel: createCollectionLabel,
147
+ createdLabel: i18n._(
148
+ msg({
149
+ message: "Collection created.",
150
+ comment:
151
+ "@context: Heading after quick collection creation in Navigation settings",
152
+ }),
153
+ ),
154
+ };
67
155
 
68
156
  const suggestedTargetLabels = {
69
157
  page: i18n._(
@@ -98,6 +186,7 @@ export function NavigationContent({
98
186
  type: item.type,
99
187
  systemKey: item.systemKey,
100
188
  collectionId: item.collectionId,
189
+ postId: item.postId,
101
190
  label: item.label,
102
191
  displayLabel: getNavItemDisplayLabel(item, i18n, sitePathPrefix),
103
192
  url,
@@ -185,6 +274,12 @@ export function NavigationContent({
185
274
  comment: "@context: Nav item type badge",
186
275
  }),
187
276
  ),
277
+ page: i18n._(
278
+ msg({
279
+ message: "page",
280
+ comment: "@context: Nav item type badge for page items",
281
+ }),
282
+ ),
188
283
  system: i18n._(
189
284
  msg({
190
285
  message: "system",
@@ -235,6 +330,13 @@ export function NavigationContent({
235
330
  "@context: Confirm dialog for deleting a custom navigation link",
236
331
  }),
237
332
  ),
333
+ confirmDeletePage: i18n._(
334
+ msg({
335
+ message:
336
+ "Remove this page from navigation? The page itself won't be deleted.",
337
+ comment: "@context: Confirm dialog for removing a page from navigation",
338
+ }),
339
+ ),
238
340
  orderSaved: i18n._(
239
341
  msg({
240
342
  message: "Navigation order updated.",
@@ -353,6 +455,182 @@ export function NavigationContent({
353
455
  comment: "@context: Toast after adding a suggested nav link",
354
456
  }),
355
457
  ),
458
+ addPageToNavigation: i18n._(
459
+ msg({
460
+ message: "Add page to navigation",
461
+ comment: "@context: Section heading for adding a page to navigation",
462
+ }),
463
+ ),
464
+ addPageDescription: i18n._(
465
+ msg({
466
+ message:
467
+ "Choose a titled note that isn't already in navigation, or create a new page.",
468
+ comment: "@context: Description for adding a page to navigation",
469
+ }),
470
+ ),
471
+ addPage: i18n._(
472
+ msg({
473
+ message: "Add Page",
474
+ comment: "@context: Button that opens the navigation page picker",
475
+ }),
476
+ ),
477
+ searchPages: i18n._(
478
+ msg({
479
+ message: "Search pages",
480
+ comment: "@context: Placeholder for the navigation page search",
481
+ }),
482
+ ),
483
+ recentPages: i18n._(
484
+ msg({
485
+ message: "Recently updated",
486
+ comment: "@context: Heading above recent pages in the page picker",
487
+ }),
488
+ ),
489
+ searchingPages: i18n._(
490
+ msg({
491
+ message: "Searching pages…",
492
+ comment: "@context: Loading state in the navigation page picker",
493
+ }),
494
+ ),
495
+ noMatchingPages: i18n._(
496
+ msg({
497
+ message:
498
+ "No matching pages available to add. Try another title or create a new page.",
499
+ comment: "@context: Empty search results in the page picker",
500
+ }),
501
+ ),
502
+ noPages: i18n._(
503
+ msg({
504
+ message: "No pages available. Create one to add it to navigation.",
505
+ comment: "@context: Empty state in the navigation page picker",
506
+ }),
507
+ ),
508
+ pageSearchFailed: i18n._(
509
+ msg({
510
+ message: "Couldn't load pages. Try again in a moment.",
511
+ comment: "@context: Error shown when navigation page search fails",
512
+ }),
513
+ ),
514
+ createNewPage: i18n._(
515
+ msg({
516
+ message: "Create new page",
517
+ comment: "@context: Action at the bottom of the navigation page picker",
518
+ }),
519
+ ),
520
+ createPage: i18n._(
521
+ msg({
522
+ message: "Create Page",
523
+ comment: "@context: Button and dialog title for quick page creation",
524
+ }),
525
+ ),
526
+ createPageDescription: i18n._(
527
+ msg({
528
+ message: "Create a public page that won't appear in Latest.",
529
+ comment: "@context: Description in the quick-create page dialog",
530
+ }),
531
+ ),
532
+ pageTitle: i18n._(
533
+ msg({
534
+ message: "Title",
535
+ comment: "@context: Title field label in quick page creation",
536
+ }),
537
+ ),
538
+ pageAddress: i18n._(
539
+ msg({
540
+ message: "Page address",
541
+ comment: "@context: Slug field label in quick page creation",
542
+ }),
543
+ ),
544
+ pageVisibilityHint: i18n._(
545
+ msg({
546
+ message: "The page is public but stays out of Latest.",
547
+ comment: "@context: Visibility note in quick page creation",
548
+ }),
549
+ ),
550
+ titleRequired: i18n._(
551
+ msg({
552
+ message: "Enter a page title.",
553
+ comment: "@context: Validation error for an empty quick page title",
554
+ }),
555
+ ),
556
+ slugInvalid: i18n._(
557
+ msg({
558
+ message: "Use lowercase letters, numbers, and hyphens.",
559
+ comment: "@context: Validation error for an invalid page slug",
560
+ }),
561
+ ),
562
+ slugReserved: i18n._(
563
+ msg({
564
+ message: "That address is reserved. Choose another one.",
565
+ comment: "@context: Validation error for a reserved page slug",
566
+ }),
567
+ ),
568
+ slugTooLong: i18n._(
569
+ msg({
570
+ message: "Keep the page address under 200 characters.",
571
+ comment: "@context: Validation error for a long page slug",
572
+ }),
573
+ ),
574
+ slugUnavailable: i18n._(
575
+ msg({
576
+ message: "That address is already in use. Choose another one.",
577
+ comment: "@context: Validation error for an unavailable page slug",
578
+ }),
579
+ ),
580
+ checkingAddress: i18n._(
581
+ msg({
582
+ message: "Checking address…",
583
+ comment: "@context: Loading text while checking page slug availability",
584
+ }),
585
+ ),
586
+ creatingPage: i18n._(
587
+ msg({
588
+ message: "Creating page…",
589
+ comment: "@context: Loading label while creating a page",
590
+ }),
591
+ ),
592
+ createPageFailed: i18n._(
593
+ msg({
594
+ message: "Couldn't create the page. Check the details and try again.",
595
+ comment: "@context: Error when quick page creation fails",
596
+ }),
597
+ ),
598
+ pageCreated: i18n._(
599
+ msg({
600
+ message: "Page created.",
601
+ comment: "@context: Heading after quick page creation",
602
+ }),
603
+ ),
604
+ pageCreatedDescription: i18n._(
605
+ msg({
606
+ message: "Add it to navigation now or open the editor to add content.",
607
+ comment: "@context: Description after quick page creation",
608
+ }),
609
+ ),
610
+ addToNavigation: i18n._(
611
+ msg({
612
+ message: "Add to Navigation",
613
+ comment: "@context: Button that adds a created page to navigation",
614
+ }),
615
+ ),
616
+ editPage: i18n._(
617
+ msg({
618
+ message: "Edit Page",
619
+ comment: "@context: Button that opens a page for editing",
620
+ }),
621
+ ),
622
+ pageAdded: i18n._(
623
+ msg({
624
+ message: "Page added to navigation.",
625
+ comment: "@context: Confirmation after adding a page to navigation",
626
+ }),
627
+ ),
628
+ back: i18n._(
629
+ msg({
630
+ message: "Back",
631
+ comment: "@context: Button returning from page creation to page search",
632
+ }),
633
+ ),
356
634
  collection: i18n._(
357
635
  msg({
358
636
  message: "collection",
@@ -387,12 +665,56 @@ export function NavigationContent({
387
665
  ),
388
666
  noCollections: i18n._(
389
667
  msg({
390
- message:
391
- "No collections yet. Create one first, then add it to your navigation.",
668
+ message: "No collections yet. Create one here to add it to navigation.",
392
669
  comment:
393
670
  "@context: Empty state when no collections exist for nav picker",
394
671
  }),
395
672
  ),
673
+ createNewCollection: i18n._(
674
+ msg({
675
+ message: "Create new collection",
676
+ comment:
677
+ "@context: Action at the bottom of the Navigation collection picker",
678
+ }),
679
+ ),
680
+ createCollection: createCollectionLabel,
681
+ creatingCollection: i18n._(
682
+ msg({
683
+ message: "Creating collection…",
684
+ comment:
685
+ "@context: Loading label while creating a collection in Navigation settings",
686
+ }),
687
+ ),
688
+ createCollectionFailed: i18n._(
689
+ msg({
690
+ message:
691
+ "Couldn't create the collection. Check the details and try again.",
692
+ comment:
693
+ "@context: Error when quick collection creation fails in Navigation settings",
694
+ }),
695
+ ),
696
+ collectionCreatedDescription: i18n._(
697
+ msg({
698
+ message: "Add it to navigation now or open the editor to add details.",
699
+ comment:
700
+ "@context: Description after quick collection creation in Navigation settings",
701
+ }),
702
+ ),
703
+ editCollection: i18n._(
704
+ msg({
705
+ message: "Edit Collection",
706
+ comment:
707
+ "@context: Button that opens a newly created collection for editing",
708
+ }),
709
+ ),
710
+ collectionAdded: i18n._(
711
+ msg({
712
+ message: "Collection added to navigation.",
713
+ comment:
714
+ "@context: Confirmation after adding a collection to navigation",
715
+ }),
716
+ ),
717
+ collectionFormLabels,
396
718
  confirmDeleteCollection: i18n._(
397
719
  msg({
398
720
  message:
@@ -414,13 +736,19 @@ export function NavigationContent({
414
736
  collections={escapeJson(collectionsData)}
415
737
  suggested-links={escapeJson(suggestedLinksData)}
416
738
  site-name={siteName}
739
+ rss-feeds-enabled={rssFeedsEnabled || undefined}
417
740
  >
418
741
  {/* SSR fallback: static preview until JS hydrates */}
419
742
  {(() => {
420
- const headerNavItems = navItems.filter(
743
+ const previewItems = rssFeedsEnabled
744
+ ? navItems
745
+ : navItems.filter(
746
+ (item) => item.type !== "system" || item.systemKey !== "rss",
747
+ );
748
+ const headerNavItems = previewItems.filter(
421
749
  (item) => item.placement !== "more",
422
750
  );
423
- const moreNavItems = navItems.filter(
751
+ const moreNavItems = previewItems.filter(
424
752
  (item) => item.placement === "more",
425
753
  );
426
754
  return (
@@ -24,6 +24,7 @@ function renderNavigationContent(
24
24
  directoryData: { collections: [], items: [], directoryItems: [] },
25
25
  suggestedLinks: [],
26
26
  mainRssFeed: "latest",
27
+ rssFeedsEnabled: true,
27
28
  siteName: "Test Site",
28
29
  ...props,
29
30
  }),
@@ -53,6 +54,28 @@ describe("NavigationContent", () => {
53
54
  expect(html).toContain("Built-in links");
54
55
  });
55
56
 
57
+ it("hides the saved RSS item only from the preview when feeds are off", () => {
58
+ const html = renderNavigationContent({
59
+ rssFeedsEnabled: false,
60
+ navItems: [
61
+ {
62
+ id: "nav_rss",
63
+ type: "system",
64
+ systemKey: "rss",
65
+ label: "Saved feed",
66
+ url: "/feed",
67
+ placement: "header",
68
+ position: "a0",
69
+ createdAt: 1,
70
+ updatedAt: 1,
71
+ },
72
+ ],
73
+ });
74
+
75
+ expect(html).not.toContain(">Saved feed<");
76
+ expect(html).toContain("&quot;systemKey&quot;:&quot;rss&quot;");
77
+ });
78
+
56
79
  it("serializes suggested links with translated target labels", () => {
57
80
  const html = renderNavigationContent({
58
81
  suggestedLinks: [