@jant/core 0.7.0 → 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 (158) hide show
  1. package/bin/commands/export.js +3 -1
  2. package/bin/commands/import-site.js +689 -216
  3. package/bin/commands/setup.js +136 -0
  4. package/bin/commands/site/export.js +71 -34
  5. package/bin/commands/site/pull-media.js +2 -6
  6. package/bin/commands/site/snapshot/export.js +18 -60
  7. package/bin/commands/site/snapshot/import.js +22 -23
  8. package/bin/lib/d1-query.js +87 -2
  9. package/bin/lib/hugo-markdown.js +4 -0
  10. package/bin/lib/site-pull-media.js +21 -28
  11. package/bin/lib/site-selection.js +10 -1
  12. package/bin/lib/site-snapshot.js +338 -3
  13. package/bin/lib/sql-export.js +68 -5
  14. package/bin/lib/wrangler-cli.js +9 -0
  15. package/bin/lib/zip-archive.js +187 -0
  16. package/dist/{app-K_Aa1MMn.js → app-ZcaI1kPN.js} +732 -217
  17. package/dist/client/.vite/manifest.json +20 -20
  18. package/dist/client/_assets/chunks/{create-editor-CD3FhrOB.js → create-editor-B-m7X7S5.js} +50 -46
  19. package/dist/client/_assets/chunks/{sortable-list-CgaL2jCs.js → sortable-list-BJyd-LXE.js} +1 -1
  20. package/dist/client/_assets/chunks/{unsafe-svg-0QCkP0vZ.js → unsafe-svg-BkscJx69.js} +2 -2
  21. package/dist/client/_assets/{client-GiYENVw8.css → client-DAhoqPdr.css} +1 -1
  22. package/dist/client/_assets/{client-auth-k8gJ6QJj.js → client-auth-CAMfTrKW.js} +1 -1
  23. package/dist/client/_assets/{client-compose-B_kDtWkW.js → client-compose-D6rExKVK.js} +1 -1
  24. package/dist/client/_assets/{client-VnFxJN7G.js → client-knSEyUJO.js} +1 -1
  25. package/dist/client/_assets/{client-manage-M90aSTOk.js → client-manage-sVOkqVbH.js} +1 -1
  26. package/dist/client/_assets/{client-settings-DfYs9n1F.js → client-settings-CGR_nZ78.js} +7 -7
  27. package/dist/{github-sync-BPAvT999.js → github-sync-Gw4orAHk.js} +799 -110
  28. package/dist/index.js +2 -2
  29. package/dist/node.js +9 -5
  30. package/package.json +13 -3
  31. package/src/__tests__/dev-scripts.test.ts +203 -0
  32. package/src/__tests__/export-collection-order.test.ts +276 -0
  33. package/src/__tests__/export-feed-ids.test.ts +184 -0
  34. package/src/__tests__/export-feed-order.test.ts +294 -0
  35. package/src/__tests__/export-hugo-build.test.ts +130 -0
  36. package/src/__tests__/export-import-roundtrip.test.ts +94 -0
  37. package/src/__tests__/export-service.test.ts +611 -28
  38. package/src/__tests__/export-smart-collection.test.ts +329 -0
  39. package/src/__tests__/helpers/hugo-site.ts +146 -0
  40. package/src/__tests__/import-site-command.test.ts +487 -1
  41. package/src/__tests__/mise-config.test.ts +75 -4
  42. package/src/__tests__/node-dev-tasks.test.ts +264 -0
  43. package/src/__tests__/site-export-canonical-import.test.ts +149 -0
  44. package/src/__tests__/snapshot-canonical-replay.test.ts +179 -0
  45. package/src/__tests__/snapshot-settings.test.ts +97 -0
  46. package/src/__tests__/snapshot-tables.test.ts +219 -0
  47. package/src/__tests__/sql-export.test.ts +173 -0
  48. package/src/__tests__/zip-archive.test.ts +106 -0
  49. package/src/app.tsx +15 -6
  50. package/src/client/components/__tests__/jant-settings-avatar.test.ts +1 -1
  51. package/src/client/components/__tests__/jant-settings-general.test.ts +21 -1
  52. package/src/client/components/jant-repo-picker-types.ts +6 -1
  53. package/src/client/components/jant-repo-picker.ts +4 -7
  54. package/src/client/components/jant-settings-general.ts +17 -12
  55. package/src/client/tiptap/__tests__/list-editing.test.ts +224 -86
  56. package/src/client/tiptap/__tests__/mark-exit.test.ts +1 -2
  57. package/src/client/tiptap/__tests__/markdown-clipboard.test.ts +26 -0
  58. package/src/client/tiptap/extensions.ts +0 -3
  59. package/src/client/tiptap/structural-keymap.ts +158 -47
  60. package/src/db/__tests__/d1-query.test.ts +56 -1
  61. package/src/i18n/locales/settings/en.po +8 -8
  62. package/src/i18n/locales/settings/en.ts +1 -1
  63. package/src/i18n/locales/settings/zh-Hans.po +8 -8
  64. package/src/i18n/locales/settings/zh-Hans.ts +1 -1
  65. package/src/i18n/locales/settings/zh-Hant.po +8 -8
  66. package/src/i18n/locales/settings/zh-Hant.ts +1 -1
  67. package/src/lib/__tests__/github-sync-repo-name.test.ts +40 -0
  68. package/src/lib/__tests__/image.test.ts +27 -1
  69. package/src/lib/__tests__/markdown-to-tiptap.test.ts +105 -0
  70. package/src/lib/__tests__/markdown.test.ts +10 -0
  71. package/src/lib/__tests__/resolve-config.test.ts +67 -0
  72. package/src/lib/__tests__/schemas.test.ts +27 -1
  73. package/src/lib/__tests__/timeline.test.ts +87 -0
  74. package/src/lib/__tests__/tiptap-to-markdown.test.ts +172 -4
  75. package/src/lib/discover.ts +3 -1
  76. package/src/lib/github-sync-repo-name.ts +45 -0
  77. package/src/lib/hugo-markdown.ts +46 -0
  78. package/src/lib/image.ts +17 -4
  79. package/src/lib/markdown-manager.ts +392 -2
  80. package/src/lib/post-body-html.ts +11 -4
  81. package/src/lib/resolve-config.ts +58 -1
  82. package/src/lib/schemas.ts +50 -5
  83. package/src/lib/thread-fold.ts +3 -3
  84. package/src/lib/timeline.ts +1 -1
  85. package/src/lib/tiptap-to-markdown.ts +13 -7
  86. package/src/lib/url.ts +20 -0
  87. package/src/lib/view.ts +2 -2
  88. package/src/node/__tests__/cli-setup.test.ts +163 -0
  89. package/src/node/__tests__/cli-site-snapshot.test.ts +67 -0
  90. package/src/node/__tests__/cli-snapshot-meta.test.ts +20 -0
  91. package/src/node/__tests__/runtime.test.ts +38 -0
  92. package/src/node/index.ts +2 -0
  93. package/src/node/request-handler.ts +3 -1
  94. package/src/routes/api/__tests__/posts.test.ts +24 -0
  95. package/src/routes/api/__tests__/upload.test.ts +34 -0
  96. package/src/routes/api/export.ts +3 -3
  97. package/src/routes/api/internal/sites.ts +0 -1
  98. package/src/routes/api/posts.ts +2 -0
  99. package/src/routes/api/public/posts.ts +21 -1
  100. package/src/routes/api/upload.ts +10 -3
  101. package/src/routes/compose.tsx +4 -0
  102. package/src/routes/dash/__tests__/github-sync-app.test.ts +365 -0
  103. package/src/routes/dash/settings.tsx +212 -70
  104. package/src/routes/pages/__tests__/post-page-round-trips.test.ts +211 -0
  105. package/src/routes/pages/__tests__/thread-order.test.ts +179 -0
  106. package/src/routes/pages/archive.tsx +17 -11
  107. package/src/routes/pages/featured.tsx +11 -5
  108. package/src/routes/pages/page.tsx +53 -31
  109. package/src/routes/pages/search.tsx +4 -2
  110. package/src/runtime/__tests__/readiness.test.ts +23 -0
  111. package/src/runtime/node.ts +49 -0
  112. package/src/runtime/readiness.ts +15 -0
  113. package/src/services/__tests__/bootstrap-setup-instance.test.ts +230 -0
  114. package/src/services/__tests__/custom-url.test.ts +34 -0
  115. package/src/services/__tests__/github-app-installations.test.ts +153 -0
  116. package/src/services/__tests__/github-sync-push.test.ts +46 -0
  117. package/src/services/__tests__/media.test.ts +31 -0
  118. package/src/services/__tests__/path.test.ts +56 -0
  119. package/src/services/__tests__/post-timeline.test.ts +127 -0
  120. package/src/services/__tests__/post.test.ts +74 -0
  121. package/src/services/bootstrap.ts +263 -44
  122. package/src/services/custom-url.ts +2 -2
  123. package/src/services/export-theme/layouts/_default/alias.html +27 -1
  124. package/src/services/export-theme/layouts/_default/list.html +2 -63
  125. package/src/services/export-theme/layouts/_default/rss.xml +27 -38
  126. package/src/services/export-theme/layouts/collections/list.html +3 -3
  127. package/src/services/export-theme/layouts/featured/list.html +1 -4
  128. package/src/services/export-theme/layouts/index.html +40 -26
  129. package/src/services/export-theme/layouts/partials/collection-members.html +100 -0
  130. package/src/services/export-theme/layouts/partials/collection-threads.html +33 -0
  131. package/src/services/export-theme/layouts/partials/featured-members.html +35 -0
  132. package/src/services/export-theme/layouts/partials/featured-thread.html +1 -1
  133. package/src/services/export-theme/layouts/partials/footer.html +1 -1
  134. package/src/services/export-theme/layouts/partials/head.html +1 -1
  135. package/src/services/export-theme/layouts/partials/header.html +5 -3
  136. package/src/services/export-theme/layouts/partials/jant-data.html +23 -0
  137. package/src/services/export-theme/layouts/partials/latest-members.html +48 -0
  138. package/src/services/export-theme/layouts/partials/smart-collection-members.html +129 -0
  139. package/src/services/export-theme/layouts/partials/thread-preview.html +1 -1
  140. package/src/services/export-theme/layouts/post/list.html +1 -1
  141. package/src/services/export-theme/layouts/smart_collection/list.html +24 -0
  142. package/src/services/export-theme/styles/main.css +0 -1
  143. package/src/services/export-theme/theme.toml +1 -1
  144. package/src/services/export.ts +620 -71
  145. package/src/services/github-app-installations.ts +171 -4
  146. package/src/services/github-sync.ts +69 -15
  147. package/src/services/mcp.ts +19 -1
  148. package/src/services/media.ts +8 -1
  149. package/src/services/path.ts +34 -1
  150. package/src/services/post.ts +214 -39
  151. package/src/services/site-admin.ts +3 -7
  152. package/src/services/site.ts +83 -31
  153. package/src/styles/ui.css +7 -1
  154. package/src/types/app-context.ts +16 -0
  155. package/src/types/bindings.ts +5 -0
  156. package/src/types/operations.ts +10 -0
  157. package/src/ui/dash/settings/GeneralContent.tsx +10 -8
  158. package/src/client/tiptap/exitable-marks.ts +0 -73
@@ -0,0 +1,129 @@
1
+ {{- /*
2
+ The Thread roots a smart collection's conditions select, in its order.
3
+
4
+ The same set and order Jant shows a signed-out reader on the smart
5
+ collection's page (`smartCollections.toPostFilters` handed to
6
+ `posts.list`), computed from the exported front matter so the page keeps
7
+ up with the posts in this repository. Every condition reads the root:
8
+
9
+ format `format`
10
+ title `title`; for a quote, `source_name`, which is what Jant
11
+ stores in the title column
12
+ year `date`, the publication time, in UTC
13
+ media the root's own `media` entries: `any`, `none`, or a list of
14
+ kinds, any one of which matches
15
+ replies whether the root has published replies
16
+ visibility `public` and `latest_hidden` match `visibility`; `featured`
17
+ matches a root with `featured_at`
18
+ collection a `collections` entry with that slug
19
+
20
+ Drafts and private roots are exported as Hugo drafts and never reach here;
21
+ they are checked again so a `--buildDrafts` preview agrees with Jant.
22
+
23
+ Takes a dict: `page`, the smart collection's section page, and `feed`,
24
+ true for its Atom feed.
25
+
26
+ Orders, each ending on the post ID so no two roots tie:
27
+ newest Thread activity (`last_activity_at`, else `date`), newest first
28
+ oldest publication, oldest first
29
+ rating_desc rated before unrated, higher rating first, then as newest.
30
+ On the page, fewer than two rated roots fall back to
31
+ newest, as Jant's page does; the feed keeps the stored
32
+ order, as Jant's feed does.
33
+
34
+ `src/__tests__/export-smart-collection.test.ts` builds a site with Hugo
35
+ and compares every condition and order against Jant's own list.
36
+ */ -}}
37
+ {{- $page := .page -}}
38
+ {{- $feed := .feed -}}
39
+ {{- $selection := $page.Params.selection | default dict -}}
40
+ {{- $roots := where (where site.Pages "Type" "post") "Kind" "section" -}}
41
+ {{- $members := slice -}}
42
+ {{- range $roots -}}
43
+ {{- $post := . -}}
44
+ {{- $params := .Params -}}
45
+ {{- $matches := and (eq ($params.status | default "published") "published") (ne $params.visibility "private") -}}
46
+ {{- if and $matches (isset $selection "format") -}}
47
+ {{- $matches = eq $params.format $selection.format -}}
48
+ {{- end -}}
49
+ {{- if and $matches (isset $selection "title") -}}
50
+ {{- $title := $params.title -}}
51
+ {{- if eq $params.format "quote" -}}{{- $title = $params.source_name -}}{{- end -}}
52
+ {{- $matches = eq (gt (len (string ($title | default ""))) 0) $selection.title -}}
53
+ {{- end -}}
54
+ {{- if and $matches (isset $selection "year") -}}
55
+ {{- $matches = eq $post.Date.UTC.Year (int $selection.year) -}}
56
+ {{- end -}}
57
+ {{- if and $matches (isset $selection "media") -}}
58
+ {{- $media := $params.media | default slice -}}
59
+ {{- $wanted := $selection.media -}}
60
+ {{- if reflect.IsSlice $wanted -}}
61
+ {{- $found := false -}}
62
+ {{- range $media -}}{{- if in $wanted .kind -}}{{- $found = true -}}{{- end -}}{{- end -}}
63
+ {{- $matches = $found -}}
64
+ {{- else if eq $wanted "any" -}}
65
+ {{- $matches = gt (len $media) 0 -}}
66
+ {{- else -}}
67
+ {{- $matches = eq (len $media) 0 -}}
68
+ {{- end -}}
69
+ {{- end -}}
70
+ {{- if and $matches (isset $selection "replies") -}}
71
+ {{- $matches = eq (gt (len $post.Pages) 0) $selection.replies -}}
72
+ {{- end -}}
73
+ {{- if and $matches (isset $selection "visibility") -}}
74
+ {{- if eq $selection.visibility "featured" -}}
75
+ {{- $matches = ne ($params.featured_at | default "") "" -}}
76
+ {{- else -}}
77
+ {{- $matches = eq $params.visibility $selection.visibility -}}
78
+ {{- end -}}
79
+ {{- end -}}
80
+ {{- if and $matches (isset $selection "collection") -}}
81
+ {{- $inCollection := false -}}
82
+ {{- range $params.collections -}}
83
+ {{- if eq .slug $selection.collection -}}{{- $inCollection = true -}}{{- end -}}
84
+ {{- end -}}
85
+ {{- $matches = $inCollection -}}
86
+ {{- end -}}
87
+
88
+ {{- if $matches -}}
89
+ {{- $activity := $post.Date.Unix -}}
90
+ {{- with $params.last_activity_at -}}{{- $activity = (time.AsTime .).Unix -}}{{- end -}}
91
+ {{- $rated := ne $params.rating nil -}}
92
+ {{- $rating := 0 -}}
93
+ {{- if $rated -}}{{- $rating = int $params.rating -}}{{- end -}}
94
+ {{- $members = $members | append (dict
95
+ "post" $post
96
+ "id" $params.id
97
+ "published" $post.Date.Unix
98
+ "activity" $activity
99
+ "rated" $rated
100
+ "rating" $rating
101
+ ) -}}
102
+ {{- end -}}
103
+ {{- end -}}
104
+
105
+ {{- $order := $page.Params.sort_order | default "newest" -}}
106
+ {{- if and (not $feed) (eq $order "rating_desc") (le (len (where $members "rated" true)) 1) -}}
107
+ {{- $order = "newest" -}}
108
+ {{- end -}}
109
+
110
+ {{- /* One string key per root, fixed-width numbers first, so a single sort
111
+ orders by every key in turn. */ -}}
112
+ {{- $keyed := slice -}}
113
+ {{- range $members -}}
114
+ {{- $key := printf "%020d %s" .activity .id -}}
115
+ {{- if eq $order "oldest" -}}
116
+ {{- $key = printf "%020d %s" .published .id -}}
117
+ {{- else if eq $order "rating_desc" -}}
118
+ {{- $key = printf "%d %02d %020d %s" (cond .rated 1 0) .rating .activity .id -}}
119
+ {{- end -}}
120
+ {{- $keyed = $keyed | append (dict "key" $key "post" .post) -}}
121
+ {{- end -}}
122
+
123
+ {{- $ordered := slice -}}
124
+ {{- if $keyed -}}
125
+ {{- range sort $keyed "key" (cond (eq $order "oldest") "asc" "desc") -}}
126
+ {{- $ordered = $ordered | append .post -}}
127
+ {{- end -}}
128
+ {{- end -}}
129
+ {{- return $ordered -}}
@@ -20,7 +20,7 @@
20
20
  */ -}}
21
21
  {{- $root := . -}}
22
22
  {{- $replies := where $root.Pages "Params.visibility" "public" -}}
23
- {{- $replies = $replies.ByDate -}}
23
+ {{- $replies = $replies.ByWeight -}}
24
24
  {{- $replyCount := len $replies -}}
25
25
  {{- if eq $replyCount 0 -}}
26
26
  {{ partial "post-card.html" $root }}
@@ -5,7 +5,7 @@
5
5
  {{- $media := $root.Params.media | default slice -}}
6
6
  {{- $collections := $root.Params.collections | default slice -}}
7
7
  {{- $linkUrl := $root.Params.link_url -}}
8
- {{- $replies := $root.Pages.ByDate -}}
8
+ {{- $replies := $root.Pages.ByWeight -}}
9
9
  {{- $hasReplies := gt (len $replies) 0 -}}
10
10
  <article class="thread thread-{{ $format }}{{ if $hasReplies }} thread-has-replies{{ end }}" id="{{ $slug }}" data-format="{{ $format }}" data-slug="{{ $slug }}"
11
11
  {{- if $root.Params.pinned_at }} data-post-pinned{{ end -}}
@@ -0,0 +1,24 @@
1
+ {{ define "main" }}
2
+ {{- /*
3
+ A smart collection's page (`type: smart_collection`). The members come
4
+ from its conditions, applied to the posts in this site by the
5
+ `smart-collection-members` partial.
6
+ */ -}}
7
+ {{- $posts := partial "smart-collection-members.html" (dict "page" . "feed" false) -}}
8
+ {{- $pageSize := .Site.Params.page_size | default 10 -}}
9
+ {{- $paginator := .Paginate $posts $pageSize -}}
10
+
11
+ <section class="section section-collection section-smart-collection">
12
+ <header class="section-header">
13
+ <h1 class="section-title">{{ .Title }}</h1>
14
+ {{- with .Params.summary_text -}}
15
+ <p class="section-summary">{{ . }}</p>
16
+ {{- end -}}
17
+ {{- with len $posts -}}
18
+ <p class="section-meta">{{ . }} {{ if eq . 1 }}thread{{ else }}threads{{ end }}</p>
19
+ {{- end -}}
20
+ {{ .Content }}
21
+ </header>
22
+ {{ partial "collection-threads.html" (dict "paginator" $paginator "empty" "Nothing matches these conditions yet.") }}
23
+ </section>
24
+ {{ end }}
@@ -693,7 +693,6 @@ time {
693
693
  .home-branding-credit {
694
694
  margin-top: var(--space-xl);
695
695
  padding-bottom: var(--space-xl);
696
- text-align: center;
697
696
  color: var(--site-text-secondary);
698
697
  font-size: var(--type-base);
699
698
  }
@@ -5,7 +5,7 @@ description = "Default theme packaged with Jant exports."
5
5
  homepage = "https://jant.so"
6
6
  tags = ["blog", "microblog", "minimal"]
7
7
  features = ["pagination", "aliases"]
8
- min_version = "0.160.1"
8
+ min_version = "0.147.7"
9
9
 
10
10
  [author]
11
11
  name = "Jant"