@rmdes/indiekit-syndicator-bluesky 1.0.4 → 1.0.6
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/lib/bluesky.js +10 -6
- package/lib/utils.js +86 -2
- package/package.json +1 -1
package/lib/bluesky.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
getPostImage,
|
|
7
7
|
getPostText,
|
|
8
8
|
getLikePostText,
|
|
9
|
+
buildPostText,
|
|
9
10
|
getPostParts,
|
|
10
11
|
uriToPostUrl,
|
|
11
12
|
fetchOpenGraphData,
|
|
@@ -365,16 +366,19 @@ export class Bluesky {
|
|
|
365
366
|
return this.postPost(richText, { images, externalEmbed });
|
|
366
367
|
}
|
|
367
368
|
|
|
368
|
-
// Regular post -
|
|
369
|
-
const
|
|
369
|
+
// Regular post - determine external URL and build text accordingly
|
|
370
|
+
const externalUrl = getExternalUrl(properties);
|
|
371
|
+
const text = buildPostText(properties, { externalUrl });
|
|
370
372
|
const richText = await createRichText(client, text);
|
|
371
373
|
|
|
372
|
-
//
|
|
374
|
+
// Create OG embed:
|
|
375
|
+
// - External URL exists → use it as OG card (permalink is in text)
|
|
376
|
+
// - No external URL → use permalink as OG card
|
|
373
377
|
let externalEmbed = null;
|
|
374
378
|
if (!images?.length) {
|
|
375
|
-
const
|
|
376
|
-
if (
|
|
377
|
-
externalEmbed = await this.createExternalEmbed(
|
|
379
|
+
const embedUrl = externalUrl || properties.url;
|
|
380
|
+
if (embedUrl) {
|
|
381
|
+
externalEmbed = await this.createExternalEmbed(embedUrl);
|
|
378
382
|
}
|
|
379
383
|
}
|
|
380
384
|
|
package/lib/utils.js
CHANGED
|
@@ -180,7 +180,7 @@ export const uriToPostUrl = (profileUrl, uri) => {
|
|
|
180
180
|
};
|
|
181
181
|
|
|
182
182
|
/**
|
|
183
|
-
* Get post text from given JF2 properties
|
|
183
|
+
* Get post text from given JF2 properties (legacy, used for likes/bookmarks)
|
|
184
184
|
* @param {object} properties - JF2 properties
|
|
185
185
|
* @param {boolean} [includePermalink] - Include permalink in post
|
|
186
186
|
* @returns {string} Post text
|
|
@@ -197,8 +197,9 @@ export const getPostText = (properties, includePermalink) => {
|
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
// Truncate status if longer than 300 characters
|
|
200
|
+
// ALWAYS include permalink when truncating so readers can see full post
|
|
200
201
|
if (text.length > 300) {
|
|
201
|
-
const suffix =
|
|
202
|
+
const suffix = `\n\n${properties.url}`;
|
|
202
203
|
const maxLen = 300 - suffix.length - 3;
|
|
203
204
|
text = text.slice(0, maxLen).trim() + "..." + suffix;
|
|
204
205
|
} else if (includePermalink && !text.includes(properties.url)) {
|
|
@@ -208,6 +209,89 @@ export const getPostText = (properties, includePermalink) => {
|
|
|
208
209
|
return text;
|
|
209
210
|
};
|
|
210
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Extract plain text content from properties without appending URLs
|
|
214
|
+
* @param {object} properties - JF2 properties
|
|
215
|
+
* @returns {string} Plain text content
|
|
216
|
+
*/
|
|
217
|
+
export function getContentText(properties) {
|
|
218
|
+
if (properties.name && properties.name !== "") {
|
|
219
|
+
return properties.name;
|
|
220
|
+
}
|
|
221
|
+
if (properties.content?.html) {
|
|
222
|
+
return htmlToText(properties.content.html, {
|
|
223
|
+
selectors: [
|
|
224
|
+
{ selector: "a", options: { ignoreHref: true } },
|
|
225
|
+
{ selector: "img", format: "skip" },
|
|
226
|
+
],
|
|
227
|
+
wordwrap: false,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
if (properties.content?.text) {
|
|
231
|
+
return properties.content.text;
|
|
232
|
+
}
|
|
233
|
+
return "";
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Remove a URL from text, cleaning up surrounding whitespace and prefixes
|
|
238
|
+
* @param {string} text - Text containing the URL
|
|
239
|
+
* @param {string} url - URL to remove
|
|
240
|
+
* @returns {string} Cleaned text
|
|
241
|
+
*/
|
|
242
|
+
export function removeUrlFromText(text, url) {
|
|
243
|
+
if (!text || !url) return text;
|
|
244
|
+
let result = text.replace(url, "");
|
|
245
|
+
// Clean up common prefixes left behind when URL was at the end
|
|
246
|
+
result = result.replace(/\s*(Réf|Ref|ref|via|Via|source|Source|link|Link|→|—)\s*$/im, "");
|
|
247
|
+
// Clean up excessive whitespace
|
|
248
|
+
result = result.replace(/\n{3,}/g, "\n\n").replace(/[ \t]{2,}/g, " ").trim();
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Build post text for Bluesky syndication with proper URL and character handling.
|
|
254
|
+
*
|
|
255
|
+
* Two modes:
|
|
256
|
+
* 1. External URL exists → remove from text (shown as OG card), append permalink as text
|
|
257
|
+
* 2. No external URL → content only (permalink shown as OG card)
|
|
258
|
+
*
|
|
259
|
+
* @param {object} properties - JF2 properties
|
|
260
|
+
* @param {object} [options] - Options
|
|
261
|
+
* @param {string} [options.externalUrl] - External URL that will be used as OG card
|
|
262
|
+
* @returns {string} Post text fitting within 300 chars
|
|
263
|
+
*/
|
|
264
|
+
export function buildPostText(properties, options = {}) {
|
|
265
|
+
const { externalUrl } = options;
|
|
266
|
+
const LIMIT = 300;
|
|
267
|
+
|
|
268
|
+
let text = getContentText(properties);
|
|
269
|
+
|
|
270
|
+
if (externalUrl) {
|
|
271
|
+
// External URL will be shown as OG card — remove from text to save space
|
|
272
|
+
text = removeUrlFromText(text, externalUrl);
|
|
273
|
+
|
|
274
|
+
// Always append permalink to original post
|
|
275
|
+
const permalink = properties.url;
|
|
276
|
+
if (permalink) {
|
|
277
|
+
const suffix = `\n\n${permalink}`;
|
|
278
|
+
const available = LIMIT - suffix.length;
|
|
279
|
+
if (text.length > available) {
|
|
280
|
+
text = text.slice(0, available - 1).trim() + "\u2026";
|
|
281
|
+
}
|
|
282
|
+
return (text + suffix).trim();
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// No external URL — permalink will be shown as OG card
|
|
287
|
+
// No need to duplicate it in text
|
|
288
|
+
if (text.length > LIMIT) {
|
|
289
|
+
text = text.slice(0, LIMIT - 1).trim() + "\u2026";
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return text.trim();
|
|
293
|
+
}
|
|
294
|
+
|
|
211
295
|
/**
|
|
212
296
|
* Get post text for a like of an external URL
|
|
213
297
|
* @param {object} properties - JF2 properties
|