A CLI for publishing standard.site documents to ATProto sequoia.pub
standard site lexicon cli publishing
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();