@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
@@ -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
- JANT_REPO_URL,
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={JANT_REPO_URL}
13
+ href={JANT_HOME_URL}
14
14
  target="_blank"
15
15
  rel="noopener noreferrer"
16
16
  class="home-branding-link"
@@ -208,6 +208,7 @@ export const MediaGallery: FC<MediaGalleryProps> = ({
208
208
  return cat === "image" || cat === "video";
209
209
  })
210
210
  .map((a) => ({
211
+ id: a.id,
211
212
  url: a.url,
212
213
  alt: a.altText || "",
213
214
  width: a.width,
@@ -97,7 +97,11 @@ export const CompactCollectionTags: FC<{
97
97
  interface PostPublishedLinkProps {
98
98
  post: Pick<
99
99
  PostView,
100
- "permalink" | "publishedAt" | "publishedAtFormatted" | "publishedAtTime"
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
- const publishedLabel = i18n._(
111
- msg({
112
- message: "Published on {date} at {time}",
113
- comment:
114
- "@context: Tooltip text for the published timestamp in post metadata",
115
- }),
116
- {
117
- date: post.publishedAtFormatted,
118
- time: post.publishedAtTime,
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={post.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://github.com/jant-me/jant");
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("&quot;id&quot;:&quot;media-3&quot;");
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. If it comes before Featured, the homepage opens here.",
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 your featured posts. If it comes before Latest, the homepage opens here.",
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: Toast shown after creating a collection",
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? Posts inside won't be removed.",
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
+ }
@@ -1,6 +0,0 @@
1
- import "./url-BMYO-Zlt.js";
2
- import { t as createApp } from "./app-2i7-WQHg.js";
3
- import "./export-DWn149b7.js";
4
- import "./env-OHRKGcMj.js";
5
- import "./github-sync-Ckk0sJxK.js";
6
- export { createApp };