mirror of
https://github.com/john-okeefe/foliate-js.git
synced 2026-09-09 11:29:14 -04:00
Footnotes: reject when failing to show footnote
Now `handle()` could return either undefined or a promise, which you can catch to handle the case where footnote fails to show. Also improve footnote extraction.
This commit is contained in:
+36
-22
@@ -32,11 +32,17 @@ const getReferencedType = el => {
|
|||||||
const isInline = 'a, span, sup, sub, em, strong, i, b, small, big'
|
const isInline = 'a, span, sup, sub, em, strong, i, b, small, big'
|
||||||
const extractFootnote = (doc, anchor) => {
|
const extractFootnote = (doc, anchor) => {
|
||||||
let el = anchor(doc)
|
let el = anchor(doc)
|
||||||
|
const target = el
|
||||||
while (el.matches(isInline)) {
|
while (el.matches(isInline)) {
|
||||||
const parent = el.parentElement
|
const parent = el.parentElement
|
||||||
if (!parent) break
|
if (!parent) break
|
||||||
el = parent
|
el = parent
|
||||||
}
|
}
|
||||||
|
if (el === doc.body) {
|
||||||
|
const sibling = target.nextElementSibling
|
||||||
|
if (sibling && !sibling.matches(isInline)) return sibling
|
||||||
|
throw new Error('Failed to extract footnote')
|
||||||
|
}
|
||||||
return el
|
return el
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,41 +50,49 @@ export class FootnoteHandler extends EventTarget {
|
|||||||
detectFootnotes = true
|
detectFootnotes = true
|
||||||
#showFragment(book, { index, anchor }, href) {
|
#showFragment(book, { index, anchor }, href) {
|
||||||
const view = document.createElement('foliate-view')
|
const view = document.createElement('foliate-view')
|
||||||
view.addEventListener('load', e => {
|
return new Promise((resolve, reject) => {
|
||||||
const { doc } = e.detail
|
view.addEventListener('load', e => {
|
||||||
const el = anchor(doc)
|
try {
|
||||||
const type = getReferencedType(el)
|
const { doc } = e.detail
|
||||||
const hidden = el?.matches?.('aside') && type === 'footnote'
|
const el = anchor(doc)
|
||||||
if (el) {
|
const type = getReferencedType(el)
|
||||||
const range = el.startContainer ? el : doc.createRange()
|
const hidden = el?.matches?.('aside') && type === 'footnote'
|
||||||
if (!el.startContainer) {
|
if (el) {
|
||||||
if (el.matches('li, aside')) range.selectNodeContents(el)
|
const range = el.startContainer ? el : doc.createRange()
|
||||||
else range.selectNode(el)
|
if (!el.startContainer) {
|
||||||
|
if (el.matches('li, aside')) range.selectNodeContents(el)
|
||||||
|
else range.selectNode(el)
|
||||||
|
}
|
||||||
|
const frag = range.extractContents()
|
||||||
|
doc.body.replaceChildren()
|
||||||
|
doc.body.appendChild(frag)
|
||||||
|
}
|
||||||
|
const detail = { view, href, type, hidden, target: el }
|
||||||
|
this.dispatchEvent(new CustomEvent('render', { detail }))
|
||||||
|
resolve()
|
||||||
|
} catch (e) {
|
||||||
|
reject(e)
|
||||||
}
|
}
|
||||||
const frag = range.extractContents()
|
})
|
||||||
doc.body.replaceChildren()
|
view.open(book)
|
||||||
doc.body.appendChild(frag)
|
.then(() => this.dispatchEvent(new CustomEvent('before-render', { detail: { view } })))
|
||||||
}
|
.then(() => view.goTo(index))
|
||||||
const detail = { view, href, type, hidden, target: el }
|
.catch(reject)
|
||||||
this.dispatchEvent(new CustomEvent('render', { detail }))
|
|
||||||
})
|
})
|
||||||
view.open(book)
|
|
||||||
.then(() => this.dispatchEvent(new CustomEvent('before-render', { detail: { view } })))
|
|
||||||
.then(() => view.goTo(index))
|
|
||||||
}
|
}
|
||||||
handle(book, e) {
|
handle(book, e) {
|
||||||
const { a, href } = e.detail
|
const { a, href } = e.detail
|
||||||
const { yes, maybe } = isFootnoteReference(a)
|
const { yes, maybe } = isFootnoteReference(a)
|
||||||
if (yes) {
|
if (yes) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
Promise.resolve(book.resolveHref(href)).then(target =>
|
return Promise.resolve(book.resolveHref(href)).then(target =>
|
||||||
this.#showFragment(book, target, href))
|
this.#showFragment(book, target, href))
|
||||||
}
|
}
|
||||||
else if (this.detectFootnotes && maybe()) {
|
else if (this.detectFootnotes && maybe()) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
Promise.resolve(book.resolveHref(href)).then(({ index, anchor }) => {
|
return Promise.resolve(book.resolveHref(href)).then(({ index, anchor }) => {
|
||||||
const target = { index, anchor: doc => extractFootnote(doc, anchor) }
|
const target = { index, anchor: doc => extractFootnote(doc, anchor) }
|
||||||
this.#showFragment(book, target, href)
|
return this.#showFragment(book, target, href)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user