mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-03 14:59:18 +02:00
Added compare
This commit is contained in:
parent
7c3af4493c
commit
ca6d27f4f8
5 changed files with 212 additions and 23 deletions
56
dist/epub.js
vendored
56
dist/epub.js
vendored
|
@ -5253,11 +5253,12 @@ function EpubCFI(cfiFrom, base, options){
|
||||||
this.fromNode(cfiFrom);
|
this.fromNode(cfiFrom);
|
||||||
} else if (type === 'EpubCFI') {
|
} else if (type === 'EpubCFI') {
|
||||||
return cfiFrom;
|
return cfiFrom;
|
||||||
|
} else if (!cfiFrom) {
|
||||||
|
return this;
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError('not a valid argument for EpubCFI');
|
throw new TypeError('not a valid argument for EpubCFI');
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EpubCFI.prototype.checkType = function(cfi) {
|
EpubCFI.prototype.checkType = function(cfi) {
|
||||||
|
@ -5267,9 +5268,9 @@ EpubCFI.prototype.checkType = function(cfi) {
|
||||||
cfi[cfi.length-1] === ")") {
|
cfi[cfi.length-1] === ")") {
|
||||||
return 'string';
|
return 'string';
|
||||||
// Is a range object
|
// Is a range object
|
||||||
} else if (typeof cfi === 'object' && cfi.startContainer && cfi.startOffset){
|
} else if (typeof cfi === 'object' && cfi instanceof window.Range){
|
||||||
return 'range';
|
return 'range';
|
||||||
} else if (typeof cfi === 'object' && cfi.nodeType){ // || typeof cfi === 'function'
|
} else if (typeof cfi === 'object' && cfi instanceof window.Node ){ // || typeof cfi === 'function'
|
||||||
return 'node';
|
return 'node';
|
||||||
} else if (typeof cfi === 'object' && cfi instanceof EpubCFI){
|
} else if (typeof cfi === 'object' && cfi instanceof EpubCFI){
|
||||||
return 'EpubCFI';
|
return 'EpubCFI';
|
||||||
|
@ -5499,6 +5500,55 @@ EpubCFI.prototype.toString = function() {
|
||||||
return cfiString;
|
return cfiString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EpubCFI.prototype.compare = function(cfiOne, cfiTwo) {
|
||||||
|
if(typeof cfiOne === 'string') {
|
||||||
|
cfiOne = new EpubCFI(cfiOne);
|
||||||
|
}
|
||||||
|
if(typeof cfiTwo === 'string') {
|
||||||
|
cfiTwo = new EpubCFI(cfiTwo);
|
||||||
|
}
|
||||||
|
// Compare Spine Positions
|
||||||
|
if(cfiOne.spinePos > cfiTwo.spinePos) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(cfiOne.spinePos < cfiTwo.spinePos) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Compare Each Step in the First item
|
||||||
|
for (var i = 0; i < cfiOne.path.steps.length; i++) {
|
||||||
|
if(!cfiTwo.path.steps[i]) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(cfiOne.path.steps[i].index > cfiTwo.path.steps[i].index) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(cfiOne.path.steps[i].index < cfiTwo.path.steps[i].index) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Otherwise continue checking
|
||||||
|
}
|
||||||
|
|
||||||
|
// All steps in First present in Second
|
||||||
|
if(cfiOne.path.steps.length < cfiTwo.path.steps.length) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the charecter offset of the text node
|
||||||
|
if(cfiOne.path.terminal.offset > cfiTwo.path.terminal.offset) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(cfiOne.path.terminal.offset < cfiTwo.path.terminal.offset) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: compare ranges
|
||||||
|
|
||||||
|
// CFI's are equal
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = EpubCFI;
|
module.exports = EpubCFI;
|
||||||
|
|
||||||
},{"./core":8,"urijs":5}],10:[function(require,module,exports){
|
},{"./core":8,"urijs":5}],10:[function(require,module,exports){
|
||||||
|
|
2
dist/epub.js.map
vendored
2
dist/epub.js.map
vendored
File diff suppressed because one or more lines are too long
10
gulpfile.js
10
gulpfile.js
|
@ -18,7 +18,7 @@ var sourcemaps = require('gulp-sourcemaps');
|
||||||
|
|
||||||
var size = require('gulp-size');
|
var size = require('gulp-size');
|
||||||
var URI = require('urijs');
|
var URI = require('urijs');
|
||||||
|
var mochify = require('mochify');
|
||||||
// https://github.com/mishoo/UglifyJS2/pull/265
|
// https://github.com/mishoo/UglifyJS2/pull/265
|
||||||
// uglify.AST_Node.warn_function = function() {};
|
// uglify.AST_Node.warn_function = function() {};
|
||||||
|
|
||||||
|
@ -60,8 +60,12 @@ gulp.task('serve', function() {
|
||||||
server();
|
server();
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test', function() {
|
gulp.task('test', function(cb) {
|
||||||
|
mochify('./test/*.js', {
|
||||||
|
reporter: 'spec',
|
||||||
|
watch: true
|
||||||
|
})
|
||||||
|
.bundle();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Default
|
// Default
|
||||||
|
|
|
@ -71,11 +71,12 @@ function EpubCFI(cfiFrom, base, options){
|
||||||
this.fromNode(cfiFrom);
|
this.fromNode(cfiFrom);
|
||||||
} else if (type === 'EpubCFI') {
|
} else if (type === 'EpubCFI') {
|
||||||
return cfiFrom;
|
return cfiFrom;
|
||||||
|
} else if (!cfiFrom) {
|
||||||
|
return this;
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError('not a valid argument for EpubCFI');
|
throw new TypeError('not a valid argument for EpubCFI');
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EpubCFI.prototype.checkType = function(cfi) {
|
EpubCFI.prototype.checkType = function(cfi) {
|
||||||
|
@ -85,9 +86,9 @@ EpubCFI.prototype.checkType = function(cfi) {
|
||||||
cfi[cfi.length-1] === ")") {
|
cfi[cfi.length-1] === ")") {
|
||||||
return 'string';
|
return 'string';
|
||||||
// Is a range object
|
// Is a range object
|
||||||
} else if (typeof cfi === 'object' && cfi.startContainer && cfi.startOffset){
|
} else if (typeof cfi === 'object' && cfi instanceof window.Range){
|
||||||
return 'range';
|
return 'range';
|
||||||
} else if (typeof cfi === 'object' && cfi.nodeType){ // || typeof cfi === 'function'
|
} else if (typeof cfi === 'object' && cfi instanceof window.Node ){ // || typeof cfi === 'function'
|
||||||
return 'node';
|
return 'node';
|
||||||
} else if (typeof cfi === 'object' && cfi instanceof EpubCFI){
|
} else if (typeof cfi === 'object' && cfi instanceof EpubCFI){
|
||||||
return 'EpubCFI';
|
return 'EpubCFI';
|
||||||
|
@ -317,4 +318,53 @@ EpubCFI.prototype.toString = function() {
|
||||||
return cfiString;
|
return cfiString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EpubCFI.prototype.compare = function(cfiOne, cfiTwo) {
|
||||||
|
if(typeof cfiOne === 'string') {
|
||||||
|
cfiOne = new EpubCFI(cfiOne);
|
||||||
|
}
|
||||||
|
if(typeof cfiTwo === 'string') {
|
||||||
|
cfiTwo = new EpubCFI(cfiTwo);
|
||||||
|
}
|
||||||
|
// Compare Spine Positions
|
||||||
|
if(cfiOne.spinePos > cfiTwo.spinePos) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(cfiOne.spinePos < cfiTwo.spinePos) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Compare Each Step in the First item
|
||||||
|
for (var i = 0; i < cfiOne.path.steps.length; i++) {
|
||||||
|
if(!cfiTwo.path.steps[i]) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(cfiOne.path.steps[i].index > cfiTwo.path.steps[i].index) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(cfiOne.path.steps[i].index < cfiTwo.path.steps[i].index) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Otherwise continue checking
|
||||||
|
}
|
||||||
|
|
||||||
|
// All steps in First present in Second
|
||||||
|
if(cfiOne.path.steps.length < cfiTwo.path.steps.length) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the charecter offset of the text node
|
||||||
|
if(cfiOne.path.terminal.offset > cfiTwo.path.terminal.offset) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(cfiOne.path.terminal.offset < cfiTwo.path.terminal.offset) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: compare ranges
|
||||||
|
|
||||||
|
// CFI's are equal
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = EpubCFI;
|
module.exports = EpubCFI;
|
||||||
|
|
111
test/epubcfi.js
111
test/epubcfi.js
|
@ -4,34 +4,47 @@ var assert = require('assert');
|
||||||
describe('EpubCFI', function() {
|
describe('EpubCFI', function() {
|
||||||
var EpubCFI = require('../src/epubcfi.js');
|
var EpubCFI = require('../src/epubcfi.js');
|
||||||
|
|
||||||
describe('EpubCFI()', function() {
|
it('parse a cfi on init', function() {
|
||||||
|
var cfi = EpubCFI("epubcfi(/6/2[cover]!/6)");
|
||||||
|
|
||||||
|
assert.equal( cfi.spinePos, 0, "spinePos is parsed as the first item" );
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parse a cfi and ignore the base if present', function() {
|
||||||
|
var cfi = EpubCFI("epubcfi(/6/2[cover]!/6)", "/6/6[end]");
|
||||||
|
|
||||||
|
assert.equal( cfi.spinePos, 0, "base is ignored and spinePos is parsed as the first item" );
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#parse()', function() {
|
||||||
|
var cfi = new EpubCFI();
|
||||||
|
|
||||||
it('parse a cfi on init', function() {
|
it('parse a cfi on init', function() {
|
||||||
var cfi = EpubCFI("epubcfi(/6/2[cover]!/6)");
|
var parsed = cfi.parse("epubcfi(/6/2[cover]!/6)");
|
||||||
|
|
||||||
assert.equal( cfi.spinePos, 0, "spinePos is parsed as the first item" );
|
assert.equal( parsed.spinePos, 0, "spinePos is parsed as the first item" );
|
||||||
});
|
});
|
||||||
|
|
||||||
it('parse a cfi and ignore the base if present', function() {
|
it('parse a cfi and ignore the base if present', function() {
|
||||||
var cfi = EpubCFI("epubcfi(/6/2[cover]!/6)", "/6/6[end]");
|
var parsed = cfi.parse("epubcfi(/6/2[cover]!/6)", "/6/6[end]");
|
||||||
|
|
||||||
assert.equal( cfi.spinePos, 0, "base is ignored and spinePos is parsed as the first item" );
|
assert.equal( parsed.spinePos, 0, "base is ignored and spinePos is parsed as the first item" );
|
||||||
});
|
});
|
||||||
|
|
||||||
it('parse a cfi with a charecter offset', function() {
|
it('parse a cfi with a charecter offset', function() {
|
||||||
var cfi = EpubCFI("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)");
|
var parsed = cfi.parse("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)");
|
||||||
|
|
||||||
assert.equal( cfi.path.terminal.offset, 3, "Path has a terminal offset of 3" );
|
assert.equal( parsed.path.terminal.offset, 3, "Path has a terminal offset of 3" );
|
||||||
});
|
});
|
||||||
|
|
||||||
it('parse a cfi with a range', function() {
|
it('parse a cfi with a range', function() {
|
||||||
var cfi = EpubCFI("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)");
|
var parsed = cfi.parse("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)");
|
||||||
|
|
||||||
assert.equal( cfi.range, true, "Range is true" );
|
assert.equal( parsed.range, true, "Range is true" );
|
||||||
assert.equal( cfi.start.steps.length, 2, "Start steps are present" );
|
assert.equal( parsed.start.steps.length, 2, "Start steps are present" );
|
||||||
assert.equal( cfi.end.steps.length, 1, "End steps are present" );
|
assert.equal( parsed.end.steps.length, 1, "End steps are present" );
|
||||||
assert.equal( cfi.start.terminal.offset, 1, "Start has a terminal offset of 1" );
|
assert.equal( parsed.start.terminal.offset, 1, "Start has a terminal offset of 1" );
|
||||||
assert.equal( cfi.end.terminal.offset, 4, "End has a terminal offset of 4" );
|
assert.equal( parsed.end.terminal.offset, 4, "End has a terminal offset of 4" );
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -47,4 +60,76 @@ describe('EpubCFI', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#checkType()', function() {
|
||||||
|
it('determine the type of a cfi string', function() {
|
||||||
|
var cfi = new EpubCFI();
|
||||||
|
|
||||||
|
assert.equal( cfi.checkType('epubcfi(/6/2[cover]!/6)'), 'string' );
|
||||||
|
assert.equal( cfi.checkType('/6/2[cover]!/6'), false );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('determine the type of a cfi', function() {
|
||||||
|
var ogcfi = EpubCFI("epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)");
|
||||||
|
var cfi = new EpubCFI();
|
||||||
|
|
||||||
|
assert.equal( cfi.checkType(ogcfi), 'EpubCFI' );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('determine the type of a node', function() {
|
||||||
|
var cfi = new EpubCFI();
|
||||||
|
var el = document.createElement('div');
|
||||||
|
|
||||||
|
assert.equal( cfi.checkType(el), 'node' );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('determine the type of a range', function() {
|
||||||
|
var cfi = new EpubCFI();
|
||||||
|
var range = document.createRange();
|
||||||
|
|
||||||
|
assert.equal( cfi.checkType(range), 'range' );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#compare()', function() {
|
||||||
|
it('compare CFIs', function() {
|
||||||
|
var epubcfi = new EpubCFI();
|
||||||
|
|
||||||
|
// Spines
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/4[cover]!/4)", "epubcfi(/6/2[cover]!/4)"), 1, "First spine is greater");
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/4[cover]!/4)", "epubcfi(/6/6[cover]!/4)"), -1, "Second spine is greater");
|
||||||
|
|
||||||
|
// First is deeper
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/8/2)", "epubcfi(/6/2[cover]!/6)"), 1, "First Element is greater");
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/2)", "epubcfi(/6/2[cover]!/6)"), -1, "Second Element is greater");
|
||||||
|
|
||||||
|
// Second is deeper
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/8/2)", "epubcfi(/6/2[cover]!/6/4/2/2)"), 1, "First Element is greater");
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/4)", "epubcfi(/6/2[cover]!/6/4/2/2)"), -1, "Second Element is greater");
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/6)", "epubcfi(/6/2[cover]!/4/6/8/1:0)"), -1, "Second");
|
||||||
|
|
||||||
|
// Same Depth
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/6/8)", "epubcfi(/6/2[cover]!/6/2)"), 1, "First Element is greater");
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/20)", "epubcfi(/6/2[cover]!/6/10)"), -1, "Second Element is greater");
|
||||||
|
|
||||||
|
// Text nodes
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/5)", "epubcfi(/6/2[cover]!/4/3)"), 1, "First TextNode is greater");
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/7)", "epubcfi(/6/2[cover]!/4/13)"), -1, "Second TextNode is greater");
|
||||||
|
|
||||||
|
// Char offset
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/5:1)", "epubcfi(/6/2[cover]!/4/5:0)"), 1, "First Char Offset is greater");
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/5:2)", "epubcfi(/6/2[cover]!/4/5:30)"), -1, "Second Char Offset is greater");
|
||||||
|
|
||||||
|
// Normal example
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/8/5:1)", "epubcfi(/6/2[cover]!/4/6/15:2)"), 1, "First Element is greater");
|
||||||
|
assert.equal(epubcfi.compare("epubcfi(/6/2[cover]!/4/8/1:0)", "epubcfi(/6/2[cover]!/4/8/1:0)"), 0, "All Equal");
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue