diff --git a/background.js b/background.js index 4a1cf0b..d55afe1 100644 --- a/background.js +++ b/background.js @@ -1,9 +1,11 @@ // Capture web requests chrome.webRequest.onBeforeSendHeaders.addListener( function (event) { - main(event); + if (event.documentLifecycle !== 'prerender') { + main(event); + } }, - { urls: ['*://*.fandom.com/*', '*://*.wiki.fextralife.com/*'], types: ['main_frame'] } + { urls: ['*://*.fandom.com/*', '*://*.wiki.fextralife.com/*'], types: ['main_frame', 'sub_frame'] } ); // Listen for user turning extension on or off, to update icon @@ -324,98 +326,104 @@ async function getData() { async function main(eventInfo) { // Store tab URL and remove any search parameters and section anchors - const url = new URL(eventInfo.url.replace(/(\?|#).*/i, '')); - - // Check for Fandom or Fextralife in hostname and quit early if not - if (eventInfo.documentLifecycle !== 'prerender') { - // Create object prototypes for getting and setting attributes - Object.prototype.get = function (prop) { - this[prop] = this[prop] || {}; - return this[prop]; - }; - Object.prototype.set = function (prop, value) { - this[prop] = value; - } - - // Check if tab is actually available - // This is mainly to prevent background processes from triggering an event - let sites = []; - - sites = await getData(); - - chrome.storage.local.get(function (localStorage) { - chrome.storage.sync.get(function (syncStorage) { - const storage = { ...syncStorage, ...localStorage }; - if ((storage.power ?? 'on') === 'on') { - // Check if site is in our list of wikis: - let matchingSites = sites.filter(el => url.href.replace(/^https?:\/\//, '').startsWith(el.origin_base_url)); - if (matchingSites.length > 0) { - // Select match with longest base URL - let closestMatch = ""; - matchingSites.forEach(site => { - if (site.origin_base_url.length > closestMatch.length) { - closestMatch = site.origin_base_url; - } - }); - let site = matchingSites.find(site => site.origin_base_url === closestMatch); - if (site) { - // Get user's settings for the wiki - let settings = storage.wikiSettings || {}; - let id = site['id']; - let siteSetting = settings[id] || storage.defaultWikiAction || 'alert'; - // Check if redirects are enabled for the site - if (siteSetting === 'redirect') { - // Get article name from the end of the URL; - // We can't just take the last part of the path due to subpages; - // Instead, we take everything after the wiki's base URL + content path - let article = url.href.split(site['origin_base_url'] + site['origin_content_path'])[1]; - // Set up URL to redirect user to based on wiki platform - if (article || (!article && !url.href.split(site['origin_base_url'] + '/')[1])) { - let newURL = ''; - if (article) { - let searchParams = ''; - switch (site['destination_platform']) { - case 'mediawiki': - searchParams = 'Special:Search/' + site['destination_content_prefix'] + article; - break; - case 'doku': - searchParams = 'start?do=search&q=' + article; - break; - } - newURL = 'https://' + site["destination_base_url"] + site["destination_content_path"] + searchParams; - } else { - newURL = 'https://' + site["destination_base_url"]; - } - - // Perform redirect - chrome.tabs.update(eventInfo.tabId, { url: newURL }); - - // Increase redirect count - chrome.storage.sync.set({ 'countRedirects': (storage.countRedirects ?? 0) + 1 }); - - // Notify if enabled - if ((storage.notifications ?? 'on') === 'on') { - // Notify that user is being redirected - let notifID = 'independent-wiki-redirector-notification-' + Math.floor(Math.random() * 1E16); - chrome.notifications.create(notifID, { - "type": "basic", - "iconUrl": 'images/logo-48.png', - "title": "You've been redirected!", - "message": "Indie Wiki Buddy has sent you from " + site['origin'] + " to " + site['destination'] - }); - // Self-clear notification after 6 seconds - setTimeout(function () { chrome.notifications.clear(notifID); }, 6000); - } - } - } else if ((storage.breezewiki ?? 'off') === 'on') { - redirectToBreezeWiki(storage, eventInfo, url); - } - } - } else if ((storage.breezewiki ?? 'off') === 'on') { - redirectToBreezeWiki(storage, eventInfo, url); - } - } - }); - }); + let url = ''; + if (eventInfo.type === 'main_frame') { + url = new URL(eventInfo.url.replace(/(\?|#).*/i, '')); + } else { + url = new URL(eventInfo.initiator); } + + // Create object prototypes for getting and setting attributes + Object.prototype.get = function (prop) { + this[prop] = this[prop] || {}; + return this[prop]; + }; + Object.prototype.set = function (prop, value) { + this[prop] = value; + } + + // Check if tab is actually available + // This is mainly to prevent background processes from triggering an event + let sites = []; + + sites = await getData(); + + chrome.storage.local.get(function (localStorage) { + chrome.storage.sync.get(function (syncStorage) { + const storage = { ...syncStorage, ...localStorage }; + if ((storage.power ?? 'on') === 'on') { + let crossLanguageSetting = storage.crossLanguage || 'off'; + // Check if site is in our list of wikis: + let matchingSites = []; + if (crossLanguageSetting === 'on') { + matchingSites = sites.filter(el => url.href.replace(/^https?:\/\//, '').startsWith(el.origin_base_url)); + } else { + matchingSites = sites.filter(el => url.href.replace(/^https?:\/\//, '').startsWith(el.origin_base_url + el.origin_content_path)); + } + if (matchingSites.length > 0) { + // Select match with longest base URL + let closestMatch = ""; + matchingSites.forEach(site => { + if (site.origin_base_url.length > closestMatch.length) { + closestMatch = site.origin_base_url; + } + }); + let site = matchingSites.find(site => site.origin_base_url === closestMatch); + if (site) { + // Get user's settings for the wiki + let settings = storage.wikiSettings || {}; + let id = site['id']; + let siteSetting = settings[id] || storage.defaultWikiAction || 'alert'; + // Check if redirects are enabled for the site + if (siteSetting === 'redirect') { + // Get article name from the end of the URL; + // We can't just take the last part of the path due to subpages; + // Instead, we take everything after the wiki's base URL + content path + let article = url.href.split(site['origin_base_url'] + site['origin_content_path'])[1]; + // Set up URL to redirect user to based on wiki platform + let newURL = ''; + if (article) { + let searchParams = ''; + switch (site['destination_platform']) { + case 'mediawiki': + searchParams = 'Special:Search/' + site['destination_content_prefix'] + article; + break; + case 'doku': + searchParams = 'start?do=search&q=' + article; + break; + } + newURL = 'https://' + site["destination_base_url"] + site["destination_content_path"] + searchParams; + } else { + newURL = 'https://' + site["destination_base_url"]; + } + + // Perform redirect + chrome.tabs.update(eventInfo.tabId, { url: newURL }); + + // Increase redirect count + chrome.storage.sync.set({ 'countRedirects': (storage.countRedirects ?? 0) + 1 }); + + // Notify if enabled + if ((storage.notifications ?? 'on') === 'on') { + // Notify that user is being redirected + let notifID = 'independent-wiki-redirector-notification-' + Math.floor(Math.random() * 1E16); + chrome.notifications.create(notifID, { + "type": "basic", + "iconUrl": 'images/logo-48.png', + "title": "You've been redirected!", + "message": "Indie Wiki Buddy has sent you from " + site['origin'] + " to " + site['destination'] + }); + // Self-clear notification after 6 seconds + setTimeout(function () { chrome.notifications.clear(notifID); }, 6000); + } + } else if ((storage.breezewiki ?? 'off') === 'on') { + redirectToBreezeWiki(storage, eventInfo, url); + } + } + } else if ((storage.breezewiki ?? 'off') === 'on') { + redirectToBreezeWiki(storage, eventInfo, url); + } + } + }); + }); } diff --git a/content-banners.js b/content-banners.js index 14c003f..f65acd4 100644 --- a/content-banners.js +++ b/content-banners.js @@ -42,7 +42,7 @@ async function getData() { return sites; } -function displayRedirectBanner(url, id, destination, storage) { +function displayRedirectBanner(origin, newUrl, id, destinationName, destinationLanguage, storage) { // Output CSS styleString = ` #indie-wiki-banner { @@ -184,12 +184,16 @@ function displayRedirectBanner(url, id, destination, storage) { var bannerText = document.createElement('span'); bannerText.classList.add('indie-wiki-banner-big-text'); banner.appendChild(bannerText); - bannerText.textContent = 'There is an independent wiki covering this topic!'; + if (destinationLanguage === 'EN' && origin.href.match(/fandom\.com\/[a-z]{2}\/wiki\//)) { + bannerText.textContent = 'There is an independent wiki covering this topic in English!'; + } else { + bannerText.textContent = 'There is an independent wiki covering this topic!'; + } var bannerWikiLink = document.createElement('a'); bannerWikiLink.classList.add('indie-wiki-banner-link'); bannerText.appendChild(bannerWikiLink); - bannerWikiLink.href = url; - bannerWikiLink.textContent = 'Visit ' + destination + ' →'; + bannerWikiLink.href = newUrl; + bannerWikiLink.textContent = 'Visit ' + destinationName + ' →'; // Function to insert banner into DOM before body element function addBannerToDOM() { @@ -237,11 +241,18 @@ function main() { } } getData().then(sites => { + let crossLanguageSetting = storage.crossLanguage || 'off'; // Check if site is in our list of wikis: - let matchingSites = sites.filter(el => String(origin).replace(/^https?:\/\//, '').startsWith(el.origin_base_url)); + // let matchingSites = sites.filter(el => String(origin).replace(/^https?:\/\//, '').startsWith(el.origin_base_url)); + let matchingSites = []; + if (crossLanguageSetting === 'on') { + matchingSites = sites.filter(el => String(origin).replace(/^https?:\/\//, '').startsWith(el.origin_base_url)); + } else { + matchingSites = sites.filter(el => String(origin).replace(/^https?:\/\//, '').startsWith(el.origin_base_url + el.origin_content_path)); + } if (matchingSites.length > 0) { // Select match with longest base URL - let closestMatch = ""; + let closestMatch = ''; matchingSites.forEach(site => { if (site.origin_base_url.length > closestMatch.length) { closestMatch = site.origin_base_url; @@ -250,46 +261,44 @@ function main() { let site = matchingSites.find(site => site.origin_base_url === closestMatch); if (site) { // Get user's settings for the wiki - let settings = storage.wikiSettings || {}; let id = site['id']; + let settings = storage.wikiSettings || {}; let siteSetting = settings[id] || storage.defaultWikiAction || 'alert'; // Notify if enabled for the wiki: if (siteSetting === 'alert') { // Get article name from the end of the URL; // We can't just take the last part of the path due to subpages; // Instead, we take everything after the wiki's base URL + content path: - let article = String(origin).split(site['origin_base_url'] + site['origin_content_path'])[1]; + let article = String(origin).split(site['origin_content_path'])[1]; // Set up URL to redirect user to based on wiki platform: - if (article || (!article && !url.href.split(site['origin_base_url'] + '/')[1])) { - let newURL = ''; - if (article) { - let searchParams = ''; - switch (site['destination_platform']) { - case 'mediawiki': - searchParams = 'Special:Search/' + site['destination_content_prefix'] + article; - break; - case 'doku': - searchParams = 'start?do=search&q=' + article; - break; - } - newURL = 'https://' + site["destination_base_url"] + site["destination_content_path"] + searchParams.replaceAll('+', '_'); - // We replace plus signs with underscores since Fextralife uses pluses instead of spaces/underscores - } else { - newURL = 'https://' + site["destination_base_url"]; + let newURL = ''; + if (article) { + let searchParams = ''; + switch (site['destination_platform']) { + case 'mediawiki': + searchParams = 'Special:Search/' + site['destination_content_prefix'] + article; + break; + case 'doku': + searchParams = 'start?do=search&q=' + article; + break; } - // When head elem is loaded, notify that another wiki is available - const docObserver = new MutationObserver(function (mutations, mutationInstance) { - const headElement = document.querySelector('head'); - if (headElement) { - displayRedirectBanner(newURL, site['id'], site['destination'], storage); - mutationInstance.disconnect(); - } - }); - docObserver.observe(document, { - childList: true, - subtree: true - }); + newURL = 'https://' + site["destination_base_url"] + site["destination_content_path"] + searchParams.replaceAll('+', '_'); + // We replace plus signs with underscores since Fextralife uses pluses instead of spaces/underscores + } else { + newURL = 'https://' + site["destination_base_url"]; } + // When head elem is loaded, notify that another wiki is available + const docObserver = new MutationObserver(function (mutations, mutationInstance) { + const headElement = document.querySelector('head'); + if (headElement) { + displayRedirectBanner(origin, newURL, site['id'], site['destination'], site['lang'], storage); + mutationInstance.disconnect(); + } + }); + docObserver.observe(document, { + childList: true, + subtree: true + }); } } } diff --git a/popup.html b/popup.html index 17c5359..45a362f 100644 --- a/popup.html +++ b/popup.html @@ -1,273 +1,280 @@ - - - - Indie Wiki Buddy - - + /* NOTIFICATIONS */ + #notificationBannerContainer { + background-color: #f8f3d6; + font-size: .9em; + line-height: 1.3em; + } - -