File size: 2,056 Bytes
979853c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | import { visit } from 'unist-util-visit'
import type { Plugin } from 'unified'
import type { Root, Text } from 'mdast'
// Simple footnote plugin for remark - only renders inline citations
export const remarkFootnotes: Plugin<[], Root> = () => {
return (tree: Root) => {
// Find footnote references and replace them with inline citations
visit(tree, 'text', (node: Text, index, parent) => {
if (!parent || typeof index !== 'number') return
const text = node.value
const footnoteRegex = /\[\^([^\]]+)\]/g
let match
const replacements: any[] = []
let lastIndex = 0
while ((match = footnoteRegex.exec(text)) !== null) {
const [fullMatch, id] = match
const startIndex = match.index!
// Add text before footnote
if (startIndex > lastIndex) {
replacements.push({
type: 'text',
value: text.slice(lastIndex, startIndex)
})
}
// Check if there's another footnote immediately following this one
const nextIndex = startIndex + fullMatch.length
const remainingText = text.slice(nextIndex)
const hasConsecutiveFootnote = /^\[\^[^\]]+\]/.test(remainingText)
// Add footnote reference as HTML with placeholder link
const footnoteHtml = `<sup><a href="#footnote-${id}" class="footnote-ref">${id}</a></sup>`
// Add spacing if there's a consecutive footnote
const htmlWithSpacing = hasConsecutiveFootnote
? footnoteHtml + ' '
: footnoteHtml
replacements.push({
type: 'html',
value: htmlWithSpacing
})
lastIndex = startIndex + fullMatch.length
}
// Add remaining text
if (lastIndex < text.length) {
replacements.push({
type: 'text',
value: text.slice(lastIndex)
})
}
// Replace the text node if we found footnotes
if (replacements.length > 1) {
parent.children.splice(index, 1, ...replacements)
}
})
}
}
|