@jant/core 0.6.16 → 0.7.0

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