@jant/core 0.4.0 → 0.4.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 (35) hide show
  1. package/dist/{app-B9XQDSoB.js → app-DQgkp6yV.js} +46 -63
  2. package/dist/app-DYJLFZaM.js +6 -0
  3. package/dist/client/.vite/manifest.json +3 -3
  4. package/dist/client/_assets/client-BbJ0FhON.css +2 -0
  5. package/dist/client/_assets/client-DqsPJKiP.js +272 -0
  6. package/dist/client/_assets/{client-auth-DFDajqqT.js → client-auth-N6fiJcOg.js} +82 -82
  7. package/dist/{export-ZBlfKSKm.js → export-DwH3ga3Y.js} +2 -2
  8. package/dist/{github-sync-C593r22F.js → github-sync-D2FO19Re.js} +2 -2
  9. package/dist/{github-sync-bL1hnx3Q.js → github-sync-eHOTYZGO.js} +1 -1
  10. package/dist/index.js +3 -3
  11. package/dist/node.js +4 -4
  12. package/package.json +1 -1
  13. package/src/client/__tests__/compose-shortcuts.test.ts +1 -4
  14. package/src/client/components/__tests__/jant-compose-dialog.test.ts +1 -1
  15. package/src/client/components/__tests__/jant-media-lightbox.test.ts +89 -0
  16. package/src/client/components/compose-types.ts +6 -1
  17. package/src/client/components/jant-compose-dialog.ts +2 -0
  18. package/src/client/components/jant-compose-editor.ts +2 -1
  19. package/src/client/components/jant-media-lightbox.ts +33 -10
  20. package/src/client/compose-bridge.ts +83 -25
  21. package/src/client/compose-launch.ts +0 -13
  22. package/src/client/thread-context.ts +1 -140
  23. package/src/client/upload-session.ts +77 -31
  24. package/src/i18n/locales/public/en.po +0 -4
  25. package/src/i18n/locales/public/zh-Hans.po +0 -4
  26. package/src/i18n/locales/public/zh-Hant.po +0 -4
  27. package/src/services/export-theme/assets/client-site.js +1 -1
  28. package/src/styles/tokens.css +0 -1
  29. package/src/styles/ui.css +0 -71
  30. package/src/ui/feed/ThreadPreview.tsx +34 -65
  31. package/src/ui/feed/__tests__/thread-preview.test.ts +64 -58
  32. package/src/ui/feed/thread-preview-state.ts +0 -48
  33. package/dist/app-CHW6VVQt.js +0 -6
  34. package/dist/client/_assets/client-BoUn7xBo.css +0 -2
  35. package/dist/client/_assets/client-dSfWfMe9.js +0 -272
@@ -7,10 +7,7 @@ import { createI18n } from "../../../i18n/i18n.js";
7
7
  import type { PostView, TimelineItemView } from "../../../types.js";
8
8
  import { CuratedThreadPreview } from "../CuratedThreadPreview.js";
9
9
  import { ThreadPreview } from "../ThreadPreview.js";
10
- import {
11
- getThreadPreviewState,
12
- isThreadContextLikelyOverflow,
13
- } from "../thread-preview-state.js";
10
+ import { getThreadPreviewState } from "../thread-preview-state.js";
14
11
 
15
12
  function createPostView(overrides: Partial<PostView> = {}): PostView {
16
13
  return {
@@ -128,56 +125,6 @@ describe("getThreadPreviewState", () => {
128
125
  });
129
126
  });
130
127
 
131
- it("treats hidden ancestors as likely overflow", () => {
132
- expect(
133
- isThreadContextLikelyOverflow({
134
- rootPost: createPostView(),
135
- hiddenCount: 1,
136
- }),
137
- ).toBe(true);
138
- });
139
-
140
- it("treats media-heavy context as likely overflow", () => {
141
- expect(
142
- isThreadContextLikelyOverflow({
143
- rootPost: createPostView({
144
- media: [
145
- {
146
- id: "media-1",
147
- url: "/image.jpg",
148
- thumbnailUrl: "/image-thumb.jpg",
149
- mimeType: "image/jpeg",
150
- },
151
- ],
152
- }),
153
- hiddenCount: 0,
154
- }),
155
- ).toBe(true);
156
- });
157
-
158
- it("keeps very short context collapsed without affordances", () => {
159
- expect(
160
- isThreadContextLikelyOverflow({
161
- rootPost: createPostView({
162
- bodyHtml: "<p>Short note.</p>",
163
- }),
164
- secondReply: createPostView({
165
- id: "post-2",
166
- permalink: "/post-2",
167
- slug: "post-2",
168
- bodyHtml: "<p>Tiny reply.</p>",
169
- }),
170
- penultimateReply: createPostView({
171
- id: "post-3",
172
- permalink: "/post-3",
173
- slug: "post-3",
174
- bodyHtml: "<p>Brief note.</p>",
175
- }),
176
- hiddenCount: 0,
177
- }),
178
- ).toBe(false);
179
- });
180
-
181
128
  it("keeps thread preview items shrinkable within the grid track", () => {
182
129
  const css = readFileSync(
183
130
  new URL("../../../styles/ui.css", import.meta.url),
@@ -249,7 +196,7 @@ describe("getThreadPreviewState", () => {
249
196
  expect(html).not.toContain('id="continue"');
250
197
  });
251
198
 
252
- it("always renders collapsible context shell with toggle even when all thread slots are visible", () => {
199
+ it("renders ancestor context fully without collapse affordances", () => {
253
200
  const html = renderWithI18n(() =>
254
201
  ThreadPreview({
255
202
  rootPost: createPostView({
@@ -280,9 +227,68 @@ describe("getThreadPreviewState", () => {
280
227
  }),
281
228
  );
282
229
 
283
- expect(html).toContain("data-thread-context");
284
- expect(html).toContain("data-thread-context-toggle");
285
- expect(html).toContain("thread-context-collapsed");
230
+ expect(html).not.toContain("data-thread-context");
231
+ expect(html).not.toContain("data-thread-context-toggle");
232
+ expect(html).not.toContain("thread-context-collapsed");
233
+ expect(html).not.toContain("thread-context-fade");
234
+ });
235
+
236
+ it("points the hidden-posts gap link to the second reply so the detail page opens just above the hidden range", () => {
237
+ const html = renderWithI18n(() =>
238
+ ThreadPreview({
239
+ rootPost: createPostView({ bodyHtml: "<p>Root</p>" }),
240
+ secondReply: createPostView({
241
+ id: "post-2",
242
+ permalink: "/post-2",
243
+ slug: "post-2",
244
+ bodyHtml: "<p>Second</p>",
245
+ }),
246
+ penultimateReply: createPostView({
247
+ id: "post-4",
248
+ permalink: "/post-4",
249
+ slug: "post-4",
250
+ bodyHtml: "<p>Penultimate</p>",
251
+ }),
252
+ latestReply: createPostView({
253
+ id: "post-5",
254
+ permalink: "/post-5",
255
+ slug: "post-5",
256
+ bodyHtml: "<p>Latest</p>",
257
+ isLastInThread: true,
258
+ }),
259
+ totalReplyCount: 4,
260
+ }),
261
+ );
262
+
263
+ expect(html).toMatch(
264
+ /<a[^>]*\bhref="\/post-2"[^>]*\bclass="thread-gap-link"|<a[^>]*\bclass="thread-gap-link"[^>]*\bhref="\/post-2"/,
265
+ );
266
+ });
267
+
268
+ it("falls back to the latest reply for the gap link when there is no second reply", () => {
269
+ const html = renderWithI18n(() =>
270
+ ThreadPreview({
271
+ rootPost: createPostView({ bodyHtml: "<p>Root</p>" }),
272
+ penultimateReply: createPostView({
273
+ id: "post-4",
274
+ permalink: "/post-4",
275
+ slug: "post-4",
276
+ bodyHtml: "<p>Penultimate</p>",
277
+ }),
278
+ latestReply: createPostView({
279
+ id: "post-5",
280
+ permalink: "/post-5",
281
+ slug: "post-5",
282
+ bodyHtml: "<p>Latest</p>",
283
+ isLastInThread: true,
284
+ }),
285
+ totalReplyCount: 3,
286
+ }),
287
+ );
288
+
289
+ expect(html).toMatch(
290
+ /<a[^>]*\bhref="\/post-5"[^>]*\bclass="thread-gap-link"|<a[^>]*\bclass="thread-gap-link"[^>]*\bhref="\/post-5"/,
291
+ );
286
292
  });
287
293
 
288
294
  it("renders article summaries in curated thread previews", () => {
@@ -22,51 +22,3 @@ export function getThreadPreviewState({
22
22
  hiddenCount,
23
23
  };
24
24
  }
25
-
26
- function getRenderedTextLength(post?: PostView): number {
27
- if (!post) return 0;
28
-
29
- return (
30
- (post.title?.length ?? 0) +
31
- (post.quoteText?.length ?? 0) +
32
- (post.summary?.length ?? 0) +
33
- (post.excerpt?.length ?? 0)
34
- );
35
- }
36
-
37
- export function isThreadContextLikelyOverflow({
38
- rootPost,
39
- secondReply,
40
- penultimateReply,
41
- hiddenCount,
42
- }: {
43
- rootPost: PostView;
44
- secondReply?: PostView;
45
- penultimateReply?: PostView;
46
- hiddenCount: number;
47
- }): boolean {
48
- if (hiddenCount > 0) return true;
49
-
50
- const contextPosts = [rootPost];
51
- if (secondReply) {
52
- contextPosts.push(secondReply);
53
- }
54
- if (penultimateReply && penultimateReply.id !== secondReply?.id) {
55
- contextPosts.push(penultimateReply);
56
- }
57
-
58
- if (
59
- contextPosts.some(
60
- (post) => post.media.length > 0 || post.summaryHasMore === true,
61
- )
62
- ) {
63
- return true;
64
- }
65
-
66
- const renderedTextLength = contextPosts.reduce(
67
- (sum, post) => sum + getRenderedTextLength(post),
68
- 0,
69
- );
70
-
71
- return renderedTextLength > 220;
72
- }
@@ -1,6 +0,0 @@
1
- import "./url-umUptr5z.js";
2
- import { t as createApp } from "./app-B9XQDSoB.js";
3
- import "./export-ZBlfKSKm.js";
4
- import "./env-CgaH9Mut.js";
5
- import "./github-sync-bL1hnx3Q.js";
6
- export { createApp };