diff --git a/src/lib/utils/markdown/advancedMarkdownParser.ts b/src/lib/utils/markdown/advancedMarkdownParser.ts index 07851c7..9a29073 100644 --- a/src/lib/utils/markdown/advancedMarkdownParser.ts +++ b/src/lib/utils/markdown/advancedMarkdownParser.ts @@ -125,51 +125,46 @@ function processFootnotes(content: string): string { try { if (!content) return ''; - // First collect all footnote references and definitions + // Collect all footnote definitions const footnotes = new Map(); - const references = new Map(); - const referenceLocations = new Set(); - let nextNumber = 1; - - // First pass: collect all references to establish order - let processedContent = content.replace(FOOTNOTE_REFERENCE_REGEX, (match, id) => { - if (!referenceLocations.has(id) && !references.has(id)) { - references.set(id, nextNumber++); - } - referenceLocations.add(id); - return match; // Keep the reference for now - }); - - // Second pass: collect all definitions - processedContent = processedContent.replace(FOOTNOTE_DEFINITION_REGEX, (match, id, text) => { + let processedContent = content.replace(FOOTNOTE_DEFINITION_REGEX, (match, id, text) => { footnotes.set(id, text.trim()); - return ''; // Remove the definition + return ''; }); - // Third pass: process references with collected information + // Track all references to each footnote + const referenceOrder: { id: string, refNum: number, label: string }[] = []; + const referenceMap = new Map(); // id -> [refNum, ...] + let globalRefNum = 1; processedContent = processedContent.replace(FOOTNOTE_REFERENCE_REGEX, (match, id) => { if (!footnotes.has(id)) { console.warn(`Footnote reference [^${id}] found but no definition exists`); return match; } - - const num = references.get(id)!; - return `[${num}]`; + const refNum = globalRefNum++; + if (!referenceMap.has(id)) referenceMap.set(id, []); + referenceMap.get(id)!.push(refNum); + referenceOrder.push({ id, refNum, label: id }); + return `[${refNum}]`; }); // Add footnotes section if we have any - if (references.size > 0) { - processedContent += '\n\n

Footnotes

\n
    \n'; - - // Sort footnotes by their reference number - const sortedFootnotes = Array.from(references.entries()) - .sort((a, b) => a[1] - b[1]) - .filter(([id]) => footnotes.has(id)); // Only include footnotes that have definitions - - // Add each footnote in order - for (const [id, num] of sortedFootnotes) { + if (footnotes.size > 0 && referenceOrder.length > 0) { + processedContent += '\n\n

    Footnotes

    \n
      \n'; + // Only include each unique footnote once, in order of first reference + const seen = new Set(); + for (const { id, label } of referenceOrder) { + if (seen.has(id)) continue; + seen.add(id); const text = footnotes.get(id) || ''; - processedContent += `
    1. ${text}
    2. \n`; + // List of backrefs for this footnote + const refs = referenceMap.get(id) || []; + const backrefs = refs.map((num, i) => + `↩${num}` + ).join(' '); + // If label is not a number, show it after all backrefs + const labelSuffix = isNaN(Number(label)) ? ` ${label}` : ''; + processedContent += `
    3. ${text} ${backrefs}${labelSuffix}
    4. \n`; } processedContent += '
    '; } diff --git a/src/lib/utils/markdown/markdownTestfile.md b/src/lib/utils/markdown/markdownTestfile.md index 08f1d71..b7e5dbf 100644 --- a/src/lib/utils/markdown/markdownTestfile.md +++ b/src/lib/utils/markdown/markdownTestfile.md @@ -184,7 +184,7 @@ content starts at 4-columns in. Test out some emojis :heart: and :trophy: -#### Here is an image! +#### Here is an image![^some reference text] ![Nostr logo](https://user-images.githubusercontent.com/99301796/219900773-d6d02038-e2a0-4334-9f28-c14d40ab6fe7.png)