mirror of
https://github.com/john-okeefe/foliate-js.git
synced 2026-09-09 11:29:14 -04:00
Add destroy method
Which revokes all blob URLs and removes the element from document.
This commit is contained in:
@@ -36,5 +36,9 @@ export const makeComicBook = ({ entries, loadBlob, getSize }, file) => {
|
||||
book.resolveHref = href => ({ index: book.sections.findIndex(s => s.id === href) })
|
||||
book.splitTOCHref = href => [href, null]
|
||||
book.getTOCFragment = doc => doc.documentElement
|
||||
book.destroy = () => {
|
||||
for (const arr of urls.values())
|
||||
for (const url of arr) URL.revokeObjectURL(url)
|
||||
}
|
||||
return book
|
||||
}
|
||||
|
||||
@@ -611,6 +611,9 @@ class Loader {
|
||||
unloadItem(item) {
|
||||
this.unref(item?.href)
|
||||
}
|
||||
destroy() {
|
||||
for (const url of this.#cache.values()) URL.revokeObjectURL(url)
|
||||
}
|
||||
}
|
||||
|
||||
const getHTMLFragment = (doc, id) => doc.getElementById(id)
|
||||
@@ -628,6 +631,7 @@ const getPageSpread = properties => {
|
||||
|
||||
export class EPUB {
|
||||
parser = new DOMParser()
|
||||
#loader
|
||||
#encryption
|
||||
constructor({ loadText, loadBlob, getSize, sha1 }) {
|
||||
this.loadText = loadText
|
||||
@@ -662,7 +666,7 @@ export class EPUB {
|
||||
opf,
|
||||
resolveHref: url => resolveURL(url, opfPath),
|
||||
})
|
||||
const loader = new Loader({
|
||||
this.#loader = new Loader({
|
||||
loadText: this.loadText,
|
||||
loadBlob: uri => Promise.resolve(this.loadBlob(uri))
|
||||
.then(this.#encryption.getDecoder(uri)),
|
||||
@@ -677,8 +681,8 @@ export class EPUB {
|
||||
}
|
||||
return {
|
||||
id: this.resources.getItemByID(idref)?.href,
|
||||
load: () => loader.loadItem(item),
|
||||
unload: () => loader.unloadItem(item),
|
||||
load: () => this.#loader.loadItem(item),
|
||||
unload: () => this.#loader.unloadItem(item),
|
||||
createDocument: () => this.loadDocument(item),
|
||||
size: this.getSize(item.href),
|
||||
cfi: this.resources.cfis[index],
|
||||
@@ -805,4 +809,7 @@ export class EPUB {
|
||||
return JSON.parse(json)
|
||||
}
|
||||
}
|
||||
destroy() {
|
||||
this.#loader?.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,6 +272,7 @@ export const makeFB2 = async blob => {
|
||||
}), converted]
|
||||
})
|
||||
|
||||
const urls = []
|
||||
const sectionData = bodyData[0][0]
|
||||
// make a separate section for each section in the first body
|
||||
.map(({ el, ids }) => {
|
||||
@@ -294,6 +295,7 @@ export const makeFB2 = async blob => {
|
||||
const str = template(el.outerHTML)
|
||||
const blob = new Blob([str], { type: MIME.XHTML })
|
||||
const url = URL.createObjectURL(blob)
|
||||
urls.push(url)
|
||||
const title = normalizeWhitespace(
|
||||
el.querySelector('.title, .subtitle, p')?.textContent
|
||||
?? (el.classList.contains('title') ? el.textContent : ''))
|
||||
@@ -338,5 +340,8 @@ export const makeFB2 = async blob => {
|
||||
book.splitTOCHref = href => href?.split('#')?.map(x => Number(x)) ?? []
|
||||
book.getTOCFragment = (doc, id) => doc.querySelector(`[${dataID}="${id}"]`)
|
||||
|
||||
book.destroy = () => {
|
||||
for (const url of urls) URL.revokeObjectURL(url)
|
||||
}
|
||||
return book
|
||||
}
|
||||
|
||||
+9
-1
@@ -30,6 +30,7 @@ const getViewport = (doc, viewport) => {
|
||||
}
|
||||
|
||||
class Container {
|
||||
#observer = new ResizeObserver(() => this.render())
|
||||
#element = document.createElement('div')
|
||||
defaultViewport
|
||||
spread
|
||||
@@ -46,7 +47,7 @@ class Container {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
})
|
||||
new ResizeObserver(() => this.render()).observe(this.#element)
|
||||
this.#observer.observe(this.#element)
|
||||
}
|
||||
get element() {
|
||||
return this.#element
|
||||
@@ -170,6 +171,10 @@ class Container {
|
||||
return true
|
||||
}
|
||||
}
|
||||
destroy() {
|
||||
this.#observer.unobserve(this.#element)
|
||||
this.#element.remove()
|
||||
}
|
||||
}
|
||||
|
||||
export class FixedLayout {
|
||||
@@ -289,4 +294,7 @@ export class FixedLayout {
|
||||
for (const frame of this.#container.element.querySelectorAll('iframe'))
|
||||
frame.contentWindow.getSelection().removeAllRanges()
|
||||
}
|
||||
destroy() {
|
||||
this.#container.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -842,6 +842,10 @@ class MOBI6 {
|
||||
isExternal(uri) {
|
||||
return /^(?!blob|filepos)\w+:/i.test(uri)
|
||||
}
|
||||
destroy() {
|
||||
for (const url of this.#resourceCache.values()) URL.revokeObjectURL(url)
|
||||
for (const url of this.#cache.values()) URL.revokeObjectURL(url)
|
||||
}
|
||||
}
|
||||
|
||||
// handlers for `kindle:` uris
|
||||
@@ -1154,4 +1158,7 @@ class KF8 {
|
||||
isExternal(uri) {
|
||||
return /^(?!blob|kindle)\w+:/i.test(uri)
|
||||
}
|
||||
destroy() {
|
||||
for (const url of this.#cache.values()) URL.revokeObjectURL(url)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -329,6 +329,7 @@ class View {
|
||||
export class Paginator {
|
||||
#gap = 0
|
||||
#shouldUpdateGap = true
|
||||
#observer = new ResizeObserver(() => this.render())
|
||||
#element = document.createElement('div')
|
||||
#background = document.createElement('div')
|
||||
#maxSizeContainer = document.createElement('div')
|
||||
@@ -394,7 +395,7 @@ export class Paginator {
|
||||
this.#maxSizeContainer.append(this.#header)
|
||||
this.#maxSizeContainer.append(this.#footer)
|
||||
|
||||
new ResizeObserver(() => this.render()).observe(this.#element)
|
||||
this.#observer.observe(this.#element)
|
||||
this.#container.addEventListener('scroll', debounce(() => {
|
||||
if (this.scrolled) this.#afterScroll('scroll')
|
||||
}, 250))
|
||||
@@ -774,4 +775,8 @@ export class Paginator {
|
||||
this.#anchor = anchor
|
||||
await this.#scrollToAnchor(select)
|
||||
}
|
||||
destroy() {
|
||||
this.#observer.unobserve(this.#element)
|
||||
this.#element.remove()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user