@jant/core 0.6.6 → 0.6.8
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/bin/commands/uploads/cleanup.js +1 -0
- package/dist/{app-BJkOcMbZ.js → app-9P4rVCe2.js} +396 -117
- package/dist/app-DaxS_Cz-.js +6 -0
- package/dist/client/.vite/manifest.json +3 -3
- package/dist/client/_assets/client-C6peCkkD.css +2 -0
- package/dist/client/_assets/{client-mBvc8KAT.js → client-CXnEhyyv.js} +2 -2
- package/dist/client/_assets/{client-auth-BlfwVtHz.js → client-auth-CSItbyU8.js} +360 -358
- package/dist/{env-CoSe-1y4.js → env-OHRKGcMj.js} +1 -1
- package/dist/{export-DLukCOO3.js → export-Be082J0n.js} +33 -8
- package/dist/{github-api-UD4u_7fa.js → github-api-BgSiE71w.js} +1 -1
- package/dist/{github-app-DeX6Td1O.js → github-app-BbklkFmU.js} +1 -1
- package/dist/{github-sync-BtHY2AST.js → github-sync-D1Cw8mOY.js} +3 -3
- package/dist/{github-sync-BeDecPen.js → github-sync-_kPWM4m9.js} +3 -3
- package/dist/index.js +5 -5
- package/dist/node.js +6 -6
- package/dist/{url-XF0GbKGO.js → url-BMYO-Zlt.js} +42 -2
- package/package.json +1 -1
- package/src/__tests__/bin/uploads-cleanup.test.ts +2 -0
- package/src/client/__tests__/compose-bridge.test.ts +105 -0
- package/src/client/__tests__/hydrate-partial.test.ts +27 -0
- package/src/client/__tests__/json.test.ts +94 -0
- package/src/client/__tests__/note-expand.test.ts +130 -0
- package/src/client/archive-nav.js +2 -1
- package/src/client/audio-player.ts +7 -3
- package/src/client/components/__tests__/compose-format-convert.test.ts +357 -0
- package/src/client/components/__tests__/jant-compose-dialog.test.ts +357 -0
- package/src/client/components/__tests__/jant-compose-editor.test.ts +2 -0
- package/src/client/components/__tests__/jant-compose-fullscreen.test.ts +2 -0
- package/src/client/components/compose-format-convert.ts +255 -0
- package/src/client/components/compose-types.ts +2 -0
- package/src/client/components/jant-collection-directory.ts +1 -0
- package/src/client/components/jant-collection-form.ts +1 -0
- package/src/client/components/jant-command-palette.ts +4 -0
- package/src/client/components/jant-compose-dialog.ts +106 -44
- package/src/client/components/jant-compose-editor.ts +65 -11
- package/src/client/components/jant-compose-fullscreen.ts +3 -0
- package/src/client/components/jant-nav-manager.ts +4 -0
- package/src/client/components/jant-post-menu.ts +3 -0
- package/src/client/components/jant-repo-picker.ts +3 -0
- package/src/client/components/jant-settings-general.ts +3 -0
- package/src/client/compose-bridge.ts +17 -0
- package/src/client/feed-video-player.ts +1 -1
- package/src/client/hydrate-partial.ts +25 -0
- package/src/client/json.ts +56 -2
- package/src/client/multipart-upload.ts +17 -7
- package/src/client/note-expand.ts +63 -0
- package/src/client/upload-session.ts +17 -9
- package/src/client.ts +1 -0
- package/src/i18n/locales/public/en.po +41 -0
- package/src/i18n/locales/public/en.ts +1 -1
- package/src/i18n/locales/public/zh-Hans.po +41 -0
- package/src/i18n/locales/public/zh-Hans.ts +1 -1
- package/src/i18n/locales/public/zh-Hant.po +41 -0
- package/src/i18n/locales/public/zh-Hant.ts +1 -1
- package/src/i18n/locales/settings/en.po +12 -12
- package/src/i18n/locales/settings/en.ts +1 -1
- package/src/i18n/locales/settings/zh-Hans.po +12 -12
- package/src/i18n/locales/settings/zh-Hans.ts +1 -1
- package/src/i18n/locales/settings/zh-Hant.po +12 -12
- package/src/i18n/locales/settings/zh-Hant.ts +1 -1
- package/src/lib/__tests__/markdown-to-tiptap.test.ts +1 -1
- package/src/lib/__tests__/markdown.test.ts +1 -1
- package/src/lib/__tests__/summary.test.ts +87 -0
- package/src/lib/__tests__/timeline.test.ts +48 -1
- package/src/lib/__tests__/tiptap-render.test.ts +4 -4
- package/src/lib/__tests__/url.test.ts +44 -0
- package/src/lib/__tests__/view.test.ts +168 -1
- package/src/lib/navigation.ts +1 -0
- package/src/lib/resolve-config.ts +2 -2
- package/src/lib/summary.ts +42 -3
- package/src/lib/tiptap-render.ts +6 -2
- package/src/lib/upload.ts +2 -2
- package/src/lib/url.ts +41 -0
- package/src/lib/view.ts +102 -40
- package/src/preset.css +7 -1
- package/src/routes/api/internal/__tests__/uploads.test.ts +68 -0
- package/src/routes/api/internal/sites.ts +77 -1
- package/src/routes/api/public/__tests__/archive.test.ts +66 -0
- package/src/routes/api/public/archive.ts +22 -6
- package/src/routes/api/telegram.ts +2 -1
- package/src/routes/dash/custom-urls.tsx +1 -1
- package/src/routes/dash/settings.tsx +8 -5
- package/src/routes/pages/__tests__/archive-params.test.ts +135 -0
- package/src/routes/pages/archive.tsx +116 -20
- package/src/routes/pages/collections.tsx +1 -0
- package/src/services/__tests__/media.test.ts +83 -0
- package/src/services/__tests__/post.test.ts +81 -0
- package/src/services/export-theme/assets/client-site.js +1 -1
- package/src/services/export-theme/styles/main.css +49 -15
- package/src/services/media.ts +31 -1
- package/src/services/post.ts +22 -2
- package/src/services/search.ts +4 -4
- package/src/services/site-admin.ts +121 -0
- package/src/services/upload-session.ts +18 -0
- package/src/styles/tokens.css +1 -1
- package/src/styles/ui.css +163 -34
- package/src/types/config.ts +1 -1
- package/src/types/props.ts +3 -0
- package/src/ui/compose/ComposeDialog.tsx +13 -0
- package/src/ui/dash/settings/AccountMenuContent.tsx +0 -39
- package/src/ui/dash/settings/SettingsDirectory.tsx +26 -1
- package/src/ui/dash/settings/SettingsRootContent.tsx +46 -1
- package/src/ui/dash/settings/__tests__/SettingsRootContent.test.tsx +55 -0
- package/src/ui/feed/NoteCard.tsx +54 -5
- package/src/ui/feed/__tests__/timeline-cards.test.ts +73 -0
- package/src/ui/pages/ArchivePage.tsx +89 -6
- package/src/ui/pages/CollectionsPage.tsx +7 -1
- package/src/ui/pages/__tests__/ArchivePage.test.tsx +37 -0
- package/src/ui/shared/CollectionDirectory.tsx +13 -3
- package/src/ui/shared/CollectionsManager.tsx +3 -0
- package/dist/app-CL2PC1Fl.js +0 -6
- package/dist/client/_assets/client-BMPMuwvV.css +0 -2
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import type { JSONContent } from "@tiptap/core";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
convertComposeFormat,
|
|
6
|
+
type ComposeConvertFields,
|
|
7
|
+
} from "../compose-format-convert.js";
|
|
8
|
+
|
|
9
|
+
const EMPTY: ComposeConvertFields = {
|
|
10
|
+
title: "",
|
|
11
|
+
url: "",
|
|
12
|
+
quoteText: "",
|
|
13
|
+
quoteAuthor: "",
|
|
14
|
+
showTitle: false,
|
|
15
|
+
bodyJson: null,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function fields(
|
|
19
|
+
overrides: Partial<ComposeConvertFields>,
|
|
20
|
+
): ComposeConvertFields {
|
|
21
|
+
return { ...EMPTY, ...overrides };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function doc(...content: JSONContent[]): JSONContent {
|
|
25
|
+
return { type: "doc", content };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function paragraph(text: string): JSONContent {
|
|
29
|
+
return { type: "paragraph", content: [{ type: "text", text }] };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function linkParagraph(url: string, text = url): JSONContent {
|
|
33
|
+
return {
|
|
34
|
+
type: "paragraph",
|
|
35
|
+
content: [
|
|
36
|
+
{ type: "text", text, marks: [{ type: "link", attrs: { href: url } }] },
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** First block of the resulting body. */
|
|
42
|
+
function firstBlock(result: ComposeConvertFields): JSONContent | undefined {
|
|
43
|
+
return result.bodyJson?.content?.[0];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
describe("convertComposeFormat", () => {
|
|
47
|
+
it("returns input unchanged when from === to", () => {
|
|
48
|
+
const input = fields({ quoteText: "x" });
|
|
49
|
+
expect(convertComposeFormat("quote", "quote", input)).toBe(input);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("note → quote folds a title into a leading heading", () => {
|
|
53
|
+
const result = convertComposeFormat(
|
|
54
|
+
"note",
|
|
55
|
+
"quote",
|
|
56
|
+
fields({
|
|
57
|
+
title: "My thoughts",
|
|
58
|
+
showTitle: true,
|
|
59
|
+
bodyJson: doc(paragraph("body")),
|
|
60
|
+
}),
|
|
61
|
+
);
|
|
62
|
+
expect(result.title).toBe("");
|
|
63
|
+
expect(firstBlock(result)).toEqual({
|
|
64
|
+
type: "heading",
|
|
65
|
+
attrs: { level: 2 },
|
|
66
|
+
content: [{ type: "text", text: "My thoughts" }],
|
|
67
|
+
});
|
|
68
|
+
expect(result.bodyJson?.content?.[1]).toEqual(paragraph("body"));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("quote → note folds the quote into a leading blockquote with attribution", () => {
|
|
72
|
+
const result = convertComposeFormat(
|
|
73
|
+
"quote",
|
|
74
|
+
"note",
|
|
75
|
+
fields({ quoteText: "Stay hungry", quoteAuthor: "Jobs" }),
|
|
76
|
+
);
|
|
77
|
+
expect(result.quoteText).toBe("");
|
|
78
|
+
expect(result.quoteAuthor).toBe("");
|
|
79
|
+
const bq = firstBlock(result);
|
|
80
|
+
expect(bq?.type).toBe("blockquote");
|
|
81
|
+
expect(bq?.content?.[0]).toEqual(paragraph("Stay hungry"));
|
|
82
|
+
expect(bq?.content?.[1]).toEqual(paragraph("— Jobs"));
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("quote → note links the author to the source url and clears url", () => {
|
|
86
|
+
const result = convertComposeFormat(
|
|
87
|
+
"quote",
|
|
88
|
+
"note",
|
|
89
|
+
fields({
|
|
90
|
+
quoteText: "Be water",
|
|
91
|
+
quoteAuthor: "Lee",
|
|
92
|
+
url: "https://example.com",
|
|
93
|
+
}),
|
|
94
|
+
);
|
|
95
|
+
expect(result.url).toBe("");
|
|
96
|
+
const bq = firstBlock(result);
|
|
97
|
+
expect(bq?.content?.[1]).toEqual({
|
|
98
|
+
type: "paragraph",
|
|
99
|
+
content: [
|
|
100
|
+
{ type: "text", text: "— " },
|
|
101
|
+
{
|
|
102
|
+
type: "text",
|
|
103
|
+
text: "Lee",
|
|
104
|
+
marks: [{ type: "link", attrs: { href: "https://example.com" } }],
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("quote → note with a url but no author links the url itself", () => {
|
|
111
|
+
const result = convertComposeFormat(
|
|
112
|
+
"quote",
|
|
113
|
+
"note",
|
|
114
|
+
fields({ quoteText: "Anon", url: "https://example.com" }),
|
|
115
|
+
);
|
|
116
|
+
const bq = firstBlock(result);
|
|
117
|
+
expect(bq?.content?.[1]).toEqual({
|
|
118
|
+
type: "paragraph",
|
|
119
|
+
content: [
|
|
120
|
+
{ type: "text", text: "— " },
|
|
121
|
+
{
|
|
122
|
+
type: "text",
|
|
123
|
+
text: "https://example.com",
|
|
124
|
+
marks: [{ type: "link", attrs: { href: "https://example.com" } }],
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("note → quote recovers a url-only attribution without a phantom author", () => {
|
|
131
|
+
const note = convertComposeFormat(
|
|
132
|
+
"quote",
|
|
133
|
+
"note",
|
|
134
|
+
fields({ quoteText: "Anon", url: "https://example.com" }),
|
|
135
|
+
);
|
|
136
|
+
const back = convertComposeFormat("note", "quote", note);
|
|
137
|
+
expect(back.quoteText).toBe("Anon");
|
|
138
|
+
expect(back.quoteAuthor).toBe("");
|
|
139
|
+
expect(back.url).toBe("https://example.com");
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("note → quote still parses the legacy plain-text attribution form", () => {
|
|
143
|
+
const result = convertComposeFormat(
|
|
144
|
+
"note",
|
|
145
|
+
"quote",
|
|
146
|
+
fields({
|
|
147
|
+
bodyJson: doc({
|
|
148
|
+
type: "blockquote",
|
|
149
|
+
content: [
|
|
150
|
+
paragraph("Be water"),
|
|
151
|
+
paragraph("— Lee https://example.com"),
|
|
152
|
+
],
|
|
153
|
+
}),
|
|
154
|
+
}),
|
|
155
|
+
);
|
|
156
|
+
expect(result.quoteText).toBe("Be water");
|
|
157
|
+
expect(result.quoteAuthor).toBe("Lee");
|
|
158
|
+
expect(result.url).toBe("https://example.com");
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("quote → note → quote round-trips quote text and author", () => {
|
|
162
|
+
const start = fields({ quoteText: "Stay hungry", quoteAuthor: "Jobs" });
|
|
163
|
+
const note = convertComposeFormat("quote", "note", start);
|
|
164
|
+
const back = convertComposeFormat("note", "quote", note);
|
|
165
|
+
expect(back.quoteText).toBe("Stay hungry");
|
|
166
|
+
expect(back.quoteAuthor).toBe("Jobs");
|
|
167
|
+
expect(back.bodyJson).toBeNull();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("quote → note → quote round-trips the source url too", () => {
|
|
171
|
+
const start = fields({
|
|
172
|
+
quoteText: "Be water",
|
|
173
|
+
quoteAuthor: "Lee",
|
|
174
|
+
url: "https://example.com",
|
|
175
|
+
});
|
|
176
|
+
const note = convertComposeFormat("quote", "note", start);
|
|
177
|
+
const back = convertComposeFormat("note", "quote", note);
|
|
178
|
+
expect(back.quoteText).toBe("Be water");
|
|
179
|
+
expect(back.quoteAuthor).toBe("Lee");
|
|
180
|
+
expect(back.url).toBe("https://example.com");
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("link → quote preserves the url and folds a title into a heading", () => {
|
|
184
|
+
const result = convertComposeFormat(
|
|
185
|
+
"link",
|
|
186
|
+
"quote",
|
|
187
|
+
fields({ title: "Cool link", url: "https://example.com" }),
|
|
188
|
+
);
|
|
189
|
+
expect(result.url).toBe("https://example.com");
|
|
190
|
+
expect(result.title).toBe("");
|
|
191
|
+
expect(firstBlock(result)?.type).toBe("heading");
|
|
192
|
+
expect(result.quoteText).toBe("");
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it("quote → link preserves the url and folds the quote, leaving no title", () => {
|
|
196
|
+
const result = convertComposeFormat(
|
|
197
|
+
"quote",
|
|
198
|
+
"link",
|
|
199
|
+
fields({
|
|
200
|
+
quoteText: "Quoted",
|
|
201
|
+
quoteAuthor: "Author",
|
|
202
|
+
url: "https://example.com",
|
|
203
|
+
}),
|
|
204
|
+
);
|
|
205
|
+
expect(result.url).toBe("https://example.com");
|
|
206
|
+
expect(result.title).toBe("");
|
|
207
|
+
expect(result.quoteText).toBe("");
|
|
208
|
+
const bq = firstBlock(result);
|
|
209
|
+
expect(bq?.type).toBe("blockquote");
|
|
210
|
+
expect(bq?.content?.[1]).toEqual(paragraph("— Author"));
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it("note → link preserves the title and leaves the url empty", () => {
|
|
214
|
+
const result = convertComposeFormat(
|
|
215
|
+
"note",
|
|
216
|
+
"link",
|
|
217
|
+
fields({
|
|
218
|
+
title: "Keep me",
|
|
219
|
+
showTitle: true,
|
|
220
|
+
bodyJson: doc(paragraph("body")),
|
|
221
|
+
}),
|
|
222
|
+
);
|
|
223
|
+
expect(result.title).toBe("Keep me");
|
|
224
|
+
expect(result.url).toBe("");
|
|
225
|
+
expect(result.bodyJson).toEqual(doc(paragraph("body")));
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it("link → note preserves the title and folds the url into a link paragraph", () => {
|
|
229
|
+
const result = convertComposeFormat(
|
|
230
|
+
"link",
|
|
231
|
+
"note",
|
|
232
|
+
fields({
|
|
233
|
+
title: "Keep me",
|
|
234
|
+
url: "https://example.com",
|
|
235
|
+
bodyJson: doc(paragraph("body")),
|
|
236
|
+
}),
|
|
237
|
+
);
|
|
238
|
+
expect(result.title).toBe("Keep me");
|
|
239
|
+
expect(result.showTitle).toBe(true);
|
|
240
|
+
expect(result.url).toBe("");
|
|
241
|
+
expect(firstBlock(result)).toEqual({
|
|
242
|
+
type: "paragraph",
|
|
243
|
+
content: [
|
|
244
|
+
{
|
|
245
|
+
type: "text",
|
|
246
|
+
text: "https://example.com",
|
|
247
|
+
marks: [{ type: "link", attrs: { href: "https://example.com" } }],
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it("note → link extracts a leading bare-link paragraph into the url", () => {
|
|
254
|
+
const result = convertComposeFormat(
|
|
255
|
+
"note",
|
|
256
|
+
"link",
|
|
257
|
+
fields({
|
|
258
|
+
title: "T",
|
|
259
|
+
bodyJson: doc(linkParagraph("https://example.com"), paragraph("body")),
|
|
260
|
+
}),
|
|
261
|
+
);
|
|
262
|
+
expect(result.url).toBe("https://example.com");
|
|
263
|
+
expect(result.bodyJson).toEqual(doc(paragraph("body")));
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it("link → note → link round-trips the url, title, and body", () => {
|
|
267
|
+
const start = fields({
|
|
268
|
+
title: "Keep me",
|
|
269
|
+
url: "https://example.com",
|
|
270
|
+
bodyJson: doc(paragraph("body")),
|
|
271
|
+
});
|
|
272
|
+
const note = convertComposeFormat("link", "note", start);
|
|
273
|
+
const back = convertComposeFormat("note", "link", note);
|
|
274
|
+
expect(back.title).toBe("Keep me");
|
|
275
|
+
expect(back.url).toBe("https://example.com");
|
|
276
|
+
expect(back.bodyJson).toEqual(doc(paragraph("body")));
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it("note → link leaves a labeled-link first line in the body", () => {
|
|
280
|
+
const result = convertComposeFormat(
|
|
281
|
+
"note",
|
|
282
|
+
"link",
|
|
283
|
+
fields({
|
|
284
|
+
title: "T",
|
|
285
|
+
bodyJson: doc(
|
|
286
|
+
linkParagraph("https://example.com", "Read this"),
|
|
287
|
+
paragraph("body"),
|
|
288
|
+
),
|
|
289
|
+
}),
|
|
290
|
+
);
|
|
291
|
+
// A labeled link isn't a bare url — keep it in the body, leave url empty.
|
|
292
|
+
expect(result.url).toBe("");
|
|
293
|
+
expect(result.bodyJson).toEqual(
|
|
294
|
+
doc(linkParagraph("https://example.com", "Read this"), paragraph("body")),
|
|
295
|
+
);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it("note → quote with an empty body and no fields yields a null body", () => {
|
|
299
|
+
const result = convertComposeFormat("note", "quote", fields({}));
|
|
300
|
+
expect(result.bodyJson).toBeNull();
|
|
301
|
+
expect(result.quoteText).toBe("");
|
|
302
|
+
expect(result.title).toBe("");
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it("note → quote extracts a body that is only a blockquote, leaving the body null", () => {
|
|
306
|
+
const result = convertComposeFormat(
|
|
307
|
+
"note",
|
|
308
|
+
"quote",
|
|
309
|
+
fields({
|
|
310
|
+
bodyJson: doc({
|
|
311
|
+
type: "blockquote",
|
|
312
|
+
content: [paragraph("Quoted line")],
|
|
313
|
+
}),
|
|
314
|
+
}),
|
|
315
|
+
);
|
|
316
|
+
expect(result.quoteText).toBe("Quoted line");
|
|
317
|
+
expect(result.bodyJson).toBeNull();
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it("sets showTitle only for a note that ends up with a title", () => {
|
|
321
|
+
const toNote = convertComposeFormat(
|
|
322
|
+
"link",
|
|
323
|
+
"note",
|
|
324
|
+
fields({ title: "T", url: "https://example.com" }),
|
|
325
|
+
);
|
|
326
|
+
expect(toNote.showTitle).toBe(true);
|
|
327
|
+
|
|
328
|
+
const toQuote = convertComposeFormat(
|
|
329
|
+
"note",
|
|
330
|
+
"quote",
|
|
331
|
+
fields({ title: "T" }),
|
|
332
|
+
);
|
|
333
|
+
expect(toQuote.showTitle).toBe(false);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
it("treats a non-attribution last line as part of the quote text", () => {
|
|
337
|
+
const result = convertComposeFormat(
|
|
338
|
+
"note",
|
|
339
|
+
"quote",
|
|
340
|
+
fields({
|
|
341
|
+
bodyJson: doc({
|
|
342
|
+
type: "blockquote",
|
|
343
|
+
content: [paragraph("Line one"), paragraph("Line two")],
|
|
344
|
+
}),
|
|
345
|
+
}),
|
|
346
|
+
);
|
|
347
|
+
expect(result.quoteText).toBe("Line one\nLine two");
|
|
348
|
+
expect(result.quoteAuthor).toBe("");
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it("does not mutate the input bodyJson", () => {
|
|
352
|
+
const bodyJson = doc(paragraph("body"));
|
|
353
|
+
const snapshot = JSON.stringify(bodyJson);
|
|
354
|
+
convertComposeFormat("quote", "note", fields({ quoteText: "q", bodyJson }));
|
|
355
|
+
expect(JSON.stringify(bodyJson)).toBe(snapshot);
|
|
356
|
+
});
|
|
357
|
+
});
|