* Refactor image display and intelligently turn off manipulation

Former-commit-id: 0795327aae5a297607b395d15cefb0a193a8f325 [formerly e6c7358c48e984eccfa2b4e564170be66624df93 [formerly 08845f715dd25ae2d6f1b52298550c9174a60bb9]]
Former-commit-id: a693defc1ce66c9ecd4fbe3da4782734db95f944 [formerly a300360422f13db877daca4e6b7833af22531b2d]
Former-commit-id: 472cd9ea62dd5065b73c495b9ac1ec0310572662
This commit is contained in:
Jaifroid 2022-06-02 18:55:32 +01:00
parent 4f77388998
commit 1716c1486f
5 changed files with 56 additions and 27 deletions

View File

@ -295,9 +295,9 @@ self.addEventListener('fetch', function (event) {
// The response was not found in the cache so we look for it in the ZIM
// and add it to the cache if it is an asset type (css or js)
if (cache === ASSETS_CACHE && regexpZIMUrlWithNamespace.test(strippedUrl)) {
if (imageDisplay !== 'all' && /\/.*\.(jpe?g|png|svg|gif|webp)(?!.*?kiwix-display)/i.test(rqUrl)) {
if (imageDisplay !== 'all' && /\/.*\.(jpe?g|png|svg|gif|webp)(?=.*?kiwix-display)/i.test(rqUrl)) {
// If the user has disabled the display of images, and the browser wants an image, respond with empty SVG
// A URL with "?kiwix-display" query string acts as a passthrough so that the regex will not match and
// A URL without "?kiwix-display" query string acts as a passthrough so that the regex will not match and
// the image will be fetched by app.js
// DEV: If you need to hide more image types, add them to regex below and also edit equivalent regex in app.js
var svgResponse;

View File

@ -1137,14 +1137,17 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
);
}
if (this.value === 'serviceworker') {
var wikimediaZimLoaded = appstate.selectedArchive && /wikipedia|wikivoyage|mdwiki|wiktionary/i.test(appstate.selectedArchive._file.name);
if (params.displayHiddenBlockElements || params.manipulateImages || params.allowHTMLExtraction) {
uiUtil.systemAlert(
if (!wikimediaZimLoaded) uiUtil.systemAlert(
'Please note that we are disabling Image manipulation, Breakout link and/or Display hidden block elements, as these options can interfere with ZIMs that have active content. You may turn them back on, but be aware that they are only recommended for use with Wikimedia ZIMs.'
);
}
if (params.manipulateImages) document.getElementById('manipulateImagesCheck').click();
if (params.displayHiddenBlockElements) document.getElementById('displayHiddenBlockElementsCheck').click();
if (params.allowHTMLExtraction) document.getElementById('allowHTMLExtractionCheck').click();
if (!wikimediaZimLoaded) {
if (params.manipulateImages) document.getElementById('manipulateImagesCheck').click();
if (params.displayHiddenBlockElements) document.getElementById('displayHiddenBlockElementsCheck').click();
if (params.allowHTMLExtraction) document.getElementById('allowHTMLExtractionCheck').click();
}
}
params.themeChanged = true; // This will reload the page
});
@ -1204,6 +1207,11 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
uiUtil.systemAlert('This setting will be applied on next app launch');
});
$('input:checkbox[name=imageDisplayMode]').on('change', function (e) {
if (params.contentInjectionMode === 'serviceworker' && !this.checked) {
uiUtil.systemAlert('Image display can only be turned off in JQuery mode!');
this.checked = true;
return;
}
params.imageDisplay = this.checked ? true : false;
params.imageDisplayMode = this.checked ? 'progressive' : 'manual';
params.themeChanged = params.imageDisplay; //Only reload page if user asked for all images to be displayed
@ -1219,7 +1227,8 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
'<p>You will then be able to right-click or long-press images in the exported page and save them.</p>');
} else if (window.nw) {
uiUtil.systemAlert('Unfortunately there is currently no way to save an image to disk in the NWJS version of this app.<br>You can do this in the PWA version: please visit https://pwa.kiwix.org.');
} else if (params.contentInjectionMode === 'serviceworker') {
} else if (params.contentInjectionMode === 'serviceworker' && appstate.selectedArchive
&& !/wikimedia|wikivoyage|mdwiki|wiktionary/i.test(appstate.selectedArchive._file.name)) {
uiUtil.systemAlert('Please be aware that Image manipulation can interfere with non-Wikimedia ZIMs (particularly ZIMs that have active content). If you cannot access the articles in such a ZIM, please turn this setting off.');
} else if (/PWA/.test(params.appType)) {
uiUtil.systemAlert('Be aware that this option may interfere with active content if you switch to Service Worker mode.');
@ -2572,7 +2581,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
readNodeDirectoryAndCreateNodeFileObjects(params.pickedFolder, archive)
.then(function (fileset) {
var selectedFiles = fileset[0];
if (appstate.selectArchive && appstate.selectArchive._file.files[0].name === selectedFiles[0].name) return;
if (appstate.selectedArchive && appstate.selectedArchive._file.files[0].name === selectedFiles[0].name) return;
setLocalArchiveFromFileList(selectedFiles);
});
} else {
@ -2626,6 +2635,14 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
// Ensure that the new ZIM output is initially sent to the iframe (e.g. if the last article was loaded in a window)
// (this only affects jQuery mode)
appstate.target = 'iframe';
if (params.contentInjectionMode === 'serviceworker') {
var wikimediaZimLoaded = appstate.selectedArchive && /wikipedia|wikivoyage|mdwiki|wiktionary/i.test(appstate.selectedArchive._file.name);
if (!wikimediaZimLoaded) {
if (params.manipulateImages) document.getElementById('manipulateImagesCheck').click();
if (params.displayHiddenBlockElements) document.getElementById('displayHiddenBlockElementsCheck').click();
if (params.allowHTMLExtraction) document.getElementById('allowHTMLExtractionCheck').click();
}
}
// The archive is set : go back to home page to start searching
if (params.rescan) {
document.getElementById('btnConfigure').click();
@ -2980,6 +2997,14 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
// (this only affects jQuery mode)
appstate.target = 'iframe';
// The archive is set : go back to home page to start searching
if (params.contentInjectionMode === 'serviceworker') {
var wikimediaZimLoaded = appstate.selectedArchive && /wikipedia|wikivoyage|mdwiki|wiktionary/i.test(appstate.selectedArchive._file.name);
if (!wikimediaZimLoaded) {
if (params.manipulateImages) document.getElementById('manipulateImagesCheck').click();
if (params.displayHiddenBlockElements) document.getElementById('displayHiddenBlockElementsCheck').click();
if (params.allowHTMLExtraction) document.getElementById('allowHTMLExtractionCheck').click();
}
}
params.storedFile = archive._file._files[0].name;
settingsStore.setItem("lastSelectedArchive", params.storedFile, Infinity);
settingsStore.setItem("lastSelectedArchivePath", archive._file._files[0].path ? archive._file._files[0].path : '', Infinity);
@ -3689,7 +3714,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
if (params.windowOpener) setTimeout(function () {
parseAnchorsJQuery(dirEntry);
}, 1500);
if (/manual|progressive/.test(params.imageDisplayMode)) images.prepareImagesServiceWorker(articleWindow);
if (params.manipulateImages && /manual|progressive/.test(params.imageDisplayMode)) images.prepareImagesServiceWorker(articleWindow);
if (params.allowHTMLExtraction && appstate.target === 'iframe') {
var determinedTheme = params.cssTheme == 'auto' ? cssUIThemeGetOrSet('auto') : params.cssTheme;
uiUtil.insertBreakoutLink(determinedTheme);
@ -4073,15 +4098,20 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
htmlArticle = htmlArticle.replace(/(<(audio|video)\b(?:[^<]|<(?!\/\2))+<\/\2>)/ig, function (p0) {
return /(?:src|data-kiwixurl)\s*=\s*["']/.test(p0) ? p0 : '';
});
} else if (wikiLang) {
} else if (wikiLang || params.manipulateImages) {
htmlArticle = htmlArticle.replace(params.regexpTagsWithZimUrl, function(match, blockStart, equals, quote, relAssetUrl, blockClose) {
newBlock = match;
// For Wikipedia archives, hyperlink the image to the File version
var assetZIMUrl = decodeURIComponent(relAssetUrl);
if (/^<img/i.test(blockStart) && !/usemap=/i.test(match)) {
newBlock = '<a href="https://' + (wikimediaZimFlavour !== 'mdwiki' ? wikiLang + '.' : '') + wikimediaZimFlavour
+ '.org/wiki/File:' + assetZIMUrl.replace(/^.+\/([^/]+?\.(?:jpe?g|svg|png|gif))[^/]*$/i, '$1')
+ '" target="_blank">' + newBlock + '</a>'
// Add the kiwix-display directive so that the SW sends a dummy image instead
if (params.manipulateImages && params.imageDisplay !== 'all' && /^<img/i.test(blockStart))
newBlock = newBlock.replace(relAssetUrl, relAssetUrl + '?kiwix-display');
if (wikiLang) {
// For Wikipedia archives, hyperlink the image to the File version
var assetZIMUrl = decodeURIComponent(relAssetUrl);
if (/^<img/i.test(blockStart) && !/usemap=/i.test(match)) {
newBlock = '<a href="https://' + (wikimediaZimFlavour !== 'mdwiki' ? wikiLang + '.' : '') + wikimediaZimFlavour
+ '.org/wiki/File:' + assetZIMUrl.replace(/^.+\/([^/]+?\.(?:jpe?g|svg|png|gif))[^/]*$/i, '$1')
+ '" target="_blank">' + newBlock + '</a>'
}
}
return newBlock;
});

View File

@ -84,7 +84,7 @@ params['cssTheme'] = getSetting('cssTheme') || 'light'; //Set default to 'auto',
params['cssUITheme'] = getSetting('cssUITheme') || 'light'; //Set default to 'auto', 'light' or 'dark' to use respective themes for UI'
params['resetDisplayOnResize'] = getSetting('resetDisplayOnResize') != null ? getSetting('resetDisplayOnResize') : false; // Default for the display reset feature that fixes bugs with secondary displays
params['imageDisplay'] = getSetting('imageDisplay') != null ? getSetting('imageDisplay') : true; //Set default to display images from Zim
params['manipulateImages'] = getSetting('manipulateImages') != null ? getSetting('manipulateImages') : false; //Makes dataURIs by default instead of BLOB URIs for images
params['manipulateImages'] = getSetting('manipulateImages') != null ? getSetting('manipulateImages') : true; //Makes dataURIs by default instead of BLOB URIs for images
params['linkToWikimediaImageFile'] = getSetting('linkToWikimediaImageFile') != null ? getSetting('linkToWikimediaImageFile') : false; //Links images to Wikimedia online version if ZIM archive is a Wikipedia archive
params['hideToolbars'] = getSetting('hideToolbars') != null ? getSetting('hideToolbars') : true; //Set default to true (hides both), 'top' (hides top only), or false (no hiding)
params['rememberLastPage'] = getSetting('rememberLastPage') != null ? getSetting('rememberLastPage') : true; //Set default option to remember the last visited page between sessions

View File

@ -82,12 +82,14 @@ define(['uiUtil'], function (uiUtil) {
return;
}
if (params.contentInjectionMode === 'serviceworker' && !(params.manipulateImages || params.allowHTMLExtraction)) {
image.addEventListener('load', function () {
var transition = function () {
image.style.transition = 'opacity 0.5s ease-in';
image.style.opacity = '1';
});
// Let's add kiwix-display to the end of the url so that the SW will ask for the image
image.src = imageUrl + '?kiwix-display';
removeEventListener('load', transition);
}
image.addEventListener('load', transition);
// Let's remove kiwix-display from the end of the url so that the SW will ask for the image
image.src = imageUrl.replace(/\?kiwix-display/, '');
// Timeout allows the loop to complete so we get an accurate busy count
setTimeout(function () {
checkBatch();

View File

@ -118,8 +118,6 @@ define([], function () {
/^\//.test(assetUrl) ? assetUrl.replace(/^\//, '/' + dirEntry.namespace + '/' + params.zimitPrefix + '/') : assetUrl;
// Deal with <meta http-equiv refresh...> directives
if (/<meta\s+http-equiv[^>]+refresh\b/i.test(newBlock)) dirEntry.zimitRedirect = assetUrl.replace(/^\//, '');
// Disable lazy loading of images even if manipulateImages is off
if (/<img\b/i.test(newBlock) && !params.manipulateImages) assetUrl = assetUrl + '?kiwix-display';
newBlock = newBlock.replace(relAssetUrl, indexRoot + assetUrl);
return newBlock;
});
@ -131,7 +129,6 @@ define([], function () {
srcsetArr[i] = /^(?:\s?https?:)?\/\//i.test(srcsetArr[i]) ? srcsetArr[i].replace(/^(?:\s?https?:)?\/\//i, '/' + dirEntry.namespace + '/') :
// For root-relative links, we need to add the zimitPrefix
/^\s?\//.test(srcsetArr[i]) ? srcsetArr[i].replace(/^\s?\//, '/' + dirEntry.namespace + '/' + params.zimitPrefix + '/') : srcsetArr[i];
srcsetArr[i] = srcsetArr[i].replace(/(\s|$)/, '?kiwix-display$1');
srcsetArr[i] = indexRoot + srcsetArr[i];
}
match = match.replace(srcset, srcsetArr.join(', '));
@ -190,9 +187,9 @@ define([], function () {
// Deal with absolute URLs
/^https?:\/\//i.test(assetUrl) ? assetUrl.replace(/^https?:\/\//i, dirEntry.namespace + '/') : assetUrl;
newBlock = params.contentInjectionMode === 'serviceworker' ?
// If asset is relative, then just add the kiwix-display directive
assetUrl === url ? newBlock.replace(url, assetUrl + '?kiwix-display') :
newBlock.replace(url, '/' + selectedArchive._file.name + '/' + assetUrl + '?kiwix-display') :
// If asset is relative, no transform needed
assetUrl === url ? newBlock :
newBlock.replace(url, '/' + selectedArchive._file.name + '/' + assetUrl) :
// For jQuery mode, no change needed for relative links
assetUrl === url ? newBlock :
newBlock.replace(url, '/' + assetUrl);