@fedify/vocab 2.4.0-dev.2155 → 2.4.0-dev.2159
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/deno.json +1 -1
- package/dist/mod.cjs +2690 -940
- package/dist/mod.js +2690 -940
- package/dist-tests/{actor-B5rDT4b4.mjs → actor-CV61JExo.mjs} +2 -2
- package/dist-tests/actor.test.mjs +3 -3
- package/dist-tests/{esm-CxYTzURx.mjs → esm-2_Uqq_my.mjs} +1 -1
- package/dist-tests/gateway.test.mjs +3 -3
- package/dist-tests/{lookup-BaaHpBsf.mjs → lookup-TmMHMifw.mjs} +2 -2
- package/dist-tests/lookup.test.mjs +8 -8
- package/dist-tests/portable-lookup.test.mjs +4 -4
- package/dist-tests/signed-representation.test.mjs +1 -1
- package/dist-tests/translation.test.mjs +3 -3
- package/dist-tests/type.test.mjs +1 -1
- package/dist-tests/{vocab-CVEaA48h.mjs → vocab-D3C791xF.mjs} +2689 -939
- package/dist-tests/vocab.test.mjs +145 -2
- package/package.json +4 -4
- package/src/lookup.test.ts +6 -5
- package/src/vocab.test.ts +197 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
|
-
import { A as Object$1, B as QuoteAuthorization, C as Intent, D as Measure, E as Link, F as Person, G as Tombstone, H as Reject, I as Place, L as PropertyValue, N as OrderedCollectionPage, O as Multikey, P as Organization, R as Proposal, S as Image, T as InteractionRule, U as Service, V as QuoteRequest, W as Source, X as vocab_exports, _ as FeaturedCollection, a as Application, b as Group, d as CryptographicKey, f as Delete, g as FeatureRequest, h as FeatureAuthorization, i as Announce, j as Offer, k as Note, l as Commitment, m as Endpoints, n as Activity, p as Document, r as Agreement, s as Collection, t as Accept, u as Create, v as FeaturedItem, w as InteractionPolicy, x as Hashtag, y as Follow, z as Question } from "./vocab-
|
|
4
|
-
import { t as esm_default } from "./esm-
|
|
3
|
+
import { A as Object$1, B as QuoteAuthorization, C as Intent, D as Measure, E as Link, F as Person, G as Tombstone, H as Reject, I as Place, L as PropertyValue, N as OrderedCollectionPage, O as Multikey, P as Organization, R as Proposal, S as Image, T as InteractionRule, U as Service, V as QuoteRequest, W as Source, X as vocab_exports, _ as FeaturedCollection, a as Application, b as Group, d as CryptographicKey, f as Delete, g as FeatureRequest, h as FeatureAuthorization, i as Announce, j as Offer, k as Note, l as Commitment, m as Endpoints, n as Activity, p as Document, r as Agreement, s as Collection, t as Accept, u as Create, v as FeaturedItem, w as InteractionPolicy, x as Hashtag, y as Follow, z as Question } from "./vocab-D3C791xF.mjs";
|
|
4
|
+
import { t as esm_default } from "./esm-2_Uqq_my.mjs";
|
|
5
5
|
import { t as assertInstanceOf } from "./utils-Df2odC27.mjs";
|
|
6
6
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
7
7
|
import { deepStrictEqual, notDeepStrictEqual, ok, rejects, throws } from "node:assert/strict";
|
|
@@ -1311,6 +1311,72 @@ test({
|
|
|
1311
1311
|
deepStrictEqual(objects2[0].name, "Second object");
|
|
1312
1312
|
}
|
|
1313
1313
|
});
|
|
1314
|
+
function embeddedPropertyDocument(property) {
|
|
1315
|
+
const context = "https://www.w3.org/ns/activitystreams";
|
|
1316
|
+
return {
|
|
1317
|
+
"@context": [context, { CustomImage: `${context}#Image` }],
|
|
1318
|
+
type: property === "attachment" ? "Note" : "Create",
|
|
1319
|
+
[property]: [
|
|
1320
|
+
{
|
|
1321
|
+
"@context": [context, { "@vocab": "https://example.com/" }],
|
|
1322
|
+
type: "CustomImage",
|
|
1323
|
+
name: "Malformed when reparsed"
|
|
1324
|
+
},
|
|
1325
|
+
{
|
|
1326
|
+
"@context": context,
|
|
1327
|
+
type: "Image",
|
|
1328
|
+
name: "Cached image"
|
|
1329
|
+
},
|
|
1330
|
+
{
|
|
1331
|
+
type: "Image",
|
|
1332
|
+
name: "Decoded image"
|
|
1333
|
+
}
|
|
1334
|
+
]
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
for (const suppressError of [
|
|
1338
|
+
void 0,
|
|
1339
|
+
false,
|
|
1340
|
+
true
|
|
1341
|
+
]) {
|
|
1342
|
+
test(`Note.getAttachments() cached parse failure (suppressError: ${suppressError})`, async () => {
|
|
1343
|
+
const jsonLd = embeddedPropertyDocument("attachment");
|
|
1344
|
+
const note = await Note.fromJsonLd(jsonLd);
|
|
1345
|
+
if (suppressError) {
|
|
1346
|
+
for (let i = 0; i < 2; i++) deepStrictEqual((await Array.fromAsync(note.getAttachments({ suppressError }))).map((attachment) => attachment.name), ["Cached image", "Decoded image"]);
|
|
1347
|
+
await rejects(() => Array.fromAsync(note.getAttachments()), TypeError);
|
|
1348
|
+
} else await rejects(() => Array.fromAsync(note.getAttachments({ suppressError })), TypeError);
|
|
1349
|
+
deepStrictEqual(await note.toJsonLd(), jsonLd);
|
|
1350
|
+
});
|
|
1351
|
+
test(`Activity.getObject() cached parse failure (suppressError: ${suppressError})`, async () => {
|
|
1352
|
+
const jsonLd = embeddedPropertyDocument("object");
|
|
1353
|
+
const activity = await Activity.fromJsonLd(jsonLd);
|
|
1354
|
+
if (suppressError) {
|
|
1355
|
+
deepStrictEqual(await activity.getObject({ suppressError }), null);
|
|
1356
|
+
deepStrictEqual(await activity.getObject({ suppressError }), null);
|
|
1357
|
+
await rejects(() => activity.getObject(), TypeError);
|
|
1358
|
+
} else await rejects(() => activity.getObject({ suppressError }), TypeError);
|
|
1359
|
+
deepStrictEqual(await activity.toJsonLd(), jsonLd);
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
test("Note.getAttachments() suppresses cached context loader failures", async () => {
|
|
1363
|
+
const note = await Note.fromJsonLd(embeddedPropertyDocument("attachment"));
|
|
1364
|
+
const contextLoader = () => Promise.reject(/* @__PURE__ */ new Error("Context loader failed"));
|
|
1365
|
+
await rejects(() => Array.fromAsync(note.getAttachments({ contextLoader })), (error) => error instanceof Error && !(error instanceof TypeError));
|
|
1366
|
+
deepStrictEqual((await Array.fromAsync(note.getAttachments({
|
|
1367
|
+
contextLoader,
|
|
1368
|
+
suppressError: true
|
|
1369
|
+
}))).map((attachment) => attachment.name), ["Decoded image"]);
|
|
1370
|
+
});
|
|
1371
|
+
test("Activity.getObject() suppresses cached context loader failures", async () => {
|
|
1372
|
+
const activity = await Activity.fromJsonLd(embeddedPropertyDocument("object"));
|
|
1373
|
+
const contextLoader = () => Promise.reject(/* @__PURE__ */ new Error("Context loader failed"));
|
|
1374
|
+
await rejects(() => activity.getObject({ contextLoader }), (error) => error instanceof Error && !(error instanceof TypeError));
|
|
1375
|
+
deepStrictEqual(await activity.getObject({
|
|
1376
|
+
contextLoader,
|
|
1377
|
+
suppressError: true
|
|
1378
|
+
}), null);
|
|
1379
|
+
});
|
|
1314
1380
|
test("Activity.clone()", async () => {
|
|
1315
1381
|
const activity = new Activity({
|
|
1316
1382
|
actor: new Person({ name: "John Doe" }),
|
|
@@ -2188,6 +2254,83 @@ test("Delete.toJsonLd() compacts embedded QuoteRequest", async () => {
|
|
|
2188
2254
|
type: "Delete"
|
|
2189
2255
|
});
|
|
2190
2256
|
});
|
|
2257
|
+
test("Note.quoteUrl (IRI-typed alias terms)", async () => {
|
|
2258
|
+
const jsonLd = {
|
|
2259
|
+
"@context": ["https://www.w3.org/ns/activitystreams", {
|
|
2260
|
+
fedibird: "http://fedibird.com/ns#",
|
|
2261
|
+
misskey: "https://misskey-hub.net/ns#",
|
|
2262
|
+
_misskey_quote: {
|
|
2263
|
+
"@id": "misskey:_misskey_quote",
|
|
2264
|
+
"@type": "@id"
|
|
2265
|
+
},
|
|
2266
|
+
quoteUri: {
|
|
2267
|
+
"@id": "fedibird:quoteUri",
|
|
2268
|
+
"@type": "@id"
|
|
2269
|
+
}
|
|
2270
|
+
}],
|
|
2271
|
+
id: "https://example.com/notes/1",
|
|
2272
|
+
type: "Note",
|
|
2273
|
+
_misskey_quote: "https://example.com/notes/quoted",
|
|
2274
|
+
quoteUri: "https://example.com/notes/quoted2"
|
|
2275
|
+
};
|
|
2276
|
+
deepStrictEqual((await Note.fromJsonLd(jsonLd)).quoteUrl, new URL("https://example.com/notes/quoted"));
|
|
2277
|
+
delete jsonLd._misskey_quote;
|
|
2278
|
+
deepStrictEqual((await Note.fromJsonLd(jsonLd)).quoteUrl, new URL("https://example.com/notes/quoted2"));
|
|
2279
|
+
});
|
|
2280
|
+
test("Note.quoteUrl (IRI-typed primary term)", async () => {
|
|
2281
|
+
const context = ["https://www.w3.org/ns/activitystreams", {
|
|
2282
|
+
misskey: "https://misskey-hub.net/ns#",
|
|
2283
|
+
quoteUrl: {
|
|
2284
|
+
"@id": "as:quoteUrl",
|
|
2285
|
+
"@type": "@id"
|
|
2286
|
+
},
|
|
2287
|
+
_misskey_quote: "misskey:_misskey_quote"
|
|
2288
|
+
}];
|
|
2289
|
+
deepStrictEqual((await Note.fromJsonLd({
|
|
2290
|
+
"@context": context,
|
|
2291
|
+
type: "Note",
|
|
2292
|
+
quoteUrl: "https://example.com/object"
|
|
2293
|
+
})).quoteUrl, new URL("https://example.com/object"));
|
|
2294
|
+
deepStrictEqual((await Note.fromJsonLd({
|
|
2295
|
+
"@context": context,
|
|
2296
|
+
type: "Note",
|
|
2297
|
+
quoteUrl: "https://example.com/object",
|
|
2298
|
+
_misskey_quote: "https://example.com/object2"
|
|
2299
|
+
})).quoteUrl, new URL("https://example.com/object"));
|
|
2300
|
+
});
|
|
2301
|
+
test("Note.quoteUrl (unparsable IRI-valued terms)", async () => {
|
|
2302
|
+
const context = ["https://www.w3.org/ns/activitystreams", {
|
|
2303
|
+
misskey: "https://misskey-hub.net/ns#",
|
|
2304
|
+
_misskey_quote: {
|
|
2305
|
+
"@id": "misskey:_misskey_quote",
|
|
2306
|
+
"@type": "@id"
|
|
2307
|
+
}
|
|
2308
|
+
}];
|
|
2309
|
+
for (const quote of [
|
|
2310
|
+
{
|
|
2311
|
+
type: "Note",
|
|
2312
|
+
content: "An inlined quote without an id"
|
|
2313
|
+
},
|
|
2314
|
+
"_:b0",
|
|
2315
|
+
"",
|
|
2316
|
+
"notes/relative"
|
|
2317
|
+
]) {
|
|
2318
|
+
const loaded = await Note.fromJsonLd({
|
|
2319
|
+
"@context": context,
|
|
2320
|
+
id: "https://example.com/notes/1",
|
|
2321
|
+
type: "Note",
|
|
2322
|
+
content: "Hello",
|
|
2323
|
+
_misskey_quote: quote
|
|
2324
|
+
});
|
|
2325
|
+
deepStrictEqual(loaded.quoteUrl, null, JSON.stringify(quote));
|
|
2326
|
+
deepStrictEqual(loaded.content, "Hello");
|
|
2327
|
+
}
|
|
2328
|
+
deepStrictEqual((await Note.fromJsonLd({
|
|
2329
|
+
"@context": context,
|
|
2330
|
+
type: "Note",
|
|
2331
|
+
_misskey_quote: "at://did:plc:abc/app.bsky.feed.post/xyz"
|
|
2332
|
+
})).quoteUrl, new URL("at://" + encodeURIComponent("did:plc:abc/app.bsky.feed.post/xyz")));
|
|
2333
|
+
});
|
|
2191
2334
|
test("Key.publicKey", async () => {
|
|
2192
2335
|
const jwk = {
|
|
2193
2336
|
kty: "RSA",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/vocab",
|
|
3
|
-
"version": "2.4.0-dev.
|
|
3
|
+
"version": "2.4.0-dev.2159+bb072eda",
|
|
4
4
|
"homepage": "https://fedify.dev/",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
"jsonld": "^9.0.0",
|
|
44
44
|
"pkijs": "^3.3.3",
|
|
45
45
|
"temporal-polyfill": "^1.0.1",
|
|
46
|
-
"@fedify/
|
|
47
|
-
"@fedify/
|
|
48
|
-
"@fedify/vocab-runtime": "2.4.0-dev.
|
|
46
|
+
"@fedify/vocab-tools": "2.4.0-dev.2159+bb072eda",
|
|
47
|
+
"@fedify/webfinger": "2.4.0-dev.2159+bb072eda",
|
|
48
|
+
"@fedify/vocab-runtime": "2.4.0-dev.2159+bb072eda"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^24.12.2",
|
package/src/lookup.test.ts
CHANGED
|
@@ -80,7 +80,8 @@ test("lookupObject()", {
|
|
|
80
80
|
);
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
// Workers load fixtures through fetch(), so keep the spy fallback between steps.
|
|
84
|
+
fetchMock.removeRoutes({ includeFallback: false });
|
|
84
85
|
fetchMock.get("begin:https://example.com/.well-known/webfinger", {
|
|
85
86
|
subject: "acct:janedoe@example.com",
|
|
86
87
|
links: [
|
|
@@ -100,7 +101,7 @@ test("lookupObject()", {
|
|
|
100
101
|
);
|
|
101
102
|
});
|
|
102
103
|
|
|
103
|
-
fetchMock.removeRoutes();
|
|
104
|
+
fetchMock.removeRoutes({ includeFallback: false });
|
|
104
105
|
fetchMock.get(
|
|
105
106
|
"begin:https://example.com/.well-known/webfinger",
|
|
106
107
|
() =>
|
|
@@ -131,7 +132,7 @@ test("lookupObject()", {
|
|
|
131
132
|
deepStrictEqual(await promise, null);
|
|
132
133
|
});
|
|
133
134
|
|
|
134
|
-
fetchMock.removeRoutes();
|
|
135
|
+
fetchMock.removeRoutes({ includeFallback: false });
|
|
135
136
|
fetchMock.get(
|
|
136
137
|
"begin:https://example.com/.well-known/webfinger",
|
|
137
138
|
{
|
|
@@ -156,7 +157,7 @@ test("lookupObject()", {
|
|
|
156
157
|
deepStrictEqual(person.id, new URL("https://example.com/person"));
|
|
157
158
|
});
|
|
158
159
|
|
|
159
|
-
fetchMock.removeRoutes();
|
|
160
|
+
fetchMock.removeRoutes({ includeFallback: false });
|
|
160
161
|
fetchMock.get(
|
|
161
162
|
"begin:https://example.com/.well-known/webfinger",
|
|
162
163
|
() =>
|
|
@@ -187,7 +188,7 @@ test("lookupObject()", {
|
|
|
187
188
|
deepStrictEqual(result, null);
|
|
188
189
|
});
|
|
189
190
|
|
|
190
|
-
fetchMock.removeRoutes();
|
|
191
|
+
fetchMock.removeRoutes({ includeFallback: false });
|
|
191
192
|
fetchMock.get(
|
|
192
193
|
"https://example.com/slow-object",
|
|
193
194
|
() =>
|
package/src/vocab.test.ts
CHANGED
|
@@ -2007,6 +2007,104 @@ test({
|
|
|
2007
2007
|
},
|
|
2008
2008
|
});
|
|
2009
2009
|
|
|
2010
|
+
// The alias is inherited during initial expansion, but is unavailable when
|
|
2011
|
+
// an embedded value is reparsed standalone from the cached JSON-LD.
|
|
2012
|
+
function embeddedPropertyDocument(property: "attachment" | "object") {
|
|
2013
|
+
const context = "https://www.w3.org/ns/activitystreams";
|
|
2014
|
+
return {
|
|
2015
|
+
"@context": [context, { CustomImage: `${context}#Image` }],
|
|
2016
|
+
type: property === "attachment" ? "Note" : "Create",
|
|
2017
|
+
[property]: [
|
|
2018
|
+
{
|
|
2019
|
+
"@context": [context, { "@vocab": "https://example.com/" }],
|
|
2020
|
+
type: "CustomImage",
|
|
2021
|
+
name: "Malformed when reparsed",
|
|
2022
|
+
},
|
|
2023
|
+
{ "@context": context, type: "Image", name: "Cached image" },
|
|
2024
|
+
{ type: "Image", name: "Decoded image" },
|
|
2025
|
+
],
|
|
2026
|
+
};
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
for (const suppressError of [undefined, false, true]) {
|
|
2030
|
+
test(
|
|
2031
|
+
`Note.getAttachments() cached parse failure (suppressError: ${suppressError})`,
|
|
2032
|
+
async () => {
|
|
2033
|
+
const jsonLd = embeddedPropertyDocument("attachment");
|
|
2034
|
+
const note = await Note.fromJsonLd(jsonLd);
|
|
2035
|
+
if (suppressError) {
|
|
2036
|
+
for (let i = 0; i < 2; i++) {
|
|
2037
|
+
const attachments: (Object | Link | PropertyValue)[] = await Array
|
|
2038
|
+
.fromAsync(
|
|
2039
|
+
note.getAttachments({ suppressError }),
|
|
2040
|
+
);
|
|
2041
|
+
deepStrictEqual(
|
|
2042
|
+
attachments.map((attachment) => attachment.name),
|
|
2043
|
+
["Cached image", "Decoded image"],
|
|
2044
|
+
);
|
|
2045
|
+
}
|
|
2046
|
+
// Suppression must not remove or replace the cached malformed value.
|
|
2047
|
+
await rejects(() => Array.fromAsync(note.getAttachments()), TypeError);
|
|
2048
|
+
} else {
|
|
2049
|
+
await rejects(
|
|
2050
|
+
() => Array.fromAsync(note.getAttachments({ suppressError })),
|
|
2051
|
+
TypeError,
|
|
2052
|
+
);
|
|
2053
|
+
}
|
|
2054
|
+
deepStrictEqual(await note.toJsonLd(), jsonLd);
|
|
2055
|
+
},
|
|
2056
|
+
);
|
|
2057
|
+
|
|
2058
|
+
test(
|
|
2059
|
+
`Activity.getObject() cached parse failure (suppressError: ${suppressError})`,
|
|
2060
|
+
async () => {
|
|
2061
|
+
const jsonLd = embeddedPropertyDocument("object");
|
|
2062
|
+
const activity = await Activity.fromJsonLd(jsonLd);
|
|
2063
|
+
if (suppressError) {
|
|
2064
|
+
deepStrictEqual(await activity.getObject({ suppressError }), null);
|
|
2065
|
+
deepStrictEqual(await activity.getObject({ suppressError }), null);
|
|
2066
|
+
await rejects(() => activity.getObject(), TypeError);
|
|
2067
|
+
} else {
|
|
2068
|
+
await rejects(() => activity.getObject({ suppressError }), TypeError);
|
|
2069
|
+
}
|
|
2070
|
+
deepStrictEqual(await activity.toJsonLd(), jsonLd);
|
|
2071
|
+
},
|
|
2072
|
+
);
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
test("Note.getAttachments() suppresses cached context loader failures", async () => {
|
|
2076
|
+
const note = await Note.fromJsonLd(embeddedPropertyDocument("attachment"));
|
|
2077
|
+
const contextLoader = () =>
|
|
2078
|
+
Promise.reject(new Error("Context loader failed"));
|
|
2079
|
+
await rejects(
|
|
2080
|
+
() => Array.fromAsync(note.getAttachments({ contextLoader })),
|
|
2081
|
+
(error: unknown) => error instanceof Error && !(error instanceof TypeError),
|
|
2082
|
+
);
|
|
2083
|
+
// Both cached values need the failing loader; the decoded value remains usable.
|
|
2084
|
+
const attachments: (Object | Link | PropertyValue)[] = await Array.fromAsync(
|
|
2085
|
+
note.getAttachments({ contextLoader, suppressError: true }),
|
|
2086
|
+
);
|
|
2087
|
+
deepStrictEqual(attachments.map((attachment) => attachment.name), [
|
|
2088
|
+
"Decoded image",
|
|
2089
|
+
]);
|
|
2090
|
+
});
|
|
2091
|
+
|
|
2092
|
+
test("Activity.getObject() suppresses cached context loader failures", async () => {
|
|
2093
|
+
const activity = await Activity.fromJsonLd(
|
|
2094
|
+
embeddedPropertyDocument("object"),
|
|
2095
|
+
);
|
|
2096
|
+
const contextLoader = () =>
|
|
2097
|
+
Promise.reject(new Error("Context loader failed"));
|
|
2098
|
+
await rejects(
|
|
2099
|
+
() => activity.getObject({ contextLoader }),
|
|
2100
|
+
(error: unknown) => error instanceof Error && !(error instanceof TypeError),
|
|
2101
|
+
);
|
|
2102
|
+
deepStrictEqual(
|
|
2103
|
+
await activity.getObject({ contextLoader, suppressError: true }),
|
|
2104
|
+
null,
|
|
2105
|
+
);
|
|
2106
|
+
});
|
|
2107
|
+
|
|
2010
2108
|
test("Activity.clone()", async () => {
|
|
2011
2109
|
const activity = new Activity({
|
|
2012
2110
|
actor: new Person({
|
|
@@ -3354,6 +3452,105 @@ test("Delete.toJsonLd() compacts embedded QuoteRequest", async () => {
|
|
|
3354
3452
|
);
|
|
3355
3453
|
});
|
|
3356
3454
|
|
|
3455
|
+
test("Note.quoteUrl (IRI-typed alias terms)", async () => {
|
|
3456
|
+
const jsonLd: Record<string, unknown> = {
|
|
3457
|
+
"@context": [
|
|
3458
|
+
"https://www.w3.org/ns/activitystreams",
|
|
3459
|
+
{
|
|
3460
|
+
fedibird: "http://fedibird.com/ns#",
|
|
3461
|
+
misskey: "https://misskey-hub.net/ns#",
|
|
3462
|
+
_misskey_quote: {
|
|
3463
|
+
"@id": "misskey:_misskey_quote",
|
|
3464
|
+
"@type": "@id",
|
|
3465
|
+
},
|
|
3466
|
+
quoteUri: {
|
|
3467
|
+
"@id": "fedibird:quoteUri",
|
|
3468
|
+
"@type": "@id",
|
|
3469
|
+
},
|
|
3470
|
+
},
|
|
3471
|
+
],
|
|
3472
|
+
id: "https://example.com/notes/1",
|
|
3473
|
+
type: "Note",
|
|
3474
|
+
_misskey_quote: "https://example.com/notes/quoted",
|
|
3475
|
+
quoteUri: "https://example.com/notes/quoted2",
|
|
3476
|
+
};
|
|
3477
|
+
|
|
3478
|
+
const loaded = await Note.fromJsonLd(jsonLd);
|
|
3479
|
+
deepStrictEqual(loaded.quoteUrl, new URL("https://example.com/notes/quoted"));
|
|
3480
|
+
|
|
3481
|
+
delete jsonLd._misskey_quote;
|
|
3482
|
+
const loaded2 = await Note.fromJsonLd(jsonLd);
|
|
3483
|
+
deepStrictEqual(
|
|
3484
|
+
loaded2.quoteUrl,
|
|
3485
|
+
new URL("https://example.com/notes/quoted2"),
|
|
3486
|
+
);
|
|
3487
|
+
});
|
|
3488
|
+
|
|
3489
|
+
test("Note.quoteUrl (IRI-typed primary term)", async () => {
|
|
3490
|
+
const context = [
|
|
3491
|
+
"https://www.w3.org/ns/activitystreams",
|
|
3492
|
+
{
|
|
3493
|
+
misskey: "https://misskey-hub.net/ns#",
|
|
3494
|
+
quoteUrl: { "@id": "as:quoteUrl", "@type": "@id" },
|
|
3495
|
+
_misskey_quote: "misskey:_misskey_quote",
|
|
3496
|
+
},
|
|
3497
|
+
];
|
|
3498
|
+
|
|
3499
|
+
const loaded = await Note.fromJsonLd({
|
|
3500
|
+
"@context": context,
|
|
3501
|
+
type: "Note",
|
|
3502
|
+
quoteUrl: "https://example.com/object",
|
|
3503
|
+
});
|
|
3504
|
+
deepStrictEqual(loaded.quoteUrl, new URL("https://example.com/object"));
|
|
3505
|
+
|
|
3506
|
+
// An IRI-valued quoteUrl still takes precedence over a plain-string alias:
|
|
3507
|
+
const loaded2 = await Note.fromJsonLd({
|
|
3508
|
+
"@context": context,
|
|
3509
|
+
type: "Note",
|
|
3510
|
+
quoteUrl: "https://example.com/object",
|
|
3511
|
+
_misskey_quote: "https://example.com/object2",
|
|
3512
|
+
});
|
|
3513
|
+
deepStrictEqual(loaded2.quoteUrl, new URL("https://example.com/object"));
|
|
3514
|
+
});
|
|
3515
|
+
|
|
3516
|
+
test("Note.quoteUrl (unparsable IRI-valued terms)", async () => {
|
|
3517
|
+
const context = [
|
|
3518
|
+
"https://www.w3.org/ns/activitystreams",
|
|
3519
|
+
{
|
|
3520
|
+
misskey: "https://misskey-hub.net/ns#",
|
|
3521
|
+
_misskey_quote: { "@id": "misskey:_misskey_quote", "@type": "@id" },
|
|
3522
|
+
},
|
|
3523
|
+
];
|
|
3524
|
+
for (
|
|
3525
|
+
const quote of [
|
|
3526
|
+
{ type: "Note", content: "An inlined quote without an id" },
|
|
3527
|
+
"_:b0",
|
|
3528
|
+
"",
|
|
3529
|
+
"notes/relative",
|
|
3530
|
+
]
|
|
3531
|
+
) {
|
|
3532
|
+
const loaded = await Note.fromJsonLd({
|
|
3533
|
+
"@context": context,
|
|
3534
|
+
id: "https://example.com/notes/1",
|
|
3535
|
+
type: "Note",
|
|
3536
|
+
content: "Hello",
|
|
3537
|
+
_misskey_quote: quote,
|
|
3538
|
+
});
|
|
3539
|
+
deepStrictEqual(loaded.quoteUrl, null, JSON.stringify(quote));
|
|
3540
|
+
deepStrictEqual(loaded.content, "Hello");
|
|
3541
|
+
}
|
|
3542
|
+
|
|
3543
|
+
const atUri = await Note.fromJsonLd({
|
|
3544
|
+
"@context": context,
|
|
3545
|
+
type: "Note",
|
|
3546
|
+
_misskey_quote: "at://did:plc:abc/app.bsky.feed.post/xyz",
|
|
3547
|
+
});
|
|
3548
|
+
deepStrictEqual(
|
|
3549
|
+
atUri.quoteUrl,
|
|
3550
|
+
new URL("at://" + encodeURIComponent("did:plc:abc/app.bsky.feed.post/xyz")),
|
|
3551
|
+
);
|
|
3552
|
+
});
|
|
3553
|
+
|
|
3357
3554
|
test("Key.publicKey", async () => {
|
|
3358
3555
|
const jwk = {
|
|
3359
3556
|
kty: "RSA",
|