mirror of
https://github.com/kiwix/kiwix-js.git
synced 2025-08-03 11:16:38 -04:00
This commit is contained in:
parent
6d263537c1
commit
49d7fbc99d
8
.github/workflows/CI.yml
vendored
8
.github/workflows/CI.yml
vendored
@ -76,6 +76,10 @@ jobs:
|
||||
fi
|
||||
exit $failed
|
||||
|
||||
- name: Run ESLint
|
||||
run: |
|
||||
npx eslint
|
||||
|
||||
- name: End-to-end tests on Chrome (Linux)
|
||||
env:
|
||||
GITHUB_ACTION: ${{ github.event_name }}
|
||||
@ -181,6 +185,10 @@ jobs:
|
||||
- name: Unit tests (Windows)
|
||||
run: npm run test-unit
|
||||
|
||||
- name: Run ESLint
|
||||
run: |
|
||||
npx eslint
|
||||
|
||||
- name: End-to-end tests on Edge Chromium (Windows)
|
||||
env:
|
||||
GITHUB_ACTION: ${{ github.event_name }}
|
||||
|
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
@ -43,7 +43,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@ -54,7 +54,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@ -68,4 +68,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
@ -85,8 +85,8 @@ _You must test your code yourself before asking for review, like this_:
|
||||
* _You **must** test your fix in both "Restricted" and "ServiceWorker" modes_ (under Compatibility settings). You will be astonished the number of times a new contributor tells us
|
||||
that their fix is working, but we discover they only applied the fix in one of these two modes. Don't be **that** contributor!
|
||||
* Unit tests, which test for regressions with basic app functions, are run automatically with GitHub Actions on each PR and push to a PR. If one of these tests fails, you will want
|
||||
to debug. First, see if you can also see the failure by running the tests with `npm test`, which should run the tests in all your installed browsers. To address any issues
|
||||
identified, see [TESTS](./TESTS.md) so you can debug;
|
||||
to debug. First, see if you can also see the failure by running the tests with `npm test`, which will run the tests in the NodeJS environment.
|
||||
To address any issues identified, see [TESTS](./TESTS.md) so you can debug;
|
||||
* End-to-end (e2e) tests are also run on GitHub Actions when you push to your PR. These test typical user actions in a headless browser. Tests are currently enabled for latest
|
||||
Firefox, Edge, Chrome in Linux and Windows, and in IE Mode on Windows (this is the equivalent to testing on Internet Explorer 11). You can run these tests yourself in a
|
||||
non-headless browser with `npm run tests-e2e-firefox`, `npm run tests-e2e-iemode`, etc. For more information, see [TESTS](./TESTS.md). For IE Mode, you will need to have the Edge
|
||||
|
12
eslint.config.js
Normal file
12
eslint.config.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { defineConfig } from 'eslint/config';
|
||||
import globals from 'globals';
|
||||
import js from '@eslint/js';
|
||||
|
||||
export default defineConfig([
|
||||
{ files: ['**/*.{js,mjs,cjs}'] },
|
||||
{ files: ['**/*.{js,mjs,cjs}'], languageOptions: { globals: globals.browser } },
|
||||
{ files: ['**/*.{js,mjs,cjs}'], plugins: { js }, extends: ['js/recommended'] },
|
||||
{ ignores: ['dist/**', 'emscripten/**', '**/xzdec*.js', '**/zstddec*.js', '**/webpHero*.js', '**/jquery*.js',
|
||||
'**/bootstrap*.js', '**/require.js', '**/solid.js', '**/fontawesome.js', '**/replayWorker.js',
|
||||
'**/*-wasm*.js', '**/*-asm*.js', 'tmp/**'] }
|
||||
]);
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable quote-props, quotes, indent */
|
||||
document.localeJson = {
|
||||
"en": {
|
||||
"translation": {
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable quote-props, quotes, indent */
|
||||
document.localeJson = {
|
||||
"es": {
|
||||
"translation": {
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable quote-props, quotes, indent */
|
||||
document.localeJson = {
|
||||
"fr": {
|
||||
"translation": {
|
||||
|
11111
package-lock.json
generated
11111
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -40,6 +40,7 @@
|
||||
"@babel/core": "^7.26.0",
|
||||
"@babel/preset-env": "^7.26.0",
|
||||
"@babel/register": "^7.25.9",
|
||||
"@eslint/js": "^9.23.0",
|
||||
"@rollup/plugin-babel": "^6.0.4",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
@ -49,18 +50,18 @@
|
||||
"babel-plugin-polyfill-corejs3": "^0.7.1",
|
||||
"chai": "^5.1.2",
|
||||
"del-cli": "^5.0.0",
|
||||
"eslint": "^8.42.0",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
"eslint": "^9.23.0",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-n": "^16.0.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"globals": "^16.0.0",
|
||||
"http-server": "^14.1.1",
|
||||
"jsdom": "^25.0.1",
|
||||
"mocha": "^10.8.2",
|
||||
"nyc": "^17.1.0",
|
||||
"rollup": "^4.5.0",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"selenium-webdriver": "^4.11.1",
|
||||
"selenium-webdriver": "^4.30.0",
|
||||
"sinon": "^19.0.2",
|
||||
"start-server-and-test": "^2.0.0",
|
||||
"vite": "^6.2.3"
|
||||
|
@ -9,6 +9,9 @@ import terser from '@rollup/plugin-terser';
|
||||
import { minify } from 'terser';
|
||||
// import styles from "@ironkinoko/rollup-plugin-styles";
|
||||
|
||||
/* global process */
|
||||
/* eslint-disable no-unused-vars */
|
||||
|
||||
const config = {
|
||||
// The entry point for the bundler
|
||||
input: 'www/js/app.js',
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
/* global chrome */
|
||||
|
||||
/* eslint-disable prefer-const */
|
||||
|
||||
/**
|
||||
* App version number - ENSURE IT MATCHES VALUE IN init.js
|
||||
* DEV: Changing this will cause the browser to recognize that the Service Worker has changed, and it will
|
||||
@ -541,7 +539,7 @@ function cacheAndReturnResponseForAsset (event, response) {
|
||||
* Zimit requests may be for a range of bytes, in fact video (at least) is stored as a blob, so the appropriate response will just be a normal 200.
|
||||
* @returns {Promise<Response>} A Promise for the Response, or rejects with the invalid message port data
|
||||
*/
|
||||
function fetchUrlFromZIM (urlObjectOrString, range, expectedHeaders) {
|
||||
function fetchUrlFromZIM (urlObjectOrString, range/*, expectedHeaders*/) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var pathname = typeof urlObjectOrString === 'string' ? urlObjectOrString : urlObjectOrString.pathname;
|
||||
// Note that titles may contain bare question marks or hashes, so we must use only the pathname without any URL parameters.
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Builder } from 'selenium-webdriver';
|
||||
import legacyRayCharles from '../../spec/legacy-ray_charles.e2e.spec.js';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/* global process */
|
||||
|
||||
// Input capabilities
|
||||
const capabilities = {
|
||||
|
@ -4,7 +4,7 @@ import gutenbergRo from '../../spec/gutenberg_ro.e2e.spec.js';
|
||||
import tonedear from '../../spec/tonedear.e2e.spec.js'
|
||||
import paths from '../../paths.js';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/* global process */
|
||||
|
||||
// Input capabilities
|
||||
const capabilities = {
|
||||
|
@ -5,7 +5,7 @@ import gutenbergRo from '../../spec/gutenberg_ro.e2e.spec.js';
|
||||
import tonedearTests from '../../spec/tonedear.e2e.spec.js';
|
||||
import paths from '../../paths.js';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/* global process */
|
||||
|
||||
async function loadChromiumDriver () {
|
||||
const options = new Options();
|
||||
|
@ -3,7 +3,7 @@ import legacyRayCharles from '../../spec/legacy-ray_charles.e2e.spec.js';
|
||||
import gutenbergRo from '../../spec/gutenberg_ro.e2e.spec.js';
|
||||
import tonedear from '../../spec/tonedear.e2e.spec.js';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/* global process */
|
||||
|
||||
// Input capabilities
|
||||
const capabilities = {
|
||||
|
@ -4,8 +4,6 @@ import legacyRayCharles from '../../spec/legacy-ray_charles.e2e.spec.js';
|
||||
import gutenbergRo from '../../spec/gutenberg_ro.e2e.spec.js';
|
||||
import tonedear from '../../spec/tonedear.e2e.spec.js';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
async function loadIEModeDriver () {
|
||||
const ieOptions = new Options();
|
||||
ieOptions.setEdgeChromium(true);
|
||||
|
@ -3,7 +3,8 @@ import { Options } from 'selenium-webdriver/edge.js';
|
||||
import legacyRayCharles from '../../spec/legacy-ray_charles.e2e.spec.js';
|
||||
import gutenbergRo from '../../spec/gutenberg_ro.e2e.spec.js';
|
||||
import tonedearTests from '../../spec/tonedear.e2e.spec.js';
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
/* global process */
|
||||
|
||||
async function loadMSEdgeDriver () {
|
||||
const options = new Options();
|
||||
|
@ -5,13 +5,13 @@ import gutenbergRo from '../../spec/gutenberg_ro.e2e.spec.js';
|
||||
import tonedearTests from '../../spec/tonedear.e2e.spec.js';
|
||||
import paths from '../../paths.js';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/* global process */
|
||||
|
||||
async function loadFirefoxDriver () {
|
||||
const options = new firefox.Options();
|
||||
// Run it headless if the environment variable GITHUB_ACTIONS is set
|
||||
if (process.env.GITHUB_ACTIONS) {
|
||||
options.headless();
|
||||
options.addArguments('--headless'); // Explicitly set headless mode
|
||||
}
|
||||
options.setPreference('browser.download.folderList', 2);
|
||||
options.setPreference('browser.download.dir', paths.downloadDir);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Builder } from 'selenium-webdriver';
|
||||
import legacyRayCharles from '../../spec/legacy-ray_charles.e2e.spec.js';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/* global process */
|
||||
|
||||
// Input capabilities
|
||||
const capabilities = {
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { Builder } from 'selenium-webdriver';
|
||||
import gutenbergRo from '../../spec/gutenberg_ro.e2e.spec.js';
|
||||
import tonedear from '../../spec/tonedear.e2e.spec.js';
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
/* global process */
|
||||
|
||||
// Input capabilities
|
||||
const capabilities = {
|
||||
|
@ -3,7 +3,7 @@ import legacyRayCharles from '../../spec/legacy-ray_charles.e2e.spec.js';
|
||||
import gutenbergRo from '../../spec/gutenberg_ro.e2e.spec.js';
|
||||
import tonedearTests from '../../spec/tonedear.e2e.spec.js';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/* global process */
|
||||
|
||||
// Input capabilities
|
||||
const capabilities = {
|
||||
|
@ -26,8 +26,8 @@ import assert from 'assert';
|
||||
import paths from '../paths.js';
|
||||
import fs from 'fs';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/* global describe, it */
|
||||
/* global describe, it, process */
|
||||
/* eslint-disable no-unused-vars */
|
||||
|
||||
// Get the BrowserStack environment variable
|
||||
const BROWSERSTACK = !!process.env.BROWSERSTACK_LOCAL_IDENTIFIER;
|
||||
|
@ -19,15 +19,15 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kiwix (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
/* global describe, it, process */
|
||||
|
||||
import { By, Key, WebDriver, until } from 'selenium-webdriver';
|
||||
// import firefox from 'selenium-webdriver/firefox.js';
|
||||
import assert from 'assert';
|
||||
import paths from '../paths.js';
|
||||
|
||||
/* eslint-disable camelcase, one-var, prefer-const */
|
||||
/* global describe, it */
|
||||
|
||||
// Get the BrowserStack environment variable
|
||||
const BROWSERSTACK = !!process.env.BROWSERSTACK_LOCAL_IDENTIFIER;
|
||||
// DEV: For local testing, use line below instead
|
||||
@ -239,37 +239,50 @@ function runTests (driver, modes, keepDriver) {
|
||||
}
|
||||
|
||||
// console.log('FilesLength outer: ' + filesLength);
|
||||
// Switch to iframe and check that the index contains the specified article
|
||||
// Wait until the iframe is present and available
|
||||
await driver.wait(async function () {
|
||||
const iframe = await driver.findElement(By.id('articleContent'));
|
||||
return iframe !== null;
|
||||
}, 6000, 'Iframe with id "articleContent" was not found');
|
||||
|
||||
// Switch to the iframe
|
||||
await driver.switchTo().frame('articleContent');
|
||||
// Wait until the index has loaded
|
||||
|
||||
// Wait until the index has loaded inside the iframe
|
||||
await driver.wait(async function () {
|
||||
const contentAvailable = await driver.executeScript('return document.getElementById("mw-content-text");');
|
||||
return contentAvailable;
|
||||
}, 6000);
|
||||
// const articleLink = await driver.wait(until.elementLocated(By.xpath('/html/body/div/div/ul/li[77]/a[2]')));
|
||||
// const text = await articleLink.getText();
|
||||
let articleLink;
|
||||
return contentAvailable !== null;
|
||||
}, 6000, 'Content inside iframe did not load');
|
||||
|
||||
// Locate the article link and get its text
|
||||
const text = await driver.wait(async function () {
|
||||
articleLink = await driver.findElement(By.xpath('/html/body/div/div/ul/li[77]/a[2]'));
|
||||
const articleLink = await driver.findElement(By.xpath('/html/body/div/div/ul/li[77]/a[2]'));
|
||||
return await articleLink.getText();
|
||||
}, 6000);
|
||||
// const articleLink = await driver.findElement(By.linkText('This Little Girl of Mine'));
|
||||
|
||||
// Assert that the text matches the expected value
|
||||
assert.equal('This Little Girl of Mine', text);
|
||||
|
||||
// Re-locate the article link just before interacting with it to avoid stale reference
|
||||
const articleLink = await driver.findElement(By.xpath('/html/body/div/div/ul/li[77]/a[2]'));
|
||||
|
||||
// Scroll the element into view and navigate to it
|
||||
await driver.executeScript('var el=arguments[0]; el.scrollIntoView(true); setTimeout(function () {el.click();}, 50); return el.offsetParent;', articleLink);
|
||||
// Pause for 2 seconds to allow article to load
|
||||
|
||||
// Pause for 2 seconds to allow the article to load
|
||||
await driver.sleep(2000);
|
||||
|
||||
// Check the content of the loaded article
|
||||
let elementText = '';
|
||||
try {
|
||||
// Find the mwYw element in JavaScript and get its content
|
||||
elementText = await driver.executeScript('return document.getElementById("mwYw").textContent;');
|
||||
} catch (e) {
|
||||
// We probably got a NoSuchFrameError on Safari, so try selecting it with a different method
|
||||
// Handle cases where the frame or element is not accessible
|
||||
await driver.switchTo().defaultContent();
|
||||
elementText = await driver.executeScript('var iframeDoc = document.getElementById("articleContent").contentDocument; return iframeDoc.getElementById("mwYw").textContent;');
|
||||
}
|
||||
// console.log('Element text: ' + elementText);
|
||||
// Check that the article title is correct
|
||||
|
||||
// Assert that the article content matches the expected value
|
||||
assert.equal('Instrumentation by the Ray Charles Orchestra', elementText);
|
||||
await driver.switchTo().defaultContent();
|
||||
});
|
||||
|
@ -1,8 +1,11 @@
|
||||
/* eslint-disable no-undef */
|
||||
/* eslint-disable no-unused-vars */
|
||||
|
||||
import { By, until } from 'selenium-webdriver';
|
||||
import assert from 'assert';
|
||||
import paths from '../paths.js';
|
||||
|
||||
/* global describe, it, process */
|
||||
|
||||
const BROWSERSTACK = !!process.env.BROWSERSTACK_LOCAL_IDENTIFIER;
|
||||
const port = BROWSERSTACK ? '8099' : '8080';
|
||||
const tonedearBaseFile = BROWSERSTACK ? '/tests/zims/tonedear/tonedear.com_en_2024-09.zim' : paths.tonedearBaseFile;
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-useless-constructor */
|
||||
/**
|
||||
* init.js : Global configuration of the app
|
||||
* This file handles the dependencies between javascript libraries, for the unit tests
|
||||
@ -24,10 +23,9 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
/* global webpHero */
|
||||
/* global webpHero, global */
|
||||
|
||||
// Define global params needed for tests to run on existing app code
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
var params = {};
|
||||
// We need to turn off source verification so that the test files can be loaded normally without interruption
|
||||
params['sourceVerification'] = false;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* eslint-disable no-prototype-builtins */
|
||||
/* eslint-disable import/no-named-default */
|
||||
|
||||
/**
|
||||
* Mocha test environment setup
|
||||
*
|
||||
@ -110,6 +110,7 @@ class Worker {
|
||||
this.onerror = null;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
postMessage (msg) {
|
||||
// Implement any worker simulation logic here if needed
|
||||
if (this.onmessage) {
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-unused-expressions */
|
||||
/* eslint-disable no-undef */
|
||||
// Converted Test from test.js file
|
||||
import { expect } from 'chai';
|
||||
|
@ -497,7 +497,7 @@ document.getElementById('libzimModeSelect').addEventListener('change', function
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
document.getElementById('useLibzim').addEventListener('click', function (e) {
|
||||
document.getElementById('useLibzim').addEventListener('click', function () {
|
||||
settingsStore.setItem('useLibzim', !params.useLibzim);
|
||||
window.location.reload();
|
||||
});
|
||||
@ -533,7 +533,8 @@ document.getElementById('serviceworkerLocalModeRadio').addEventListener('click',
|
||||
});
|
||||
|
||||
// Source verification is only makes sense in SW mode as doing the same in jQuery mode is redundant.
|
||||
document.getElementById('enableSourceVerificationCheckBox').style.display = params.contentInjectionMode === ('serviceworker' || 'serviceworkerlocal') ? 'block' : 'none';
|
||||
document.getElementById('enableSourceVerificationCheckBox').style.display = (params.contentInjectionMode === 'serviceworker' ||
|
||||
params.contentInjectionMode === 'serviceworkerlocal') ? 'block' : 'none';
|
||||
|
||||
document.getElementById('enableSourceVerification').addEventListener('change', function () {
|
||||
params.sourceVerification = this.checked;
|
||||
@ -1052,9 +1053,10 @@ async function handleMessageChannelByLibzim (event) {
|
||||
// We have a redirect to follow
|
||||
// this is still a bit flawed, as we do not check if it's a redirect or the file doesn't exist
|
||||
// We have no way to know if the file exists or not, so we have to assume it does and its just a redirect
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const dirEntry = await new Promise((resolve, _reject) => selectedArchive.getMainPageDirEntry((value) => resolve(value)));
|
||||
if (dirEntry.redirect) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const redirect = await new Promise((resolve, _reject) => selectedArchive.resolveRedirect(dirEntry, (v) => resolve(v)));
|
||||
const ret = await selectedArchive.callLibzimWorker({ action: 'getEntryByPath', path: redirect.namespace + '/' + redirect.url })
|
||||
const message = { action: 'giveContent', title: title, content: ret.content, mimetype: ret.mimetype };
|
||||
@ -1069,6 +1071,7 @@ async function handleMessageChannelByLibzim (event) {
|
||||
} catch (error) {
|
||||
const message = { action: 'giveContent', title: title, content: new Uint8Array(), mimetype: '' };
|
||||
messagePort.postMessage(message);
|
||||
console.error('Error while handling messageChannel', error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1280,6 +1283,7 @@ function isMessageChannelAvailable () {
|
||||
var dummyMessageChannel = new MessageChannel();
|
||||
if (dummyMessageChannel) return true;
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@ -1791,7 +1795,7 @@ async function handleFileDrop (packet) {
|
||||
}
|
||||
|
||||
const btnLibrary = document.getElementById('btnLibrary');
|
||||
btnLibrary.addEventListener('click', function (e) {
|
||||
btnLibrary.addEventListener('click', function () {
|
||||
const libraryContent = document.getElementById('libraryContent');
|
||||
const libraryIframe = libraryContent.contentWindow.document.getElementById('libraryIframe');
|
||||
uiUtil.tabTransitionToSection('library', params.showUIAnimations);
|
||||
@ -2747,6 +2751,7 @@ function displayArticleContentInIframe (dirEntry, htmlArticle) {
|
||||
// If we couldn't get it, reconstruct it from the archive's zimitPrefix
|
||||
zimitPrefix = zimitPrefix ? zimitPrefix[1] : selectedArchive.zimitPrefix.replace(/^\w\/([^/]+).*/, '$1');
|
||||
zimitPrefix = (dirEntry.namespace === 'C' ? 'A/' : '') + zimitPrefix;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
htmlArticle = htmlArticle.replace(regexpZimitHtmlLinks, function (match, blockStart, equals, quote, relAssetUrl, blockClose) {
|
||||
var newBlock = match;
|
||||
var assetUrl = relAssetUrl;
|
||||
|
@ -250,6 +250,7 @@ function getBestAvailableStorageAPI () {
|
||||
}
|
||||
} catch (e) {
|
||||
localStorageTest = false;
|
||||
console.warn('localStorage is not available: ' + e);
|
||||
}
|
||||
document.cookie = 'tempKiwixCookieTest=working; expires=Fri, 31 Dec 9999 23:59:59 GMT; SameSite=Strict';
|
||||
var kiwixCookieTest = /tempKiwixCookieTest=working/.test(document.cookie);
|
||||
|
@ -87,6 +87,7 @@ StorageFirefoxOS.prototype.scanForArchives = function () {
|
||||
* @param path Path where to look for files
|
||||
* @return {DOMCursor} Cursor of files found in given path
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
StorageFirefoxOS.prototype.enumerate = function (path) {
|
||||
return this._storage.enumerate();
|
||||
};
|
||||
@ -342,6 +343,7 @@ async function handleFolderOrFileDropViaWebkit (event) {
|
||||
*/
|
||||
async function getFilesFromReader (reader) {
|
||||
const files = [];
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const promise = new Promise(function (resolve, _reject) {
|
||||
reader.readEntries(function (entries) {
|
||||
resolve(entries);
|
||||
@ -352,6 +354,7 @@ async function getFilesFromReader (reader) {
|
||||
for (let index = 0; index < entries.length; index++) {
|
||||
const fileOrDir = entries[index];
|
||||
if (fileOrDir.isFile) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const filePromise = await new Promise(function (resolve, _reject) {
|
||||
fileOrDir.file(function (file) {
|
||||
resolve(file);
|
||||
|
@ -20,7 +20,7 @@
|
||||
* along with Kiwix (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/* globals params, appstate, caches, assetsCache */
|
||||
/* globals params, appstate, assetsCache */
|
||||
|
||||
'use strict';
|
||||
import settingsStore from './settingsStore.js';
|
||||
@ -68,7 +68,7 @@ function test (callback) {
|
||||
var item = window.localStorage.length;
|
||||
assetsCache.capability = assetsCache.capability + '|localStorage';
|
||||
} catch (err) {
|
||||
console.log('localStorage is not supported');
|
||||
console.warn('localStorage is not supported', err);
|
||||
}
|
||||
}
|
||||
console.log('Setting storage type to ' + assetsCache.capability.match(/^[^|]+/)[0]);
|
||||
@ -188,7 +188,7 @@ function idxDB (keyOrCommand, valueOrCallback, callback) {
|
||||
// Open (or create) the database
|
||||
var open = indexedDB.open(CACHEIDB, 1);
|
||||
|
||||
open.onerror = function (e) {
|
||||
open.onerror = function () {
|
||||
// Suppress error reporting if testing (older versions of Firefox support indexedDB but cannot use it with
|
||||
// the file:// protocol, so will report an error)
|
||||
if (assetsCache.capability !== 'test') {
|
||||
@ -228,14 +228,14 @@ function idxDB (keyOrCommand, valueOrCallback, callback) {
|
||||
processData = value !== null ? store.put(value, keyOrCommand) : store.get(keyOrCommand);
|
||||
}
|
||||
// Call the callback with the result
|
||||
processData.onsuccess = function (e) {
|
||||
processData.onsuccess = function () {
|
||||
if (keyOrCommand === 'delete') {
|
||||
rtnFn(true);
|
||||
} else {
|
||||
rtnFn(processData.result);
|
||||
}
|
||||
};
|
||||
processData.onerror = function (e) {
|
||||
processData.onerror = function () {
|
||||
console.error('IndexedDB command failed: ' + processData.error);
|
||||
rtnFn(false);
|
||||
};
|
||||
@ -579,6 +579,7 @@ function clear (items, callback) {
|
||||
result = 'assetsCache';
|
||||
}
|
||||
// Delete and reinitialize assetsCache
|
||||
// eslint-disable-next-line no-global-assign
|
||||
assetsCache = new Map();
|
||||
assetsCache.capability = capability;
|
||||
// Loose test here ensures we clear localStorage even if it wasn't being used in this session
|
||||
|
@ -31,8 +31,7 @@ import translateUI from './translateUI.js';
|
||||
* @returns {boolean} True if the browser can execute required code in the library iframe
|
||||
*/
|
||||
function canExecuteCode () {
|
||||
try {
|
||||
// eslint-disable-next-line no-new-func
|
||||
try {
|
||||
Function('try{}catch{}')();
|
||||
return true;
|
||||
} catch (error) {
|
||||
|
@ -464,7 +464,7 @@ function isSafari () {
|
||||
* @param {Document} doc The doucment on which to operate
|
||||
*/
|
||||
function addEventListenersToPopoverIcons (anchor, popover, doc) {
|
||||
const breakout = function (e) {
|
||||
const breakout = function () {
|
||||
// Adding the newcontainer property to the anchor will be cauught by the filterClickEvent function and will open in new tab
|
||||
anchor.newcontainer = true;
|
||||
anchor.click();
|
||||
|
@ -40,6 +40,7 @@ function getBestAvailableStorageAPI () {
|
||||
}
|
||||
} catch (e) {
|
||||
localStorageTest = false;
|
||||
console.warn('localStorage not supported in this context', e);
|
||||
}
|
||||
// Now test for document.cookie API support
|
||||
document.cookie = 'tempKiwixCookieTest=working; expires=Fri, 31 Dec 9999 23:59:59 GMT; SameSite=Strict';
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
/* eslint-disable indent */
|
||||
/* global webpMachine, webpHero, params */
|
||||
|
||||
import util from './util.js';
|
||||
@ -576,6 +575,8 @@ function displayFileDownloadAlert (title, download, contentType, content) {
|
||||
window.navigator.msSaveBlob(blob, filename);
|
||||
e.preventDefault();
|
||||
});
|
||||
} else {
|
||||
console.error('Error downloading file: ' + err);
|
||||
}
|
||||
}
|
||||
spinnerDisplay(false);
|
||||
|
@ -24,8 +24,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
/* eslint-disable eqeqeq */
|
||||
|
||||
var utf8 = {};
|
||||
|
||||
/**
|
||||
|
@ -22,9 +22,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
/* eslint-disable indent */
|
||||
/* eslint-disable one-var */
|
||||
|
||||
var regExpFindStringParts = /(?:^|.+?)(?:[\s$£€\uFFE5^+=`~<>{}[\]|\u3000-\u303F!-#%-\x2A,-/:;\x3F@\x5B-\x5D_\x7B}\u00A1\u00A7\u00AB\u00B6\u00B7\u00BB\u00BF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E3B\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]+|$)/g;
|
||||
|
||||
/**
|
||||
|
@ -677,7 +677,8 @@ ZIMArchive.prototype.getMetadata = function (key, callback) {
|
||||
ZIMArchive.prototype.addMetadataToZIMFile = function (key) {
|
||||
var that = this;
|
||||
var lcaseKey = key.toLocaleLowerCase();
|
||||
return new Promise(function (resolve, reject) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
return new Promise(function (resolve, _reject) {
|
||||
that.getMetadata(key, function (data) {
|
||||
data = data || '';
|
||||
that[lcaseKey] = data;
|
||||
|
Loading…
x
Reference in New Issue
Block a user