diff --git a/README.md b/README.md index 22bedce..ff3c376 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ Features: - Does not depend on or include any library for unzipping; bring your own Zip library - Does not require loading whole file into memory - Does not care about older browsers -- No tests :( - No continuous scrolling mode :( ## Demo diff --git a/epubcfi.js b/epubcfi.js index dac0771..ed45d4e 100644 --- a/epubcfi.js +++ b/epubcfi.js @@ -244,9 +244,8 @@ const partsToNode = (node, parts) => { let sum = 0 for (const n of node) { const { length } = n.nodeValue - if (sum + length > offset) return { node: n, offset: offset - sum } + if (sum + length >= offset) return { node: n, offset: offset - sum } sum += length - if (n === node[node.length - 1]) return { node: n, offset: length - 1 } } } diff --git a/tests/epubcfi-tests.js b/tests/epubcfi-tests.js new file mode 100644 index 0000000..ec91e4b --- /dev/null +++ b/tests/epubcfi-tests.js @@ -0,0 +1,202 @@ +import * as CFI from '../epubcfi.js' + +const parser = new DOMParser() +const XML = str => parser.parseFromString(str, 'application/xml') +const XHTML = str => parser.parseFromString(str, 'application/xhtml+xml') + +{ + // example from EPUB CFI spec + const opf = XML(` + + + + + + + + en + + + + + + + + + + + + + + + + + + + +`) + + const page = XHTML(` + + + + + +

+

+

+

+

xxxyyy0123456789

+

+

+ … +

+

+ +`) + + // the exact same page with some text nodes removed, CDATA sections added, + // and characters changed to entities + const page2 = XHTML(` + + + + +

+

xxxyyy4589

+

+

+ … +

+

+ +`) + + const a = opf.getElementById('chap01ref') + const b = CFI.toElement(opf, CFI.parse('/6/4[chap01ref]')[0]) + const c = CFI.toElement(opf, CFI.parse('/6/4')[0]) + console.assert(a === b) + console.assert(a === c) + + const test = page => { + for (const cfi of [ + '/4[body01]/10[para05]/3:10', + '/4[body01]/16[svgimg]', + '/4[body01]/10[para05]/1:0', + '/4[body01]/10[para05]/2/1:0', + '/4[body01]/10[para05]/2/1:3', + ]) { + const range = CFI.toRange(page, CFI.parse(cfi)) + const a = CFI.fromRange(range) + const b = `epubcfi(${cfi})` + console.assert(a === b, `expected ${b}, got ${a}`) + } + for (let i = 0; i < 10; i++) { + const cfi = `/4/10,/3:${i},/3:${i+1}` + const range = CFI.toRange(page, CFI.parse(cfi)) + const n = `${i}` + console.assert(range.toString() === n, `expted ${n}, got ${range}`) + } + } + test(page) + test(page2) +} + +{ + // special characters in ID assertions + const opf = XML(` + + + + + + + + + + +`) + + const a = opf.getElementById('chap0]!/1ref^') + const b = CFI.toElement(opf, CFI.parse('/6/4[chap0^]!/1ref^^]')[0]) + console.assert(a === b) + + const page = XHTML(` + + + + +

+

+

+

+

xxxyyy0123456789

+

+

+ … +

+

+ +`) + + for (const cfi of [ + '/4[body0^]!/1^^]/10[para^]/0^,/5]/3:10', + '/4[body0^]!/1^^]/16[s^]^[vgimg]', + '/4[body0^]!/1^^]/10[para^]/0^,/5]/1:0', + '/4[body0^]!/1^^]/10[para^]/0^,/5]/2/1:0', + '/4[body0^]!/1^^]/10[para^]/0^,/5]/2/1:3', + ]) { + const range = CFI.toRange(page, CFI.parse(cfi)) + const a = CFI.fromRange(range) + const b = `epubcfi(${cfi})` + console.assert(a === b, `expected ${b}, got ${a}`) + } + for (let i = 0; i < 10; i++) { + const cfi = `/4[body0^]!/1^^]/10[para^]/0^,^/5],/3:${i},/3:${i+1}` + const range = CFI.toRange(page, CFI.parse(cfi)) + const n = `${i}` + console.assert(range.toString() === n, `expted ${n}, got ${range}`) + } +} + +{ + for (const [a, b, c] of [ + ['/6/4!/10', '/6/4!/10', 0], + ['/6/4!/2/3:0', '/6/4!/2', 1], + ['/6/4!/2/4/6/8/10/3:0', '/6/4!/4', -1], + [ + '/6/4[chap0^]!/1ref^^]!/4[body01^^]/10[para^]^,05^^]', + '/6/4!/4/10', + 0, + ], + [ + '/6/4[chap0^]!/1ref^^]!/4[body01^^],/10[para^]^,05^^],/15:10[foo^]]', + '/6/4!/4/12', + -1, + ], + ]) { + const x = CFI.compare(a, b) + console.assert(x === c, `compare ${a} and ${b}, expected ${c}, got ${x}`) + } +} diff --git a/tests/tests.html b/tests/tests.html new file mode 100644 index 0000000..2652dab --- /dev/null +++ b/tests/tests.html @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/tests.js b/tests/tests.js new file mode 100644 index 0000000..c0227f1 --- /dev/null +++ b/tests/tests.js @@ -0,0 +1 @@ +import './epubcfi-tests.js'