Fetch Published Letter
Retrieve content from a published letter URL
Source Code
const [url] = process.argv.slice(2);
if (!url) {
console.error("Error: url is required");
process.exit(1);
}
console.log(`Fetching published letter from: ${url}`);
try {
const response = await fetch(url);
if (!response.ok) {
if (response.status === 404) {
console.error("Letter not found. It may not have deployed yet (GitHub Pages can take 1-2 minutes).");
} else {
console.error(`Failed to fetch: ${response.status} ${response.statusText}`);
}
process.exit(1);
}
const html = await response.text();
// Extract title from <title> tag
const titleMatch = html.match(/<title>([^<]+)<\/title>/);
const title = titleMatch ? titleMatch[1] : "";
// Extract content from .content div
const contentMatch = html.match(/<div class="content">([\s\S]*?)<\/div>\s*<\/article>/);
const contentHtml = contentMatch ? contentMatch[1].trim() : "";
// Extract author from meta tag
const authorMatch = html.match(/<meta name="author" content="([^"]+)">/);
const author = authorMatch ? authorMatch[1] : "";
// Extract date from .meta span (second span if author exists)
const metaMatch = html.match(/<div class="meta">([\s\S]*?)<\/div>/);
let date = "";
if (metaMatch) {
const spans = metaMatch[1].match(/<span>([^<]+)<\/span>/g);
if (spans) {
// If author exists, date is second span; otherwise first
date = author && spans.length > 1
? spans[1].replace(/<\/?span>/g, "")
: spans[0].replace(/<\/?span>/g, "");
}
}
// Detect style from CSS variables or colors
let style = "modern"; // default
if (html.includes("#faf8f5") || html.includes("Georgia, 'Times New Roman'")) {
style = "classic";
} else if (html.includes("#fcfcfa") || html.includes("Source Serif Pro")) {
style = "serif";
}
// Extract header image if present
const imageMatch = html.match(/<img src="([^"]+)" alt="" class="header-image">/);
const imageUrl = imageMatch ? imageMatch[1] : "";
console.log(` Title: ${title}`);
console.log(` Style: ${style}`);
console.log(` Author: ${author || "(none)"}`);
console.log(` Date: ${date || "(none)"}`);
console.log(` Has image: ${imageUrl ? "yes" : "no"}`);
console.log(` Content length: ${contentHtml.length} chars`);
console.log("\n--- RESULT ---");
console.log(JSON.stringify({
success: true,
title,
contentHtml,
style,
author,
date,
imageUrl,
url,
}, null, 2));
} catch (error) {
console.error(`Failed to fetch letter: ${error.message}`);
process.exit(1);
}