refactor(packages): migrate to yarn workspaces
24
.commitlintrc
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"extends": [
|
||||||
|
"@commitlint/config-conventional"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"scope-case": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"header-max-length": [
|
||||||
|
0,
|
||||||
|
"always",
|
||||||
|
110
|
||||||
|
],
|
||||||
|
"scope-enum": [
|
||||||
|
2,
|
||||||
|
"always",
|
||||||
|
[
|
||||||
|
"browser-extension",
|
||||||
|
"packages",
|
||||||
|
"report-service"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
6
.gitignore
vendored
@ -1,2 +1,6 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
release
|
.pnp.*
|
||||||
|
.yarn/*
|
||||||
|
!.yarn/releases
|
||||||
|
!.yarn/plugins
|
||||||
|
build
|
||||||
|
4
.husky/commit-msg
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
yarn commitlint --edit "$1"
|
4
.husky/pre-commit
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
yarn lint-staged
|
6
.lintstagedrc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"packages/**/*.{js,ts}": [
|
||||||
|
"prettier --loglevel=silent --write",
|
||||||
|
"yarn lint"
|
||||||
|
]
|
||||||
|
}
|
6
.prettierrc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "es5"
|
||||||
|
}
|
6
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
".commitlintrc": "json",
|
||||||
|
".lintstagedrc": "json",
|
||||||
|
},
|
||||||
|
}
|
33
.yarn/plugins/@yarnpkg/plugin-outdated.cjs
vendored
Normal file
28
.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
vendored
Normal file
785
.yarn/releases/yarn-3.2.0.cjs
vendored
Executable file
7
.yarnrc.yml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
plugins:
|
||||||
|
- path: .yarn/plugins/@yarnpkg/plugin-outdated.cjs
|
||||||
|
spec: "https://mskelton.dev/yarn-outdated/v2"
|
||||||
|
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
|
||||||
|
spec: "@yarnpkg/plugin-workspace-tools"
|
||||||
|
|
||||||
|
yarnPath: .yarn/releases/yarn-3.2.0.cjs
|
@ -2,46 +2,7 @@
|
|||||||
|
|
||||||
A browser extension that eats cookie consent dialogs.
|
A browser extension that eats cookie consent dialogs.
|
||||||
|
|
||||||
## Downloads
|
## Repositories
|
||||||
|
|
||||||
- [Chrome Web Store](https://chrome.google.com/webstore/detail/djcbfpkdhdkaflcigibkbpboflaplabg)
|
- [Browser extension](/packages/browser-extension/)
|
||||||
- [Firefox Add-ons](https://addons.mozilla.org/firefox/addon/cookie-dialog-monster/)
|
- [Report service](/packages/report-service/)
|
||||||
|
|
||||||
## Compatibility
|
|
||||||
|
|
||||||
- Google Chrome 51+.
|
|
||||||
- Microsoft Edge 15+.
|
|
||||||
- Mozilla Firefox 54+.
|
|
||||||
- Opera 38+.
|
|
||||||
|
|
||||||
## Installation (on Google Chrome)
|
|
||||||
|
|
||||||
1. Clone this repository.
|
|
||||||
2. Go to [chrome://extensions](chrome://extensions).
|
|
||||||
3. Enable **Developer mode** by clicking the toggle switch next to **Developer Mode**.
|
|
||||||
4. Then, click the **LOAD UNPACKED** button and select the cloned folder.
|
|
||||||
5. That's all, you have a development build of this extension.
|
|
||||||
|
|
||||||
## Installation (on Mozilla Firefox)
|
|
||||||
|
|
||||||
1. Clone this repository.
|
|
||||||
2. Go to [about:debugging](about:debugging).
|
|
||||||
3. Enter **This Firefox** section.
|
|
||||||
4. Then, click the **LOAD TEMPORARY ADD-ON** button and select any file inside the cloned folder.
|
|
||||||
5. That's all, you have a development build of this extension.
|
|
||||||
|
|
||||||
## Installation (on Microsoft Edge)
|
|
||||||
|
|
||||||
1. Clone this repository.
|
|
||||||
2. Go to [edge://extensions](edge://extensions).
|
|
||||||
3. Enable **Developer mode** by clicking the toggle switch next to **Developer Mode**.
|
|
||||||
4. Then, click the **LOAD UNPACKED** button and select the cloned folder.
|
|
||||||
5. That's all, you have a development build of this extension.
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
[MIT](https://choosealicense.com/licenses/mit/)
|
|
||||||
|
21
package.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "cookie-dialog-monster",
|
||||||
|
"private": true,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"build": "yarn workspaces foreach -p run build",
|
||||||
|
"lint": "yarn workspaces foreach -p run lint",
|
||||||
|
"prepare": "husky install"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@commitlint/cli": "^16.2.4",
|
||||||
|
"@commitlint/config-conventional": "^16.2.4",
|
||||||
|
"husky": "^7.0.4",
|
||||||
|
"lint-staged": "^12.4.1",
|
||||||
|
"prettier": "^2.6.2"
|
||||||
|
},
|
||||||
|
"workspaces": [
|
||||||
|
"packages/*"
|
||||||
|
],
|
||||||
|
"packageManager": "yarn@3.2.0"
|
||||||
|
}
|
12
packages/browser-extension/.eslintrc
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"es6": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"plugin:prettier/recommended"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": "latest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
45
packages/browser-extension/docs/README.md
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Cookie Monster Dialog Browser Extension
|
||||||
|
|
||||||
|
## Downloads
|
||||||
|
|
||||||
|
- [Chrome Web Store](https://chrome.google.com/webstore/detail/djcbfpkdhdkaflcigibkbpboflaplabg)
|
||||||
|
- [Firefox Add-ons](https://addons.mozilla.org/firefox/addon/cookie-dialog-monster/)
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
- Google Chrome 51+.
|
||||||
|
- Microsoft Edge 15+.
|
||||||
|
- Mozilla Firefox 54+.
|
||||||
|
- Opera 38+.
|
||||||
|
|
||||||
|
## Installation (on Google Chrome)
|
||||||
|
|
||||||
|
1. Clone this repository.
|
||||||
|
2. Go to [chrome://extensions](chrome://extensions).
|
||||||
|
3. Enable **Developer mode** by clicking the toggle switch next to **Developer Mode**.
|
||||||
|
4. Then, click the **LOAD UNPACKED** button and select the cloned folder.
|
||||||
|
5. That's all, you have a development build of this extension.
|
||||||
|
|
||||||
|
## Installation (on Mozilla Firefox)
|
||||||
|
|
||||||
|
1. Clone this repository.
|
||||||
|
2. Go to [about:debugging](about:debugging).
|
||||||
|
3. Enter **This Firefox** section.
|
||||||
|
4. Then, click the **LOAD TEMPORARY ADD-ON** button and select any file inside the cloned folder.
|
||||||
|
5. That's all, you have a development build of this extension.
|
||||||
|
|
||||||
|
## Installation (on Microsoft Edge)
|
||||||
|
|
||||||
|
1. Clone this repository.
|
||||||
|
2. Go to [edge://extensions](edge://extensions).
|
||||||
|
3. Enable **Developer mode** by clicking the toggle switch next to **Developer Mode**.
|
||||||
|
4. Then, click the **LOAD UNPACKED** button and select the cloned folder.
|
||||||
|
5. That's all, you have a development build of this extension.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](https://choosealicense.com/licenses/mit/)
|
18
packages/browser-extension/package.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "browser-extension",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"build": "exit 1",
|
||||||
|
"lint": "eslint src/**/*.js --fix"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^8.8.0",
|
||||||
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
"eslint-plugin-prettier": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "16.x"
|
||||||
|
},
|
||||||
|
"packageManager": "yarn@3.2.0",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 1016 B After Width: | Height: | Size: 1016 B |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
@ -2,7 +2,7 @@
|
|||||||
* @description Context menu identifier
|
* @description Context menu identifier
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const contextMenuId = "CDM_MENU";
|
const contextMenuId = 'CDM_MENU';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Cache initial state
|
* @description Cache initial state
|
||||||
@ -18,7 +18,7 @@ const initial = {
|
|||||||
* @param {object} [cache]
|
* @param {object} [cache]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const check = (cache) => typeof cache.enabled === "boolean";
|
const check = (cache) => typeof cache.enabled === 'boolean';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Disables icon
|
* @description Disables icon
|
||||||
@ -27,7 +27,7 @@ const check = (cache) => typeof cache.enabled === "boolean";
|
|||||||
|
|
||||||
const disableIcon = (tabId) => {
|
const disableIcon = (tabId) => {
|
||||||
chrome.browserAction.setIcon({
|
chrome.browserAction.setIcon({
|
||||||
path: "assets/icons/disabled.png",
|
path: 'assets/icons/disabled.png',
|
||||||
tabId,
|
tabId,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -39,7 +39,7 @@ const disableIcon = (tabId) => {
|
|||||||
|
|
||||||
const disablePopup = (tabId) => {
|
const disablePopup = (tabId) => {
|
||||||
chrome.browserAction.setPopup({
|
chrome.browserAction.setPopup({
|
||||||
popup: "",
|
popup: '',
|
||||||
tabId,
|
tabId,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -51,7 +51,7 @@ const disablePopup = (tabId) => {
|
|||||||
|
|
||||||
const enableIcon = (tabId) => {
|
const enableIcon = (tabId) => {
|
||||||
chrome.browserAction.setIcon({
|
chrome.browserAction.setIcon({
|
||||||
path: "assets/icons/enabled.png",
|
path: 'assets/icons/enabled.png',
|
||||||
tabId,
|
tabId,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -63,7 +63,7 @@ const enableIcon = (tabId) => {
|
|||||||
|
|
||||||
const enablePopup = (tabId) => {
|
const enablePopup = (tabId) => {
|
||||||
chrome.browserAction.setPopup({
|
chrome.browserAction.setPopup({
|
||||||
popup: "popup.html",
|
popup: 'popup.html',
|
||||||
tabId,
|
tabId,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -100,13 +100,13 @@ const getCache = (hostname, callback) => {
|
|||||||
const getClasses = async (callback) => {
|
const getClasses = async (callback) => {
|
||||||
try {
|
try {
|
||||||
const url =
|
const url =
|
||||||
"https://raw.githubusercontent.com/wanhose/cookie-dialog-monster/master/data/classes.txt";
|
'https://raw.githubusercontent.com/wanhose/cookie-dialog-monster/master/data/classes.txt';
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
const data = await response.text();
|
const data = await response.text();
|
||||||
|
|
||||||
if (response.status !== 200) throw new Error();
|
if (response.status !== 200) throw new Error();
|
||||||
|
|
||||||
callback({ classes: data.split("\n") });
|
callback({ classes: data.split('\n') });
|
||||||
} catch {
|
} catch {
|
||||||
callback({ classes: [] });
|
callback({ classes: [] });
|
||||||
}
|
}
|
||||||
@ -122,13 +122,13 @@ const getClasses = async (callback) => {
|
|||||||
const getFixes = async (callback) => {
|
const getFixes = async (callback) => {
|
||||||
try {
|
try {
|
||||||
const url =
|
const url =
|
||||||
"https://raw.githubusercontent.com/wanhose/cookie-dialog-monster/master/data/fixes.txt";
|
'https://raw.githubusercontent.com/wanhose/cookie-dialog-monster/master/data/fixes.txt';
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
const data = await response.text();
|
const data = await response.text();
|
||||||
|
|
||||||
if (response.status !== 200) throw new Error();
|
if (response.status !== 200) throw new Error();
|
||||||
|
|
||||||
callback({ fixes: data.split("\n") });
|
callback({ fixes: data.split('\n') });
|
||||||
} catch {
|
} catch {
|
||||||
callback({ fixes: [] });
|
callback({ fixes: [] });
|
||||||
}
|
}
|
||||||
@ -144,13 +144,13 @@ const getFixes = async (callback) => {
|
|||||||
const getSelectors = async (callback) => {
|
const getSelectors = async (callback) => {
|
||||||
try {
|
try {
|
||||||
const url =
|
const url =
|
||||||
"https://raw.githubusercontent.com/wanhose/cookie-dialog-monster/master/data/elements.txt";
|
'https://raw.githubusercontent.com/wanhose/cookie-dialog-monster/master/data/elements.txt';
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
const data = await response.text();
|
const data = await response.text();
|
||||||
|
|
||||||
if (response.status !== 200) throw new Error();
|
if (response.status !== 200) throw new Error();
|
||||||
|
|
||||||
callback({ selectors: data.split("\n") });
|
callback({ selectors: data.split('\n') });
|
||||||
} catch {
|
} catch {
|
||||||
callback({ selectors: [] });
|
callback({ selectors: [] });
|
||||||
}
|
}
|
||||||
@ -182,16 +182,16 @@ const report = () => {
|
|||||||
const version = chrome.runtime.getManifest().version;
|
const version = chrome.runtime.getManifest().version;
|
||||||
|
|
||||||
if (tab) {
|
if (tab) {
|
||||||
fetch("https://cdm-report-service.herokuapp.com/rest/v1/report/", {
|
fetch('https://cdm-report-service.herokuapp.com/rest/v1/report/', {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
text: `There's a problem with ${tab.url} using ${userAgent} in CDM ${version}`,
|
text: `There's a problem with ${tab.url} using ${userAgent} in CDM ${version}`,
|
||||||
to: "wanhose.development@gmail.com",
|
to: 'wanhose.development@gmail.com',
|
||||||
subject: "Cookie Dialog Monster Report",
|
subject: 'Cookie Dialog Monster Report',
|
||||||
}),
|
}),
|
||||||
headers: {
|
headers: {
|
||||||
"Content-type": "application/json",
|
'Content-type': 'application/json',
|
||||||
},
|
},
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -210,7 +210,7 @@ const updateCache = (hostname, state) => {
|
|||||||
chrome.storage.local.set({
|
chrome.storage.local.set({
|
||||||
[hostname]: {
|
[hostname]: {
|
||||||
enabled:
|
enabled:
|
||||||
typeof state.enabled === "undefined"
|
typeof state.enabled === 'undefined'
|
||||||
? current.enabled
|
? current.enabled
|
||||||
: state.enabled,
|
: state.enabled,
|
||||||
},
|
},
|
||||||
@ -227,34 +227,34 @@ chrome.runtime.onMessage.addListener((request, sender, callback) => {
|
|||||||
let tabId = sender.tab ? sender.tab.id : undefined;
|
let tabId = sender.tab ? sender.tab.id : undefined;
|
||||||
|
|
||||||
switch (request.type) {
|
switch (request.type) {
|
||||||
case "DISABLE_ICON":
|
case 'DISABLE_ICON':
|
||||||
if (hasPermission && tabId) disableIcon(tabId);
|
if (hasPermission && tabId) disableIcon(tabId);
|
||||||
break;
|
break;
|
||||||
case "DISABLE_POPUP":
|
case 'DISABLE_POPUP':
|
||||||
if (hasPermission && tabId) disablePopup(tabId);
|
if (hasPermission && tabId) disablePopup(tabId);
|
||||||
break;
|
break;
|
||||||
case "ENABLE_ICON":
|
case 'ENABLE_ICON':
|
||||||
if (hasPermission && tabId) enableIcon(tabId);
|
if (hasPermission && tabId) enableIcon(tabId);
|
||||||
break;
|
break;
|
||||||
case "ENABLE_POPUP":
|
case 'ENABLE_POPUP':
|
||||||
if (hasPermission && tabId) enablePopup(tabId);
|
if (hasPermission && tabId) enablePopup(tabId);
|
||||||
break;
|
break;
|
||||||
case "GET_CACHE":
|
case 'GET_CACHE':
|
||||||
getCache(request.hostname, callback);
|
getCache(request.hostname, callback);
|
||||||
break;
|
break;
|
||||||
case "GET_CLASSES":
|
case 'GET_CLASSES':
|
||||||
getClasses(callback);
|
getClasses(callback);
|
||||||
break;
|
break;
|
||||||
case "GET_FIXES":
|
case 'GET_FIXES':
|
||||||
getFixes(callback);
|
getFixes(callback);
|
||||||
break;
|
break;
|
||||||
case "GET_SELECTORS":
|
case 'GET_SELECTORS':
|
||||||
getSelectors(callback);
|
getSelectors(callback);
|
||||||
break;
|
break;
|
||||||
case "GET_TAB":
|
case 'GET_TAB':
|
||||||
getTab(callback);
|
getTab(callback);
|
||||||
break;
|
break;
|
||||||
case "UPDATE_CACHE":
|
case 'UPDATE_CACHE':
|
||||||
updateCache(request.hostname, request.state);
|
updateCache(request.hostname, request.state);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -269,9 +269,9 @@ chrome.runtime.onMessage.addListener((request, sender, callback) => {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
chrome.contextMenus.create({
|
chrome.contextMenus.create({
|
||||||
contexts: ["all"],
|
contexts: ['all'],
|
||||||
id: contextMenuId,
|
id: contextMenuId,
|
||||||
title: chrome.i18n.getMessage("contextMenuText"),
|
title: chrome.i18n.getMessage('contextMenuText'),
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
@ -30,7 +30,7 @@ const hostname = document.location.hostname;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const isPreview =
|
const isPreview =
|
||||||
hostname.startsWith("consent.") || hostname.startsWith("myprivacy.");
|
hostname.startsWith('consent.') || hostname.startsWith('myprivacy.');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Options provided to observer
|
* @description Options provided to observer
|
||||||
@ -59,8 +59,8 @@ const target = document.body || document.documentElement;
|
|||||||
const check = (node) =>
|
const check = (node) =>
|
||||||
node instanceof HTMLElement &&
|
node instanceof HTMLElement &&
|
||||||
node.parentElement &&
|
node.parentElement &&
|
||||||
!["BODY", "HTML"].includes(node.tagName) &&
|
!['BODY', 'HTML'].includes(node.tagName) &&
|
||||||
!(node.id && ["APP", "ROOT"].includes(node.id.toUpperCase?.()));
|
!(node.id && ['APP', 'ROOT'].includes(node.id.toUpperCase?.()));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Cleans DOM
|
* @description Cleans DOM
|
||||||
@ -69,7 +69,7 @@ const check = (node) =>
|
|||||||
const clean = () => {
|
const clean = () => {
|
||||||
if (selectors.length) {
|
if (selectors.length) {
|
||||||
const nodes = Array.from(document.querySelectorAll(selectors));
|
const nodes = Array.from(document.querySelectorAll(selectors));
|
||||||
nodes.filter(check).forEach((node) => (node.outerHTML = ""));
|
nodes.filter(check).forEach((node) => (node.outerHTML = ''));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -82,30 +82,30 @@ const fix = () => {
|
|||||||
const html = document.documentElement;
|
const html = document.documentElement;
|
||||||
|
|
||||||
body?.classList.remove(...classes);
|
body?.classList.remove(...classes);
|
||||||
body?.style.setProperty("position", "initial", "important");
|
body?.style.setProperty('position', 'initial', 'important');
|
||||||
body?.style.setProperty("overflow-y", "initial", "important");
|
body?.style.setProperty('overflow-y', 'initial', 'important');
|
||||||
html?.classList.remove(...classes);
|
html?.classList.remove(...classes);
|
||||||
html?.style.setProperty("position", "initial", "important");
|
html?.style.setProperty('position', 'initial', 'important');
|
||||||
html?.style.setProperty("overflow-y", "initial", "important");
|
html?.style.setProperty('overflow-y', 'initial', 'important');
|
||||||
|
|
||||||
fixes.forEach((fix) => {
|
fixes.forEach((fix) => {
|
||||||
const [match, selector, action, property] = fix.split("##");
|
const [match, selector, action, property] = fix.split('##');
|
||||||
|
|
||||||
if (hostname.includes(match)) {
|
if (hostname.includes(match)) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case "click": {
|
case 'click': {
|
||||||
const node = document.querySelector(selector);
|
const node = document.querySelector(selector);
|
||||||
node?.click();
|
node?.click();
|
||||||
}
|
}
|
||||||
case "remove": {
|
case 'remove': {
|
||||||
const node = document.querySelector(selector);
|
const node = document.querySelector(selector);
|
||||||
node?.style?.removeProperty(property);
|
node?.style?.removeProperty(property);
|
||||||
}
|
}
|
||||||
case "reset": {
|
case 'reset': {
|
||||||
const node = document.querySelector(selector);
|
const node = document.querySelector(selector);
|
||||||
node?.style?.setProperty(property, "initial", "important");
|
node?.style?.setProperty(property, 'initial', 'important');
|
||||||
}
|
}
|
||||||
case "resetAll": {
|
case 'resetAll': {
|
||||||
const nodes = document.querySelectorAll(selector);
|
const nodes = document.querySelectorAll(selector);
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
nodes.forEach((node) => node?.style?.setProperty(property, "initial", "important"));
|
nodes.forEach((node) => node?.style?.setProperty(property, "initial", "important"));
|
||||||
@ -126,7 +126,7 @@ const observer = new MutationObserver((mutations, instance) => {
|
|||||||
for (const node of mutation.addedNodes) {
|
for (const node of mutation.addedNodes) {
|
||||||
const valid = check(node);
|
const valid = check(node);
|
||||||
|
|
||||||
if (valid && node.matches(selectors)) node.outerHTML = "";
|
if (valid && node.matches(selectors)) node.outerHTML = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ const observer = new MutationObserver((mutations, instance) => {
|
|||||||
|
|
||||||
const queryClasses = () =>
|
const queryClasses = () =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
dispatch({ type: "GET_CLASSES" }, null, resolve);
|
dispatch({ type: 'GET_CLASSES' }, null, resolve);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -151,7 +151,7 @@ const queryClasses = () =>
|
|||||||
|
|
||||||
const queryFixes = () =>
|
const queryFixes = () =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
dispatch({ type: "GET_FIXES" }, null, resolve);
|
dispatch({ type: 'GET_FIXES' }, null, resolve);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -161,7 +161,7 @@ const queryFixes = () =>
|
|||||||
|
|
||||||
const querySelectors = () =>
|
const querySelectors = () =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
dispatch({ type: "GET_SELECTORS" }, null, resolve);
|
dispatch({ type: 'GET_SELECTORS' }, null, resolve);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -169,9 +169,9 @@ const querySelectors = () =>
|
|||||||
* @listens document#readystatechange
|
* @listens document#readystatechange
|
||||||
*/
|
*/
|
||||||
|
|
||||||
document.addEventListener("readystatechange", () => {
|
document.addEventListener('readystatechange', () => {
|
||||||
dispatch({ hostname, type: "GET_CACHE" }, null, async ({ enabled }) => {
|
dispatch({ hostname, type: 'GET_CACHE' }, null, async ({ enabled }) => {
|
||||||
if (document.readyState === "complete" && enabled && !isPreview) {
|
if (document.readyState === 'complete' && enabled && !isPreview) {
|
||||||
fix();
|
fix();
|
||||||
clean();
|
clean();
|
||||||
setTimeout(clean, 2000);
|
setTimeout(clean, 2000);
|
||||||
@ -184,14 +184,14 @@ document.addEventListener("readystatechange", () => {
|
|||||||
* @listens window#unload
|
* @listens window#unload
|
||||||
*/
|
*/
|
||||||
|
|
||||||
window.addEventListener("unload", () => {});
|
window.addEventListener('unload', () => {});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Setups everything and starts to observe if enabled
|
* @description Setups everything and starts to observe if enabled
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dispatch({ hostname, type: "GET_CACHE" }, null, async ({ enabled }) => {
|
dispatch({ hostname, type: 'GET_CACHE' }, null, async ({ enabled }) => {
|
||||||
dispatch({ type: "ENABLE_POPUP" });
|
dispatch({ type: 'ENABLE_POPUP' });
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
const promises = [queryClasses(), queryFixes(), querySelectors()];
|
const promises = [queryClasses(), queryFixes(), querySelectors()];
|
||||||
@ -201,6 +201,6 @@ dispatch({ hostname, type: "GET_CACHE" }, null, async ({ enabled }) => {
|
|||||||
fixes = results[1]?.fixes ?? [];
|
fixes = results[1]?.fixes ?? [];
|
||||||
selectors = results[2]?.selectors ?? [];
|
selectors = results[2]?.selectors ?? [];
|
||||||
observer.observe(target, options);
|
observer.observe(target, options);
|
||||||
dispatch({ type: "ENABLE_ICON" });
|
dispatch({ type: 'ENABLE_ICON' });
|
||||||
}
|
}
|
||||||
});
|
});
|
139
packages/browser-extension/src/scripts/popup.js
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/**
|
||||||
|
* @constant chromeUrl
|
||||||
|
* @description Chrome Web Store link
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const chromeUrl =
|
||||||
|
'https://chrome.google.com/webstore/detail/djcbfpkdhdkaflcigibkbpboflaplabg';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constant dispatch
|
||||||
|
* @description Shortcut to send messages to background script
|
||||||
|
* @type {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const dispatch = chrome.runtime.sendMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constant firefoxUrl
|
||||||
|
* @description Firefox Add-ons link
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const firefoxUrl =
|
||||||
|
'https://addons.mozilla.org/es/firefox/addon/cookie-dialog-monster/';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constant isChromium
|
||||||
|
* @description Is current browser an instance of Chromium?
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const isChromium = chrome.runtime.getURL('').startsWith('chrome-extension://');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Disables or enables extension on current page
|
||||||
|
*/
|
||||||
|
|
||||||
|
const handlePowerChange = () => {
|
||||||
|
dispatch({ type: 'GET_TAB' }, null, ({ hostname, id }) => {
|
||||||
|
dispatch({ hostname, type: 'GET_CACHE' }, null, ({ enabled }) => {
|
||||||
|
const power = document.getElementById('power');
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
hostname,
|
||||||
|
state: { enabled: !enabled },
|
||||||
|
type: 'UPDATE_CACHE',
|
||||||
|
});
|
||||||
|
dispatch({
|
||||||
|
type: !enabled === true ? 'ENABLE_ICON' : 'DISABLE_ICON',
|
||||||
|
});
|
||||||
|
if (!enabled === false) power.removeAttribute('checked');
|
||||||
|
if (!enabled === true) power.setAttribute('checked', 'checked');
|
||||||
|
chrome.tabs.reload(id, { bypassCache: true });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Reload current page
|
||||||
|
*/
|
||||||
|
|
||||||
|
const handleReload = () => {
|
||||||
|
dispatch({ type: 'GET_TAB' }, null, ({ id }) => {
|
||||||
|
chrome.tabs.reload(id, { bypassCache: true });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Shows negative or positive messages
|
||||||
|
* @param {MouseEvent} event
|
||||||
|
*/
|
||||||
|
|
||||||
|
const handleRate = (event) => {
|
||||||
|
const negative = document.getElementById('negative');
|
||||||
|
const positive = document.getElementById('positive');
|
||||||
|
|
||||||
|
switch (event.currentTarget.id) {
|
||||||
|
case 'unlike':
|
||||||
|
positive.setAttribute('hidden', 'true');
|
||||||
|
negative.removeAttribute('hidden');
|
||||||
|
break;
|
||||||
|
case 'like':
|
||||||
|
negative.setAttribute('hidden', 'true');
|
||||||
|
positive.removeAttribute('hidden');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Setup stars handlers and result message links
|
||||||
|
*/
|
||||||
|
|
||||||
|
const handleContentLoaded = () => {
|
||||||
|
dispatch({ type: 'GET_TAB' }, null, ({ hostname }) => {
|
||||||
|
dispatch({ hostname, type: 'GET_CACHE' }, null, ({ enabled }) => {
|
||||||
|
translate();
|
||||||
|
|
||||||
|
const host = document.getElementById('host');
|
||||||
|
const like = document.getElementById('like');
|
||||||
|
const power = document.getElementById('power');
|
||||||
|
const reload = document.getElementById('reload');
|
||||||
|
const store = document.getElementById('store');
|
||||||
|
const unlike = document.getElementById('unlike');
|
||||||
|
|
||||||
|
like.addEventListener('click', handleRate);
|
||||||
|
power.addEventListener('change', handlePowerChange);
|
||||||
|
reload.addEventListener('click', handleReload);
|
||||||
|
store.setAttribute('href', isChromium ? chromeUrl : firefoxUrl);
|
||||||
|
unlike.addEventListener('click', handleRate);
|
||||||
|
if (location) host.innerText = hostname.replace('www.', '');
|
||||||
|
if (!enabled) power.removeAttribute('checked');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Applies translations to tags with i18n data attribute
|
||||||
|
*/
|
||||||
|
|
||||||
|
const translate = () => {
|
||||||
|
const nodes = document.querySelectorAll('[data-i18n]');
|
||||||
|
|
||||||
|
for (let i = nodes.length; i--; ) {
|
||||||
|
const node = nodes[i];
|
||||||
|
const { i18n } = node.dataset;
|
||||||
|
|
||||||
|
node.innerHTML = chrome.i18n.getMessage(i18n);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Listen to document ready
|
||||||
|
* @listens document#ready
|
||||||
|
*/
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', handleContentLoaded);
|
3
packages/report-service/.env
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
CHROME_EXTENSION_ID=?
|
||||||
|
MAIL_PASS=?
|
||||||
|
MAIL_USER=?
|
19
packages/report-service/.eslintrc
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"es6": true,
|
||||||
|
"jest": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"plugin:prettier/recommended"
|
||||||
|
],
|
||||||
|
"globals": {
|
||||||
|
"Atomics": "readonly",
|
||||||
|
"SharedArrayBuffer": "readonly"
|
||||||
|
},
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": "latest"
|
||||||
|
}
|
||||||
|
}
|
21
packages/report-service/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License Copyright (c) 2020 Juan José Vílchez Naranjo
|
||||||
|
|
||||||
|
Permission is hereby
|
||||||
|
granted, free of charge, to any person obtaining a copy of this software and
|
||||||
|
associated documentation files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to the
|
||||||
|
following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice
|
||||||
|
(including the next paragraph) shall be included in all copies or substantial
|
||||||
|
portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||||
|
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
||||||
|
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
9
packages/report-service/docs/README.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Cookie Monster Dialog Report Service
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](https://choosealicense.com/licenses/mit/)
|
6
packages/report-service/nodemon.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"exec": "ts-node -r tsconfig-paths/register ./src/index.ts",
|
||||||
|
"ext": ".ts",
|
||||||
|
"ignore": [],
|
||||||
|
"watch": ["src"]
|
||||||
|
}
|
38
packages/report-service/package.json
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "report-service",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"build": "rimraf build && tsc",
|
||||||
|
"dev": "nodemon",
|
||||||
|
"lint": "eslint src/**/*.ts --fix",
|
||||||
|
"setup": "rimraf .husky && husky install && husky add .husky/pre-commit \"yarn lint-staged\" && husky add .husky/commit-msg 'npx --no -- commitlint --edit \"$1\"'",
|
||||||
|
"start": "NODE_PATH=build node build/index.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"dotenv": "^16.0.0",
|
||||||
|
"fastify": "^3.27.1",
|
||||||
|
"fastify-cors": "^6.0.2",
|
||||||
|
"fastify-rate-limit": "^5.7.0",
|
||||||
|
"nodemailer": "^6.7.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tsconfig/node16": "^1.0.2",
|
||||||
|
"@types/node": "^17.0.16",
|
||||||
|
"@types/nodemailer": "^6.4.4",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.11.0",
|
||||||
|
"@typescript-eslint/parser": "^5.11.0",
|
||||||
|
"eslint": "^8.8.0",
|
||||||
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
|
"nodemon": "^2.0.15",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"ts-node": "^10.5.0",
|
||||||
|
"tsconfig-paths": "^3.12.0",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "16.x"
|
||||||
|
},
|
||||||
|
"packageManager": "yarn@3.2.0",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
37
packages/report-service/src/index.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import fastify from 'fastify';
|
||||||
|
import cors from 'fastify-cors';
|
||||||
|
import rateLimit from 'fastify-rate-limit';
|
||||||
|
import v1ReportRoutes from 'routes/v1/report';
|
||||||
|
import environment from 'services/environment';
|
||||||
|
|
||||||
|
const server = fastify({ logger: true });
|
||||||
|
|
||||||
|
server.register(cors, {
|
||||||
|
origin: (origin, callback) => {
|
||||||
|
const moz =
|
||||||
|
/moz-extension:\/\/[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}/g;
|
||||||
|
|
||||||
|
switch (true) {
|
||||||
|
case environment.extension.chrome === origin:
|
||||||
|
case moz.test(origin):
|
||||||
|
callback(null, true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
callback(new Error('Not allowed'), false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
server.register(rateLimit, { max: 1, timeWindow: 30000 });
|
||||||
|
|
||||||
|
server.register(v1ReportRoutes, { prefix: '/rest/v1' });
|
||||||
|
|
||||||
|
server.listen(environment.port, '0.0.0.0', (error, address) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Server listening at ${address}`);
|
||||||
|
});
|
45
packages/report-service/src/routes/v1/report.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { FastifyInstance, RouteShorthandOptions } from 'fastify';
|
||||||
|
import { sendMail } from 'services/mailing';
|
||||||
|
|
||||||
|
type PostReportBody = {
|
||||||
|
subject: string;
|
||||||
|
text: string;
|
||||||
|
to: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default (
|
||||||
|
server: FastifyInstance,
|
||||||
|
options: RouteShorthandOptions,
|
||||||
|
done: () => void
|
||||||
|
) => {
|
||||||
|
server.post<{ Body: PostReportBody }>(
|
||||||
|
'/report/',
|
||||||
|
{
|
||||||
|
schema: {
|
||||||
|
body: {
|
||||||
|
properties: {
|
||||||
|
subject: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['subject', 'text', 'to'],
|
||||||
|
type: 'object',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async (request, reply) => {
|
||||||
|
const { subject, text, to } = request.body;
|
||||||
|
|
||||||
|
sendMail({ text, to, subject });
|
||||||
|
reply.send({ success: true });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
done();
|
||||||
|
};
|
14
packages/report-service/src/services/environment.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import dotenv from 'dotenv';
|
||||||
|
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
|
export default {
|
||||||
|
extension: {
|
||||||
|
chrome: process.env.CHROME_EXTENSION_ID ?? '',
|
||||||
|
},
|
||||||
|
mail: {
|
||||||
|
pass: process.env.MAIL_PASS ?? '',
|
||||||
|
user: process.env.MAIL_USER ?? '',
|
||||||
|
},
|
||||||
|
port: process.env.PORT ?? 8080,
|
||||||
|
};
|
12
packages/report-service/src/services/mailing.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import nodemailer, { SendMailOptions } from 'nodemailer';
|
||||||
|
import environment from './environment';
|
||||||
|
|
||||||
|
const mailing = nodemailer.createTransport({
|
||||||
|
auth: { pass: environment.mail.pass, user: environment.mail.user },
|
||||||
|
host: 'smtp.zoho.eu',
|
||||||
|
port: 465,
|
||||||
|
secure: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const sendMail = (options: SendMailOptions) =>
|
||||||
|
mailing.sendMail({ ...options, from: environment.mail.user }, () => null);
|
12
packages/report-service/tsconfig.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "src",
|
||||||
|
"outDir": "build",
|
||||||
|
"rootDir": "src"
|
||||||
|
},
|
||||||
|
"extends": "@tsconfig/node16/tsconfig.json",
|
||||||
|
"include": ["src/**/*.ts"],
|
||||||
|
"ts-node": {
|
||||||
|
"files": true
|
||||||
|
}
|
||||||
|
}
|
139
scripts/popup.js
@ -1,139 +0,0 @@
|
|||||||
/**
|
|
||||||
* @constant chromeUrl
|
|
||||||
* @description Chrome Web Store link
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
|
|
||||||
const chromeUrl =
|
|
||||||
"https://chrome.google.com/webstore/detail/djcbfpkdhdkaflcigibkbpboflaplabg";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @constant dispatch
|
|
||||||
* @description Shortcut to send messages to background script
|
|
||||||
* @type {void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
const dispatch = chrome.runtime.sendMessage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @constant firefoxUrl
|
|
||||||
* @description Firefox Add-ons link
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
|
|
||||||
const firefoxUrl =
|
|
||||||
"https://addons.mozilla.org/es/firefox/addon/cookie-dialog-monster/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @constant isChromium
|
|
||||||
* @description Is current browser an instance of Chromium?
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
const isChromium = chrome.runtime.getURL("").startsWith("chrome-extension://");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Disables or enables extension on current page
|
|
||||||
*/
|
|
||||||
|
|
||||||
const handlePowerChange = () => {
|
|
||||||
dispatch({ type: "GET_TAB" }, null, ({ hostname, id }) => {
|
|
||||||
dispatch({ hostname, type: "GET_CACHE" }, null, ({ enabled }) => {
|
|
||||||
const power = document.getElementById("power");
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
hostname,
|
|
||||||
state: { enabled: !enabled },
|
|
||||||
type: "UPDATE_CACHE",
|
|
||||||
});
|
|
||||||
dispatch({
|
|
||||||
type: !enabled === true ? "ENABLE_ICON" : "DISABLE_ICON",
|
|
||||||
});
|
|
||||||
if (!enabled === false) power.removeAttribute("checked");
|
|
||||||
if (!enabled === true) power.setAttribute("checked", "checked");
|
|
||||||
chrome.tabs.reload(id, { bypassCache: true });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Reload current page
|
|
||||||
*/
|
|
||||||
|
|
||||||
const handleReload = () => {
|
|
||||||
dispatch({ type: "GET_TAB" }, null, ({ id }) => {
|
|
||||||
chrome.tabs.reload(id, { bypassCache: true });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Shows negative or positive messages
|
|
||||||
* @param {MouseEvent} event
|
|
||||||
*/
|
|
||||||
|
|
||||||
const handleRate = (event) => {
|
|
||||||
const negative = document.getElementById("negative");
|
|
||||||
const positive = document.getElementById("positive");
|
|
||||||
|
|
||||||
switch (event.currentTarget.id) {
|
|
||||||
case "unlike":
|
|
||||||
positive.setAttribute("hidden", "true");
|
|
||||||
negative.removeAttribute("hidden");
|
|
||||||
break;
|
|
||||||
case "like":
|
|
||||||
negative.setAttribute("hidden", "true");
|
|
||||||
positive.removeAttribute("hidden");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Setup stars handlers and result message links
|
|
||||||
*/
|
|
||||||
|
|
||||||
const handleContentLoaded = () => {
|
|
||||||
dispatch({ type: "GET_TAB" }, null, ({ hostname }) => {
|
|
||||||
dispatch({ hostname, type: "GET_CACHE" }, null, ({ enabled }) => {
|
|
||||||
translate();
|
|
||||||
|
|
||||||
const host = document.getElementById("host");
|
|
||||||
const like = document.getElementById("like");
|
|
||||||
const power = document.getElementById("power");
|
|
||||||
const reload = document.getElementById("reload");
|
|
||||||
const store = document.getElementById("store");
|
|
||||||
const unlike = document.getElementById("unlike");
|
|
||||||
|
|
||||||
like.addEventListener("click", handleRate);
|
|
||||||
power.addEventListener("change", handlePowerChange);
|
|
||||||
reload.addEventListener("click", handleReload);
|
|
||||||
store.setAttribute("href", isChromium ? chromeUrl : firefoxUrl);
|
|
||||||
unlike.addEventListener("click", handleRate);
|
|
||||||
if (location) host.innerText = hostname.replace("www.", "");
|
|
||||||
if (!enabled) power.removeAttribute("checked");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Applies translations to tags with i18n data attribute
|
|
||||||
*/
|
|
||||||
|
|
||||||
const translate = () => {
|
|
||||||
const nodes = document.querySelectorAll("[data-i18n]");
|
|
||||||
|
|
||||||
for (let i = nodes.length; i--; ) {
|
|
||||||
const node = nodes[i];
|
|
||||||
const { i18n } = node.dataset;
|
|
||||||
|
|
||||||
node.innerHTML = chrome.i18n.getMessage(i18n);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Listen to document ready
|
|
||||||
* @listens document#ready
|
|
||||||
*/
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", handleContentLoaded);
|
|