mirror of
https://github.com/kiwix/kiwix-js-pwa.git
synced 2025-09-14 23:09:46 -04:00
Merge branch 'master-dev'
Former-commit-id: f6bd74054ee15b39a7623ad256c4ab00b4065c03 [formerly 764cda12ba119e35fc203d381692431fb77283f5] Former-commit-id: 20a23d7d2967167e5d034065aa8170838e33d768
This commit is contained in:
commit
5a4c6252ed
@ -143,6 +143,7 @@
|
||||
<Content Include="www\-\s\style-mobile.css" />
|
||||
<Content Include="www\-\s\style.css" />
|
||||
<Content Include="www\-\s\vector.css" />
|
||||
<Content Include="www\article.html" />
|
||||
<Content Include="www\css\app.css" />
|
||||
<Content Include="www\css\bootstrap-theme.min.css" />
|
||||
<Content Include="www\css\bootstrap.min.css" />
|
||||
|
@ -127,19 +127,6 @@ function fetchEventListener(event) {
|
||||
console.log("It's a layout dependency : " + title);
|
||||
if (regexpJS.test(title)) {
|
||||
contentType = 'text/javascript';
|
||||
var responseInit = {
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
headers: {
|
||||
'Content-Type': contentType
|
||||
}
|
||||
};
|
||||
|
||||
var httpResponse = new Response(';', responseInit);
|
||||
|
||||
// TODO : temporary before the backend actually sends a proper content
|
||||
resolve(httpResponse);
|
||||
return;
|
||||
}
|
||||
else if (regexpCSS.test(title)) {
|
||||
contentType = 'text/css';
|
||||
|
@ -30,7 +30,7 @@ input {
|
||||
line-height: normal
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
ul {
|
||||
list-style: none
|
||||
}
|
||||
|
||||
@ -580,10 +580,6 @@ span[rel='mw:referencedBy'] a:after {
|
||||
content: ' '
|
||||
}
|
||||
|
||||
x-thereisnoelementwiththisname[rel='mw:referencedBy']:before, span.mw-linkback-text {
|
||||
display: none
|
||||
}
|
||||
|
||||
#issues_container div.hatnote {
|
||||
display: none
|
||||
}
|
||||
@ -1984,10 +1980,6 @@ input {
|
||||
line-height: normal
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
list-style: none
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse
|
||||
}
|
||||
|
8
www/article.html
Normal file
8
www/article.html
Normal file
@ -0,0 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Placeholder for injecting an article into the iframe</title>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
@ -73,7 +73,7 @@ body {
|
||||
background-color: whitesmoke !important;
|
||||
}
|
||||
|
||||
div:not(.panel-success) {
|
||||
div:not(.panel-success, .alert-message) {
|
||||
-ms-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
|
@ -10,7 +10,7 @@
|
||||
Home page : http://www.kiwix.org
|
||||
|
||||
Main authors of this application :
|
||||
Mossroy - mossroy@mossroy.fr
|
||||
Mossroy - https://github.com/mossroy - mossroy@mossroy.fr
|
||||
Peter-x - https://github.com/peter-x
|
||||
Jaifroid - Adapted for UWP for Windows 10 and Windows Mobile 10 : Geoffrey Kantaris egk10@cam.ac.uk
|
||||
|
||||
@ -42,8 +42,8 @@
|
||||
<!-- Modal info -->
|
||||
<div id="myModal" class="modal">
|
||||
<div class="modal-dialog modal-full">
|
||||
<div class="modal-content dark">
|
||||
<div class="modal-body">
|
||||
<div id="modalTheme" class="modal-content dark">
|
||||
<div id="largeModal" class="modal-body">
|
||||
<button class="close" aria-hidden="true" type="button" data-dismiss="modal">×</button>
|
||||
<img style="float:left; padding-right:1em;" alt="Kiwix icon" src="img/icons/kiwix-midnightblue-90.png">
|
||||
|
||||
@ -97,6 +97,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div id="extraModalFooterContent"></div>
|
||||
<button class="btn btn-primary" type="button" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -236,7 +237,7 @@
|
||||
</p>
|
||||
<p>
|
||||
To use this app, you will need to download one or more archives (called ZIM archives) from the Kiwix website. You will then have
|
||||
offline access to Wikipedia, Wiktionary, Wikivoyage and many other sources even if you are undertaking a long plane journey, hiking,
|
||||
offline access to Wikipedia, Wiktionary, Wikivoyage and many other sources even if you are undertaking a long plane journey, hiking,
|
||||
and travelling or living in areas with weak Internet access.
|
||||
</p>
|
||||
<p>
|
||||
@ -275,7 +276,7 @@
|
||||
If you have enough space, you can put several archives on your device storage. If you download the content directly in the app, note the location
|
||||
of the saved file when you get the notification that it has completed. If you downloaded via a PC, you will generally need to use a USB
|
||||
cable to copy the ZIM archive(s) to an accessible location on your device, such as the SD card or the main storage area if there is enough
|
||||
space there.
|
||||
space there.
|
||||
</p>
|
||||
<h4>Step 3: open this app, go to the "Configure" menu and select your ZIM file</h4>
|
||||
<p>
|
||||
@ -393,8 +394,8 @@
|
||||
</div>
|
||||
<div id="hideFileSelectors">
|
||||
<div id="scanningForArchives" style="display: none;">
|
||||
<br /> Scanning for archives... Please wait <img src="img/spinner.gif" alt="Please wait..." />
|
||||
</div>
|
||||
<br /> Scanning for archives... Please wait <img src="img/spinner.gif" alt="Please wait..." />
|
||||
</div>
|
||||
<div id="chooseArchiveFromLocalStorage" style="display: none;">
|
||||
<div id="archivesFound" class="row">
|
||||
<p><span id="archiveNumber">Archives found on this device (tap "Select storage" to rescan)</span>:</p>
|
||||
@ -417,7 +418,7 @@
|
||||
<div id="UWPInstructions" class="row">
|
||||
<div class="col-xs-6">
|
||||
<p>For a single unsplit archive</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<p>For multiple or split archives</p>
|
||||
</div>
|
||||
@ -449,12 +450,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="downloads">
|
||||
<div class="row">
|
||||
<h3>Download links</h3>
|
||||
<p>
|
||||
Files can be very large, <b>do not attempt to download using mobile data!</b>
|
||||
</p>
|
||||
<div class="col-xs-12">
|
||||
<div class="row">
|
||||
<h3>Download links</h3>
|
||||
<p>
|
||||
Files can be very large, <b>do not attempt to download using mobile data!</b>
|
||||
</p>
|
||||
<div class="col-xs-12">
|
||||
<table>
|
||||
<tr>
|
||||
<td><input id="downloadTrigger" type="button" class="btn btn-primary" value="Open library" style="float:left; margin-right:1em;" /></td>
|
||||
@ -463,13 +464,13 @@
|
||||
</table>
|
||||
<p style="padding-top:10px;">
|
||||
<input type="checkbox" name="allowInternetAccess" id="allowInternetAccessCheck"><b> Allow Internet access?</b>
|
||||
</p>
|
||||
</p>
|
||||
</div>
|
||||
<div id="downloadLinks" style="display: none;"></div>
|
||||
<pre id="serverResponse" class="panel-footer" style="display:none;"></pre>
|
||||
</div>
|
||||
<div id="downloadLinks" style="display: none;"></div>
|
||||
<pre id="serverResponse" class="panel-footer" style="display:none;"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="row">
|
||||
@ -534,11 +535,23 @@
|
||||
<input type="checkbox" name="imageDisplayMode" id="imageDisplayModeCheck">
|
||||
<b>Display images if any</b> (if hidden, tap the <span style="background-color:lightblue; color:black;"> blue area </span> to display one-by-one)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="hideActiveContentWarning" id="hideActiveContentWarningCheck">
|
||||
<b>Permanently hide warning about active content</b> (only hide if you know how to access the Archive Index [<i>Hint: type a space in the search box</i>])
|
||||
</label>
|
||||
<label class="text">
|
||||
<b>Start character</b> of alphabet:
|
||||
<input type="text" name="alphaChar" id="alphaCharTxt" value="A" style="width:2em;">
|
||||
(use capital letters if they exist in your locale)<br />
|
||||
<b>End character</b> of alphabet:
|
||||
<input type="text" name="omegaChar" id="omegaCharTxt" value="Z" style="width:2em;">
|
||||
(these are used to set appropriate alphabet for the Archive Index)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="returntoArticle" style="text-align:center;"></div>
|
||||
<div>
|
||||
<div class="row">
|
||||
@ -616,9 +629,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Bootstrap alert box will be created here -->
|
||||
<div id="alertBoxDiv" style="text-align: center;"></div>
|
||||
<iframe id="articleContent" class="articleIFrame"></iframe>
|
||||
</article>
|
||||
<footer id="footer">
|
||||
<!-- Bootstrap alert box -->
|
||||
<div id="alertBoxDivFooter"></div>
|
||||
<div id="navigationButtons" class="btn-group btn-group-justified">
|
||||
<div class="row">
|
||||
<a class="btn btn-default col-xs-2" id="btnHomeBottom" title="Home"><span class="glyphicon glyphicon-home"></span></a>
|
||||
|
1120
www/js/app.js
1120
www/js/app.js
File diff suppressed because it is too large
Load Diff
@ -22,6 +22,12 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
// Set a global error handler to prevent app crashes
|
||||
window.onerror = function (msg, url) {
|
||||
console.error('Error caught in app [' + url + ']:\n' + msg);
|
||||
return true;
|
||||
};
|
||||
|
||||
// Parameters that define overall operation of app
|
||||
var params = {};
|
||||
params['version'] = "0.9.9.82 Beta-dev"; //DEV: do not set this dynamically -- it is compared to the cookie "version" in order to show first-time info, and the cookie is updated in app.js
|
||||
@ -30,7 +36,7 @@ params['fileVersion'] = "wikipedia_en_ray_charles_novid_2018-10.zim (12-Oct-2018
|
||||
params['cachedStartPage'] = false; //If you have cached the start page for quick start, give its URI here
|
||||
params['kiwixDownloadLink'] = "https://download.kiwix.org/zim/"; //Include final slash
|
||||
|
||||
params['results'] = params['results'] || 15; //Number of search results to display
|
||||
params['results'] = params['results'] || 50; //Number of search results to display
|
||||
params['relativeFontSize'] = ~~(getCookie('relativeFontSize') || 100); //Sets the initial font size for articles (as a percentage) - user can adjust using zoom buttons
|
||||
params['relativeUIFontSize'] = ~~(getCookie('relativeUIFontSize') || 100); //Sets the initial font size for UI (as a percentage) - user can adjust using slider in Config
|
||||
params['cssSource'] = getCookie('cssSource') || "auto"; //Set default to "auto", "desktop" or "mobile"
|
||||
@ -45,6 +51,9 @@ params['rememberLastPage'] = getCookie('rememberLastPage') != null ? getCookie('
|
||||
params['useMathJax'] = getCookie('useMathJax') != null ? getCookie('useMathJax') : true; //Set default to true to display math formulae with MathJax, false to use fallback SVG images only
|
||||
//params['showFileSelectors'] = getCookie('showFileSelectors') != null ? getCookie('showFileSelectors') : false; //Set to true to display hidden file selectors in packaged apps
|
||||
params['showFileSelectors'] = false; //This will cause file selectors to be hidden on each load of the app (by ignoring cookie)
|
||||
params['hideActiveContentWarning'] = getCookie('hideActiveContentWarning') != null ? getCookie('hideActiveContentWarning') : false;
|
||||
params['alphaChar'] = getCookie('alphaChar') || 'A'; //Set default start of alphabet string (used by the Archive Index)
|
||||
params['omegaChar'] = getCookie('omegaChar') || 'Z'; //Set default end of alphabet string
|
||||
|
||||
//Do not touch these values unless you know what they do! Some are global variables, some are set programmatically
|
||||
params['storedFile'] = getCookie('lastSelectedArchive') || params['packagedFile'];
|
||||
@ -60,6 +69,14 @@ params['allowInternetAccess'] = params['allowInternetAccess'] || false; //Do not
|
||||
params['printIntercept'] = false;
|
||||
params['printInterception'] = false;
|
||||
|
||||
//Prevent app boot loop with problematic pages that cause an app crash
|
||||
if (getCookie('lastPageLoad') == 'failed') {
|
||||
params.lastPageVisit = "";
|
||||
} else {
|
||||
//Cookie will signal failure until article is fully loaded
|
||||
document.cookie = 'lastPageLoad=failed;expires=Fri, 31 Dec 9999 23:59:59 GMT';
|
||||
}
|
||||
|
||||
//Initialize checkbox, radio and other values
|
||||
document.getElementById('cssCacheModeCheck').checked = params.cssCache;
|
||||
document.getElementById('imageDisplayModeCheck').checked = params.imageDisplay;
|
||||
@ -75,6 +92,10 @@ document.getElementById('cssUIDarkThemeCheck').checked = params.cssUITheme == 'd
|
||||
document.getElementById('useMathJaxRadio' + (params.useMathJax ? 'True' : 'False')).checked = true;
|
||||
document.getElementById('rememberLastPageCheck').checked = params.rememberLastPage;
|
||||
document.getElementById('displayFileSelectorsCheck').checked = params.showFileSelectors;
|
||||
document.getElementById('hideActiveContentWarningCheck').checked = params.hideActiveContentWarning;
|
||||
document.getElementById('alphaCharTxt').value = params.alphaChar;
|
||||
document.getElementById('omegaCharTxt').value = params.omegaChar;
|
||||
|
||||
var versionSpans = document.getElementsByClassName('version');
|
||||
for (var i = 0; i < versionSpans.length; i++) {
|
||||
versionSpans[i].innerHTML = i ? params.version : params.version.replace(/\s+.*$/, "");
|
||||
|
@ -417,7 +417,7 @@ define([], function () {
|
||||
}
|
||||
var headerDoc = 'We found the following links to your file:';
|
||||
var bodyDoc = '<p><a id="returnLink" href="#" data-kiwix-dl="' + URL.replace(/\/[^\/]*\.meta4$/i, "\/") + '"><< Back to list of files</a></p>\r\n';
|
||||
bodyDoc += /\/ted\//i.test(URL) ? '<h4 style="color:red">IMPORTANT: <b>TED TALKS</b> are not yet supported by this app due to lack of video playback capability</h4>\r\n<p>We apologize for the inconvenience. You may download the file here, and other playback solutions may be available from <a href="http://kiwix.org">Kiwix</a>.' : "";
|
||||
bodyDoc += /\/ted\//i.test(URL) ? '<h4 style="color:red">IMPORTANT: <b>TED TALKS</b> videos can be played in the UWP app on Windows 10, but not currently on Windows 10 Mobile due to lack of webm support on mobile.</h4>\r\n<p>We apologize for the inconvenience. Please note you will need to search for the talks using standard ZIM search, because the ZIM\'s proprietary UI does not yet work in this app.' : "";
|
||||
bodyDoc += "<h5";
|
||||
bodyDoc += megabytes > 200 ? ' style="color:red;"> WARNING: ' : '>';
|
||||
bodyDoc += 'File size is <b>' + (megabytes ? megabytes$ + 'MB' : 'unknown') + '</b>' + (size ? ' (' + size + ' bytes)' : '') + '</h5>\r\n';
|
||||
@ -425,13 +425,13 @@ define([], function () {
|
||||
'<p><b>BitTorrent link</b>: <a href="' + URL.replace(/\.meta4$/, ".torrent") + '" target="_blank">' +
|
||||
URL.replace(/\.meta4$/, ".torrent") + '</a></p>';
|
||||
if (megabytes > 4000 && /\.zim\.meta4$/i.test(URL)) {
|
||||
bodyDoc += '<p style="color:red;">This archive is larger than the maximum file size permitted on an SD card formatted as FAT32 (max size is approx. 4GB). If your card or other storage area is formatted in this way, you will need to download a split version of this file: see <a href="http://wiki.kiwix.org/wiki/FAQ/en">Frequently Asked Questions</a>.</p>\r\n';
|
||||
bodyDoc += '<p style="color:red;">This archive is larger than the maximum file size permitted on an SD card formatted as FAT32 (max size is approx. 4GB). On Windows, this is not normally a problem. However, if your card or other storage area is formatted in this way, you will need to download a split version of this file: see <a href="http://wiki.kiwix.org/wiki/FAQ/en">Frequently Asked Questions</a>.</p>\r\n';
|
||||
bodyDoc += '<p><b>To browse for a split version of this archive click here: <a id="portable" href="#" data-kiwix-dl="' +
|
||||
URL.replace(/\/zim\/([^/]+\/).*$/m, "/portable/$1") + '">' + URL.replace(/\/zim\/([^/]+\/).*$/m, "/portable/$1") +
|
||||
'</a>.</b></p>\r\n';
|
||||
}
|
||||
if (/\.zip\.meta4$/i.test(URL)) {
|
||||
if (megabytes > 4000) bodyDoc += '<p style="color:red;">This ZIP file contains a split version of the archive, but the ZIP itself is larger than the maximum file size permitted on an SD card formatted as FAT32. You will need to save it in a non-FAT32 location (e.g. a PC hard drive).</p>\r\n';
|
||||
if (megabytes > 4000) bodyDoc += '<p style="color:red;">This ZIP file contains a split version of the archive, but the ZIP itself is larger than the maximum file size permitted on an SD card formatted as FAT32. Be sure to save it in a non-FAT32 location (e.g. a PC hard drive).</p>\r\n';
|
||||
bodyDoc += '<p>INSTRUCTIONS: You may need to open this ZIP file on a regular computer. After you have downloaded it, open the ZIP in\r\n' +
|
||||
'File Explorer. You will need to extract the contents of the folder <span style="font-family: monospace;"><b>> data > content</b></span>,\r\n' +
|
||||
'and transfer ALL of the files there to an accessible folder on your device. After that, you can search for the folder in this app (see above).</p>\r\n';
|
||||
|
@ -185,6 +185,36 @@ define([], function() {
|
||||
printOptions.innerHTML = printStyleInnerHTML;
|
||||
}
|
||||
|
||||
function downloadBlobUWP(blob, filename, message) {
|
||||
// Copy BLOB to downloads folder and launch from there in Edge
|
||||
// First create an empty file in the folder
|
||||
Windows.Storage.DownloadsFolder.createFileAsync(filename, Windows.Storage.CreationCollisionOption.generateUniqueName)
|
||||
.then(function (file) {
|
||||
// Open the returned dummy file in order to copy the data into it
|
||||
file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (output) {
|
||||
// Get the InputStream stream from the blob object
|
||||
var input = blob.msDetachStream();
|
||||
// Copy the stream from the blob to the File stream
|
||||
Windows.Storage.Streams.RandomAccessStream.copyAsync(input, output).then(function () {
|
||||
output.flushAsync().done(function () {
|
||||
input.close();
|
||||
output.close();
|
||||
// Finally, tell the system to open the file if it's not a subtitle file
|
||||
if (!/\.(?:ttml|ssa|ass|srt|idx|sub|vtt)$/i.test(filename)) Windows.System.Launcher.launchFileAsync(file);
|
||||
if (file.isAvailable) {
|
||||
var fileLink = file.path.replace(/\\/g, '/');
|
||||
fileLink = fileLink.replace(/^([^:]+:\/)(.*)/, function (p0, p1, p2) {
|
||||
return 'file:///' + p1 + encodeURIComponent(p2);
|
||||
});
|
||||
message.innerHTML = '<strong>Download:</strong> Your file was saved as <a href="' +
|
||||
fileLink + '" target="_blank" class="alert-link">' + file.path + '</a>';
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions and classes exposed by this module
|
||||
*/
|
||||
@ -197,6 +227,7 @@ define([], function() {
|
||||
poll: poll,
|
||||
clear: clear,
|
||||
XHR: XHR,
|
||||
printCustomElements: printCustomElements
|
||||
printCustomElements: printCustomElements,
|
||||
downloadBlobUWP: downloadBlobUWP
|
||||
};
|
||||
});
|
||||
|
@ -227,16 +227,18 @@ define(['q'], function (q) {
|
||||
* continue the search.
|
||||
* If lowerBound is not set, returns only indices where query returns 0 and null otherwise.
|
||||
* If lowerBound is set, returns the smallest index where query does not return > 0.
|
||||
* @param {Integer} begin
|
||||
* @param {Integer} end
|
||||
* @param query Function
|
||||
* @param {Boolean} lowerBound
|
||||
* @param {Integer} begin The beginning of the search window
|
||||
* @param {Integer} end The end of the search window
|
||||
* @param {Function} query The query to run to test the current point in the window
|
||||
* @param {Boolean} lowerBound Determines the type of search
|
||||
* @returns {Promise} Promise for the lowest dirEntry that fulfils (or fails to fulfil) the query
|
||||
*/
|
||||
function binarySearch(begin, end, query, lowerBound) {
|
||||
if (end <= begin)
|
||||
return lowerBound ? begin : null;
|
||||
var mid = Math.floor((begin + end) / 2);
|
||||
return query(mid).then(function (decision) {
|
||||
return query(mid).then(function(decision)
|
||||
{
|
||||
if (decision < 0)
|
||||
return binarySearch(begin, mid, query, lowerBound);
|
||||
else if (decision > 0)
|
||||
@ -244,7 +246,7 @@ define(['q'], function (q) {
|
||||
else
|
||||
return mid;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Base64 Content to a Blob
|
||||
|
@ -37,6 +37,10 @@ define(['zimfile', 'zimDirEntry', 'util', 'utf8'],
|
||||
* @param {ZIMArchive} zimArchive Ready-to-use ZIMArchive
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback callbackMetadata
|
||||
* @param {String} data metadata string
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a ZIM archive object to access the ZIM file at the given path in the given storage.
|
||||
@ -168,37 +172,50 @@ define(['zimfile', 'zimDirEntry', 'util', 'utf8'],
|
||||
};
|
||||
|
||||
/**
|
||||
* Look for DirEntries with title starting with the given prefix (case-sensitive)
|
||||
* Look for dirEntries with title starting with the given prefix (case-sensitive)
|
||||
*
|
||||
* @param {String} prefix
|
||||
* @param {Integer} resultSize
|
||||
* @param {callbackDirEntryList} callback
|
||||
* @param {String} prefix The case-sensitive value against which dirEntry titles (or url) will be compared
|
||||
* @param {Integer} resultSize The maximum number of results to return
|
||||
* @param {Function} callback The function to call with the array of dirEntries with titles that begin with prefix
|
||||
*/
|
||||
ZIMArchive.prototype.findDirEntriesWithPrefixCaseSensitive = function(prefix, resultSize, callback) {
|
||||
ZIMArchive.prototype.findDirEntriesWithPrefixCaseSensitive = function(prefix, resultSize, callback, startIndex) {
|
||||
// Save the value of startIndex because value of null has a special meaning in combination with prefix:
|
||||
// produces a list of matches starting with first match and then next x dirEntries thereafter
|
||||
var saveStartIndex = startIndex;
|
||||
startIndex = startIndex || 0;
|
||||
prefix = prefix || '';
|
||||
var that = this;
|
||||
util.binarySearch(0, this._file.articleCount, function(i) {
|
||||
util.binarySearch(startIndex, this._file.articleCount, function(i) {
|
||||
return that._file.dirEntryByTitleIndex(i).then(function(dirEntry) {
|
||||
if (dirEntry.title === "")
|
||||
return -1; // ZIM sorts empty titles (assets) to the end
|
||||
else if (dirEntry.namespace < "A")
|
||||
return 1;
|
||||
else if (dirEntry.namespace > "A")
|
||||
return -1;
|
||||
return prefix <= dirEntry.title ? -1 : 1;
|
||||
if (dirEntry.namespace < "A") return 1;
|
||||
if (dirEntry.namespace > "A") return -1;
|
||||
// We should now be in namespace A
|
||||
if (dirEntry.title) {
|
||||
return prefix <= dirEntry.title ? -1 : 1;
|
||||
} else {
|
||||
// Some dirEntries (e.g. subtitles) have no title, but are still sorted in the A namespace,
|
||||
// so we have to use the url as a comparator [kiwix-js #440 #443]
|
||||
return prefix <= dirEntry.url ? -1 : 1;
|
||||
}
|
||||
});
|
||||
}, true).then(function(firstIndex) {
|
||||
var dirEntries = [];
|
||||
var addDirEntries = function(index) {
|
||||
if (index >= firstIndex + resultSize || index >= that._file.articleCount)
|
||||
return dirEntries;
|
||||
return {
|
||||
'dirEntries': dirEntries,
|
||||
'nextStart': index
|
||||
};
|
||||
return that._file.dirEntryByTitleIndex(index).then(function(dirEntry) {
|
||||
if (dirEntry.title.slice(0, prefix.length) === prefix && dirEntry.namespace === "A")
|
||||
if ((saveStartIndex === null || dirEntry.title.slice(0, prefix.length) === prefix) && dirEntry.namespace === "A")
|
||||
dirEntries.push(dirEntry);
|
||||
return addDirEntries(index + 1);
|
||||
});
|
||||
};
|
||||
return addDirEntries(firstIndex);
|
||||
}).then(callback);
|
||||
}).then(function(objWithIndex) {
|
||||
callback(objWithIndex.dirEntries, objWithIndex.nextStart);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -281,6 +298,28 @@ define(['zimfile', 'zimDirEntry', 'util', 'utf8'],
|
||||
this._file.dirEntryByUrlIndex(index).then(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read a Metadata string inside the ZIM file.
|
||||
* @param {String} key
|
||||
* @param {callbackMetadata} callback
|
||||
*/
|
||||
ZIMArchive.prototype.getMetadata = function (key, callback) {
|
||||
var that = this;
|
||||
this.getDirEntryByTitle("M/" + key).then(function (dirEntry) {
|
||||
if (dirEntry === null || dirEntry === undefined) {
|
||||
console.warn("Title M/" + key + " not found in the archive");
|
||||
callback();
|
||||
} else {
|
||||
that.readUtf8File(dirEntry, function (dirEntryRead, data) {
|
||||
callback(data);
|
||||
});
|
||||
}
|
||||
}).fail(function (e) {
|
||||
console.warn("Metadata with key " + key + " not found in the archive", e);
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Functions and classes exposed by this module
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user