@jant/core 0.6.11 → 0.6.13

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 (139) hide show
  1. package/bin/commands/import-site.js +47 -30
  2. package/bin/commands/migrate-text-attachments.js +1 -3
  3. package/bin/commands/site/export.js +1 -3
  4. package/bin/commands/telegram/register-webhooks.js +9 -3
  5. package/bin/lib/site-snapshot.js +1 -5
  6. package/dist/app-CWJFPjuR.js +6 -0
  7. package/dist/{app-CpmficmQ.js → app-HnzmsaqU.js} +721 -473
  8. package/dist/client/.vite/manifest.json +3 -3
  9. package/dist/client/_assets/{client-Dd9U383b.js → client-3_OaxhTs.js} +1 -1
  10. package/dist/client/_assets/client-DCrcHVJl.css +2 -0
  11. package/dist/client/_assets/{client-auth-DkpSdIDz.js → client-auth-TsYq90xm.js} +625 -561
  12. package/dist/{export-Ba7NJImL.js → export-Dfbq9aot.js} +12 -15
  13. package/dist/{github-sync-Cb4_6_i7.js → github-sync--PSoE-Ne.js} +1 -1
  14. package/dist/{github-sync-BD4w2m8-.js → github-sync-BGTLx8Mf.js} +2 -2
  15. package/dist/index.js +3 -3
  16. package/dist/node.js +4 -4
  17. package/package.json +1 -1
  18. package/src/__tests__/export-service.test.ts +1 -2
  19. package/src/__tests__/helpers/app.ts +3 -0
  20. package/src/__tests__/helpers/export-fixtures.ts +0 -1
  21. package/src/__tests__/import-site-command.test.ts +76 -2
  22. package/src/__tests__/vite-dev-plugins.test.ts +34 -0
  23. package/src/client/__tests__/compose-launch.test.ts +50 -1
  24. package/src/client/__tests__/compose-shortcuts.test.ts +74 -18
  25. package/src/client/__tests__/site-header-nav.test.ts +36 -2
  26. package/src/client/components/__tests__/compose-title-from-heading.test.ts +57 -0
  27. package/src/client/components/__tests__/jant-command-palette.test.ts +63 -0
  28. package/src/client/components/__tests__/jant-compose-dialog.test.ts +33 -0
  29. package/src/client/components/__tests__/jant-compose-editor-rehost-notice.test.ts +20 -1
  30. package/src/client/components/__tests__/jant-compose-editor.test.ts +94 -2
  31. package/src/client/components/__tests__/jant-nav-manager.test.ts +181 -20
  32. package/src/client/components/__tests__/jant-settings-avatar.test.ts +6 -0
  33. package/src/client/components/__tests__/jant-settings-general.test.ts +72 -0
  34. package/src/client/components/compose-title-from-heading.ts +66 -0
  35. package/src/client/components/compose-types.ts +8 -0
  36. package/src/client/components/inline-image-issues.ts +17 -0
  37. package/src/client/components/jant-command-palette.ts +67 -2
  38. package/src/client/components/jant-compose-dialog.ts +10 -2
  39. package/src/client/components/jant-compose-editor.ts +78 -1
  40. package/src/client/components/jant-compose-fullscreen.ts +2 -0
  41. package/src/client/components/jant-nav-manager.ts +382 -152
  42. package/src/client/components/jant-settings-general.ts +56 -0
  43. package/src/client/components/nav-manager-types.ts +14 -10
  44. package/src/client/components/settings-types.ts +30 -0
  45. package/src/client/compose-launch.ts +30 -0
  46. package/src/client/compose-shortcuts.ts +46 -3
  47. package/src/client/site-header-nav.d.ts +1 -0
  48. package/src/client/site-header-nav.js +105 -47
  49. package/src/client/tiptap/__tests__/block-insertion.test.ts +35 -0
  50. package/src/client/tiptap/__tests__/image-input-rules.test.ts +117 -0
  51. package/src/client/tiptap/__tests__/rehost-images.test.ts +66 -13
  52. package/src/client/tiptap/create-editor.ts +7 -0
  53. package/src/client/tiptap/extensions.ts +7 -2
  54. package/src/client/tiptap/image-input-rules.ts +48 -0
  55. package/src/client/tiptap/image-node.ts +189 -7
  56. package/src/client/tiptap/rehost-images.ts +5 -1
  57. package/src/client-auth.ts +0 -1
  58. package/src/i18n/__tests__/fallback.test.ts +24 -0
  59. package/src/i18n/locales/public/en.po +20 -4
  60. package/src/i18n/locales/public/en.ts +1 -1
  61. package/src/i18n/locales/public/zh-Hans.po +22 -6
  62. package/src/i18n/locales/public/zh-Hans.ts +1 -1
  63. package/src/i18n/locales/public/zh-Hant.po +22 -6
  64. package/src/i18n/locales/public/zh-Hant.ts +1 -1
  65. package/src/i18n/locales/settings/en.po +77 -20
  66. package/src/i18n/locales/settings/en.ts +1 -1
  67. package/src/i18n/locales/settings/zh-Hans.po +85 -28
  68. package/src/i18n/locales/settings/zh-Hans.ts +1 -1
  69. package/src/i18n/locales/settings/zh-Hant.po +79 -22
  70. package/src/i18n/locales/settings/zh-Hant.ts +1 -1
  71. package/src/lib/__tests__/feed.test.ts +96 -10
  72. package/src/lib/__tests__/navigation.test.ts +4 -37
  73. package/src/lib/__tests__/resolve-config.test.ts +6 -1
  74. package/src/lib/__tests__/view.test.ts +6 -30
  75. package/src/lib/feed.ts +63 -3
  76. package/src/lib/github-sync-site-config.ts +0 -2
  77. package/src/lib/hugo-markdown.ts +1 -1
  78. package/src/lib/navigation.ts +5 -22
  79. package/src/lib/post-display.ts +14 -8
  80. package/src/lib/resolve-config.ts +9 -2
  81. package/src/lib/site-header-fragment.tsx +37 -0
  82. package/src/lib/view.ts +2 -7
  83. package/src/node/__tests__/cli-site-snapshot.test.ts +45 -45
  84. package/src/preset.css +60 -18
  85. package/src/routes/api/__tests__/nav-items.test.ts +26 -0
  86. package/src/routes/api/export.ts +0 -2
  87. package/src/routes/api/internal/__tests__/uploads.test.ts +9 -13
  88. package/src/routes/api/internal/sites.ts +5 -5
  89. package/src/routes/api/nav-items.ts +25 -4
  90. package/src/routes/dash/settings.tsx +48 -3
  91. package/src/routes/feed/__tests__/feed.test.ts +42 -0
  92. package/src/routes/feed/__tests__/sitemap.test.ts +2 -13
  93. package/src/routes/feed/feed.ts +1 -0
  94. package/src/routes/feed/sitemap.ts +2 -6
  95. package/src/routes/pages/__tests__/draft-about-edit.test.ts +65 -0
  96. package/src/routes/pages/archive.tsx +1 -0
  97. package/src/routes/pages/collection.tsx +1 -0
  98. package/src/routes/pages/featured.tsx +0 -4
  99. package/src/routes/pages/home.tsx +4 -51
  100. package/src/routes/pages/latest.tsx +2 -51
  101. package/src/routes/pages/page.tsx +44 -12
  102. package/src/services/__tests__/about-page.test.ts +116 -0
  103. package/src/services/__tests__/github-app-installations.test.ts +10 -10
  104. package/src/services/__tests__/navigation.test.ts +231 -1
  105. package/src/services/__tests__/post-timeline.test.ts +175 -2
  106. package/src/services/__tests__/post.test.ts +33 -0
  107. package/src/services/__tests__/settings.test.ts +5 -20
  108. package/src/services/about-page.ts +143 -0
  109. package/src/services/export-theme/assets/client-site.js +10 -10
  110. package/src/services/export-theme/layouts/_default/rss.xml +7 -16
  111. package/src/services/export-theme/layouts/index.html +26 -39
  112. package/src/services/export-theme/layouts/partials/feed-post-content.xml +25 -1
  113. package/src/services/export-theme/styles/main.css +46 -14
  114. package/src/services/export.ts +5 -10
  115. package/src/services/github-app-installations.ts +1 -3
  116. package/src/services/index.ts +27 -17
  117. package/src/services/navigation.ts +186 -1
  118. package/src/services/post.ts +103 -63
  119. package/src/services/settings.ts +0 -10
  120. package/src/services/site-admin.ts +0 -2
  121. package/src/services/upload-session.ts +4 -18
  122. package/src/styles/components.css +20 -0
  123. package/src/styles/tokens.css +28 -10
  124. package/src/styles/ui.css +349 -13
  125. package/src/types/bindings.ts +0 -1
  126. package/src/types/config.ts +3 -7
  127. package/src/types/views.ts +13 -0
  128. package/src/ui/compose/ComposeDialog.tsx +28 -0
  129. package/src/ui/dash/appearance/NavigationContent.tsx +58 -1
  130. package/src/ui/dash/appearance/__tests__/NavigationContent.test.tsx +19 -0
  131. package/src/ui/dash/settings/AccountMenuContent.tsx +2 -2
  132. package/src/ui/dash/settings/GeneralContent.tsx +44 -0
  133. package/src/ui/dash/settings/SettingsRootContent.tsx +3 -3
  134. package/src/ui/dash/settings/__tests__/GeneralContent.test.tsx +8 -0
  135. package/src/ui/feed/__tests__/timeline-cards.test.ts +162 -1
  136. package/src/ui/layouts/SiteLayout.tsx +249 -216
  137. package/dist/app-DqKkZenB.js +0 -6
  138. package/dist/client/_assets/client-BhHHVvSY.css +0 -2
  139. package/src/client/nav-manager-bridge.ts +0 -54
@@ -504,19 +504,15 @@ async function mediaSpecFromJantMedia(entry, sourceRootDir) {
504
504
  srcFilePath,
505
505
  poster,
506
506
  posterFilePath,
507
- mimeType:
508
- typeof entry.mime_type === "string" ? entry.mime_type : undefined,
507
+ mimeType: typeof entry.mime_type === "string" ? entry.mime_type : undefined,
509
508
  originalName,
510
509
  size: typeof entry.size === "number" ? entry.size : undefined,
511
510
  width: typeof entry.width === "number" ? entry.width : undefined,
512
511
  height: typeof entry.height === "number" ? entry.height : undefined,
513
512
  alt: typeof entry.alt === "string" ? entry.alt : undefined,
514
- position:
515
- typeof entry.position === "string" ? entry.position : undefined,
516
- blurhash:
517
- typeof entry.blurhash === "string" ? entry.blurhash : undefined,
518
- waveform:
519
- typeof entry.waveform === "string" ? entry.waveform : undefined,
513
+ position: typeof entry.position === "string" ? entry.position : undefined,
514
+ blurhash: typeof entry.blurhash === "string" ? entry.blurhash : undefined,
515
+ waveform: typeof entry.waveform === "string" ? entry.waveform : undefined,
520
516
  summary: typeof entry.summary === "string" ? entry.summary : undefined,
521
517
  chars: typeof entry.chars === "number" ? entry.chars : undefined,
522
518
  };
@@ -587,8 +583,7 @@ async function normalizeTextAttachmentSpec(spec, siteConfig, sourceRootDir) {
587
583
  return null;
588
584
  }
589
585
 
590
- const summary =
591
- typeof spec.summary === "string" ? spec.summary : undefined;
586
+ const summary = typeof spec.summary === "string" ? spec.summary : undefined;
592
587
 
593
588
  // Legacy inline content path — no network fetch needed.
594
589
  if (
@@ -756,8 +751,8 @@ function coerceBoolean(value) {
756
751
  * Hugo writes two sources of truth:
757
752
  * - `hugo.toml`: baseURL, title, languageCode, theme params
758
753
  * - `data/jant.toml`: everything Jant owns — nav items, branding modes,
759
- * home_default_view, site_footer, avatar urls, display preferences,
760
- * and the ordered collections directory under `[[directory]]`.
754
+ * site_footer, avatar urls, display preferences, and the ordered
755
+ * collections directory under `[[directory]]`.
761
756
  *
762
757
  * This merger normalizes them into a single shape that downstream helpers
763
758
  * (`buildSettingsUpdatesFromConfig`, `normalizeImportedNavItems`,
@@ -837,12 +832,6 @@ async function loadSiteConfig(rootDir) {
837
832
  theme_mode:
838
833
  (typeof params.theme_mode === "string" && params.theme_mode) ||
839
834
  (typeof jantData.theme_mode === "string" ? jantData.theme_mode : ""),
840
- home_default_view:
841
- (typeof params.home_default_view === "string" &&
842
- params.home_default_view) ||
843
- (typeof jantData.home_default_view === "string"
844
- ? jantData.home_default_view
845
- : ""),
846
835
  show_jant_branding_on_home: coerceBoolean(
847
836
  params.show_jant_branding_on_home ??
848
837
  jantData.show_jant_branding_on_home,
@@ -905,8 +894,6 @@ function buildSettingsUpdatesFromConfig(siteConfig, customCss = "") {
905
894
  SITE_DESCRIPTION: String(siteConfig?.description || ""),
906
895
  SITE_LANGUAGE: String(siteConfig?.default_language || "en"),
907
896
  SITE_FOOTER: String(jant.site_footer_markdown || ""),
908
- HOME_DEFAULT_VIEW:
909
- String(jant.home_default_view || "") === "featured" ? "featured" : "",
910
897
  SHOW_JANT_BRANDING_ON_HOME: jant.show_jant_branding_on_home ? "true" : "",
911
898
  NOINDEX: jant.noindex ? "true" : "",
912
899
  SHOW_HEADER_AVATAR: jant.show_header_avatar ? "true" : "",
@@ -1648,9 +1635,7 @@ function resolveCollectionMemberships(frontMatter, collectionSlugToId) {
1648
1635
  if (!id) continue;
1649
1636
  const entry = { collectionId: id };
1650
1637
  if (typeof raw.collected_at === "string" && raw.collected_at) {
1651
- entry.createdAt = Math.floor(
1652
- new Date(raw.collected_at).getTime() / 1000,
1653
- );
1638
+ entry.createdAt = Math.floor(new Date(raw.collected_at).getTime() / 1000);
1654
1639
  }
1655
1640
  if (typeof raw.position === "number") {
1656
1641
  entry.position = raw.position;
@@ -1664,6 +1649,38 @@ function resolveCollectionMemberships(frontMatter, collectionSlugToId) {
1664
1649
  return { entries, ids };
1665
1650
  }
1666
1651
 
1652
+ function parseImportTimestamp(value) {
1653
+ if (typeof value !== "string" || value.trim() === "") return null;
1654
+ const timestamp = Date.parse(value);
1655
+ return Number.isFinite(timestamp) ? Math.floor(timestamp / 1000) : null;
1656
+ }
1657
+
1658
+ function getImportedRootLastActivityAt(frontMatter) {
1659
+ return (
1660
+ parseImportTimestamp(frontMatter.last_activity_at) ??
1661
+ parseImportTimestamp(frontMatter.date)
1662
+ );
1663
+ }
1664
+
1665
+ function getImportedPostStatus(frontMatter) {
1666
+ if (frontMatter.status === "draft" || frontMatter.status === "published") {
1667
+ return frontMatter.status;
1668
+ }
1669
+ return frontMatter.draft ? "draft" : "published";
1670
+ }
1671
+
1672
+ function shouldImportReplyQuietly(rootFrontMatter, replyFrontMatter) {
1673
+ if (getImportedPostStatus(replyFrontMatter) !== "published") return false;
1674
+
1675
+ const rootLastActivityAt = getImportedRootLastActivityAt(rootFrontMatter);
1676
+ const replyPublishedAt = parseImportTimestamp(replyFrontMatter.date);
1677
+ return (
1678
+ rootLastActivityAt !== null &&
1679
+ replyPublishedAt !== null &&
1680
+ replyPublishedAt > rootLastActivityAt
1681
+ );
1682
+ }
1683
+
1667
1684
  /**
1668
1685
  * Build the payload for `target.createPost()` from a parsed bundle. Works
1669
1686
  * for both root bundles (`forReply: false`) and reply leaf bundles — the
@@ -1690,7 +1707,8 @@ function buildPostPayloadFromBundle(bundle, options) {
1690
1707
  frontMatter.visibility === "private"
1691
1708
  ? frontMatter.visibility
1692
1709
  : undefined;
1693
- const { entries: collectionEntries, ids: collectionIds } = options.memberships;
1710
+ const { entries: collectionEntries, ids: collectionIds } =
1711
+ options.memberships;
1694
1712
 
1695
1713
  const data = {
1696
1714
  format,
@@ -1728,6 +1746,7 @@ function buildPostPayloadFromBundle(bundle, options) {
1728
1746
  : undefined,
1729
1747
  rating:
1730
1748
  typeof frontMatter.rating === "number" ? frontMatter.rating : undefined,
1749
+ quietReply: options.quietReply ? true : undefined,
1731
1750
  };
1732
1751
 
1733
1752
  if (options.replyToId) {
@@ -1777,6 +1796,7 @@ export const __test__ = {
1777
1796
  mediaSpecFromJantMedia,
1778
1797
  resolveCollectionMemberships,
1779
1798
  buildPostPayloadFromBundle,
1799
+ shouldImportReplyQuietly,
1780
1800
  };
1781
1801
 
1782
1802
  function printImportUsage() {
@@ -2096,8 +2116,7 @@ export async function run(argv) {
2096
2116
  for (const rootBundle of rootBundles) {
2097
2117
  const { frontMatter: rootFm } = rootBundle;
2098
2118
  const postSlug = rootBundle.slug;
2099
- const format =
2100
- typeof rootFm.format === "string" ? rootFm.format : "note";
2119
+ const format = typeof rootFm.format === "string" ? rootFm.format : "note";
2101
2120
  const postLabel =
2102
2121
  (format === "quote"
2103
2122
  ? typeof rootFm.source_name === "string"
@@ -2215,9 +2234,7 @@ export async function run(argv) {
2215
2234
  if (dryRun) {
2216
2235
  console.log(`[dry-run] Would create post: ${postLabel} (${format})`);
2217
2236
  if (rootBundle.children.length > 0) {
2218
- console.log(
2219
- ` [dry-run] With ${rootBundle.children.length} replies`,
2220
- );
2237
+ console.log(` [dry-run] With ${rootBundle.children.length} replies`);
2221
2238
  }
2222
2239
  postsCreated++;
2223
2240
  repliesCreated += rootBundle.children.length;
@@ -2349,6 +2366,7 @@ export async function run(argv) {
2349
2366
  attachments: replyAttachments,
2350
2367
  memberships: replyMemberships,
2351
2368
  replyToId: threadTailId,
2369
+ quietReply: shouldImportReplyQuietly(rootFm, replyFm),
2352
2370
  });
2353
2371
 
2354
2372
  try {
@@ -2410,4 +2428,3 @@ export async function run(argv) {
2410
2428
  }
2411
2429
  }
2412
2430
  }
2413
-
@@ -75,9 +75,7 @@ export async function run(argv) {
75
75
  });
76
76
 
77
77
  if (values.help) {
78
- console.log(
79
- "Usage: jant migrate-text-attachments [--url <url>] [options]",
80
- );
78
+ console.log("Usage: jant migrate-text-attachments [--url <url>] [options]");
81
79
  console.log("");
82
80
  console.log("Convert legacy text attachments to the current markdown-only");
83
81
  console.log("storage format. Handles both prior layouts:");
@@ -95,9 +95,7 @@ function printUsage() {
95
95
  console.log(" jant site export https://your-site.example");
96
96
  console.log("");
97
97
  console.log("Examples:");
98
- console.log(
99
- " jant site export https://your-site.example -o ./export.zip",
100
- );
98
+ console.log(" jant site export https://your-site.example -o ./export.zip");
101
99
  console.log(
102
100
  " jant site export https://your-site.example -d ./jant-site && cd ./jant-site && hugo serve",
103
101
  );
@@ -34,11 +34,17 @@ export async function run(argv) {
34
34
  "Registers a webhook for every bot in TELEGRAM_BOT_TOKENS, pointing at",
35
35
  );
36
36
  console.log("<base-url>/api/telegram/webhook/<bot_id> with the shared");
37
- console.log("TELEGRAM_WEBHOOK_SECRET. Run once after configuring the pool.");
37
+ console.log(
38
+ "TELEGRAM_WEBHOOK_SECRET. Run once after configuring the pool.",
39
+ );
38
40
  console.log("");
39
41
  console.log("Environment (also read from .env.node):");
40
- console.log(" TELEGRAM_BOT_TOKENS Comma-separated <bot_id>:<secret> tokens");
41
- console.log(" TELEGRAM_WEBHOOK_SECRET Shared secret_token for the webhooks");
42
+ console.log(
43
+ " TELEGRAM_BOT_TOKENS Comma-separated <bot_id>:<secret> tokens",
44
+ );
45
+ console.log(
46
+ " TELEGRAM_WEBHOOK_SECRET Shared secret_token for the webhooks",
47
+ );
42
48
  process.exit(values.help ? 0 : 1);
43
49
  }
44
50
 
@@ -29,7 +29,6 @@ export const SNAPSHOT_SETTING_KEYS = [
29
29
  "SITE_NAME",
30
30
  "SITE_DESCRIPTION",
31
31
  "SITE_LANGUAGE",
32
- "HOME_DEFAULT_VIEW",
33
32
  "MAIN_RSS_FEED",
34
33
  "THEME",
35
34
  "CUSTOM_CSS",
@@ -213,10 +212,7 @@ export function assertSnapshotMeta(meta) {
213
212
  );
214
213
  }
215
214
 
216
- if (
217
- meta.dialect !== undefined &&
218
- !SNAPSHOT_DIALECTS.includes(meta.dialect)
219
- ) {
215
+ if (meta.dialect !== undefined && !SNAPSHOT_DIALECTS.includes(meta.dialect)) {
220
216
  throw new Error(
221
217
  `Snapshot meta has unsupported dialect "${String(meta.dialect)}". Expected one of ${SNAPSHOT_DIALECTS.join(", ")}.`,
222
218
  );
@@ -0,0 +1,6 @@
1
+ import "./url-BMYO-Zlt.js";
2
+ import { t as createApp } from "./app-HnzmsaqU.js";
3
+ import "./export-Dfbq9aot.js";
4
+ import "./env-OHRKGcMj.js";
5
+ import "./github-sync--PSoE-Ne.js";
6
+ export { createApp };