#!/usr/bin/env node /** * Fix Glossary Translation Newlines * * The German and French glossary translations have all newlines collapsed * into single lines, making them unreadable. This script restores proper * markdown formatting by: * * 1. Detecting markdown structure markers (headings, lists, etc.) * 2. Inserting appropriate newlines * 3. Preserving paragraph breaks */ const fs = require('fs'); const path = require('path'); function fixMarkdownNewlines(content) { // Step 1: Normalize by removing frontmatter (we'll add it back later) const frontmatterMatch = content.match(/^---\n(.*?)\n---\n(.*)$/s); if (!frontmatterMatch) { console.error('No frontmatter found'); return content; } const frontmatter = frontmatterMatch[1]; let markdown = frontmatterMatch[2]; // Step 2: Fix the main structural issues // Add newlines before and after --- markdown = markdown.replace(/\s*---\s*/g, '\n\n---\n\n'); // Add newlines before ## headings markdown = markdown.replace(/\s+(##\s+)/g, '\n\n$1'); // Add newline after ## headings (before next content) markdown = markdown.replace(/(##\s+[^\n]+)\s+/g, '$1\n\n'); // Add newlines before ### headings markdown = markdown.replace(/\s+(###\s+)/g, '\n\n$1'); // Add newline after ### headings markdown = markdown.replace(/(###\s+[^\n]+)\s+/g, '$1\n\n'); // Add newlines before #### headings markdown = markdown.replace(/\s+(####\s+)/g, '\n\n$1'); // Add newline after #### headings markdown = markdown.replace(/(####\s+[^\n]+)\s+/g, '$1\n\n'); // Fix the # h1 (main title) - special case // The translation created: # Title\n- Rest **Bold:** text // We want: # Title - Rest\n\n**Bold:** text markdown = markdown.replace(/^(# [^\n-]+)\n-\s+([^\*\n]+)(\s+\*\*)/m, '$1 - $2\n\n$3'); // Fix metadata lines (Version, Last Updated, etc.) - each on own line markdown = markdown.replace(/(\*\*[A-Za-zäöüÄÖÜß\s]+:\*\*\s+[0-9\-\.]+)(\s+)(\*\*)/g, '$1\n$3'); markdown = markdown.replace(/(\*\*[A-Za-zäöüÄÖÜß\s]+:\*\*\s+[^*\n]+?)(\s+)(\*\*)/g, '$1\n$3'); // Fix last metadata line before --- markdown = markdown.replace(/(\*\*[A-Za-zäöüÄÖÜß\s]+:\*\*\s+[^\n]+?)\s+(---)/g, '$1\n\n$2'); // Add newlines before **What it means:**, **Why it matters:**, etc. markdown = markdown.replace(/\s+(\*\*Was\s+es\s+bedeutet:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Warum\s+es\s+wichtig\s+ist:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Wie\s+es\s+funktioniert:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Analogie\s+zur\s+realen\s+Welt:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Im?\s+Tractatus:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*In\s+Tractatus:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Beispiele:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Merkmale:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Persistenz:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Menschliche\s+Aufsicht:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Überprüfungshäufigkeit:)/gi, '\n\n$1'); // French patterns markdown = markdown.replace(/\s+(\*\*Ce\s+que\s+cela\s+signifie\s*:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Pourquoi\s+c'est\s+important\s*:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Comment\s+cela\s+fonctionne\s*:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Analogie\s+du\s+monde\s+réel\s*:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Dans\s+Tractatus\s*:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Exemples\s*:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Caractéristiques\s*:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Persistance\s*:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Surveillance\s+humaine\s*:)/gi, '\n\n$1'); markdown = markdown.replace(/\s+(\*\*Fréquence\s+de\s+révision\s*:)/gi, '\n\n$1'); // Add newlines before list items (but only at start of line or after newline) markdown = markdown.replace(/([^\n])\s*\n?\s*(-\s+\*\*)/g, '$1\n\n$2'); markdown = markdown.replace(/([^\n])\s+(-\s+[A-Z])/g, '$1\n$2'); // Fix multiple consecutive newlines (max 2) markdown = markdown.replace(/\n{3,}/g, '\n\n'); // Trim leading/trailing whitespace markdown = markdown.trim(); // Step 3: Reassemble with frontmatter return `---\n${frontmatter}\n---\n\n${markdown}\n`; } async function main() { const baseDir = path.join(__dirname, '..'); const deFile = path.join(baseDir, 'docs/markdown/GLOSSARY-DE.md'); const frFile = path.join(baseDir, 'docs/markdown/GLOSSARY-FR.md'); console.log('Fixing German glossary newlines...'); const deContent = fs.readFileSync(deFile, 'utf-8'); const deFixed = fixMarkdownNewlines(deContent); fs.writeFileSync(deFile, deFixed, 'utf-8'); console.log('✓ German glossary fixed'); console.log('\nFixing French glossary newlines...'); const frContent = fs.readFileSync(frFile, 'utf-8'); const frFixed = fixMarkdownNewlines(frContent); fs.writeFileSync(frFile, frFixed, 'utf-8'); console.log('✓ French glossary fixed'); console.log('\nDone! Now re-import documents to database with:'); console.log(' npm run migrate:docs -- --source docs/markdown --force'); } main().catch(console.error);