@jant/core 0.6.16 → 0.7.1

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 (592) hide show
  1. package/README.md +11 -11
  2. package/bin/commands/assets/upload.js +192 -15
  3. package/bin/commands/export.js +3 -1
  4. package/bin/commands/import-site.js +749 -220
  5. package/bin/commands/reset-password.js +21 -8
  6. package/bin/commands/setup.js +136 -0
  7. package/bin/commands/site/export.js +71 -34
  8. package/bin/commands/site/pull-media.js +2 -6
  9. package/bin/commands/site/snapshot/export.js +19 -61
  10. package/bin/commands/site/snapshot/import.js +23 -24
  11. package/bin/lib/d1-query.js +92 -18
  12. package/bin/lib/hugo-markdown.js +4 -0
  13. package/bin/lib/node-env.js +40 -4
  14. package/bin/lib/site-pull-media.js +21 -28
  15. package/bin/lib/site-selection.js +94 -29
  16. package/bin/lib/site-snapshot.js +338 -3
  17. package/bin/lib/sql-export.js +68 -5
  18. package/bin/lib/wrangler-cli.js +37 -2
  19. package/bin/lib/wrangler-json.js +35 -0
  20. package/bin/lib/zip-archive.js +187 -0
  21. package/dist/{app-C7_4oab9.js → app-ZcaI1kPN.js} +53190 -13529
  22. package/dist/client/.vite/manifest.json +255 -90
  23. package/dist/client/_assets/chunks/confirm-D7GrwsCN.js +45 -0
  24. package/dist/client/_assets/chunks/create-editor-B-m7X7S5.js +261 -0
  25. package/dist/client/_assets/chunks/{native-DpcrFAPh.js → emoji-mart-C4RpRKcU.js} +716 -1
  26. package/dist/client/_assets/chunks/footnote-rail-CmeoVtnU.js +1 -0
  27. package/dist/client/_assets/chunks/heic-to-CuP2Qlsw.js +1 -0
  28. package/dist/client/_assets/chunks/jant-locale-picker-DL6mIOT5.js +69 -0
  29. package/dist/client/_assets/chunks/lit-DW8VmJAT.js +2 -0
  30. package/dist/client/_assets/chunks/mediabunny-DRaCQ1r-.js +31 -0
  31. package/dist/client/_assets/chunks/rolldown-runtime-hePW80VL.js +1 -0
  32. package/dist/client/_assets/chunks/settings-paths-BcdySNx6.js +84 -0
  33. package/dist/client/_assets/chunks/site-header-nav-DzXsFk05.js +1 -0
  34. package/dist/client/_assets/chunks/slug-format-CRXO1AL5.js +1 -0
  35. package/dist/client/_assets/chunks/slugify-373citbs.js +1 -0
  36. package/dist/client/_assets/chunks/sortable-list-BJyd-LXE.js +2 -0
  37. package/dist/client/_assets/chunks/types-D5iF3H1a.js +1 -0
  38. package/dist/client/_assets/chunks/unsafe-html-B5ZEXaxg.js +1 -0
  39. package/dist/client/_assets/chunks/unsafe-svg-BkscJx69.js +2 -0
  40. package/dist/client/_assets/client-DAhoqPdr.css +2 -0
  41. package/dist/client/_assets/client-auth-CAMfTrKW.js +828 -0
  42. package/dist/client/_assets/client-author-DQ8R-8KR.css +2 -0
  43. package/dist/client/_assets/client-compose-D6rExKVK.js +2004 -0
  44. package/dist/client/_assets/client-knSEyUJO.js +295 -0
  45. package/dist/client/_assets/client-manage-sVOkqVbH.js +2170 -0
  46. package/dist/client/_assets/client-settings-CGR_nZ78.js +1112 -0
  47. package/dist/github-sync-Gw4orAHk.js +8398 -0
  48. package/dist/index.js +2 -5
  49. package/dist/node.js +11 -9
  50. package/package.json +15 -5
  51. package/src/__tests__/auth-session-freshness.test.ts +57 -0
  52. package/src/__tests__/basecoat-variants.test.ts +121 -0
  53. package/src/__tests__/bin/assets-upload.test.ts +68 -0
  54. package/src/__tests__/dev-scripts.test.ts +203 -0
  55. package/src/__tests__/export-collection-order.test.ts +276 -0
  56. package/src/__tests__/export-feed-ids.test.ts +184 -0
  57. package/src/__tests__/export-feed-order.test.ts +294 -0
  58. package/src/__tests__/export-hugo-build.test.ts +390 -0
  59. package/src/__tests__/export-import-roundtrip.test.ts +94 -0
  60. package/src/__tests__/export-service.test.ts +842 -28
  61. package/src/__tests__/export-smart-collection.test.ts +329 -0
  62. package/src/__tests__/helpers/component-css.ts +91 -0
  63. package/src/__tests__/helpers/db.ts +33 -0
  64. package/src/__tests__/helpers/export-fixtures.ts +3 -0
  65. package/src/__tests__/helpers/hugo-site.ts +146 -0
  66. package/src/__tests__/import-site-command.test.ts +487 -1
  67. package/src/__tests__/mise-config.test.ts +75 -4
  68. package/src/__tests__/node-dev-tasks.test.ts +264 -0
  69. package/src/__tests__/site-export-canonical-import.test.ts +149 -0
  70. package/src/__tests__/snapshot-canonical-replay.test.ts +179 -0
  71. package/src/__tests__/snapshot-settings.test.ts +97 -0
  72. package/src/__tests__/snapshot-tables.test.ts +219 -0
  73. package/src/__tests__/sql-export.test.ts +173 -0
  74. package/src/__tests__/stylesheet-audience.test.ts +159 -0
  75. package/src/__tests__/stylesheet-breakpoints.test.ts +183 -0
  76. package/src/__tests__/zip-archive.test.ts +106 -0
  77. package/src/app.tsx +86 -22
  78. package/src/auth.ts +18 -1
  79. package/src/client/__tests__/collection-page-actions.test.ts +51 -2
  80. package/src/client/__tests__/compose-bridge-image-upload.test.ts +196 -0
  81. package/src/client/__tests__/compose-bridge-video-poster.test.ts +159 -0
  82. package/src/client/__tests__/compose-bridge.test.ts +272 -0
  83. package/src/client/__tests__/compose-launch.test.ts +62 -1
  84. package/src/client/__tests__/compose-shortcuts.test.ts +38 -9
  85. package/src/client/__tests__/compose-triggers.test.ts +90 -0
  86. package/src/client/__tests__/copy-field.test.ts +162 -0
  87. package/src/client/__tests__/custom-url-menu.test.ts +127 -6
  88. package/src/client/__tests__/image-processor.test.ts +324 -2
  89. package/src/client/__tests__/lazy-entries.test.ts +92 -0
  90. package/src/client/__tests__/media-scroll-hint.test.ts +155 -0
  91. package/src/client/__tests__/runtime-paths.test.ts +84 -0
  92. package/src/client/__tests__/smart-collection-page-actions.test.ts +158 -0
  93. package/src/client/__tests__/toast.test.ts +23 -0
  94. package/src/client/__tests__/video-processor-probe.test.ts +175 -0
  95. package/src/client/__tests__/video-processor.test.ts +181 -0
  96. package/src/client/audio-processor.ts +24 -15
  97. package/src/client/audio-waveform.ts +49 -0
  98. package/src/client/collection-dialog-host.ts +72 -0
  99. package/src/client/collection-navigation.ts +51 -16
  100. package/src/client/collection-page-actions.ts +26 -0
  101. package/src/client/components/__tests__/jant-collection-dialog.test.ts +329 -0
  102. package/src/client/components/__tests__/jant-collection-directory.test.ts +274 -10
  103. package/src/client/components/__tests__/jant-collection-form.test.ts +59 -178
  104. package/src/client/components/__tests__/jant-command-palette.test.ts +28 -0
  105. package/src/client/components/__tests__/jant-compose-dialog-draft-storage.test.ts +340 -0
  106. package/src/client/components/__tests__/jant-compose-dialog.test.ts +1250 -53
  107. package/src/client/components/__tests__/jant-compose-editor.test.ts +544 -40
  108. package/src/client/components/__tests__/jant-compose-fullscreen.test.ts +0 -1
  109. package/src/client/components/__tests__/jant-locale-picker.test.ts +207 -0
  110. package/src/client/components/__tests__/jant-nav-manager.test.ts +234 -15
  111. package/src/client/components/__tests__/jant-post-menu.test.ts +413 -2
  112. package/src/client/components/__tests__/jant-post-picker.test.ts +197 -0
  113. package/src/client/components/__tests__/jant-settings-avatar.test.ts +15 -12
  114. package/src/client/components/__tests__/jant-settings-general.test.ts +561 -172
  115. package/src/client/components/__tests__/jant-settings-language.test.ts +851 -0
  116. package/src/client/components/__tests__/jant-smart-collection-dialog.test.ts +665 -0
  117. package/src/client/components/collection-dialog-types.ts +49 -0
  118. package/src/client/components/collection-manager-types.ts +32 -1
  119. package/src/client/components/collection-types.ts +1 -15
  120. package/src/client/components/compose-types.ts +75 -1
  121. package/src/client/components/jant-collection-dialog.ts +722 -0
  122. package/src/client/components/jant-collection-directory.ts +567 -182
  123. package/src/client/components/jant-collection-form.ts +53 -232
  124. package/src/client/components/jant-command-palette.ts +100 -49
  125. package/src/client/components/jant-compose-dialog.ts +1486 -707
  126. package/src/client/components/jant-compose-editor.ts +673 -336
  127. package/src/client/components/jant-compose-fullscreen.ts +51 -43
  128. package/src/client/components/jant-config-editor.ts +65 -53
  129. package/src/client/components/jant-confirm-dialog.ts +13 -11
  130. package/src/client/components/jant-locale-picker.ts +418 -0
  131. package/src/client/components/jant-media-lightbox.ts +146 -136
  132. package/src/client/components/jant-nav-manager.ts +690 -366
  133. package/src/client/components/jant-post-menu.ts +1086 -282
  134. package/src/client/components/jant-post-picker.ts +324 -0
  135. package/src/client/components/jant-repo-picker-types.ts +6 -1
  136. package/src/client/components/jant-repo-picker.ts +137 -108
  137. package/src/client/components/jant-settings-avatar.ts +31 -27
  138. package/src/client/components/jant-settings-general.ts +622 -543
  139. package/src/client/components/jant-settings-language.ts +1087 -0
  140. package/src/client/components/jant-smart-collection-dialog.ts +1021 -0
  141. package/src/client/components/jant-text-preview.ts +94 -86
  142. package/src/client/components/nav-manager-types.ts +62 -1
  143. package/src/client/components/settings-types.ts +14 -29
  144. package/src/client/components/smart-collection-conditions.ts +285 -0
  145. package/src/client/components/smart-collection-dialog-types.ts +68 -0
  146. package/src/client/compose-bridge.ts +214 -141
  147. package/src/client/compose-launch.ts +76 -2
  148. package/src/client/compose-shortcuts.ts +6 -8
  149. package/src/client/compose-triggers.ts +50 -0
  150. package/src/client/copy-field.ts +108 -0
  151. package/src/client/custom-url-menu.ts +60 -4
  152. package/src/client/icons.ts +14 -0
  153. package/src/client/image-plan.ts +165 -0
  154. package/src/client/image-processor.ts +195 -117
  155. package/src/client/image-worker-client.ts +45 -0
  156. package/src/client/image-worker.ts +135 -0
  157. package/src/client/lazy-entries.ts +95 -0
  158. package/src/client/lazy-slugify.ts +2 -2
  159. package/src/client/media-scroll-hint.ts +43 -2
  160. package/src/client/mediabunny.ts +29 -0
  161. package/src/client/post-picker.ts +41 -0
  162. package/src/client/runtime-paths.ts +74 -1
  163. package/src/client/settings-bridge.ts +4 -10
  164. package/src/client/site-header-nav.js +18 -6
  165. package/src/client/smart-collection-dialog-host.ts +116 -0
  166. package/src/client/smart-collection-page-actions.ts +208 -0
  167. package/src/client/tiptap/__tests__/bubble-menu.test.ts +110 -0
  168. package/src/client/tiptap/__tests__/floating-position.test.ts +136 -1
  169. package/src/client/tiptap/__tests__/inline-image-upload.test.ts +37 -0
  170. package/src/client/tiptap/__tests__/list-editing.test.ts +224 -86
  171. package/src/client/tiptap/__tests__/mark-exit.test.ts +1 -2
  172. package/src/client/tiptap/__tests__/markdown-clipboard.test.ts +26 -0
  173. package/src/client/tiptap/bubble-menu.ts +47 -16
  174. package/src/client/tiptap/extensions.ts +0 -3
  175. package/src/client/tiptap/floating-position.ts +216 -2
  176. package/src/client/tiptap/inline-image-upload.ts +7 -3
  177. package/src/client/tiptap/link-toolbar.ts +22 -9
  178. package/src/client/tiptap/structural-keymap.ts +158 -47
  179. package/src/client/toast.ts +13 -0
  180. package/src/client/types/vite-worker.d.ts +12 -0
  181. package/src/client/upload-with-metadata.ts +3 -13
  182. package/src/client/video-processor.ts +351 -107
  183. package/src/client-auth.ts +14 -31
  184. package/src/client-compose.ts +19 -0
  185. package/src/client-manage.ts +13 -0
  186. package/src/client-settings.ts +14 -0
  187. package/src/client-site.ts +10 -3
  188. package/src/client.ts +4 -0
  189. package/src/db/__tests__/backfill-nav-label-mirrors.test.ts +149 -0
  190. package/src/db/__tests__/d1-query.test.ts +56 -1
  191. package/src/db/__tests__/schema-enum-sources.test.ts +33 -0
  192. package/src/db/__tests__/smart-collection-placement.test.ts +402 -0
  193. package/src/db/backfills/0006_clear_mirrored_page_nav_labels.sql +31 -0
  194. package/src/db/migrations/0032_married_tomas.sql +3 -0
  195. package/src/db/migrations/0033_busy_johnny_storm.sql +198 -0
  196. package/src/db/migrations/0034_cheerful_rumiko_fujikawa.sql +35 -0
  197. package/src/db/migrations/meta/0032_snapshot.json +2582 -0
  198. package/src/db/migrations/meta/0033_snapshot.json +2816 -0
  199. package/src/db/migrations/meta/0034_snapshot.json +2816 -0
  200. package/src/db/migrations/meta/_journal.json +21 -0
  201. package/src/db/migrations/pg/0030_abandoned_nighthawk.sql +3 -0
  202. package/src/db/migrations/pg/0031_strong_ultimatum.sql +128 -0
  203. package/src/db/migrations/pg/0032_furry_multiple_man.sql +6 -0
  204. package/src/db/migrations/pg/meta/0030_snapshot.json +3329 -0
  205. package/src/db/migrations/pg/meta/0031_snapshot.json +3660 -0
  206. package/src/db/migrations/pg/meta/0032_snapshot.json +3660 -0
  207. package/src/db/migrations/pg/meta/_journal.json +21 -0
  208. package/src/db/pg/schema.ts +195 -27
  209. package/src/db/post-visibility.ts +117 -0
  210. package/src/db/schema.ts +222 -27
  211. package/src/i18n/__tests__/detect.test.ts +26 -81
  212. package/src/i18n/__tests__/supported-locales.test.ts +83 -0
  213. package/src/i18n/context.tsx +12 -2
  214. package/src/i18n/detect.ts +7 -66
  215. package/src/i18n/locales/glossary.zh-Hans.yml +44 -4
  216. package/src/i18n/locales/glossary.zh-Hant.yml +44 -4
  217. package/src/i18n/locales/public/en.po +490 -158
  218. package/src/i18n/locales/public/en.ts +1 -1
  219. package/src/i18n/locales/public/zh-Hans.po +487 -155
  220. package/src/i18n/locales/public/zh-Hans.ts +1 -1
  221. package/src/i18n/locales/public/zh-Hant.po +487 -155
  222. package/src/i18n/locales/public/zh-Hant.ts +1 -1
  223. package/src/i18n/locales/settings/en.po +555 -73
  224. package/src/i18n/locales/settings/en.ts +1 -1
  225. package/src/i18n/locales/settings/zh-Hans.po +601 -119
  226. package/src/i18n/locales/settings/zh-Hans.ts +1 -1
  227. package/src/i18n/locales/settings/zh-Hant.po +614 -132
  228. package/src/i18n/locales/settings/zh-Hant.ts +1 -1
  229. package/src/i18n/locales.ts +94 -0
  230. package/src/i18n/middleware.ts +12 -2
  231. package/src/i18n/supported-locales.ts +80 -0
  232. package/src/lib/__tests__/api-settings.test.ts +11 -2
  233. package/src/lib/__tests__/asset-path.test.ts +92 -0
  234. package/src/lib/__tests__/deferred.test.ts +90 -0
  235. package/src/lib/__tests__/discover-ping.test.ts +89 -0
  236. package/src/lib/__tests__/discover.test.ts +410 -0
  237. package/src/lib/__tests__/feed-policy.test.ts +26 -0
  238. package/src/lib/__tests__/feed.test.ts +1526 -15
  239. package/src/lib/__tests__/filter-dimensions.test.ts +341 -0
  240. package/src/lib/__tests__/github-sync-repo-name.test.ts +40 -0
  241. package/src/lib/__tests__/hosted-signin.test.ts +1 -1
  242. package/src/lib/__tests__/http-cache.test.ts +162 -0
  243. package/src/lib/__tests__/image.test.ts +27 -1
  244. package/src/lib/__tests__/jant-docs-dev.test.ts +21 -0
  245. package/src/lib/__tests__/jant-docs.test.ts +23 -0
  246. package/src/lib/__tests__/lang-detect.test.ts +231 -0
  247. package/src/lib/__tests__/markdown-to-tiptap.test.ts +105 -0
  248. package/src/lib/__tests__/markdown.test.ts +10 -0
  249. package/src/lib/__tests__/media-helpers.test.ts +81 -0
  250. package/src/lib/__tests__/navigation.test.ts +135 -1
  251. package/src/lib/__tests__/resolve-config.test.ts +131 -3
  252. package/src/lib/__tests__/schemas.test.ts +69 -5
  253. package/src/lib/__tests__/site-unavailable-page.test.ts +25 -0
  254. package/src/lib/__tests__/slug.test.ts +70 -0
  255. package/src/lib/__tests__/slugify.test.ts +85 -0
  256. package/src/lib/__tests__/storage.test.ts +32 -0
  257. package/src/lib/__tests__/thread-fold.test.ts +113 -0
  258. package/src/lib/__tests__/timeline.test.ts +87 -0
  259. package/src/lib/__tests__/tiptap-to-markdown.test.ts +172 -4
  260. package/src/lib/__tests__/upload-sideload.test.ts +14 -0
  261. package/src/lib/__tests__/url-fetch.test.ts +1 -2
  262. package/src/lib/__tests__/url.test.ts +78 -72
  263. package/src/lib/__tests__/view-language.test.ts +413 -0
  264. package/src/lib/__tests__/worker-response-cache.test.ts +90 -0
  265. package/src/lib/address.ts +57 -0
  266. package/src/lib/api-posts.ts +12 -0
  267. package/src/lib/asset-path.ts +98 -1
  268. package/src/lib/build-env.ts +16 -0
  269. package/src/lib/collection-groups.ts +5 -1
  270. package/src/lib/collection-paths.ts +3 -10
  271. package/src/lib/constants.ts +28 -3
  272. package/src/lib/copy-field.ts +36 -0
  273. package/src/lib/crypto.ts +40 -0
  274. package/src/lib/csp-builder.ts +2 -1
  275. package/src/lib/deferred.ts +79 -0
  276. package/src/lib/discover-ping.ts +141 -0
  277. package/src/lib/discover.ts +439 -0
  278. package/src/lib/env.ts +134 -0
  279. package/src/lib/errors.ts +33 -0
  280. package/src/lib/feed-policy.ts +236 -2
  281. package/src/lib/feed.ts +926 -73
  282. package/src/lib/filter-dimensions.ts +1349 -0
  283. package/src/lib/github-sync-repo-name.ts +45 -0
  284. package/src/lib/github-sync-site-config.ts +3 -0
  285. package/src/lib/hosted-signin.ts +1 -1
  286. package/src/lib/http-cache.ts +148 -0
  287. package/src/lib/hugo-markdown.ts +62 -0
  288. package/src/lib/icons.ts +9 -2
  289. package/src/lib/ids.ts +3 -0
  290. package/src/lib/image.ts +17 -4
  291. package/src/lib/jant-docs.ts +42 -0
  292. package/src/lib/lang-detect.ts +308 -0
  293. package/src/lib/markdown-manager.ts +392 -2
  294. package/src/lib/media-helpers.ts +13 -1
  295. package/src/lib/navigation.ts +78 -11
  296. package/src/lib/pagination.ts +28 -24
  297. package/src/lib/per-language-surfaces.ts +67 -0
  298. package/src/lib/post-body-html.ts +11 -4
  299. package/src/lib/post-meta.ts +19 -0
  300. package/src/lib/render.tsx +55 -7
  301. package/src/lib/resolve-config.ts +111 -6
  302. package/src/lib/schemas.ts +251 -15
  303. package/src/lib/site-header-fragment.tsx +2 -1
  304. package/src/lib/site-unavailable-page.ts +47 -0
  305. package/src/lib/slug.ts +51 -7
  306. package/src/lib/slugify.ts +113 -0
  307. package/src/lib/startup-config.ts +4 -6
  308. package/src/lib/storage.ts +7 -0
  309. package/src/lib/summary.ts +50 -0
  310. package/src/lib/thread-fold.ts +161 -0
  311. package/src/lib/time.ts +32 -0
  312. package/src/lib/timeline.ts +43 -2
  313. package/src/lib/tiptap-render.ts +1 -2
  314. package/src/lib/tiptap-to-markdown.ts +13 -7
  315. package/src/lib/upload.ts +16 -13
  316. package/src/lib/url.ts +159 -86
  317. package/src/lib/version.ts +10 -8
  318. package/src/lib/view-language.ts +436 -0
  319. package/src/lib/view.ts +53 -25
  320. package/src/lib/viewer-context.ts +62 -0
  321. package/src/middleware/__tests__/auth.test.ts +70 -2
  322. package/src/middleware/__tests__/cache-control.test.ts +71 -3
  323. package/src/middleware/__tests__/onboarding.test.ts +76 -5
  324. package/src/middleware/__tests__/secure-headers.test.ts +1 -1
  325. package/src/middleware/__tests__/session.test.ts +181 -33
  326. package/src/middleware/auth.ts +50 -31
  327. package/src/middleware/cache-control.ts +75 -10
  328. package/src/middleware/config.ts +6 -6
  329. package/src/middleware/error-handler.ts +12 -0
  330. package/src/middleware/onboarding.ts +32 -10
  331. package/src/middleware/secure-headers.ts +1 -1
  332. package/src/middleware/session.ts +96 -8
  333. package/src/node/__tests__/cli-migrate.test.ts +21 -19
  334. package/src/node/__tests__/cli-reset-password.test.ts +81 -8
  335. package/src/node/__tests__/cli-runtime-target.test.ts +48 -1
  336. package/src/node/__tests__/cli-setup.test.ts +163 -0
  337. package/src/node/__tests__/cli-site-selection.test.ts +128 -38
  338. package/src/node/__tests__/cli-site-snapshot.test.ts +67 -0
  339. package/src/node/__tests__/cli-snapshot-meta.test.ts +20 -0
  340. package/src/node/__tests__/runtime.test.ts +75 -0
  341. package/src/node/index.ts +3 -0
  342. package/src/node/request-handler.ts +3 -1
  343. package/src/preset.css +76 -22
  344. package/src/routes/__tests__/feed-validator.test.ts +156 -0
  345. package/src/routes/api/__tests__/collections.test.ts +114 -0
  346. package/src/routes/api/__tests__/discover.test.ts +222 -0
  347. package/src/routes/api/__tests__/nav-items.test.ts +212 -2
  348. package/src/routes/api/__tests__/post-translations.test.ts +829 -0
  349. package/src/routes/api/__tests__/posts.test.ts +24 -0
  350. package/src/routes/api/__tests__/settings.test.ts +24 -3
  351. package/src/routes/api/__tests__/telegram.test.ts +6 -5
  352. package/src/routes/api/__tests__/upload.test.ts +34 -0
  353. package/src/routes/api/collections.ts +49 -6
  354. package/src/routes/api/custom-urls.ts +0 -1
  355. package/src/routes/api/discover.ts +95 -0
  356. package/src/routes/api/export.ts +6 -3
  357. package/src/routes/api/internal/__tests__/sites.test.ts +42 -2
  358. package/src/routes/api/internal/sites.ts +0 -1
  359. package/src/routes/api/nav-items.ts +55 -8
  360. package/src/routes/api/posts.ts +161 -0
  361. package/src/routes/api/public/__tests__/archive.test.ts +111 -0
  362. package/src/routes/api/public/archive.ts +77 -81
  363. package/src/routes/api/public/posts.ts +44 -7
  364. package/src/routes/api/smart-collections.ts +132 -0
  365. package/src/routes/api/telegram.ts +2 -40
  366. package/src/routes/api/upload.ts +10 -3
  367. package/src/routes/api/uploads.ts +1 -2
  368. package/src/routes/auth/__tests__/setup-auth.test.ts +137 -0
  369. package/src/routes/auth/__tests__/setup-discover.test.ts +204 -0
  370. package/src/routes/auth/__tests__/setup-flow.test.ts +270 -0
  371. package/src/routes/auth/__tests__/setup-page.test.tsx +329 -0
  372. package/src/routes/auth/__tests__/setup-steps.test.ts +310 -0
  373. package/src/routes/auth/__tests__/setup.test.ts +278 -26
  374. package/src/routes/auth/__tests__/signin.test.ts +135 -0
  375. package/src/routes/auth/setup.tsx +934 -186
  376. package/src/routes/auth/signin.tsx +10 -8
  377. package/src/routes/compose.tsx +9 -0
  378. package/src/routes/dash/__tests__/custom-urls-archive.test.ts +44 -0
  379. package/src/routes/dash/__tests__/custom-urls-page.test.ts +49 -0
  380. package/src/routes/dash/__tests__/delete-account.test.ts +106 -0
  381. package/src/routes/dash/__tests__/github-sync-app.test.ts +365 -0
  382. package/src/routes/dash/__tests__/settings-discover.test.ts +213 -0
  383. package/src/routes/dash/custom-urls.tsx +1 -37
  384. package/src/routes/dash/settings.tsx +714 -111
  385. package/src/routes/discover-announce.ts +96 -0
  386. package/src/routes/feed/__tests__/feed.test.ts +165 -2
  387. package/src/routes/feed/feed.ts +69 -40
  388. package/src/routes/feed/sitemap.ts +95 -11
  389. package/src/routes/pages/__tests__/archive-indexing.test.ts +200 -0
  390. package/src/routes/pages/__tests__/archive-params.test.ts +370 -6
  391. package/src/routes/pages/__tests__/collection-routing.test.ts +16 -0
  392. package/src/routes/pages/__tests__/collections-feed-links.test.ts +72 -0
  393. package/src/routes/pages/__tests__/collections.test.ts +9 -3
  394. package/src/routes/pages/__tests__/custom-archive-url.test.ts +119 -0
  395. package/src/routes/pages/__tests__/feed-autodiscovery.test.ts +148 -0
  396. package/src/routes/pages/__tests__/language-routing.test.ts +679 -0
  397. package/src/routes/pages/__tests__/post-page-round-trips.test.ts +211 -0
  398. package/src/routes/pages/__tests__/post-preview-partial.test.ts +96 -0
  399. package/src/routes/pages/__tests__/smart-collection.test.ts +298 -0
  400. package/src/routes/pages/__tests__/subscribe.test.ts +248 -0
  401. package/src/routes/pages/__tests__/thread-order.test.ts +179 -0
  402. package/src/routes/pages/archive.tsx +487 -379
  403. package/src/routes/pages/collection.tsx +94 -96
  404. package/src/routes/pages/collections.tsx +38 -50
  405. package/src/routes/pages/featured.tsx +43 -18
  406. package/src/routes/pages/home.tsx +25 -6
  407. package/src/routes/pages/language.tsx +113 -0
  408. package/src/routes/pages/latest.tsx +26 -16
  409. package/src/routes/pages/new.tsx +3 -0
  410. package/src/routes/pages/page.tsx +228 -45
  411. package/src/routes/pages/partials.tsx +41 -0
  412. package/src/routes/pages/search.tsx +22 -5
  413. package/src/routes/pages/smart-collection.tsx +340 -0
  414. package/src/routes/pages/subscribe.tsx +182 -0
  415. package/src/runtime/__tests__/index.test.ts +19 -0
  416. package/src/runtime/__tests__/node.test.ts +129 -4
  417. package/src/runtime/__tests__/readiness.test.ts +23 -0
  418. package/src/runtime/cloudflare.ts +21 -2
  419. package/src/runtime/index.ts +27 -1
  420. package/src/runtime/node.ts +67 -1
  421. package/src/runtime/readiness.ts +15 -0
  422. package/src/runtime/site.ts +95 -24
  423. package/src/services/__tests__/auth.test.ts +116 -7
  424. package/src/services/__tests__/bootstrap-setup-instance.test.ts +230 -0
  425. package/src/services/__tests__/collection.test.ts +108 -4
  426. package/src/services/__tests__/custom-url.test.ts +34 -0
  427. package/src/services/__tests__/github-app-installations.test.ts +153 -0
  428. package/src/services/__tests__/github-sync-push.test.ts +46 -0
  429. package/src/services/__tests__/language.test.ts +495 -0
  430. package/src/services/__tests__/media.test.ts +31 -0
  431. package/src/services/__tests__/navigation.test.ts +213 -10
  432. package/src/services/__tests__/path.test.ts +236 -0
  433. package/src/services/__tests__/post-language.test.ts +830 -0
  434. package/src/services/__tests__/post-timeline.test.ts +127 -0
  435. package/src/services/__tests__/post.test.ts +120 -9
  436. package/src/services/__tests__/settings.test.ts +228 -17
  437. package/src/services/__tests__/site-admin.test.ts +5 -5
  438. package/src/services/__tests__/smart-collection.test.ts +651 -0
  439. package/src/services/about-page.ts +22 -1
  440. package/src/services/auth.ts +51 -49
  441. package/src/services/bootstrap.ts +408 -39
  442. package/src/services/collection-directory-position.ts +76 -0
  443. package/src/services/collection.ts +331 -46
  444. package/src/services/custom-url.ts +29 -24
  445. package/src/services/export-theme/assets/client-site.css +1 -1
  446. package/src/services/export-theme/assets/client-site.js +123 -123
  447. package/src/services/export-theme/layouts/_default/alias.html +27 -1
  448. package/src/services/export-theme/layouts/_default/list.html +2 -63
  449. package/src/services/export-theme/layouts/_default/rss.xml +103 -38
  450. package/src/services/export-theme/layouts/collections/list.html +3 -3
  451. package/src/services/export-theme/layouts/featured/list.html +1 -4
  452. package/src/services/export-theme/layouts/index.html +40 -26
  453. package/src/services/export-theme/layouts/partials/collection-members.html +100 -0
  454. package/src/services/export-theme/layouts/partials/collection-threads.html +33 -0
  455. package/src/services/export-theme/layouts/partials/featured-members.html +35 -0
  456. package/src/services/export-theme/layouts/partials/featured-thread.html +1 -1
  457. package/src/services/export-theme/layouts/partials/feed-post-content.xml +105 -2
  458. package/src/services/export-theme/layouts/partials/footer.html +1 -1
  459. package/src/services/export-theme/layouts/partials/head.html +1 -1
  460. package/src/services/export-theme/layouts/partials/header.html +5 -3
  461. package/src/services/export-theme/layouts/partials/jant-data.html +23 -0
  462. package/src/services/export-theme/layouts/partials/latest-members.html +48 -0
  463. package/src/services/export-theme/layouts/partials/media-gallery.html +35 -21
  464. package/src/services/export-theme/layouts/partials/pagination.html +14 -13
  465. package/src/services/export-theme/layouts/partials/post-card.html +8 -4
  466. package/src/services/export-theme/layouts/partials/reply.html +2 -1
  467. package/src/services/export-theme/layouts/partials/smart-collection-members.html +129 -0
  468. package/src/services/export-theme/layouts/partials/thread-preview.html +41 -31
  469. package/src/services/export-theme/layouts/post/list.html +1 -1
  470. package/src/services/export-theme/layouts/smart_collection/list.html +24 -0
  471. package/src/services/export-theme/styles/main.css +13 -2
  472. package/src/services/export-theme/theme.toml +1 -1
  473. package/src/services/export.ts +880 -72
  474. package/src/services/github-app-installations.ts +171 -4
  475. package/src/services/github-sync.ts +69 -15
  476. package/src/services/index.ts +34 -3
  477. package/src/services/language.ts +412 -0
  478. package/src/services/mcp.ts +22 -2
  479. package/src/services/media.ts +22 -7
  480. package/src/services/navigation.ts +429 -67
  481. package/src/services/path.ts +254 -6
  482. package/src/services/post.ts +1234 -190
  483. package/src/services/search.ts +39 -2
  484. package/src/services/settings.ts +238 -43
  485. package/src/services/site-admin.ts +27 -14
  486. package/src/services/site.ts +160 -32
  487. package/src/services/smart-collection.ts +636 -0
  488. package/src/services/telegram.ts +20 -22
  489. package/src/services/upload-session.ts +1 -3
  490. package/src/style-author.css +27 -0
  491. package/src/styles/components-author.css +1622 -0
  492. package/src/styles/components.css +24 -1571
  493. package/src/styles/site-media.css +16 -2
  494. package/src/styles/tokens.css +82 -12
  495. package/src/styles/ui-author.css +7602 -0
  496. package/src/styles/ui.css +1090 -7216
  497. package/src/types/app-context.ts +23 -0
  498. package/src/types/bindings.ts +8 -0
  499. package/src/types/config.ts +94 -15
  500. package/src/types/constants.ts +188 -16
  501. package/src/types/entities.ts +87 -1
  502. package/src/types/operations.ts +74 -2
  503. package/src/types/props.ts +157 -31
  504. package/src/types/views.ts +55 -1
  505. package/src/ui/__tests__/font-themes.test.ts +52 -12
  506. package/src/ui/compose/ComposeDialog.tsx +201 -7
  507. package/src/ui/compose/ComposePrompt.tsx +1 -5
  508. package/src/ui/compose/__tests__/ComposeDialog.test.tsx +125 -0
  509. package/src/ui/dash/appearance/AdvancedContent.tsx +2 -2
  510. package/src/ui/dash/appearance/CodeInjectionContent.tsx +12 -16
  511. package/src/ui/dash/appearance/NavigationContent.tsx +117 -16
  512. package/src/ui/dash/appearance/__tests__/NavigationContent.test.tsx +33 -11
  513. package/src/ui/dash/appearance/__tests__/system-nav-descriptions.test.ts +44 -0
  514. package/src/ui/dash/appearance/system-nav-descriptions.ts +75 -0
  515. package/src/ui/dash/settings/AccountMenuContent.tsx +2 -2
  516. package/src/ui/dash/settings/ApiTokensContent.tsx +2 -1
  517. package/src/ui/dash/settings/ConfigEditorContent.tsx +35 -16
  518. package/src/ui/dash/settings/GeneralContent.tsx +277 -113
  519. package/src/ui/dash/settings/LanguageContent.tsx +409 -0
  520. package/src/ui/dash/settings/SettingsRootContent.tsx +19 -1
  521. package/src/ui/dash/settings/__tests__/GeneralContent.test.tsx +324 -4
  522. package/src/ui/dash/settings/__tests__/LanguageContent.test.tsx +144 -0
  523. package/src/ui/dash/settings/__tests__/discover-copy.test.ts +66 -0
  524. package/src/ui/dash/settings/discover-copy.ts +116 -0
  525. package/src/ui/feed/LinkCard.tsx +55 -45
  526. package/src/ui/feed/NoteCard.tsx +9 -4
  527. package/src/ui/feed/PostStatusBadges.tsx +90 -43
  528. package/src/ui/feed/QuoteCard.tsx +55 -30
  529. package/src/ui/feed/ThreadPreview.tsx +6 -2
  530. package/src/ui/feed/__tests__/thread-preview.test.ts +13 -16
  531. package/src/ui/feed/__tests__/timeline-cards.test.ts +314 -49
  532. package/src/ui/feed/thread-preview-state.ts +20 -6
  533. package/src/ui/font-themes.ts +39 -29
  534. package/src/ui/layouts/BaseLayout.tsx +155 -10
  535. package/src/ui/layouts/SiteLayout.tsx +192 -34
  536. package/src/ui/layouts/__tests__/BaseLayout.test.tsx +196 -17
  537. package/src/ui/layouts/__tests__/SiteLayout.test.tsx +109 -85
  538. package/src/ui/pages/ArchivePage.tsx +282 -289
  539. package/src/ui/pages/CollectionPage.tsx +86 -76
  540. package/src/ui/pages/CollectionsPage.tsx +5 -0
  541. package/src/ui/pages/ComposePage.tsx +8 -0
  542. package/src/ui/pages/PostPage.tsx +47 -0
  543. package/src/ui/pages/SearchPage.tsx +3 -3
  544. package/src/ui/pages/SmartCollectionPage.tsx +434 -0
  545. package/src/ui/pages/SubscribePage.tsx +236 -0
  546. package/src/ui/pages/__tests__/ArchivePage.test.tsx +65 -9
  547. package/src/ui/pages/__tests__/collections-directory-rows.test.tsx +92 -0
  548. package/src/ui/pages/__tests__/collections-view-links.test.tsx +81 -0
  549. package/src/ui/shared/CollectionDirectory.tsx +178 -3
  550. package/src/ui/shared/CollectionsManager.tsx +70 -17
  551. package/src/ui/shared/CopyField.tsx +127 -0
  552. package/src/ui/shared/EmptyPostContent.tsx +23 -0
  553. package/src/ui/shared/MediaGallery.tsx +125 -46
  554. package/src/ui/shared/Pagination.tsx +20 -5
  555. package/src/ui/shared/PostFooter.tsx +20 -11
  556. package/src/ui/shared/__tests__/archive-labels.test.ts +100 -0
  557. package/src/ui/shared/__tests__/media-gallery.test.ts +210 -2
  558. package/src/ui/shared/__tests__/navigation-labels.test.ts +16 -22
  559. package/src/ui/shared/__tests__/pagination.test.ts +38 -24
  560. package/src/ui/shared/__tests__/post-footer.test.ts +32 -0
  561. package/src/ui/shared/archive-labels.ts +98 -0
  562. package/src/ui/shared/collection-management-labels.ts +94 -16
  563. package/src/ui/shared/navigation-labels.ts +45 -71
  564. package/src/ui/shared/post-article-attributes.ts +2 -0
  565. package/src/ui/shared/smart-collection-labels.ts +343 -0
  566. package/dist/app-C75Zc8dD.js +0 -6
  567. package/dist/client/_assets/chunks/heic-to-DUUaO23q.js +0 -1
  568. package/dist/client/_assets/chunks/module-DcsAZQZ_.js +0 -716
  569. package/dist/client/_assets/chunks/url-CU9pEbk5.js +0 -1
  570. package/dist/client/_assets/client-Bq0vre8Y.js +0 -296
  571. package/dist/client/_assets/client-D3VZyG4L.css +0 -2
  572. package/dist/client/_assets/client-auth-F2rb9WfF.js +0 -5571
  573. package/dist/env-BPYViDJJ.js +0 -281
  574. package/dist/export-Dl5KCiEs.js +0 -5562
  575. package/dist/github-api-BNF35Lkx.js +0 -176
  576. package/dist/github-app-DdiD-bC4.js +0 -275
  577. package/dist/github-sync-Bqg62IvV.js +0 -4
  578. package/dist/github-sync-HdK2EgvJ.js +0 -431
  579. package/dist/url-CbLAtlZe.js +0 -900
  580. package/src/client/__tests__/collection-created-notice.test.ts +0 -36
  581. package/src/client/__tests__/collection-form-bridge.test.ts +0 -216
  582. package/src/client/__tests__/post-form-bridge.test.ts +0 -82
  583. package/src/client/collection-created-notice.ts +0 -66
  584. package/src/client/collection-form-bridge.ts +0 -191
  585. package/src/client/components/__tests__/jant-post-form.test.ts +0 -193
  586. package/src/client/components/jant-post-form.ts +0 -422
  587. package/src/client/components/post-form-template.ts +0 -352
  588. package/src/client/components/post-form-types.ts +0 -96
  589. package/src/client/media-metadata.ts +0 -247
  590. package/src/client/post-form-bridge.ts +0 -193
  591. package/src/client/tiptap/exitable-marks.ts +0 -73
  592. package/src/ui/pages/CollectionEditorPage.tsx +0 -175
@@ -2,8 +2,8 @@
2
2
  * General settings form
3
3
  *
4
4
  * Server-side template that renders the <jant-settings-general> Lit
5
- * component for site name, description, footer, homepage branding, language,
6
- * timezone, and search settings.
5
+ * component: site name, description, and footer; site visibility (search
6
+ * indexing and Jant Discover); feeds; time zone; and home page branding.
7
7
  * The settings-bridge.ts script handles server communication.
8
8
  */
9
9
 
@@ -11,13 +11,85 @@ import { msg } from "@lingui/core/macro";
11
11
  import { useLingui } from "../../../i18n/context.js";
12
12
  import type { TimezoneEntry } from "../../../lib/timezones.js";
13
13
  import type { AboutPageStatus } from "../../../services/about-page.js";
14
+ import type {
15
+ DiscoverMode,
16
+ DiscoverPageUrls,
17
+ DiscoverSetting,
18
+ } from "../../../lib/discover.js";
19
+ import { getJantDocsUrl } from "../../../lib/jant-docs.js";
20
+ import { now } from "../../../lib/time.js";
21
+ import { getDiscoverCopy } from "./discover-copy.js";
22
+
23
+ const FEEDS_DOCS_URL = getJantDocsUrl("feeds");
24
+
25
+ /**
26
+ * Where the site stands in the directory, as far as the site itself can tell.
27
+ *
28
+ * Every field is local evidence. The directory takes no status queries, so
29
+ * nothing here is fetched, and nothing here can say whether a person has
30
+ * moderated the site.
31
+ */
32
+ export interface DiscoverStatus {
33
+ /** Last announcement succeeded, failed, or was never made. */
34
+ announced: boolean | null;
35
+ /** Why the last announcement failed. */
36
+ announceError: string | null;
37
+ /** Unix seconds of the last announcement attempt. */
38
+ announceAt: number | null;
39
+ /** A directory is configured at all. */
40
+ hasDirectory: boolean;
41
+ /**
42
+ * A control plane runs this deployment and enrols its blogs itself.
43
+ *
44
+ * The announcement exists because a directory cannot list a site it has
45
+ * never heard of. That is not this site's situation: the platform hosting it
46
+ * registers its whole fleet, so "never announced" is not a defect here and
47
+ * there is nothing for the owner to send. The ping still fires when they
48
+ * switch this back on — a directory reads it as "read me now" and re-polls
49
+ * at once instead of waiting out the backstop — but that is plumbing, not a
50
+ * task, and it is reported nowhere.
51
+ */
52
+ managedByHost: boolean;
53
+ /** The directory's manual submission form, when there is one. */
54
+ submitUrl: string | null;
55
+ /** What this site's feeds actually declare right now. */
56
+ declaredMode: DiscoverMode;
57
+ publicPostCount: number;
58
+ /** Featured thread roots — what a `featured` feed would actually carry. */
59
+ featuredPostCount: number;
60
+ /** The directory's threshold is met. */
61
+ established: boolean;
62
+ minPublicPosts: number;
63
+ firstReadMaxHours: number;
64
+ }
65
+
66
+ /**
67
+ * Whether a directory could still be reading the announcement for the first
68
+ * time.
69
+ *
70
+ * The window is the directory's own backstop: it polls a newly announced feed
71
+ * within `firstReadMaxHours`, so up to that point "sent, nothing visible yet"
72
+ * is the expected state and worth saying. Past it, the site is either listed
73
+ * or it is not, and neither answer comes back here.
74
+ *
75
+ * @param status - The site's Discover status, as assembled by the route
76
+ * @returns `true` while the first read is still due
77
+ * @example
78
+ * ```ts
79
+ * isFirstReadPending({ announceAt: now() - 60, firstReadMaxHours: 6 }); // true
80
+ * ```
81
+ */
82
+ function isFirstReadPending(status: {
83
+ announceAt: number | null;
84
+ firstReadMaxHours: number;
85
+ }): boolean {
86
+ if (status.announceAt === null) return false;
87
+ return now() < status.announceAt + status.firstReadMaxHours * 3600;
88
+ }
14
89
 
15
90
  export function GeneralContent({
16
91
  siteName,
17
92
  siteDescription,
18
- siteLanguage,
19
- dashboardLanguage,
20
- cjkSerifFont,
21
93
  siteNameFallback,
22
94
  siteDescriptionFallback,
23
95
  mainRssFeed,
@@ -29,6 +101,11 @@ export function GeneralContent({
29
101
  siteFooter,
30
102
  showJantBrandingOnHome,
31
103
  noindex,
104
+ discover,
105
+ discoverDefault,
106
+ discoverPages,
107
+ discoverStatus,
108
+ rssFeedsEnabled,
32
109
  demoMode,
33
110
  timezones,
34
111
  aboutPage,
@@ -37,9 +114,6 @@ export function GeneralContent({
37
114
  }: {
38
115
  siteName: string;
39
116
  siteDescription: string;
40
- siteLanguage: string;
41
- dashboardLanguage: string;
42
- cjkSerifFont: string;
43
117
  siteNameFallback: string;
44
118
  siteDescriptionFallback: string;
45
119
  mainRssFeed: string;
@@ -51,6 +125,21 @@ export function GeneralContent({
51
125
  siteFooter: string;
52
126
  showJantBrandingOnHome: boolean;
53
127
  noindex: boolean;
128
+ /** The stored choice, or "" when the owner has never used the control. */
129
+ discover: string;
130
+ /**
131
+ * The deployment's own answer, unresolved: `""` when it has none.
132
+ *
133
+ * Not the effective mode. `noindex` is a control on this same page, so
134
+ * folding it in here would hand the browser a value that is already stale by
135
+ * the first click; the component applies it, and the rest of the rules,
136
+ * itself.
137
+ */
138
+ discoverDefault: DiscoverSetting | "";
139
+ /** The directory's own pages, or `null` when none is configured. */
140
+ discoverPages: DiscoverPageUrls | null;
141
+ discoverStatus: DiscoverStatus;
142
+ rssFeedsEnabled: boolean;
54
143
  demoMode: boolean;
55
144
  timezones: TimezoneEntry[];
56
145
  aboutPage: AboutPageStatus;
@@ -59,7 +148,17 @@ export function GeneralContent({
59
148
  }) {
60
149
  const { i18n } = useLingui();
61
150
 
151
+ // Shared with the setup screen, which asks the same question once.
152
+ const discoverCopy = getDiscoverCopy(i18n);
153
+
62
154
  const labels = JSON.stringify({
155
+ // The component finds the name and the rules in the help line (and the
156
+ // name in the demo notice that replaces it) to make them links, so it gets
157
+ // them on their own as well as inside the lines.
158
+ discoverName: discoverCopy.name,
159
+ discoverRules: discoverCopy.rules,
160
+ discoverEnabled: discoverCopy.label,
161
+ discoverIntro: discoverCopy.intro,
63
162
  general: i18n._(
64
163
  msg({
65
164
  message: "General",
@@ -104,11 +203,11 @@ export function GeneralContent({
104
203
  comment: "@context: Compact conflict message when /about is occupied",
105
204
  }),
106
205
  ),
107
- languageAndTime: i18n._(
206
+ timeSection: i18n._(
108
207
  msg({
109
- message: "Language & Time",
208
+ message: "Time",
110
209
  comment:
111
- "@context: Settings subsection heading for language and time zone fields",
210
+ "@context: Settings subsection heading for the time zone field",
112
211
  }),
113
212
  ),
114
213
  home: i18n._(
@@ -117,11 +216,11 @@ export function GeneralContent({
117
216
  comment: "@context: Settings subsection heading for home page settings",
118
217
  }),
119
218
  ),
120
- search: i18n._(
219
+ siteVisibility: i18n._(
121
220
  msg({
122
- message: "Search",
221
+ message: "Site visibility",
123
222
  comment:
124
- "@context: Settings section heading for search engine indexing settings",
223
+ "@context: Settings section heading covering search engine indexing and the Jant Discover directory",
125
224
  }),
126
225
  ),
127
226
  siteName: i18n._(
@@ -142,69 +241,6 @@ export function GeneralContent({
142
241
  comment: "@context: Help text for site description field",
143
242
  }),
144
243
  ),
145
- siteLanguage: i18n._(
146
- msg({
147
- message: "Content language",
148
- comment:
149
- "@context: Settings form field for the public content language",
150
- }),
151
- ),
152
- siteLanguageHelp: i18n._(
153
- msg({
154
- message:
155
- "The language your posts are written in. Announced to readers and search engines through HTML lang and your RSS feed. Any BCP 47 tag works.",
156
- comment: "@context: Help text under the content language picker",
157
- }),
158
- ),
159
- contentLanguagePreview: i18n._(
160
- msg({
161
- message: "Readers and search engines see",
162
- comment:
163
- "@context: Lead text before a live <html lang> preview of the content language",
164
- }),
165
- ),
166
- dashboardLanguage: i18n._(
167
- msg({
168
- message: "Dashboard language",
169
- comment:
170
- "@context: Settings form field for the admin interface language",
171
- }),
172
- ),
173
- dashboardLanguageHelp: i18n._(
174
- msg({
175
- message:
176
- "The language this admin dashboard shows in. Available in English, 简体中文, and 繁體中文.",
177
- comment: "@context: Help text under the dashboard language picker",
178
- }),
179
- ),
180
- siteLanguageSearchPlaceholder: i18n._(
181
- msg({
182
- message: "Search…",
183
- comment:
184
- "@context: Placeholder inside the language combobox search field",
185
- }),
186
- ),
187
- siteLanguageNoMatches: i18n._(
188
- msg({
189
- message: "No matches.",
190
- comment:
191
- "@context: Empty state shown when the language search filters out every entry",
192
- }),
193
- ),
194
- cjkFont: i18n._(
195
- msg({
196
- message: "CJK fallback",
197
- comment:
198
- "@context: Settings field for a manual Chinese, Japanese, or Korean font fallback",
199
- }),
200
- ),
201
- cjkFontHelp: i18n._(
202
- msg({
203
- message:
204
- "Used when the content language has no built-in font profile. Your font theme still controls serif and sans styling.",
205
- comment: "@context: Help text for the manual CJK font fallback setting",
206
- }),
207
- ),
208
244
  timeZone: i18n._(
209
245
  msg({
210
246
  message: "Time Zone",
@@ -251,6 +287,13 @@ export function GeneralContent({
251
287
  comment: "@context: Label for the list of stable RSS feed URLs",
252
288
  }),
253
289
  ),
290
+ feedsDocs: i18n._(
291
+ msg({
292
+ message: "All feed addresses",
293
+ comment:
294
+ "@context: Link text to the feeds documentation, under the fixed feed URLs in General settings",
295
+ }),
296
+ ),
254
297
  availableFeedUrlsHelp: i18n._(
255
298
  msg({
256
299
  message: "Use these when you want a feed URL that never changes.",
@@ -349,6 +392,43 @@ export function GeneralContent({
349
392
  "@context: Help text explaining that SEO indexing is locked in demo mode",
350
393
  }),
351
394
  ),
395
+ discoverSearchOff: i18n._(
396
+ msg({
397
+ message:
398
+ "Search engine indexing is off, so this site is not listed by default. Ticking the box above lists it anyway.",
399
+ comment:
400
+ "@context: Shown under the Jant Discover checkbox when the site has turned search engines away and has never answered Discover itself, which is what unticks the box. Says why the box moved, and that it is still the owner's to tick.",
401
+ }),
402
+ ),
403
+ discoverAnnounce: i18n._(
404
+ msg({
405
+ message: "Announce my site",
406
+ comment:
407
+ "@context: Button sending the Discover announcement, shown when the site has never announced itself or when the announcement failed",
408
+ }),
409
+ ),
410
+ discoverAnnounceManual: i18n._(
411
+ msg({
412
+ message: "Or submit your address by hand",
413
+ comment:
414
+ "@context: Link to the directory's manual submission form, shown only when the automatic announcement failed",
415
+ }),
416
+ ),
417
+ discoverDemoLocked: i18n._(
418
+ msg({
419
+ message: "Demo sites are never listed in {name}.",
420
+ comment:
421
+ "@context: Help text under the Jant Discover checkbox explaining that Discover is locked off in demo mode, shown in place of the usual help line. {name} is the directory's name and is rendered as the link to it, so keep it as one run of text.",
422
+ }),
423
+ { name: discoverCopy.name },
424
+ ),
425
+ discoverFeedsOffLocked: i18n._(
426
+ msg({
427
+ message: "Discover reads your Atom feed, so it needs feeds turned on.",
428
+ comment:
429
+ "@context: Help text explaining that Discover cannot work while Atom feeds are disabled",
430
+ }),
431
+ ),
352
432
  save: i18n._(
353
433
  msg({
354
434
  message: "Save",
@@ -387,67 +467,151 @@ export function GeneralContent({
387
467
  timezones.map((tz) => ({ value: tz.value, label: tz.label })),
388
468
  ).replace(/</g, "\\u003c");
389
469
 
390
- // The 3 catalog locales Jant's dashboard is translated into. Native-script
391
- // labels so each reads in its own language, like the CJK font options.
392
- const dashboardLanguagesJson = JSON.stringify([
393
- { value: "en", label: "English" },
394
- { value: "zh-Hans", label: "简体中文" },
395
- { value: "zh-Hant", label: "繁體中文" },
396
- ]).replace(/</g, "\\u003c");
397
-
398
- const cjkFontsJson = JSON.stringify([
399
- {
400
- value: "off",
401
- label: i18n._(
402
- msg({
403
- message: "Follow content language",
404
- comment:
405
- "@context: CJK font fallback option that uses the configured content language",
406
- }),
407
- ),
408
- },
409
- {
410
- value: "zh-Hans",
411
- label: "\u7B80\u4F53\u4E2D\u6587 (Simplified Chinese)",
412
- },
413
- {
414
- value: "zh-Hant",
415
- label: "\u7E41\u9AD4\u4E2D\u6587 (Traditional Chinese)",
416
- },
417
- { value: "ja", label: "\u65E5\u672C\u8A9E (Japanese)" },
418
- { value: "ko", label: "\uD55C\uAD6D\uC5B4 (Korean)" },
419
- ]).replace(/</g, "\\u003c");
420
-
421
470
  const aboutPageJson = JSON.stringify(aboutPage).replace(/</g, "\\u003c");
422
471
 
423
472
  const initialData = JSON.stringify({
424
473
  siteName,
425
474
  siteDescription,
426
- siteLanguage,
427
- dashboardLanguage,
428
- cjkSerifFont,
429
475
  mainRssFeed,
430
476
  timeZone,
431
477
  siteFooter,
432
478
  showJantBrandingOnHome,
433
479
  noindex,
480
+ discover,
434
481
  }).replace(/</g, "\\u003c");
435
482
 
483
+ // The status sentences carry runtime numbers, so they are translated here
484
+ // rather than handed to the component as templates — values belong with the
485
+ // `i18n._` call that has them. The component renders what it is given.
486
+ //
487
+ // Only what the controls above cannot say for themselves gets a line. The
488
+ // ticked box and the picked mode already state that the site is listed and
489
+ // what its feed declares, and a site past the directory's threshold has
490
+ // nothing to do about being past it — printing either turns this into a
491
+ // report that is read once and skipped forever after. What is left is a
492
+ // problem, a task, or an answer that is still outstanding.
493
+ const statusLines: string[] = [];
494
+
495
+ // A site that is not listed gets no status block at all: every line under
496
+ // it would only restate the unticked checkbox above.
497
+ if (discoverStatus.declaredMode !== "none") {
498
+ if (discoverStatus.hasDirectory && !discoverStatus.managedByHost) {
499
+ if (discoverStatus.announced === false) {
500
+ statusLines.push(
501
+ i18n._(
502
+ msg({
503
+ message: "The directory could not be reached: {reason}",
504
+ comment:
505
+ "@context: Discover status line when the announcement failed. {reason} is the error, such as an HTTP status or a network message.",
506
+ }),
507
+ { reason: discoverStatus.announceError ?? "" },
508
+ ),
509
+ );
510
+ } else if (discoverStatus.announced === null) {
511
+ statusLines.push(
512
+ i18n._(
513
+ msg({
514
+ message:
515
+ "Not announced yet. No directory has been told this site exists.",
516
+ comment:
517
+ "@context: Discover status line before the site has ever announced itself. The button under the lines is how it is sent.",
518
+ }),
519
+ ),
520
+ );
521
+ } else if (isFirstReadPending(discoverStatus)) {
522
+ // A successful announcement is worth confirming only while its answer
523
+ // is still outstanding. Inside the first-read window the owner is
524
+ // waiting for a directory to come round; after it, the directory
525
+ // either lists the site — which the directory itself shows — or has
526
+ // declined to, and this page can see neither.
527
+ statusLines.push(
528
+ i18n._(
529
+ msg({
530
+ message:
531
+ "Feed address sent. A directory reads a newly announced feed within {hours} hours.",
532
+ comment:
533
+ "@context: Discover status line right after a successful announcement, while the first crawl is still due",
534
+ }),
535
+ { hours: discoverStatus.firstReadMaxHours },
536
+ ),
537
+ );
538
+ }
539
+ }
540
+
541
+ // A site that stored `featured` under an older release: the directory
542
+ // reads only its featured feed, on every list. The box still reads as on,
543
+ // and only the owner ticking it again widens what the directory may show.
544
+ if (
545
+ discoverStatus.declaredMode === "featured" &&
546
+ discoverStatus.publicPostCount > 0 &&
547
+ discoverStatus.featuredPostCount === 0
548
+ ) {
549
+ statusLines.push(
550
+ i18n._(
551
+ msg({
552
+ message:
553
+ "This site still limits Discover to featured posts, and no post is marked Featured, so your feed carries nothing to show. Untick and tick the box to let Discover read every public post.",
554
+ comment:
555
+ "@context: Discover status line for a site that chose the old featured-only mode and has no featured posts. Says how to move to the current setting, which reads every public post.",
556
+ }),
557
+ ),
558
+ );
559
+ }
560
+
561
+ if (!discoverStatus.established) {
562
+ statusLines.push(
563
+ i18n._(
564
+ msg({
565
+ message:
566
+ "Nothing published yet. jant.me lists a blog once it has {minCount, plural, one {one public post} other {# public posts}}.",
567
+ comment:
568
+ "@context: Discover status line when the site does not meet the directory's threshold yet. Stated as jant.me's rule, because a directory of your own may decide differently.",
569
+ }),
570
+ { minCount: discoverStatus.minPublicPosts },
571
+ ),
572
+ );
573
+ }
574
+ }
575
+
576
+ const statusView = {
577
+ lines: statusLines,
578
+ // The button covers both halves of "the directory has not heard from us":
579
+ // an announcement that failed, and one that was never made — a site whose
580
+ // mode came from the deployment default has nothing else to send it with.
581
+ // The manual form, by contrast, is offered only when the automatic path
582
+ // failed. Shown next to a working announcement it would read as a normal
583
+ // route in, which is what made it look like the primary one.
584
+ showAnnounce:
585
+ discoverStatus.announced !== true &&
586
+ discoverStatus.hasDirectory &&
587
+ !discoverStatus.managedByHost &&
588
+ discoverStatus.declaredMode !== "none",
589
+ submitUrl:
590
+ discoverStatus.announced === false && !discoverStatus.managedByHost
591
+ ? discoverStatus.submitUrl
592
+ : null,
593
+ };
594
+
436
595
  return (
437
596
  <>
438
597
  <div class="flex flex-col max-w-form">
439
598
  <jant-settings-general
440
599
  labels={labels}
441
600
  timezones={timezonesJson}
442
- cjk-fonts={cjkFontsJson}
443
- dashboard-languages={dashboardLanguagesJson}
444
601
  sitename-fallback={siteNameFallback}
445
602
  sitedescription-fallback={siteDescriptionFallback}
446
603
  main-feed-url={mainFeedUrl}
447
604
  latest-feed-url={latestFeedUrl}
448
605
  featured-feed-url={featuredFeedUrl}
449
606
  archive-feed-url={archiveFeedUrl}
607
+ feeds-docs-url={FEEDS_DOCS_URL}
450
608
  demo-mode={demoMode || undefined}
609
+ discover-default={discoverDefault}
610
+ discover-pages={
611
+ discoverPages ? JSON.stringify(discoverPages) : undefined
612
+ }
613
+ discover-status={JSON.stringify(statusView)}
614
+ feeds-enabled={rssFeedsEnabled || undefined}
451
615
  about-page={aboutPageJson}
452
616
  about-edit-url={aboutEditUrl}
453
617
  about-create-url={aboutCreateUrl}