-added pako and epub-cfi-resolver as dependencies
-cfi resolving is now done by that module, therefore removed validateChildNodes and adjusted cfiToXmlNode
This commit is contained in:
parent
617ee3d781
commit
99c05650a1
1062
cps/static/js/libs/epub-cfi-resolver.js
vendored
Normal file
1062
cps/static/js/libs/epub-cfi-resolver.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
cps/static/js/libs/pako.min.js
vendored
Normal file
2
cps/static/js/libs/pako.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -6,8 +6,7 @@ class EpubParser {
|
||||||
this.encoder = new TextEncoder();
|
this.encoder = new TextEncoder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTotalByteLength() {
|
||||||
getTotalByteLength() { //TODO unrealistic values
|
|
||||||
let size = 0;
|
let size = 0;
|
||||||
for (let key of Object.keys(this.files)) {
|
for (let key of Object.keys(this.files)) {
|
||||||
let file = this.files[key];
|
let file = this.files[key];
|
||||||
|
@ -36,7 +35,6 @@ class EpubParser {
|
||||||
return this.parser.parseFromString(this.decompress(path), "text/xml");
|
return this.parser.parseFromString(this.decompress(path), "text/xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getSpine() {
|
getSpine() {
|
||||||
return Array.from(this.opfXml.getElementsByTagName("spine")[0].children).map(node => node.getAttribute("idref"));
|
return Array.from(this.opfXml.getElementsByTagName("spine")[0].children).map(node => node.getAttribute("idref"));
|
||||||
}
|
}
|
||||||
|
@ -81,71 +79,32 @@ class EpubParser {
|
||||||
}
|
}
|
||||||
return bytesize;
|
return bytesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
getIdRef(filepath){
|
getIdRef(filepath){
|
||||||
return this.opfXml.querySelector(`[href="${filepath}"]`).getAttribute("id");
|
return this.opfXml.querySelector(`[href="${filepath}"]`).getAttribute("id");
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* resolves the given cfi to the xml node it points to
|
* resolves the given cfi to the xml node it points to
|
||||||
* @param {string} cfi epub-cfi string in the form: epubcfi(/6/16[id13]!/4[id2]/4/2[doc12]/1:0)
|
* @param {string} cfistr epub-cfi string in the form: epubcfi(/6/16[id13]!/4[id2]/4/2[doc12]/1:0)
|
||||||
* @return XML Text-Node
|
* @return object with attributes "node" and "offset"
|
||||||
*/
|
*/
|
||||||
cfiToXmlNode(cfi) {
|
cfiToXmlNode(cfistr) {
|
||||||
let cfiPath = cfi.split("(")[1].split(")")[0];
|
let cfi = new CFI(cfistr);
|
||||||
|
let cfiPath = cfistr.split("(")[1].split(")")[0];
|
||||||
let fileId = cfiPath.split("!")[0].split("[")[1].split("]")[0];
|
let fileId = cfiPath.split("!")[0].split("[")[1].split("]")[0];
|
||||||
let xml = this.parser.parseFromString(this.decompress(this.resolveIDref(fileId)), "text/xml");
|
return cfi.resolveLast(this.parser.parseFromString(this.decompress(this.resolveIDref(fileId)),"text/xml"));
|
||||||
let components = cfiPath.split("!")[1].split("/").slice(1);
|
|
||||||
let currentNode = xml.getElementsByTagName("html")[0];
|
|
||||||
for (const component of components) {
|
|
||||||
this.validateChildNodes(currentNode);
|
|
||||||
// console.log(currentNode);
|
|
||||||
// console.log(component);
|
|
||||||
let index = 0;
|
|
||||||
if (component.includes("[")) {
|
|
||||||
index = parseInt(component.split("[")[0]) - 1;
|
|
||||||
currentNode = currentNode.childNodes[index];
|
|
||||||
console.assert(currentNode.getAttribute("id") === component.split("[")[1].split("]")[0], "failed to resolve node");
|
|
||||||
} else if (component.includes(":")) {
|
|
||||||
index = component.split(":")[0] - 1;
|
|
||||||
return currentNode.childNodes[index]; //exit point
|
|
||||||
} else {
|
|
||||||
index = parseInt(component);
|
|
||||||
currentNode = currentNode.childNodes[index - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* inserts missing text/element nodes to keep them alternating
|
|
||||||
* @param {*} parentNode
|
|
||||||
*/
|
|
||||||
validateChildNodes(parentNode) {
|
|
||||||
for (let index = 0; index < parentNode.childNodes.length;) {
|
|
||||||
const element = parentNode.childNodes[index];
|
|
||||||
if (index % 2 === 0 && element.nodeType === 1) {
|
|
||||||
element.parentNode.insertBefore(parentNode.ownerDocument.createTextNode(""), element);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (index % 2 === 1 && element.nodeType === 3) {
|
|
||||||
element.insertBefore(parentNode.ownerDocument.createElement("")); //TODO check
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
takes the node that the cfi points at and counts the bytes of all nodes before that
|
takes the node that the cfi points at and counts the bytes of all nodes before that
|
||||||
*/
|
*/
|
||||||
getCurrentFileProgress(CFI) {
|
getCurrentFileProgress(CFI) {
|
||||||
let size = parseInt(CFI.split(":")[1])//text offset in node
|
let parse=this.cfiToXmlNode(CFI);
|
||||||
let startnode = this.cfiToXmlNode(CFI); //returns text node
|
let size=parse.offset;
|
||||||
|
let startnode = parse.node//returns text node
|
||||||
let xmlnsLength = startnode.parentNode.namespaceURI.length;
|
let xmlnsLength = startnode.parentNode.namespaceURI.length;
|
||||||
let prev = startnode.parentNode.previousElementSibling;
|
let prev = startnode.parentNode.previousElementSibling;
|
||||||
while (prev !== null) {
|
while (prev !== null) {
|
||||||
// console.log("size: "+size)
|
|
||||||
// console.log(prev.outerHTML)
|
|
||||||
// console.log(this.encoder.encode(prev.outerHTML).length - xmlnsLength)
|
|
||||||
size += this.encoder.encode(prev.outerHTML).length - xmlnsLength;
|
size += this.encoder.encode(prev.outerHTML).length - xmlnsLength;
|
||||||
prev = prev.previousElementSibling;
|
prev = prev.previousElementSibling;
|
||||||
}
|
}
|
||||||
|
@ -153,9 +112,6 @@ class EpubParser {
|
||||||
while (parent !== null) {
|
while (parent !== null) {
|
||||||
let parentPrev = parent.previousElementSibling;
|
let parentPrev = parent.previousElementSibling;
|
||||||
while (parentPrev !== null) {
|
while (parentPrev !== null) {
|
||||||
// console.log(parentPrev.outerHTML)
|
|
||||||
// console.log(this.encoder.encode(parentPrev.outerHTML).length - xmlnsLength)
|
|
||||||
|
|
||||||
size += this.encoder.encode(parentPrev.outerHTML).length - xmlnsLength;
|
size += this.encoder.encode(parentPrev.outerHTML).length - xmlnsLength;
|
||||||
parentPrev = parentPrev.previousElementSibling;
|
parentPrev = parentPrev.previousElementSibling;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +123,7 @@ class EpubParser {
|
||||||
/**
|
/**
|
||||||
* @param currentFile filepath
|
* @param currentFile filepath
|
||||||
* @param CFI
|
* @param CFI
|
||||||
* @return {number} percentage
|
* @return {number} percentage as decimal
|
||||||
*/
|
*/
|
||||||
getProgress(currentFile, CFI) {
|
getProgress(currentFile, CFI) {
|
||||||
let percentage = (this.getPreviousFilesSize(currentFile) + this.getCurrentFileProgress(CFI))/this.getTotalByteLength();
|
let percentage = (this.getPreviousFilesSize(currentFile) + this.getCurrentFileProgress(CFI))/this.getTotalByteLength();
|
||||||
|
@ -181,6 +137,8 @@ class EpubParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//wait until variable is assigned a value
|
||||||
function waitFor(variable, callback) {
|
function waitFor(variable, callback) {
|
||||||
const interval = setInterval(function() {
|
const interval = setInterval(function() {
|
||||||
if (variable!==undefined) {
|
if (variable!==undefined) {
|
||||||
|
@ -198,14 +156,9 @@ function calculateProgress(){
|
||||||
let data=reader.rendition.currentLocation().end;
|
let data=reader.rendition.currentLocation().end;
|
||||||
return Math.round(epubParser.getProgress(data.href,data.cfi)*100);
|
return Math.round(epubParser.getProgress(data.href,data.cfi)*100);
|
||||||
}
|
}
|
||||||
var epubParser;
|
|
||||||
waitFor(reader.book,()=>{
|
// register new event emitter locationchange that fires on urlchange
|
||||||
epubParser = new EpubParser(reader.book.archive.zip.files);
|
// source: https://stackoverflow.com/a/52809105/21941129
|
||||||
});
|
|
||||||
/*
|
|
||||||
register new event emitter locationchange that fires on urlchange
|
|
||||||
source: https://stackoverflow.com/a/52809105/21941129
|
|
||||||
*/
|
|
||||||
(() => {
|
(() => {
|
||||||
let oldPushState = history.pushState;
|
let oldPushState = history.pushState;
|
||||||
history.pushState = function pushState() {
|
history.pushState = function pushState() {
|
||||||
|
@ -225,10 +178,14 @@ source: https://stackoverflow.com/a/52809105/21941129
|
||||||
window.dispatchEvent(new Event('locationchange'));
|
window.dispatchEvent(new Event('locationchange'));
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
var epubParser;
|
||||||
|
waitFor(reader.book,()=>{
|
||||||
|
epubParser = new EpubParser(reader.book.archive.zip.files);
|
||||||
|
});
|
||||||
let progressDiv=document.getElementById("progress");
|
let progressDiv=document.getElementById("progress");
|
||||||
|
|
||||||
window.addEventListener('locationchange',()=>{
|
window.addEventListener('locationchange',()=>{
|
||||||
let newPos=calculateProgress();
|
let newPos=calculateProgress();
|
||||||
console.log(newPos);
|
|
||||||
progressDiv.textContent=newPos+"%";
|
progressDiv.textContent=newPos+"%";
|
||||||
//getelement set element value
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -154,5 +154,6 @@
|
||||||
<script src="{{ url_for('static', filename='js/reading/epub.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/reading/epub.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/reading/epub-progress.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/reading/epub-progress.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/libs/pako.min.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/libs/pako.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/libs/epub-cfi-resolver.js') }}"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user