mirror of
https://github.com/kiwix/kiwix-js.git
synced 2025-09-22 12:01:15 -04:00
Refactor javascript files, so that to externalize utility functions, and split the evopedia.js file into 2 files implementing the 2 classes Title and LocalArchive
This commit is contained in:
parent
e3ef342e2e
commit
edd97188ee
22
js/app.js
22
js/app.js
@ -9,7 +9,9 @@ define(function(require) {
|
||||
var $ = require('zepto');
|
||||
|
||||
// Evopedia javascript dependencies
|
||||
var evopedia = require('evopedia');
|
||||
var evopediaTitle = require('title');
|
||||
var evopediaArchive = require('localArchive');
|
||||
var util = require('util');
|
||||
|
||||
|
||||
var localArchive = null;
|
||||
@ -50,7 +52,7 @@ define(function(require) {
|
||||
if (storage !== null) {
|
||||
// If DeviceStorage is available, we look for archives in it
|
||||
$('#scanningForArchives').show();
|
||||
evopedia.LocalArchive.scanForArchives(storage, populateDropDownListOfArchives);
|
||||
evopediaArchive.LocalArchive.scanForArchives(storage, populateDropDownListOfArchives);
|
||||
}
|
||||
else {
|
||||
// If DeviceStorage is not available, we display the file select components
|
||||
@ -99,7 +101,7 @@ define(function(require) {
|
||||
*/
|
||||
function setLocalArchiveFromArchiveList() {
|
||||
var archiveDirectory = $('#archiveList').val();
|
||||
localArchive = new evopedia.LocalArchive();
|
||||
localArchive = new evopediaArchive.LocalArchive();
|
||||
localArchive.readTitleFilesFromStorage(storage, archiveDirectory);
|
||||
localArchive.readDataFilesFromStorage(storage, archiveDirectory, 0);
|
||||
localArchive.readMathFilesFromStorage(storage, archiveDirectory);
|
||||
@ -121,7 +123,7 @@ define(function(require) {
|
||||
* Sets the localArchive from the File selects populated by user
|
||||
*/
|
||||
function setLocalArchiveFromFileSelect() {
|
||||
localArchive = new evopedia.LocalArchive();
|
||||
localArchive = new evopediaArchive.LocalArchive();
|
||||
localArchive.initializeFromArchiveFiles(document.getElementById('archiveFiles').files);
|
||||
// The archive is set : focus on the prefix field to start searching
|
||||
document.getElementById("prefix").focus();
|
||||
@ -191,7 +193,7 @@ define(function(require) {
|
||||
var titleId = event.target.getAttribute("titleId");
|
||||
$("#titleList").empty();
|
||||
findTitleFromTitleIdAndLaunchArticleRead(titleId);
|
||||
var title = evopedia.Title.parseTitleId(localArchive, titleId);
|
||||
var title = evopediaTitle.Title.parseTitleId(localArchive, titleId);
|
||||
pushBrowserHistoryState(title.name);
|
||||
return false;
|
||||
}
|
||||
@ -204,7 +206,7 @@ define(function(require) {
|
||||
*/
|
||||
function findTitleFromTitleIdAndLaunchArticleRead(titleId) {
|
||||
if (localArchive.dataFiles && localArchive.dataFiles.length > 0) {
|
||||
var title = evopedia.Title.parseTitleId(localArchive, titleId);
|
||||
var title = evopediaTitle.Title.parseTitleId(localArchive, titleId);
|
||||
$("#articleName").html(title.name);
|
||||
$("#readingArticle").show();
|
||||
$("#articleContent").html("");
|
||||
@ -281,10 +283,10 @@ define(function(require) {
|
||||
$(this).attr("target", "_blank");
|
||||
}
|
||||
else if (url.match(regexImageLink)
|
||||
&& (evopedia.endsWith(lowerCaseUrl, ".png")
|
||||
|| evopedia.endsWith(lowerCaseUrl, ".svg")
|
||||
|| evopedia.endsWith(lowerCaseUrl, ".jpg")
|
||||
|| evopedia.endsWith(lowerCaseUrl, ".jpeg"))) {
|
||||
&& (util.endsWith(lowerCaseUrl, ".png")
|
||||
|| util.endsWith(lowerCaseUrl, ".svg")
|
||||
|| util.endsWith(lowerCaseUrl, ".jpg")
|
||||
|| util.endsWith(lowerCaseUrl, ".jpeg"))) {
|
||||
// It's a link to a file of wikipedia : change the URL to the online version and open in a new tab
|
||||
var onlineWikipediaUrl = url.replace(regexImageLink, "https://"+localArchive.language+".wikipedia.org/wiki/File:$1");
|
||||
$(this).attr("href", onlineWikipediaUrl);
|
||||
|
@ -2,7 +2,9 @@ require.config({
|
||||
baseUrl: 'js/lib',
|
||||
paths: {
|
||||
'zepto': 'zepto',
|
||||
'bootstrap': 'bootstrap'
|
||||
'bootstrap': 'bootstrap',
|
||||
'title': 'evopedia/title',
|
||||
'localArchive': 'evopedia/localArchive'
|
||||
},
|
||||
shim: {
|
||||
'zepto' : {
|
||||
|
File diff suppressed because it is too large
Load Diff
132
js/lib/evopedia/title.js
Normal file
132
js/lib/evopedia/title.js
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Class for the title of an article
|
||||
*/
|
||||
define(function(require) {
|
||||
|
||||
// Module dependencies
|
||||
var utf8 = require('utf8');
|
||||
var util = require('util');
|
||||
|
||||
/**
|
||||
* Title class : defines the title of an article and some methods to manipulate it
|
||||
*/
|
||||
function Title() {
|
||||
this.name = null;
|
||||
this.fileNr = null;
|
||||
this.blockStart = null;
|
||||
this.blockOffset = null;
|
||||
this.articleLength = null;
|
||||
this.archive = null;
|
||||
this.titleOffset = null;
|
||||
this.titleEntryLength = null;
|
||||
}
|
||||
;
|
||||
|
||||
Title.prototype.getReadableName = function() {
|
||||
return this.name.replace("_", " ");
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Title instance from an encoded title line from a title file
|
||||
* @param {type} encodedTitle
|
||||
* @param {type} archive
|
||||
* @param {type} titleOffset
|
||||
* @returns {_L1.Title}
|
||||
*/
|
||||
Title.parseTitle = function(encodedTitle, archive, titleOffset) {
|
||||
if (archive === null) {
|
||||
throw "archive cannot be null";
|
||||
}
|
||||
if (titleOffset < 0) {
|
||||
throw "titleOffset cannot be negative (was " + titleOffset + ")";
|
||||
}
|
||||
var t = new Title();
|
||||
t.archive = archive;
|
||||
t.titleOffset = titleOffset;
|
||||
|
||||
if (encodedTitle === null || encodedTitle.length < 15)
|
||||
return null;
|
||||
|
||||
if (encodedTitle[encodedTitle.length - 1] == '\n') {
|
||||
t.titleEntryLength = encodedTitle.length;
|
||||
} else {
|
||||
t.titleEntryLength = encodedTitle.length + 1;
|
||||
}
|
||||
|
||||
var escapedEncodedTitle = new Uint8Array(encodedTitle);
|
||||
var escapes = util.readIntegerFrom2Bytes(encodedTitle, 0);
|
||||
if ((escapes & (1 << 14)) != 0)
|
||||
escapes |= '\n';
|
||||
for (var i = 0; i < 13; i++) {
|
||||
if ((escapes & (1 << i)) != 0)
|
||||
escapedEncodedTitle[i + 2] = 10; // Corresponds to \n
|
||||
}
|
||||
|
||||
t.fileNr = 1 * escapedEncodedTitle[2];
|
||||
t.blockStart = util.readIntegerFrom4Bytes(escapedEncodedTitle, 3);
|
||||
t.blockOffset = util.readIntegerFrom4Bytes(escapedEncodedTitle, 7);
|
||||
t.articleLength = util.readIntegerFrom4Bytes(escapedEncodedTitle, 11);
|
||||
|
||||
t.name = Title.parseNameOnly(escapedEncodedTitle);
|
||||
|
||||
return t;
|
||||
};
|
||||
|
||||
/*
|
||||
* Retrieves the name of an article from an encoded title line
|
||||
*/
|
||||
Title.parseNameOnly = function(encodedTitle) {
|
||||
var len = encodedTitle.length;
|
||||
if (len < 15) {
|
||||
return null;
|
||||
}
|
||||
if (len > 15 && encodedTitle[len - 1] == '\n') {
|
||||
len--;
|
||||
}
|
||||
return utf8.parse(encodedTitle.subarray(15, len));
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a title instance from a serialized id
|
||||
* @param {type} localArchive
|
||||
* @param {type} titleId
|
||||
* @returns {_L1.Title}
|
||||
*/
|
||||
Title.parseTitleId = function(localArchive, titleId) {
|
||||
var title = new Title();
|
||||
var idParts = titleId.split("|");
|
||||
title.archive = localArchive;
|
||||
title.fileNr = parseInt(idParts[2], 10);
|
||||
title.titleOffset = parseInt(idParts[3], 10);
|
||||
title.name = idParts[4];
|
||||
title.blockStart = parseInt(idParts[5], 10);
|
||||
title.blockOffset = parseInt(idParts[6], 10);
|
||||
title.articleLength = parseInt(idParts[7], 10);
|
||||
return title;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Serialize the title with its values
|
||||
* @returns {String}
|
||||
*/
|
||||
Title.prototype.toStringId = function() {
|
||||
return this.archive.language + "|" + this.archive.date + "|" + this.fileNr + "|"
|
||||
+ this.titleOffset + "|" + this.name + "|" + this.blockStart + "|" + this.blockOffset + "|" + this.articleLength;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize the title in a readable way
|
||||
*/
|
||||
Title.prototype.toString = function() {
|
||||
return "title.id = " + this.toStringId() + "title.name = " + this.name + " title.fileNr = " + this.fileNr + " title.blockStart = " + this.blockStart + " title.blockOffset = " + this.blockOffset + " title.articleLength = " + this.articleLength;
|
||||
};
|
||||
|
||||
/**
|
||||
* Functions and classes exposed by this module
|
||||
*/
|
||||
return {
|
||||
Title: Title
|
||||
};
|
||||
});
|
91
js/lib/util.js
Normal file
91
js/lib/util.js
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Utility functions
|
||||
*/
|
||||
define(function(require) {
|
||||
|
||||
/**
|
||||
* Utility function : return true if the given string ends with the suffix
|
||||
* @param str
|
||||
* @param suffix
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
function endsWith(str, suffix) {
|
||||
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an integer encoded in 4 bytes
|
||||
* @param {type} byteArray
|
||||
* @param {type} firstIndex
|
||||
* @returns {Number}
|
||||
*/
|
||||
function readIntegerFrom4Bytes(byteArray, firstIndex) {
|
||||
return byteArray[firstIndex] + byteArray[firstIndex + 1] * 256 + byteArray[firstIndex + 2] * 65536 + byteArray[firstIndex + 3] * 16777216;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an integer encoded in 2 bytes
|
||||
* @param {type} byteArray
|
||||
* @param {type} firstIndex
|
||||
* @returns {Number}
|
||||
*/
|
||||
function readIntegerFrom2Bytes(byteArray, firstIndex) {
|
||||
return byteArray[firstIndex] + byteArray[firstIndex + 1] * 256;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Uint8Array to a lowercase hex string
|
||||
* @param {type} byteArray
|
||||
* @returns {String}
|
||||
*/
|
||||
function uint8ArrayToHex(byteArray) {
|
||||
var s = '';
|
||||
var hexDigits = '0123456789abcdef';
|
||||
for (var i = 0; i < byteArray.length; i++) {
|
||||
var v = byteArray[i];
|
||||
s += hexDigits[(v & 0xff) >> 4];
|
||||
s += hexDigits[v & 0xf];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Uint8Array to base64
|
||||
* @param {type} byteArray
|
||||
* @returns {String}
|
||||
*/
|
||||
function uint8ArrayToBase64(byteArray) {
|
||||
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
var bits, h1, h2, h3, h4, i = 0;
|
||||
var enc = "";
|
||||
|
||||
for (var i = 0; i < byteArray.length; ) {
|
||||
bits = byteArray[i++] << 16;
|
||||
bits |= byteArray[i++] << 8;
|
||||
bits |= byteArray[i++];
|
||||
|
||||
h1 = bits >> 18 & 0x3f;
|
||||
h2 = bits >> 12 & 0x3f;
|
||||
h3 = bits >> 6 & 0x3f;
|
||||
h4 = bits & 0x3f;
|
||||
|
||||
enc += b64[h1] + b64[h2] + b64[h3] + b64[h4];
|
||||
}
|
||||
|
||||
var r = byteArray.length % 3;
|
||||
|
||||
return (r > 0 ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Functions and classes exposed by this module
|
||||
*/
|
||||
return {
|
||||
endsWith: endsWith,
|
||||
readIntegerFrom4Bytes: readIntegerFrom4Bytes,
|
||||
readIntegerFrom2Bytes : readIntegerFrom2Bytes,
|
||||
uint8ArrayToHex : uint8ArrayToHex,
|
||||
uint8ArrayToBase64 : uint8ArrayToBase64
|
||||
};
|
||||
});
|
@ -1,5 +1,9 @@
|
||||
require.config({
|
||||
baseUrl: '../js/lib'
|
||||
baseUrl: '../js/lib',
|
||||
paths: {
|
||||
'title': 'evopedia/title',
|
||||
'localArchive': 'evopedia/localArchive'
|
||||
},
|
||||
});
|
||||
|
||||
requirejs(['../../tests/tests']);
|
||||
|
@ -1,7 +1,8 @@
|
||||
define(function(require) {
|
||||
|
||||
var $ = require('zepto');
|
||||
var evopedia = require('evopedia');
|
||||
var evopediaTitle = require('title');
|
||||
var evopediaArchive = require('localArchive');
|
||||
|
||||
// Due to security restrictions in the browsers,
|
||||
// we can not read directly the files and run the unit tests
|
||||
@ -24,7 +25,7 @@ define(function(require) {
|
||||
});
|
||||
|
||||
// Create a localArchive from selected files, in order to run the following tests
|
||||
var localArchive = new evopedia.LocalArchive();
|
||||
var localArchive = new evopediaArchive.LocalArchive();
|
||||
localArchive.initializeFromArchiveFiles(document.getElementById('archiveFiles').files);
|
||||
|
||||
module("evopedia");
|
||||
@ -73,7 +74,7 @@ define(function(require) {
|
||||
});
|
||||
|
||||
// Create a title instance for the Article 'Abraham'
|
||||
var titleAbraham = new evopedia.Title();
|
||||
var titleAbraham = new evopediaTitle.Title();
|
||||
titleAbraham.archive = localArchive;
|
||||
titleAbraham.articleLength = 10071;
|
||||
titleAbraham.blockOffset = 127640;
|
||||
@ -101,7 +102,7 @@ define(function(require) {
|
||||
|
||||
test("check parseTitleFromId", function() {
|
||||
var titleId = "small|2010-08-14|0|57|Abraham|2364940|127640|10071";
|
||||
var title = evopedia.Title.parseTitleId(localArchive, titleId);
|
||||
var title = evopediaTitle.Title.parseTitleId(localArchive, titleId);
|
||||
ok(title, "Title instance created");
|
||||
deepEqual(title, titleAbraham, "Parsing from titleId gives Abraham title");
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user