applesauce-core 0.0.0-next-20250103191026 → 0.0.0-next-20250109205419
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/helpers/file-metadata.d.ts +53 -0
- package/dist/helpers/file-metadata.js +90 -0
- package/dist/helpers/file-metadata.test.d.ts +1 -0
- package/dist/helpers/file-metadata.test.js +103 -0
- package/dist/helpers/index.d.ts +2 -1
- package/dist/helpers/index.js +2 -1
- package/dist/helpers/media-attachment.d.ts +11 -2
- package/dist/helpers/media-attachment.js +15 -3
- package/dist/helpers/media-attachment.test.d.ts +1 -0
- package/dist/helpers/media-attachment.test.js +59 -0
- package/dist/helpers/media-post.d.ts +4 -0
- package/dist/helpers/media-post.js +6 -0
- package/dist/helpers/picture-post.d.ts +4 -0
- package/dist/helpers/picture-post.js +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { NostrEvent } from "nostr-tools";
|
|
2
|
+
export type FileMetadata = {
|
|
3
|
+
/** URL of the file */
|
|
4
|
+
url: string;
|
|
5
|
+
/** MIME type */
|
|
6
|
+
type?: string;
|
|
7
|
+
/** sha256 hash of the file */
|
|
8
|
+
sha256?: string;
|
|
9
|
+
/**
|
|
10
|
+
* The original sha256 hash before the file was transformed
|
|
11
|
+
* @deprecated
|
|
12
|
+
*/
|
|
13
|
+
originalSha256?: string;
|
|
14
|
+
/** size of the file in bytes */
|
|
15
|
+
size?: number;
|
|
16
|
+
/** size of file in pixels in the form <width>x<height> */
|
|
17
|
+
dimensions?: string;
|
|
18
|
+
/** magnet */
|
|
19
|
+
magnet?: string;
|
|
20
|
+
/** torrent infohash */
|
|
21
|
+
infohash?: string;
|
|
22
|
+
/** URL to a thumbnail */
|
|
23
|
+
thumbnail?: string;
|
|
24
|
+
/** URL to a preview image with the same dimensions */
|
|
25
|
+
image?: string;
|
|
26
|
+
/** summary */
|
|
27
|
+
summary?: string;
|
|
28
|
+
/** description for accessability */
|
|
29
|
+
alt?: string;
|
|
30
|
+
/** blurhash */
|
|
31
|
+
blurhash?: string;
|
|
32
|
+
/** fallback URLs */
|
|
33
|
+
fallback?: string[];
|
|
34
|
+
};
|
|
35
|
+
export type MediaAttachment = FileMetadata;
|
|
36
|
+
/**
|
|
37
|
+
* Parses file metadata tags into {@link FileMetadata}
|
|
38
|
+
* @throws
|
|
39
|
+
*/
|
|
40
|
+
export declare function parseFileMetadataTags(tags: string[][]): FileMetadata;
|
|
41
|
+
/**
|
|
42
|
+
* Parses a imeta tag into a {@link FileMetadata}
|
|
43
|
+
* @throws
|
|
44
|
+
*/
|
|
45
|
+
export declare function getFileMetadataFromImetaTag(tag: string[]): FileMetadata;
|
|
46
|
+
export declare const MediaAttachmentsSymbol: unique symbol;
|
|
47
|
+
/** Gets all the media attachments on an event */
|
|
48
|
+
export declare function getMediaAttachments(event: NostrEvent): FileMetadata[];
|
|
49
|
+
/**
|
|
50
|
+
* Gets {@link FileMetadata} for a NIP-94 kind 1063 event
|
|
51
|
+
* @throws
|
|
52
|
+
*/
|
|
53
|
+
export declare function getFileMetadata(file: NostrEvent): FileMetadata;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { getOrComputeCachedValue } from "./cache.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parses file metadata tags into {@link FileMetadata}
|
|
4
|
+
* @throws
|
|
5
|
+
*/
|
|
6
|
+
export function parseFileMetadataTags(tags) {
|
|
7
|
+
const fields = {};
|
|
8
|
+
let fallback = undefined;
|
|
9
|
+
for (const [name, value] of tags) {
|
|
10
|
+
switch (name) {
|
|
11
|
+
case "fallback":
|
|
12
|
+
fallback = fallback ? [...fallback, value] : [value];
|
|
13
|
+
break;
|
|
14
|
+
default:
|
|
15
|
+
fields[name] = value;
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (!fields.url)
|
|
20
|
+
throw new Error("Missing required url in file metadata");
|
|
21
|
+
const metadata = { url: fields.url, fallback };
|
|
22
|
+
// parse size
|
|
23
|
+
if (fields.size)
|
|
24
|
+
metadata.size = parseInt(fields.size);
|
|
25
|
+
// copy optional fields
|
|
26
|
+
if (fields.m)
|
|
27
|
+
metadata.type = fields.m;
|
|
28
|
+
if (fields.x)
|
|
29
|
+
metadata.sha256 = fields.x;
|
|
30
|
+
if (fields.ox)
|
|
31
|
+
metadata.originalSha256 = fields.ox;
|
|
32
|
+
if (fields.dim)
|
|
33
|
+
metadata.dimensions = fields.dim;
|
|
34
|
+
if (fields.magnet)
|
|
35
|
+
metadata.magnet = fields.magnet;
|
|
36
|
+
if (fields.i)
|
|
37
|
+
metadata.infohash = fields.i;
|
|
38
|
+
if (fields.thumb)
|
|
39
|
+
metadata.thumbnail = fields.thumb;
|
|
40
|
+
if (fields.image)
|
|
41
|
+
metadata.image = fields.image;
|
|
42
|
+
if (fields.summary)
|
|
43
|
+
metadata.summary = fields.summary;
|
|
44
|
+
if (fields.alt)
|
|
45
|
+
metadata.alt = fields.alt;
|
|
46
|
+
if (fields.blurhash)
|
|
47
|
+
metadata.blurhash = fields.blurhash;
|
|
48
|
+
return metadata;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Parses a imeta tag into a {@link FileMetadata}
|
|
52
|
+
* @throws
|
|
53
|
+
*/
|
|
54
|
+
export function getFileMetadataFromImetaTag(tag) {
|
|
55
|
+
const parts = tag.slice(1);
|
|
56
|
+
const tags = [];
|
|
57
|
+
for (const part of parts) {
|
|
58
|
+
const match = part.match(/^(.+?)\s(.+)$/);
|
|
59
|
+
if (match) {
|
|
60
|
+
const [_, name, value] = match;
|
|
61
|
+
tags.push([name, value]);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return parseFileMetadataTags(tags);
|
|
65
|
+
}
|
|
66
|
+
export const MediaAttachmentsSymbol = Symbol.for("media-attachments");
|
|
67
|
+
/** Gets all the media attachments on an event */
|
|
68
|
+
export function getMediaAttachments(event) {
|
|
69
|
+
return getOrComputeCachedValue(event, MediaAttachmentsSymbol, () => {
|
|
70
|
+
return event.tags
|
|
71
|
+
.filter((t) => t[0] === "imeta")
|
|
72
|
+
.map((tag) => {
|
|
73
|
+
try {
|
|
74
|
+
return getFileMetadataFromImetaTag(tag);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
// ignore invalid attachments
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
.filter((a) => !!a);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Gets {@link FileMetadata} for a NIP-94 kind 1063 event
|
|
86
|
+
* @throws
|
|
87
|
+
*/
|
|
88
|
+
export function getFileMetadata(file) {
|
|
89
|
+
return parseFileMetadataTags(file.tags);
|
|
90
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { getFileMetadataFromImetaTag, parseFileMetadataTags } from "./file-metadata.js";
|
|
3
|
+
describe("file metadata helpers", () => {
|
|
4
|
+
describe("parseFileMetadataTags", () => {
|
|
5
|
+
it("should parse a simple 1060 event", () => {
|
|
6
|
+
const tags = [
|
|
7
|
+
["url", "https://image.nostr.build/30696696e57a2732d4e9f1b15ff4d4d4eaa64b759df6876863f436ff5d736eae.gif"],
|
|
8
|
+
["ox", "30696696e57a2732d4e9f1b15ff4d4d4eaa64b759df6876863f436ff5d736eae"],
|
|
9
|
+
["fallback", "https://media.tenor.com/wpvrkjn192gAAAAC/daenerys-targaryen.gif"],
|
|
10
|
+
["x", "77fcf42b2b720babcdbe686eff67273d8a68862d74a2672db672bc48439a3ea5"],
|
|
11
|
+
["m", "image/gif"],
|
|
12
|
+
["dim", "360x306"],
|
|
13
|
+
["bh", "L38zleNL00~W^kRj0L-p0KM_^kx]"],
|
|
14
|
+
["blurhash", "L38zleNL00~W^kRj0L-p0KM_^kx]"],
|
|
15
|
+
[
|
|
16
|
+
"thumb",
|
|
17
|
+
"https://image.nostr.build/thumb/30696696e57a2732d4e9f1b15ff4d4d4eaa64b759df6876863f436ff5d736eae.gif",
|
|
18
|
+
],
|
|
19
|
+
["t", "gifbuddy"],
|
|
20
|
+
["summary", "Khaleesi call dragons Daenerys Targaryen"],
|
|
21
|
+
["alt", "a woman with blonde hair and a brooch on her shoulder"],
|
|
22
|
+
[
|
|
23
|
+
"thumb",
|
|
24
|
+
"https://media.tenor.com/wpvrkjn192gAAAAx/daenerys-targaryen.webp",
|
|
25
|
+
"5d92423664fc15874b1d26c70a05a541ec09b5c438bf157977a87c8e64b31463",
|
|
26
|
+
],
|
|
27
|
+
[
|
|
28
|
+
"image",
|
|
29
|
+
"https://media.tenor.com/wpvrkjn192gAAAAe/daenerys-targaryen.png",
|
|
30
|
+
"5d92423664fc15874b1d26c70a05a541ec09b5c438bf157977a87c8e64b31463",
|
|
31
|
+
],
|
|
32
|
+
];
|
|
33
|
+
expect(parseFileMetadataTags(tags)).toEqual({
|
|
34
|
+
url: "https://image.nostr.build/30696696e57a2732d4e9f1b15ff4d4d4eaa64b759df6876863f436ff5d736eae.gif",
|
|
35
|
+
type: "image/gif",
|
|
36
|
+
dimensions: "360x306",
|
|
37
|
+
blurhash: "L38zleNL00~W^kRj0L-p0KM_^kx]",
|
|
38
|
+
sha256: "77fcf42b2b720babcdbe686eff67273d8a68862d74a2672db672bc48439a3ea5",
|
|
39
|
+
originalSha256: "30696696e57a2732d4e9f1b15ff4d4d4eaa64b759df6876863f436ff5d736eae",
|
|
40
|
+
thumbnail: "https://media.tenor.com/wpvrkjn192gAAAAx/daenerys-targaryen.webp",
|
|
41
|
+
image: "https://media.tenor.com/wpvrkjn192gAAAAe/daenerys-targaryen.png",
|
|
42
|
+
summary: "Khaleesi call dragons Daenerys Targaryen",
|
|
43
|
+
fallback: ["https://media.tenor.com/wpvrkjn192gAAAAC/daenerys-targaryen.gif"],
|
|
44
|
+
alt: "a woman with blonde hair and a brooch on her shoulder",
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
describe("getFileMetadataFromImetaTag", () => {
|
|
49
|
+
it("should parse simple imeta tag", () => {
|
|
50
|
+
expect(getFileMetadataFromImetaTag([
|
|
51
|
+
"imeta",
|
|
52
|
+
"url https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
|
|
53
|
+
"x 3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
|
|
54
|
+
"dim 1024x1024",
|
|
55
|
+
"m image/jpeg",
|
|
56
|
+
"blurhash ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
|
|
57
|
+
])).toEqual({
|
|
58
|
+
url: "https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
|
|
59
|
+
sha256: "3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
|
|
60
|
+
dimensions: "1024x1024",
|
|
61
|
+
type: "image/jpeg",
|
|
62
|
+
blurhash: "ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
it("should parse thumbnail url", () => {
|
|
66
|
+
expect(getFileMetadataFromImetaTag([
|
|
67
|
+
"imeta",
|
|
68
|
+
"url https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
|
|
69
|
+
"x 3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
|
|
70
|
+
"dim 1024x1024",
|
|
71
|
+
"m image/jpeg",
|
|
72
|
+
"blurhash ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
|
|
73
|
+
"thumb https://exmaple.com/thumb.jpg",
|
|
74
|
+
])).toEqual({
|
|
75
|
+
url: "https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
|
|
76
|
+
sha256: "3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
|
|
77
|
+
dimensions: "1024x1024",
|
|
78
|
+
type: "image/jpeg",
|
|
79
|
+
blurhash: "ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
|
|
80
|
+
thumbnail: "https://exmaple.com/thumb.jpg",
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
it("should parse multiple fallback urls", () => {
|
|
84
|
+
expect(getFileMetadataFromImetaTag([
|
|
85
|
+
"imeta",
|
|
86
|
+
"url https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
|
|
87
|
+
"x 3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
|
|
88
|
+
"dim 1024x1024",
|
|
89
|
+
"m image/jpeg",
|
|
90
|
+
"blurhash ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
|
|
91
|
+
"fallback https://exmaple.com/image2.jpg",
|
|
92
|
+
"fallback https://exmaple.com/image3.jpg",
|
|
93
|
+
])).toEqual({
|
|
94
|
+
url: "https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
|
|
95
|
+
sha256: "3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
|
|
96
|
+
dimensions: "1024x1024",
|
|
97
|
+
type: "image/jpeg",
|
|
98
|
+
blurhash: "ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
|
|
99
|
+
fallback: ["https://exmaple.com/image2.jpg", "https://exmaple.com/image3.jpg"],
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
});
|
package/dist/helpers/index.d.ts
CHANGED
|
@@ -13,7 +13,8 @@ export * from "./json.js";
|
|
|
13
13
|
export * from "./lnurl.js";
|
|
14
14
|
export * from "./lru.js";
|
|
15
15
|
export * from "./mailboxes.js";
|
|
16
|
-
export * from "./
|
|
16
|
+
export * from "./file-metadata.js";
|
|
17
|
+
export * from "./picture-post.js";
|
|
17
18
|
export * from "./pointers.js";
|
|
18
19
|
export * from "./profile.js";
|
|
19
20
|
export * from "./relays.js";
|
package/dist/helpers/index.js
CHANGED
|
@@ -13,7 +13,8 @@ export * from "./json.js";
|
|
|
13
13
|
export * from "./lnurl.js";
|
|
14
14
|
export * from "./lru.js";
|
|
15
15
|
export * from "./mailboxes.js";
|
|
16
|
-
export * from "./
|
|
16
|
+
export * from "./file-metadata.js";
|
|
17
|
+
export * from "./picture-post.js";
|
|
17
18
|
export * from "./pointers.js";
|
|
18
19
|
export * from "./profile.js";
|
|
19
20
|
export * from "./relays.js";
|
|
@@ -2,10 +2,15 @@ import { NostrEvent } from "nostr-tools";
|
|
|
2
2
|
export type MediaAttachment = {
|
|
3
3
|
/** URL of the file */
|
|
4
4
|
url: string;
|
|
5
|
-
/**
|
|
5
|
+
/** MIME type */
|
|
6
6
|
type?: string;
|
|
7
7
|
/** sha256 hash of the file */
|
|
8
8
|
sha256?: string;
|
|
9
|
+
/**
|
|
10
|
+
* The original sha256 hash before the file was transformed
|
|
11
|
+
* @deprecated
|
|
12
|
+
*/
|
|
13
|
+
originalSha256?: string;
|
|
9
14
|
/** size of the file in bytes */
|
|
10
15
|
size?: number;
|
|
11
16
|
/** size of file in pixels in the form <width>x<height> */
|
|
@@ -15,13 +20,17 @@ export type MediaAttachment = {
|
|
|
15
20
|
/** torrent infohash */
|
|
16
21
|
infohash?: string;
|
|
17
22
|
/** URL to a thumbnail */
|
|
18
|
-
|
|
23
|
+
thumbnail?: string;
|
|
19
24
|
/** URL to a preview image with the same dimensions */
|
|
20
25
|
image?: string;
|
|
21
26
|
/** summary */
|
|
22
27
|
summary?: string;
|
|
23
28
|
/** description for accessability */
|
|
24
29
|
alt?: string;
|
|
30
|
+
/** blurhash */
|
|
31
|
+
blurhash?: string;
|
|
32
|
+
/** fallback URLs */
|
|
33
|
+
fallback?: string[];
|
|
25
34
|
};
|
|
26
35
|
/**
|
|
27
36
|
* Parses a imeta tag into a {@link MediaAttachment}
|
|
@@ -6,16 +6,24 @@ import { getOrComputeCachedValue } from "./cache.js";
|
|
|
6
6
|
export function parseMediaAttachmentTag(tag) {
|
|
7
7
|
const parts = tag.slice(1);
|
|
8
8
|
const fields = {};
|
|
9
|
+
let fallback = undefined;
|
|
9
10
|
for (const part of parts) {
|
|
10
11
|
const match = part.match(/^(.+?)\s(.+)$/);
|
|
11
12
|
if (match) {
|
|
12
13
|
const [_, name, value] = match;
|
|
13
|
-
|
|
14
|
+
switch (name) {
|
|
15
|
+
case "fallback":
|
|
16
|
+
fallback = fallback ? [...fallback, value] : [value];
|
|
17
|
+
break;
|
|
18
|
+
default:
|
|
19
|
+
fields[name] = value;
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
14
22
|
}
|
|
15
23
|
}
|
|
16
24
|
if (!fields.url)
|
|
17
25
|
throw new Error("Missing required url in attachment");
|
|
18
|
-
const attachment = { url: fields.url };
|
|
26
|
+
const attachment = { url: fields.url, fallback };
|
|
19
27
|
// parse size
|
|
20
28
|
if (fields.size)
|
|
21
29
|
attachment.size = parseInt(fields.size);
|
|
@@ -24,6 +32,8 @@ export function parseMediaAttachmentTag(tag) {
|
|
|
24
32
|
attachment.type = fields.m;
|
|
25
33
|
if (fields.x)
|
|
26
34
|
attachment.sha256 = fields.x;
|
|
35
|
+
if (fields.ox)
|
|
36
|
+
attachment.originalSha256 = fields.ox;
|
|
27
37
|
if (fields.dim)
|
|
28
38
|
attachment.dimensions = fields.dim;
|
|
29
39
|
if (fields.magnet)
|
|
@@ -31,13 +41,15 @@ export function parseMediaAttachmentTag(tag) {
|
|
|
31
41
|
if (fields.i)
|
|
32
42
|
attachment.infohash = fields.i;
|
|
33
43
|
if (fields.thumb)
|
|
34
|
-
attachment.
|
|
44
|
+
attachment.thumbnail = fields.thumb;
|
|
35
45
|
if (fields.image)
|
|
36
46
|
attachment.image = fields.image;
|
|
37
47
|
if (fields.summary)
|
|
38
48
|
attachment.summary = fields.summary;
|
|
39
49
|
if (fields.alt)
|
|
40
50
|
attachment.alt = fields.alt;
|
|
51
|
+
if (fields.blurhash)
|
|
52
|
+
attachment.blurhash = fields.blurhash;
|
|
41
53
|
return attachment;
|
|
42
54
|
}
|
|
43
55
|
export const MediaAttachmentsSymbol = Symbol.for("media-attachments");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { parseMediaAttachmentTag } from "./media-attachment.js";
|
|
3
|
+
describe("media attachment helpers", () => {
|
|
4
|
+
describe("parseMediaAttachmentTag", () => {
|
|
5
|
+
it("should parse simple imeta tag", () => {
|
|
6
|
+
expect(parseMediaAttachmentTag([
|
|
7
|
+
"imeta",
|
|
8
|
+
"url https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
|
|
9
|
+
"x 3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
|
|
10
|
+
"dim 1024x1024",
|
|
11
|
+
"m image/jpeg",
|
|
12
|
+
"blurhash ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
|
|
13
|
+
])).toEqual({
|
|
14
|
+
url: "https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
|
|
15
|
+
sha256: "3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
|
|
16
|
+
dimensions: "1024x1024",
|
|
17
|
+
type: "image/jpeg",
|
|
18
|
+
blurhash: "ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
it("should parse thumbnail url", () => {
|
|
22
|
+
expect(parseMediaAttachmentTag([
|
|
23
|
+
"imeta",
|
|
24
|
+
"url https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
|
|
25
|
+
"x 3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
|
|
26
|
+
"dim 1024x1024",
|
|
27
|
+
"m image/jpeg",
|
|
28
|
+
"blurhash ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
|
|
29
|
+
"thumb https://exmaple.com/thumb.jpg",
|
|
30
|
+
])).toEqual({
|
|
31
|
+
url: "https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
|
|
32
|
+
sha256: "3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
|
|
33
|
+
dimensions: "1024x1024",
|
|
34
|
+
type: "image/jpeg",
|
|
35
|
+
blurhash: "ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
|
|
36
|
+
thumbnail: "https://exmaple.com/thumb.jpg",
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
it("should parse multiple fallback urls", () => {
|
|
40
|
+
expect(parseMediaAttachmentTag([
|
|
41
|
+
"imeta",
|
|
42
|
+
"url https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
|
|
43
|
+
"x 3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
|
|
44
|
+
"dim 1024x1024",
|
|
45
|
+
"m image/jpeg",
|
|
46
|
+
"blurhash ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
|
|
47
|
+
"fallback https://exmaple.com/image2.jpg",
|
|
48
|
+
"fallback https://exmaple.com/image3.jpg",
|
|
49
|
+
])).toEqual({
|
|
50
|
+
url: "https://blossom.primal.net/3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c.jpg",
|
|
51
|
+
sha256: "3f4dbf2797ac4e90b00bcfe2728e5c8367ed909c48230ac454cc325f1993646c",
|
|
52
|
+
dimensions: "1024x1024",
|
|
53
|
+
type: "image/jpeg",
|
|
54
|
+
blurhash: "ggH{Aws:RPWBRjaeay?^ozV@aeRjaej[$gt7kCofWVofkCrrofxuofa|ozbHx]s:tRofaet7ay",
|
|
55
|
+
fallback: ["https://exmaple.com/image2.jpg", "https://exmaple.com/image3.jpg"],
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|