kjelsrud.dev/node_modules/mdast-util-to-hast/lib/footer.js

129 lines
3.2 KiB
JavaScript
Raw Normal View History

2023-07-19 21:31:30 +02:00
/**
* @typedef {import('hast').Element} Element
* @typedef {import('hast').ElementContent} ElementContent
*
* @typedef {import('./state.js').State} State
*/
import {normalizeUri} from 'micromark-util-sanitize-uri'
/**
* Generate a hast footer for called footnote definitions.
*
* @param {State} state
* Info passed around.
* @returns {Element | undefined}
* `section` element or `undefined`.
*/
export function footer(state) {
/** @type {Array<ElementContent>} */
const listItems = []
let index = -1
while (++index < state.footnoteOrder.length) {
const def = state.footnoteById[state.footnoteOrder[index]]
if (!def) {
continue
}
const content = state.all(def)
const id = String(def.identifier).toUpperCase()
const safeId = normalizeUri(id.toLowerCase())
let referenceIndex = 0
/** @type {Array<ElementContent>} */
const backReferences = []
while (++referenceIndex <= state.footnoteCounts[id]) {
/** @type {Element} */
const backReference = {
type: 'element',
tagName: 'a',
properties: {
href:
'#' +
state.clobberPrefix +
'fnref-' +
safeId +
(referenceIndex > 1 ? '-' + referenceIndex : ''),
dataFootnoteBackref: true,
className: ['data-footnote-backref'],
ariaLabel: state.footnoteBackLabel
},
children: [{type: 'text', value: '↩'}]
}
if (referenceIndex > 1) {
backReference.children.push({
type: 'element',
tagName: 'sup',
children: [{type: 'text', value: String(referenceIndex)}]
})
}
if (backReferences.length > 0) {
backReferences.push({type: 'text', value: ' '})
}
backReferences.push(backReference)
}
const tail = content[content.length - 1]
if (tail && tail.type === 'element' && tail.tagName === 'p') {
const tailTail = tail.children[tail.children.length - 1]
if (tailTail && tailTail.type === 'text') {
tailTail.value += ' '
} else {
tail.children.push({type: 'text', value: ' '})
}
tail.children.push(...backReferences)
} else {
content.push(...backReferences)
}
/** @type {Element} */
const listItem = {
type: 'element',
tagName: 'li',
properties: {id: state.clobberPrefix + 'fn-' + safeId},
children: state.wrap(content, true)
}
state.patch(def, listItem)
listItems.push(listItem)
}
if (listItems.length === 0) {
return
}
return {
type: 'element',
tagName: 'section',
properties: {dataFootnotes: true, className: ['footnotes']},
children: [
{
type: 'element',
tagName: state.footnoteLabelTagName,
properties: {
// To do: use structured clone.
...JSON.parse(JSON.stringify(state.footnoteLabelProperties)),
id: 'footnote-label'
},
children: [{type: 'text', value: state.footnoteLabel}]
},
{type: 'text', value: '\n'},
{
type: 'element',
tagName: 'ol',
properties: {},
children: state.wrap(listItems, true)
},
{type: 'text', value: '\n'}
]
}
}