Add functions for converting Calibre CFI to standard CFI

Also demonstrate showing highlights from Calibre in the reader
This commit is contained in:
John Factotum
2023-05-27 19:34:10 +08:00
parent 0be94135fa
commit d4453bdc5c
2 changed files with 49 additions and 0 deletions
+13
View File
@@ -320,3 +320,16 @@ export const fake = {
fromIndex: index => `/6/${(index + 1) * 2}`, fromIndex: index => `/6/${(index + 1) * 2}`,
toIndex: parts => parts?.at(-1).index / 2 - 1, toIndex: parts => parts?.at(-1).index / 2 - 1,
} }
// get CFI from Calibre bookmarks
// see https://github.com/johnfactotum/foliate/issues/849
export const fromCalibrePos = pos => {
const [parts] = parse(pos)
const item = parts.shift()
parts.shift()
return toString([[{ index: 6 }, item], parts])
}
export const fromCalibreHighlight = ({ spine_index, start_cfi, end_cfi }) => {
const pre = fake.fromIndex(spine_index) + '!'
return buildRange(pre + start_cfi.slice(2), pre + end_cfi.slice(2))
}
+36
View File
@@ -1,6 +1,7 @@
import './view.js' import './view.js'
import { createTOCView } from './ui/tree.js' import { createTOCView } from './ui/tree.js'
import { createMenu } from './ui/menu.js' import { createMenu } from './ui/menu.js'
import { Overlayer } from '../foliate-js/overlayer.js'
const isZip = async file => { const isZip = async file => {
const arr = new Uint8Array(await file.slice(0, 4).arrayBuffer()) const arr = new Uint8Array(await file.slice(0, 4).arrayBuffer())
@@ -152,6 +153,8 @@ class Reader {
maxColumns: 2, maxColumns: 2,
maxColumnWidth: 720, maxColumnWidth: 720,
} }
annotations = new Map()
annotationsByValue = new Map()
closeSideBar() { closeSideBar() {
$('#dimming-overlay').classList.remove('show') $('#dimming-overlay').classList.remove('show')
$('#side-bar').classList.remove('show') $('#side-bar').classList.remove('show')
@@ -237,6 +240,39 @@ class Reader {
}) })
$('#toc-view').append(this.#tocView.element) $('#toc-view').append(this.#tocView.element)
} }
// load and show highlights embedded in the file by Calibre
const bookmarks = await book.getCalibreBookmarks?.()
if (bookmarks) {
const { fromCalibreHighlight } = await import('./epubcfi.js')
for (const obj of bookmarks) {
if (obj.type === 'highlight') {
const value = fromCalibreHighlight(obj)
const color = obj.style.which
const note = obj.notes
const annotation = { value, color, note }
const list = this.annotations.get(obj.spine_index)
if (list) list.push(annotation)
else this.annotations.set(obj.spine_index, [annotation])
this.annotationsByValue.set(value, annotation)
}
}
this.view.addEventListener('create-overlay', e => {
const { index } = e.detail
const list = this.annotations.get(index)
if (list) for (const annotation of list)
this.view.addAnnotation(annotation)
})
this.view.addEventListener('draw-annotation', e => {
const { draw, annotation } = e.detail
const { color } = annotation
draw(Overlayer.highlight, { color })
})
this.view.addEventListener('show-annotation', e => {
const annotation = this.annotationsByValue.get(e.detail.value)
if (annotation.note) alert(annotation.note)
})
}
} }
setAppearance = () => { setAppearance = () => {
this.view?.setAppearance({ css: getCSS(this.style), layout: this.layout }) this.view?.setAppearance({ css: getCSS(this.style), layout: this.layout })