@sovovs/bycli 2.1.15 → 2.1.16
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.
|
@@ -336,13 +336,20 @@ export async function downloadArticle(data, options) {
|
|
|
336
336
|
// Shape: `# Title\n[> meta\n...]\n---\n\n<markdown>` — exactly one blank
|
|
337
337
|
// line separates every section, so we never produce ≥3 consecutive newlines.
|
|
338
338
|
const headerValue = (value) => secureMarkdown ? escapeMarkdownText(value) : value;
|
|
339
|
+
// The source URL must not go through escapeMarkdownText: escaping `. _ - ( ) #`
|
|
340
|
+
// and entity-encoding `&` leaves a link that can no longer be copied or
|
|
341
|
+
// followed. safeHttpUrl already allowlists http(s) and percent-encodes `<`/`>`
|
|
342
|
+
// via URL normalization, so the autolink cannot be closed early; an empty
|
|
343
|
+
// return means a hostile or malformed URL and the line is dropped entirely.
|
|
344
|
+
const headerUrl = (value) => secureMarkdown ? safeHttpUrl(value) : value;
|
|
339
345
|
const headerLines = [`# ${headerValue(data.title)}`];
|
|
340
346
|
if (data.author)
|
|
341
347
|
headerLines.push(`> ${labels.author}: ${headerValue(data.author)}`);
|
|
342
348
|
if (data.publishTime)
|
|
343
349
|
headerLines.push(`> ${labels.publishTime}: ${headerValue(data.publishTime)}`);
|
|
344
|
-
|
|
345
|
-
|
|
350
|
+
const sourceUrl = data.sourceUrl ? headerUrl(data.sourceUrl) : '';
|
|
351
|
+
if (sourceUrl)
|
|
352
|
+
headerLines.push(`> ${labels.sourceUrl}: <${sourceUrl}>`);
|
|
346
353
|
const frontmatter = headerLines.join('\n') + '\n\n---\n\n';
|
|
347
354
|
const fullContent = frontmatter + markdown;
|
|
348
355
|
const size = Buffer.byteLength(fullContent, 'utf-8');
|