@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.
- package/dist/{app-B9XQDSoB.js → app-DQgkp6yV.js} +46 -63
- package/dist/app-DYJLFZaM.js +6 -0
- package/dist/client/.vite/manifest.json +3 -3
- package/dist/client/_assets/client-BbJ0FhON.css +2 -0
- package/dist/client/_assets/client-DqsPJKiP.js +272 -0
- package/dist/client/_assets/{client-auth-DFDajqqT.js → client-auth-N6fiJcOg.js} +82 -82
- package/dist/{export-ZBlfKSKm.js → export-DwH3ga3Y.js} +2 -2
- package/dist/{github-sync-C593r22F.js → github-sync-D2FO19Re.js} +2 -2
- package/dist/{github-sync-bL1hnx3Q.js → github-sync-eHOTYZGO.js} +1 -1
- package/dist/index.js +3 -3
- package/dist/node.js +4 -4
- package/package.json +1 -1
- package/src/client/__tests__/compose-shortcuts.test.ts +1 -4
- package/src/client/components/__tests__/jant-compose-dialog.test.ts +1 -1
- package/src/client/components/__tests__/jant-media-lightbox.test.ts +89 -0
- package/src/client/components/compose-types.ts +6 -1
- package/src/client/components/jant-compose-dialog.ts +2 -0
- package/src/client/components/jant-compose-editor.ts +2 -1
- package/src/client/components/jant-media-lightbox.ts +33 -10
- package/src/client/compose-bridge.ts +83 -25
- package/src/client/compose-launch.ts +0 -13
- package/src/client/thread-context.ts +1 -140
- package/src/client/upload-session.ts +77 -31
- package/src/i18n/locales/public/en.po +0 -4
- package/src/i18n/locales/public/zh-Hans.po +0 -4
- package/src/i18n/locales/public/zh-Hant.po +0 -4
- package/src/services/export-theme/assets/client-site.js +1 -1
- package/src/styles/tokens.css +0 -1
- package/src/styles/ui.css +0 -71
- package/src/ui/feed/ThreadPreview.tsx +34 -65
- package/src/ui/feed/__tests__/thread-preview.test.ts +64 -58
- package/src/ui/feed/thread-preview-state.ts +0 -48
- package/dist/app-CHW6VVQt.js +0 -6
- package/dist/client/_assets/client-BoUn7xBo.css +0 -2
- 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("
|
|
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
|
-
}
|