@postfetch/core 0.12.0 → 0.12.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/index.js +19 -2
- package/package.json +1 -1
- package/src/twitter.ts +20 -2
package/dist/index.js
CHANGED
|
@@ -2315,7 +2315,7 @@ function twitterMetadata(tweet) {
|
|
|
2315
2315
|
extra.parentTweet = { id: parentId, metadata: twitterMetadata(parent) };
|
|
2316
2316
|
}
|
|
2317
2317
|
return {
|
|
2318
|
-
text: twitterText(tweet) ?? undefined,
|
|
2318
|
+
text: cleanTwitterText(twitterText(tweet), tweet) ?? undefined,
|
|
2319
2319
|
author: user ? {
|
|
2320
2320
|
handle: string(user.screen_name) ?? undefined,
|
|
2321
2321
|
name: string(user.name) ?? undefined,
|
|
@@ -2339,6 +2339,23 @@ function noteText(tweet) {
|
|
|
2339
2339
|
function twitterText(tweet) {
|
|
2340
2340
|
return noteText(tweet) ?? string(tweet.full_text) ?? string(tweet.text);
|
|
2341
2341
|
}
|
|
2342
|
+
function cleanTwitterText(text, tweet) {
|
|
2343
|
+
if (text === null)
|
|
2344
|
+
return null;
|
|
2345
|
+
const entities = object(tweet.entities) ? tweet.entities : null;
|
|
2346
|
+
const media = [
|
|
2347
|
+
...entities && Array.isArray(entities.media) ? entities.media : [],
|
|
2348
|
+
...Array.isArray(tweet.mediaDetails) ? tweet.mediaDetails : []
|
|
2349
|
+
];
|
|
2350
|
+
const urls = new Set(media.filter(object).map((entry) => string(entry.url)).filter(Boolean));
|
|
2351
|
+
while (true) {
|
|
2352
|
+
const trailing = text.match(/(?:^|\s)(https?:\/\/\S+)\s*$/);
|
|
2353
|
+
if (!trailing || !urls.has(trailing[1]))
|
|
2354
|
+
break;
|
|
2355
|
+
text = text.slice(0, trailing.index).trimEnd();
|
|
2356
|
+
}
|
|
2357
|
+
return text.replace(/&(?:gt|lt);/g, (entity) => entity === ">" ? ">" : "<");
|
|
2358
|
+
}
|
|
2342
2359
|
function needsFullText(tweet) {
|
|
2343
2360
|
if (noteText(tweet) || string(tweet.full_text)) {
|
|
2344
2361
|
return false;
|
|
@@ -2569,7 +2586,7 @@ function twitterComment(reply, id) {
|
|
|
2569
2586
|
url: `https://x.com/i/status/${id}`,
|
|
2570
2587
|
items,
|
|
2571
2588
|
metadata: {
|
|
2572
|
-
text: string(reply.text) ?? undefined,
|
|
2589
|
+
text: cleanTwitterText(string(reply.text), reply) ?? undefined,
|
|
2573
2590
|
author: {
|
|
2574
2591
|
handle: string(author2.screen_name) ?? undefined,
|
|
2575
2592
|
name: string(author2.name) ?? undefined,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postfetch/core",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "Zero-dependency typed core that turns Facebook, Instagram, LinkedIn, Pinterest, Reddit, SoundCloud, TikTok, X and YouTube post URLs into media files.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/src/twitter.ts
CHANGED
|
@@ -67,7 +67,7 @@ export function twitterMetadata(tweet: Json): PostMetadata & { extra?: TwitterEx
|
|
|
67
67
|
extra.parentTweet = { id: parentId, metadata: twitterMetadata(parent) };
|
|
68
68
|
}
|
|
69
69
|
return {
|
|
70
|
-
text: twitterText(tweet) ?? undefined,
|
|
70
|
+
text: cleanTwitterText(twitterText(tweet), tweet) ?? undefined,
|
|
71
71
|
author: user
|
|
72
72
|
? {
|
|
73
73
|
handle: string(user.screen_name) ?? undefined,
|
|
@@ -96,6 +96,24 @@ function twitterText(tweet: Json): string | null {
|
|
|
96
96
|
return noteText(tweet) ?? string(tweet.full_text) ?? string(tweet.text);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
// X serializes attachments as URLs in text. Only remove a trailing URL when
|
|
100
|
+
// the same post explicitly identifies it as media; ordinary links stay intact.
|
|
101
|
+
function cleanTwitterText(text: string | null, tweet: Json): string | null {
|
|
102
|
+
if (text === null) return null;
|
|
103
|
+
const entities = object(tweet.entities) ? tweet.entities : null;
|
|
104
|
+
const media = [
|
|
105
|
+
...(entities && Array.isArray(entities.media) ? entities.media : []),
|
|
106
|
+
...(Array.isArray(tweet.mediaDetails) ? tweet.mediaDetails : []),
|
|
107
|
+
];
|
|
108
|
+
const urls = new Set(media.filter(object).map((entry) => string(entry.url)).filter(Boolean));
|
|
109
|
+
while (true) {
|
|
110
|
+
const trailing: RegExpMatchArray | null = text.match(/(?:^|\s)(https?:\/\/\S+)\s*$/);
|
|
111
|
+
if (!trailing || !urls.has(trailing[1])) break;
|
|
112
|
+
text = text.slice(0, trailing.index).trimEnd();
|
|
113
|
+
}
|
|
114
|
+
return text.replace(/&(?:gt|lt);/g, (entity) => entity === ">" ? ">" : "<");
|
|
115
|
+
}
|
|
116
|
+
|
|
99
117
|
function needsFullText(tweet: Json): boolean {
|
|
100
118
|
if (noteText(tweet) || string(tweet.full_text)) {
|
|
101
119
|
return false;
|
|
@@ -350,7 +368,7 @@ function twitterComment(reply: Json, id: string): PostComment {
|
|
|
350
368
|
url: `https://x.com/i/status/${id}`,
|
|
351
369
|
items,
|
|
352
370
|
metadata: {
|
|
353
|
-
text: string(reply.text) ?? undefined,
|
|
371
|
+
text: cleanTwitterText(string(reply.text), reply) ?? undefined,
|
|
354
372
|
author: {
|
|
355
373
|
handle: string(author.screen_name) ?? undefined,
|
|
356
374
|
name: string(author.name) ?? undefined,
|