A CLI for publishing standard.site documents to ATProto sequoia.pub
standard site lexicon cli publishing
55
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 88 lines 2.6 kB view raw
1#!/usr/bin/env bun 2 3import { readdirSync, statSync } from "node:fs"; 4import { join } from "node:path"; 5 6const distDir = "./docs/dist"; 7const ogImageUrl = "https://sequoia.pub/og.png"; 8 9// Function to recursively find all HTML files 10function findHtmlFiles(dir: string): string[] { 11 const files: string[] = []; 12 const entries = readdirSync(dir); 13 14 for (const entry of entries) { 15 const fullPath = join(dir, entry); 16 const stat = statSync(fullPath); 17 18 if (stat.isDirectory()) { 19 files.push(...findHtmlFiles(fullPath)); 20 } else if (entry.endsWith(".html")) { 21 files.push(fullPath); 22 } 23 } 24 25 return files; 26} 27 28// Function to inject OG image meta tags 29async function injectOgImageTags(filePath: string) { 30 const file = Bun.file(filePath); 31 let content = await file.text(); 32 33 // Check if og:image already exists 34 if (content.includes('property="og:image"')) { 35 console.log(`⏭️ Skipping ${filePath} - og:image already exists`); 36 return; 37 } 38 39 // Find the position to inject the meta tag 40 // We'll insert it after og:description if it exists, or before twitter:card 41 const ogDescriptionMatch = content.match( 42 /<meta property="og:description"[^>]*>/, 43 ); 44 const twitterCardMatch = content.match(/<meta name="twitter:card"[^>]*>/); 45 46 let insertPosition: number; 47 if (ogDescriptionMatch && ogDescriptionMatch.index !== undefined) { 48 insertPosition = ogDescriptionMatch.index + ogDescriptionMatch[0].length; 49 } else if (twitterCardMatch && twitterCardMatch.index !== undefined) { 50 insertPosition = twitterCardMatch.index; 51 } else { 52 // Fallback: insert before </head> 53 const headCloseMatch = content.indexOf("</head>"); 54 if (headCloseMatch === -1) { 55 console.log(`⚠️ Warning: Could not find insertion point in ${filePath}`); 56 return; 57 } 58 insertPosition = headCloseMatch; 59 } 60 61 // Inject the og:image and twitter:image meta tags 62 const ogImageTag = `<meta property="og:image" content="${ogImageUrl}"/>`; 63 const twitterImageTag = `<meta name="twitter:image" content="${ogImageUrl}"/>`; 64 const newContent = 65 content.slice(0, insertPosition) + 66 ogImageTag + 67 twitterImageTag + 68 content.slice(insertPosition); 69 70 // Write the modified content back to the file 71 await Bun.write(filePath, newContent); 72 console.log(`✅ Injected og:image tags into ${filePath}`); 73} 74 75// Main execution 76async function main() { 77 console.log("🔍 Finding HTML files in dist directory..."); 78 const htmlFiles = findHtmlFiles(distDir); 79 console.log(`📄 Found ${htmlFiles.length} HTML files`); 80 81 for (const file of htmlFiles) { 82 await injectOgImageTags(file); 83 } 84 85 console.log("\n✨ Done! All HTML files have been processed."); 86} 87 88main();