CoolFace
Apppublic

Pq234/robot-learning-tutorial

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
metadata-extractor.mjs215 linesDownload Raw Back to latex-importer
1/**2 * LaTeX Metadata Extractor3 * Extracts document metadata from LaTeX files for frontmatter generation4 */5 6/**7 * Extract metadata from LaTeX content8 * @param {string} latexContent - Raw LaTeX content9 * @returns {object} - Extracted metadata object10 */11export function extractLatexMetadata(latexContent) {12    const metadata = {};13 14    // Extract title15    const titleMatch = latexContent.match(/\\title\s*\{\s*([^}]+)\s*\}/s);16    if (titleMatch) {17        metadata.title = titleMatch[1]18            .replace(/\\[a-zA-Z]+/g, '')  // Remove LaTeX commands19            .replace(/\n/g, ' ')20            .trim();21    }22 23    // Extract authors with their specific affiliations24    const authors = [];25    const authorMatches = latexContent.matchAll(/\\authorOne\[[^\]]*\]\{([^}]+)\}/g);26 27    for (const match of authorMatches) {28        const fullAuthorInfo = match[1];29 30        // Determine affiliations based on macros present31        const affiliations = [];32        if (fullAuthorInfo.includes('\\ensps')) {33            affiliations.push(1); // École Normale Supérieure34        }35        if (fullAuthorInfo.includes('\\oxford')) {36            affiliations.push(1); // University of Oxford (index 1 dans le frontmatter)37        }38        if (fullAuthorInfo.includes('\\hf')) {39            affiliations.push(2); // Hugging Face (index 2 dans le frontmatter)40        }41 42        // Clean author name by removing macros43        let authorName = fullAuthorInfo44            .replace(/\\ensps/g, '')      // Remove École macro45            .replace(/\\hf/g, '')         // Remove Hugging Face macro46            .replace(/\\oxford/g, '')     // Remove Oxford macro47            .replace(/\\[a-zA-Z]+/g, '')  // Remove any other LaTeX commands48            .replace(/\s+/g, ' ')         // Normalize whitespace49            .trim();50 51        // Skip empty authors or placeholder entries52        if (authorName && authorName !== '...') {53            authors.push({54                name: authorName,55                affiliations: affiliations.length > 0 ? affiliations : [2] // Default to HF if no macro56            });57        }58    }59 60    if (authors.length > 0) {61        metadata.authors = authors;62    }63 64    // Extract affiliations dynamically from \contribution command65    const contributionMatch = latexContent.match(/\\contribution\[\]\{([^}]+)\}/);66    if (contributionMatch) {67        const contributionText = contributionMatch[1];68        69        // Parse affiliations from contribution text70        const affiliations = [];71        72        // Split by common separators and clean up73        const parts = contributionText74            .split(/[,;]/)75            .map(part => part.trim())76            .filter(part => part.length > 0);77        78        for (const part of parts) {79            // Remove LaTeX commands and clean up80            const cleanName = part81                .replace(/\\[a-zA-Z]+/g, '')  // Remove LaTeX commands like \oxford, \hf82                .replace(/\s+/g, ' ')         // Normalize whitespace83                .trim();84            85            if (cleanName && cleanName.length > 0) {86                affiliations.push({87                    name: cleanName88                });89            }90        }91        92        if (affiliations.length > 0) {93            metadata.affiliations = affiliations;94        }95    }96    97    // Fallback to hardcoded affiliations if no \contribution found98    if (!metadata.affiliations || metadata.affiliations.length === 0) {99        metadata.affiliations = [100            {101                name: "École Normale Supérieure Paris-Saclay"102            },103            {104                name: "University of Oxford"105            },106            {107                name: "Hugging Face"108            }109        ];110    }111 112    // Extract date if available (common LaTeX patterns)113    const datePatterns = [114        /\\date\s*\{([^}]+)\}/,115        /\\newcommand\s*\{\\date\}\s*\{([^}]+)\}/,116    ];117 118    for (const pattern of datePatterns) {119        const dateMatch = latexContent.match(pattern);120        if (dateMatch) {121            metadata.published = dateMatch[1].trim();122            break;123        }124    }125 126    // Fallback to current date if no date found127    if (!metadata.published) {128        metadata.published = new Date().toLocaleDateString('en-US', {129            year: 'numeric',130            month: 'short',131            day: '2-digit'132        });133    }134 135    return metadata;136}137 138/**139 * Generate YAML frontmatter from metadata object140 * @param {object} metadata - Metadata object141 * @returns {string} - YAML frontmatter string142 */143export function generateFrontmatter(metadata) {144    let frontmatter = '---\n';145 146    // Title147    if (metadata.title) {148        frontmatter += `title: "${metadata.title}"\n`;149    }150 151    // Authors152    if (metadata.authors && metadata.authors.length > 0) {153        frontmatter += 'authors:\n';154        metadata.authors.forEach(author => {155            frontmatter += `  - name: "${author.name}"\n`;156            if (author.url) {157                frontmatter += `    url: "${author.url}"\n`;158            }159            frontmatter += `    affiliations: [${author.affiliations.join(', ')}]\n`;160        });161    }162 163    // Affiliations164    if (metadata.affiliations && metadata.affiliations.length > 0) {165        frontmatter += 'affiliations:\n';166        metadata.affiliations.forEach((affiliation, index) => {167            frontmatter += `  - name: "${affiliation.name}"\n`;168            if (affiliation.url) {169                frontmatter += `    url: "${affiliation.url}"\n`;170            }171        });172    }173 174    // Publication date175    if (metadata.published) {176        frontmatter += `published: "${metadata.published}"\n`;177    }178 179    // Additional metadata180    if (metadata.doi) {181        frontmatter += `doi: "${metadata.doi}"\n`;182    }183 184    if (metadata.description) {185        frontmatter += `description: "${metadata.description}"\n`;186    }187 188    if (metadata.licence) {189        frontmatter += `licence: >\n  ${metadata.licence}\n`;190    }191 192    if (metadata.tags && metadata.tags.length > 0) {193        frontmatter += 'tags:\n';194        metadata.tags.forEach(tag => {195            frontmatter += `  - ${tag}\n`;196        });197    }198 199    // Default Astro configuration200    frontmatter += 'tableOfContentsAutoCollapse: true\n';201    frontmatter += '---\n\n';202 203    return frontmatter;204}205 206/**207 * Extract and generate frontmatter from LaTeX content208 * @param {string} latexContent - Raw LaTeX content209 * @returns {string} - Complete YAML frontmatter210 */211export function extractAndGenerateFrontmatter(latexContent) {212    const metadata = extractLatexMetadata(latexContent);213    return generateFrontmatter(metadata);214}215