diff --git a/.gitignore b/.gitignore index a6d1303..ed332b2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *-update/* *.DS_Store -metamorpov.zip +node_modules +src/replace-words-and-verbs.js diff --git a/Makefile b/Makefile deleted file mode 100644 index 0a2bd77..0000000 --- a/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -zip-ff: - zip ff-update manifest.json LICENSE *.png *.css *.js *.html - -zip-chrome: - zip chrome-update manifest.json *.png *.css *.js *.html diff --git a/README.md b/README.md index ea7b880..96aad0f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,13 @@ # MetamorPOV + Enables customization of reader-insert stories by replacing author-provided hooks such as Y/n, pov/s, and vrb/do/present/. +## Development + +- Uh npm, flake bla bla web-ext, nix is bad so installing pkg rollup globally fails, but that's okay because to install locally run `npm install --save-dev rollup` and then `npx rollup` to execute it. +- to-do credit englishverbshelper, apache 2 +- to-do retheme to and credit primary + ## Copyright and License + Portions of MetamorPOV are derived from InteractiveFics, licensed under [MIT](third-party-licenses/LICENSE-InteractiveFics), copyrighted 2015-2023 by Mariam Maarouf. Icons, excepting the butterfly, are redistributed from Luicide, licensed under [ISC](third-party-licenses/LICENSE-Luicide), copyrighted 2022 by Lucide Contributors. Luicide contains portions of Feather, licensed under [MIT](third-party-licenses/LICENSE-Feather), copyrighted 2013-2022 by Cole Bemis. All other portions of MetamorPOV are licensed under [GPL-3.0-or-later](LICENSE), copyrighted 2024 by Jean Viscogliosi-Pate. diff --git a/flake.nix b/flake.nix index d9e4f77..47b31bc 100644 --- a/flake.nix +++ b/flake.nix @@ -13,8 +13,8 @@ devShells = eachSystem (pkgs: { default = pkgs.mkShell { buildInputs = [ - pkgs.gnumake - pkgs.zip + pkgs.nodejs_22 + pkgs.web-ext ]; }; }); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..09436d0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,621 @@ +{ + "name": "metamorpov", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "metamorpov", + "version": "0.1.0", + "license": "GPL-3.0-or-later", + "devDependencies": { + "@rollup/plugin-commonjs": "28.0.2", + "@rollup/plugin-node-resolve": "15.3.0", + "english-verbs-gerunds": "3.3.1", + "english-verbs-helper": "3.3.1", + "english-verbs-irregular": "3.3.1", + "rollup": "^4.27.3" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/plugin-commonjs": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.2.tgz", + "integrity": "sha512-BEFI2EDqzl+vA1rl97IDRZ61AIwGH093d9nz8+dThxJNH8oSoB7MjWvPCX3dkaK1/RCJ/1v/R1XB15FuSs0fQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "fdir": "^6.2.0", + "is-reference": "1.2.1", + "magic-string": "^0.30.3", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0 || 14 >= 14.17" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz", + "integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", + "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.1.tgz", + "integrity": "sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.1.tgz", + "integrity": "sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz", + "integrity": "sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.1.tgz", + "integrity": "sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.1.tgz", + "integrity": "sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.1.tgz", + "integrity": "sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.1.tgz", + "integrity": "sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.1.tgz", + "integrity": "sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.1.tgz", + "integrity": "sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.1.tgz", + "integrity": "sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.1.tgz", + "integrity": "sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.1.tgz", + "integrity": "sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.1.tgz", + "integrity": "sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.1.tgz", + "integrity": "sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz", + "integrity": "sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz", + "integrity": "sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.1.tgz", + "integrity": "sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.1.tgz", + "integrity": "sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz", + "integrity": "sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/english-verbs-gerunds": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/english-verbs-gerunds/-/english-verbs-gerunds-3.3.1.tgz", + "integrity": "sha512-j1lltTeuvPwgwa/ROAjT/1B1RBA8724uJ2tCjGyRqn87VGAU/YKtYO/camMB1G/WaHT3j5iI3cmdVoPj5H3K2w==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/english-verbs-helper": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/english-verbs-helper/-/english-verbs-helper-3.3.1.tgz", + "integrity": "sha512-8mFnB6Z5W44aX20MTA9Wu7Fqad3KkykFcpLAcD3I930J1mIlqmsJhS81Qs8b23QCg2Aq1QfN9t0Xa2hsENFWgQ==", + "dev": true, + "license": "Apache-2.0", + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/ludan" + } + }, + "node_modules/english-verbs-irregular": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/english-verbs-irregular/-/english-verbs-irregular-3.3.1.tgz", + "integrity": "sha512-Ji6a/4QbXKryxLD/yw+tp6xz7kCOcHOdaDcesEyFYHQxUNRnWbLWybXAYnoLn3VHC0AxXbQonZwO6Bw7JvoaVA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", + "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.1.tgz", + "integrity": "sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.29.1", + "@rollup/rollup-android-arm64": "4.29.1", + "@rollup/rollup-darwin-arm64": "4.29.1", + "@rollup/rollup-darwin-x64": "4.29.1", + "@rollup/rollup-freebsd-arm64": "4.29.1", + "@rollup/rollup-freebsd-x64": "4.29.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.29.1", + "@rollup/rollup-linux-arm-musleabihf": "4.29.1", + "@rollup/rollup-linux-arm64-gnu": "4.29.1", + "@rollup/rollup-linux-arm64-musl": "4.29.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.29.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.29.1", + "@rollup/rollup-linux-riscv64-gnu": "4.29.1", + "@rollup/rollup-linux-s390x-gnu": "4.29.1", + "@rollup/rollup-linux-x64-gnu": "4.29.1", + "@rollup/rollup-linux-x64-musl": "4.29.1", + "@rollup/rollup-win32-arm64-msvc": "4.29.1", + "@rollup/rollup-win32-ia32-msvc": "4.29.1", + "@rollup/rollup-win32-x64-msvc": "4.29.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..4f7f4a1 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "metamorpov", + "title": "MetamorPOV", + "version": "0.1.0", + "description": "Enables customization of reader-insert stories by replacing author-provided hooks such as Y/n, pov/s, and vrb/do/present/.", + "repository": { + "type": "git", + "url": "git+https://git.viscogliosi-pate.com/jean/metamorpov.git" + }, + "author": "Jean Viscogliosi-Pate", + "license": "GPL-3.0-or-later", + "scripts": { + "build": "npx rollup -c" + }, + "devDependencies": { + "@rollup/plugin-node-resolve": "15.3.0", + "@rollup/plugin-commonjs": "28.0.2", + "english-verbs-helper": "3.3.1", + "english-verbs-gerunds": "3.3.1", + "english-verbs-irregular": "3.3.1", + "rollup": "^4.27.3" + } +} diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..70bc378 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,11 @@ +import { nodeResolve } from "@rollup/plugin-node-resolve"; +import commonjs from '@rollup/plugin-commonjs'; + +export default { + input: 'src/replace-words.js', + output: { + file: 'src/replace-words-and-verbs.js', + format: 'cjs', + }, + plugins: [nodeResolve(), commonjs()] +}; diff --git a/src/img/mpov-48.png b/src/img/mpov-48.png index 202c1b5..f548e7a 100644 Binary files a/src/img/mpov-48.png and b/src/img/mpov-48.png differ diff --git a/src/manifest.json b/src/manifest.json index 5bd8290..0a02945 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -10,7 +10,7 @@ "gecko": { "id": "metamorpov@viscogliosi-pate.com" }, - "gecko": {} + "gecko_android": {} }, "browser_action": { @@ -43,7 +43,7 @@ "content_scripts": [ { "js": [ - "content_script.js" + "replace-words-and-verbs.js" ], "run_at": "document_idle", "matches": [ diff --git a/src/options/options-old.js b/src/options/options-old.js index 6d27ac7..fd19cb3 100644 --- a/src/options/options-old.js +++ b/src/options/options-old.js @@ -1,214 +1,113 @@ -DEACTIVATE_KEY = 'deactivate-this-extension-pls-interactive-fics-yalla-bina'; -MUTATION_OBSERVER_KEY = 'observe-this-dom-pls-interactive-fics-yalla-bina'; - - -document.addEventListener('DOMContentLoaded', function () { - // event listeners - document.getElementById('change-name-form').addEventListener('submit', changeName) - document.getElementById('replace-other-words-form').addEventListener('submit', replaceOther) - document.getElementById('show-saved').addEventListener('click', loadSaved) - document.getElementById('refresh-replacements').addEventListener('click', refreshReplacements) - document.getElementById('enable-observer').addEventListener('click', toggleMutationObserver) - document.getElementById('toggle').addEventListener('click', togglePauseDomain) - - // set settings buttons - setMutationObserverKey() - setPauseDomainKey() -}); - - -const changeName = () => { - const person = document.getElementById('change-name-form-text').value - if (person) { - chrome.storage.sync.set({'person': person}, chrome.tabs.reload()) - } -} - -const replaceOther = () => { - const input_word = document.getElementById('replace-word').value - const replacement = document.getElementById('replace-with').value - const is_case_sensitive = document.getElementById('is-case-sensitive').checked - if (input_word && replacement) { - if (document.getElementById('is-perm').checked) { - const obj = {} - obj[input_word] = replacement - obj[`${input_word}_case_sensitive`] = is_case_sensitive - chrome.storage.sync.set(obj) - } - - chrome.tabs.query({ active: true, currentWindow: true }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - { - input_word: input_word, - replace_value: replacement, - case_sensitive: is_case_sensitive - }) - }) - } -} - -const refreshReplacements = () => { - chrome.tabs.query({ active: true, currentWindow: true }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - { - refresh: true - }) - }) -} - -const loadSaved = () => { - const list = document.getElementById('saved-items-list') - list.innerHTML = '' - chrome.storage.sync.get(null, loadSavedItemsWrapper(false)) - chrome.storage.local.get(null, loadSavedItemsWrapper(true)) -} - -const loadSavedItemsWrapper = isLocal => items => loadSavedItems(items, isLocal) - -const loadSavedItems = (items, isLocal) => { - const list = document.getElementById('saved-items-list') - for (var key in items) { - if (key !== DEACTIVATE_KEY && key !== MUTATION_OBSERVER_KEY && key !== PAUSED_KEY && !key.endsWith('_case_sensitive')) { - const label = key === 'person' ? 'Y/N' : key - const case_sensitive = !!items[`${key}_case_sensitive`] - const case_sensitive_string = case_sensitive ? 'case sensitive' : 'not case sensitive' - const representative = `${label} -> ${items[key]} (${case_sensitive_string})` - const list_item = createListItem(key, representative, 'one-saved-item', isLocal) - list.appendChild(list_item) - } - } -} - -const createListItem = (id, text, className, isLocal) => { - const text_node = document.createTextNode(text) - const list_node = document.createElement('LI') - list_node.appendChild(text_node) - list_node.className = className - list_node.id = id - list_node.addEventListener('click', () => { - if (isLocal) { - chrome.storage.local.remove(id) - } else { - chrome.storage.sync.remove(id) - } - list_node.className += ' strikethrough' - }) - return list_node -} - - -const setDeactivateKey = () => { - chrome.storage.sync.get(DEACTIVATE_KEY, obj => { - const is_deactivated = obj[DEACTIVATE_KEY] - toggleDeactivateLabel(is_deactivated) - - if (is_deactivated) { - const other_elements = document.getElementsByClassName('fade-when-deactivate') - const deactivate_only_elements = document.getElementsByClassName('fade-when-deactivate-only') - Array.from([...other_elements, ...deactivate_only_elements]).forEach(element => { - element.style.opacity = '0.5' - }) - const input_elements = document.getElementsByTagName('INPUT') - Array.from(input_elements).forEach(input => { - if (input.id !== 'deactivate') { - input.disabled = 'disabled' - } - }) - } - }) -} - -const setMutationObserverKey = () => { - chrome.storage.sync.get(MUTATION_OBSERVER_KEY, obj => { - const is_enabled = obj[MUTATION_OBSERVER_KEY] - toggleMutationObserverLabel(is_enabled) - }) -} - -const setPauseDomainKey = () => { - chrome.tabs.query({ active: true, currentWindow: true }, tabs => { - const hostname = new URL(tabs[0].url).hostname - document.getElementById('this-url').innerHTML = hostname - - const storage_key = {} - storage_key[PAUSED_KEY] = [] - chrome.storage.sync.get(storage_key, obj => { - const hostnames = obj[PAUSED_KEY] - const is_paused = hostnames.indexOf(hostname) !== -1 - togglePauseDomainLabel(is_paused) - - if (is_paused) { - const other_elements = document.getElementsByClassName('fade-when-deactivate') - const pause_only_other_elements = document.getElementsByClassName('fade-when-pause') - Array.from([...other_elements, ...pause_only_other_elements]).forEach(element => { - element.style.opacity = '0.5' - }) - const input_elements = document.getElementsByTagName('INPUT') - Array.from(input_elements).forEach(input => { - if (input.id !== 'pause' && input.id !== 'deactivate') { - input.disabled = 'disabled' - } - }) - } - }) - }) -} - -const toggleDeactivateLabel = (isDeactivated) => { - document.getElementById('deactivate').checked = isDeactivated; - -} - -const toggleMutationObserverLabel = (isEnabled) => { - document.getElementById('enable-observer').checked = isEnabled; -} - -const togglePauseDomainLabel = (isPaused) => { - document.getElementById('pause').checked = isPaused; -} - -const toggleMutationObserver = () => { - chrome.storage.sync.get(MUTATION_OBSERVER_KEY, obj => { - const was_enabled = obj[MUTATION_OBSERVER_KEY] - - if (was_enabled) { - chrome.storage.sync.remove(MUTATION_OBSERVER_KEY) - } else { - const new_object = {} - new_object[MUTATION_OBSERVER_KEY] = true - chrome.storage.sync.set(new_object) - } - - chrome.tabs.reload() - }) -} - -const togglePauseDomain = () => { - chrome.tabs.query({ active: true, currentWindow: true }, tabs => { - const hostname = new URL(tabs[0].url).hostname - - const storage_key = {} - storage_key[PAUSED_KEY] = [] - chrome.storage.sync.get(storage_key, obj => { - const hostnames = obj[PAUSED_KEY] - const was_paused = hostnames.indexOf(hostname) !== -1 - var new_hostnames; - - if (was_paused) { - new_hostnames = hostnames.filter(h => h !== hostname) - } else { - new_hostnames = hostnames - new_hostnames.push(hostname) - } - - const new_obj = {} - new_obj[PAUSED_KEY] = new_hostnames - chrome.storage.sync.set(new_obj) - - chrome.tabs.reload() - window.close() - }) - }) -} +// DEACTIVATE_KEY = 'deactivate-this-extension-pls-interactive-fics-yalla-bina'; +// +// document.addEventListener('DOMContentLoaded', function () { +// // event listeners +// document.getElementById('change-name-form').addEventListener('submit', changeName) +// document.getElementById('replace-other-words-form').addEventListener('submit', replaceOther) +// document.getElementById('show-saved').addEventListener('click', loadSaved) +// document.getElementById('refresh-replacements').addEventListener('click', refreshReplacements) +// document.getElementById('enable-observer').addEventListener('click', toggleMutationObserver) +// document.getElementById('toggle').addEventListener('click', togglePauseDomain) +// +// // set settings buttons +// setMutationObserverKey() +// setPauseDomainKey() +// }); +// +// +// const changeName = () => { +// const person = document.getElementById('change-name-form-text').value +// if (person) { +// chrome.storage.sync.set({'person': person}, chrome.tabs.reload()) +// } +// } +// +// const refreshReplacements = () => { +// chrome.tabs.query({ active: true, currentWindow: true }, tabs => { +// chrome.tabs.sendMessage( +// tabs[0].id, +// { +// refresh: true +// }) +// }) +// } +// +// const loadSaved = () => { +// const list = document.getElementById('saved-items-list') +// list.innerHTML = '' +// chrome.storage.sync.get(null, loadSavedItemsWrapper(false)) +// chrome.storage.local.get(null, loadSavedItemsWrapper(true)) +// } +// +// const loadSavedItemsWrapper = isLocal => items => loadSavedItems(items, isLocal) +// +// const loadSavedItems = (items, isLocal) => { +// const list = document.getElementById('saved-items-list') +// for (var key in items) { +// if (key !== DEACTIVATE_KEY && key !== MUTATION_OBSERVER_KEY && key !== PAUSED_KEY && !key.endsWith('_case_sensitive')) { +// const label = key === 'person' ? 'Y/N' : key +// const case_sensitive = !!items[`${key}_case_sensitive`] +// const case_sensitive_string = case_sensitive ? 'case sensitive' : 'not case sensitive' +// const representative = `${label} -> ${items[key]} (${case_sensitive_string})` +// const list_item = createListItem(key, representative, 'one-saved-item', isLocal) +// list.appendChild(list_item) +// } +// } +// } +// +// const setPauseDomainKey = () => { +// chrome.tabs.query({ active: true, currentWindow: true }, tabs => { +// const hostname = new URL(tabs[0].url).hostname +// document.getElementById('this-url').innerHTML = hostname +// +// const storage_key = {} +// storage_key[PAUSED_KEY] = [] +// chrome.storage.sync.get(storage_key, obj => { +// const hostnames = obj[PAUSED_KEY] +// const is_paused = hostnames.indexOf(hostname) !== -1 +// togglePauseDomainLabel(is_paused) +// +// if (is_paused) { +// const other_elements = document.getElementsByClassName('fade-when-deactivate') +// const pause_only_other_elements = document.getElementsByClassName('fade-when-pause') +// Array.from([...other_elements, ...pause_only_other_elements]).forEach(element => { +// element.style.opacity = '0.5' +// }) +// const input_elements = document.getElementsByTagName('INPUT') +// Array.from(input_elements).forEach(input => { +// if (input.id !== 'pause' && input.id !== 'deactivate') { +// input.disabled = 'disabled' +// } +// }) +// } +// }) +// }) +// } +// +// const togglePauseDomain = () => { +// chrome.tabs.query({ active: true, currentWindow: true }, tabs => { +// const hostname = new URL(tabs[0].url).hostname +// +// const storage_key = {} +// storage_key[PAUSED_KEY] = [] +// chrome.storage.sync.get(storage_key, obj => { +// const hostnames = obj[PAUSED_KEY] +// const was_paused = hostnames.indexOf(hostname) !== -1 +// var new_hostnames; +// +// if (was_paused) { +// new_hostnames = hostnames.filter(h => h !== hostname) +// } else { +// new_hostnames = hostnames +// new_hostnames.push(hostname) +// } +// +// const new_obj = {} +// new_obj[PAUSED_KEY] = new_hostnames +// chrome.storage.sync.set(new_obj) +// +// chrome.tabs.reload() +// window.close() +// }) +// }) +// } diff --git a/src/popup/popup.js b/src/popup/popup.js index 6d27ac7..15910c6 100644 --- a/src/popup/popup.js +++ b/src/popup/popup.js @@ -1,214 +1,214 @@ -DEACTIVATE_KEY = 'deactivate-this-extension-pls-interactive-fics-yalla-bina'; -MUTATION_OBSERVER_KEY = 'observe-this-dom-pls-interactive-fics-yalla-bina'; - - -document.addEventListener('DOMContentLoaded', function () { - // event listeners - document.getElementById('change-name-form').addEventListener('submit', changeName) - document.getElementById('replace-other-words-form').addEventListener('submit', replaceOther) - document.getElementById('show-saved').addEventListener('click', loadSaved) - document.getElementById('refresh-replacements').addEventListener('click', refreshReplacements) - document.getElementById('enable-observer').addEventListener('click', toggleMutationObserver) - document.getElementById('toggle').addEventListener('click', togglePauseDomain) - - // set settings buttons - setMutationObserverKey() - setPauseDomainKey() -}); - - -const changeName = () => { - const person = document.getElementById('change-name-form-text').value - if (person) { - chrome.storage.sync.set({'person': person}, chrome.tabs.reload()) - } -} - -const replaceOther = () => { - const input_word = document.getElementById('replace-word').value - const replacement = document.getElementById('replace-with').value - const is_case_sensitive = document.getElementById('is-case-sensitive').checked - if (input_word && replacement) { - if (document.getElementById('is-perm').checked) { - const obj = {} - obj[input_word] = replacement - obj[`${input_word}_case_sensitive`] = is_case_sensitive - chrome.storage.sync.set(obj) - } - - chrome.tabs.query({ active: true, currentWindow: true }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - { - input_word: input_word, - replace_value: replacement, - case_sensitive: is_case_sensitive - }) - }) - } -} - -const refreshReplacements = () => { - chrome.tabs.query({ active: true, currentWindow: true }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - { - refresh: true - }) - }) -} - -const loadSaved = () => { - const list = document.getElementById('saved-items-list') - list.innerHTML = '' - chrome.storage.sync.get(null, loadSavedItemsWrapper(false)) - chrome.storage.local.get(null, loadSavedItemsWrapper(true)) -} - -const loadSavedItemsWrapper = isLocal => items => loadSavedItems(items, isLocal) - -const loadSavedItems = (items, isLocal) => { - const list = document.getElementById('saved-items-list') - for (var key in items) { - if (key !== DEACTIVATE_KEY && key !== MUTATION_OBSERVER_KEY && key !== PAUSED_KEY && !key.endsWith('_case_sensitive')) { - const label = key === 'person' ? 'Y/N' : key - const case_sensitive = !!items[`${key}_case_sensitive`] - const case_sensitive_string = case_sensitive ? 'case sensitive' : 'not case sensitive' - const representative = `${label} -> ${items[key]} (${case_sensitive_string})` - const list_item = createListItem(key, representative, 'one-saved-item', isLocal) - list.appendChild(list_item) - } - } -} - -const createListItem = (id, text, className, isLocal) => { - const text_node = document.createTextNode(text) - const list_node = document.createElement('LI') - list_node.appendChild(text_node) - list_node.className = className - list_node.id = id - list_node.addEventListener('click', () => { - if (isLocal) { - chrome.storage.local.remove(id) - } else { - chrome.storage.sync.remove(id) - } - list_node.className += ' strikethrough' - }) - return list_node -} - - -const setDeactivateKey = () => { - chrome.storage.sync.get(DEACTIVATE_KEY, obj => { - const is_deactivated = obj[DEACTIVATE_KEY] - toggleDeactivateLabel(is_deactivated) - - if (is_deactivated) { - const other_elements = document.getElementsByClassName('fade-when-deactivate') - const deactivate_only_elements = document.getElementsByClassName('fade-when-deactivate-only') - Array.from([...other_elements, ...deactivate_only_elements]).forEach(element => { - element.style.opacity = '0.5' - }) - const input_elements = document.getElementsByTagName('INPUT') - Array.from(input_elements).forEach(input => { - if (input.id !== 'deactivate') { - input.disabled = 'disabled' - } - }) - } - }) -} - -const setMutationObserverKey = () => { - chrome.storage.sync.get(MUTATION_OBSERVER_KEY, obj => { - const is_enabled = obj[MUTATION_OBSERVER_KEY] - toggleMutationObserverLabel(is_enabled) - }) -} - -const setPauseDomainKey = () => { - chrome.tabs.query({ active: true, currentWindow: true }, tabs => { - const hostname = new URL(tabs[0].url).hostname - document.getElementById('this-url').innerHTML = hostname - - const storage_key = {} - storage_key[PAUSED_KEY] = [] - chrome.storage.sync.get(storage_key, obj => { - const hostnames = obj[PAUSED_KEY] - const is_paused = hostnames.indexOf(hostname) !== -1 - togglePauseDomainLabel(is_paused) - - if (is_paused) { - const other_elements = document.getElementsByClassName('fade-when-deactivate') - const pause_only_other_elements = document.getElementsByClassName('fade-when-pause') - Array.from([...other_elements, ...pause_only_other_elements]).forEach(element => { - element.style.opacity = '0.5' - }) - const input_elements = document.getElementsByTagName('INPUT') - Array.from(input_elements).forEach(input => { - if (input.id !== 'pause' && input.id !== 'deactivate') { - input.disabled = 'disabled' - } - }) - } - }) - }) -} - -const toggleDeactivateLabel = (isDeactivated) => { - document.getElementById('deactivate').checked = isDeactivated; - -} - -const toggleMutationObserverLabel = (isEnabled) => { - document.getElementById('enable-observer').checked = isEnabled; -} - -const togglePauseDomainLabel = (isPaused) => { - document.getElementById('pause').checked = isPaused; -} - -const toggleMutationObserver = () => { - chrome.storage.sync.get(MUTATION_OBSERVER_KEY, obj => { - const was_enabled = obj[MUTATION_OBSERVER_KEY] - - if (was_enabled) { - chrome.storage.sync.remove(MUTATION_OBSERVER_KEY) - } else { - const new_object = {} - new_object[MUTATION_OBSERVER_KEY] = true - chrome.storage.sync.set(new_object) - } - - chrome.tabs.reload() - }) -} - -const togglePauseDomain = () => { - chrome.tabs.query({ active: true, currentWindow: true }, tabs => { - const hostname = new URL(tabs[0].url).hostname - - const storage_key = {} - storage_key[PAUSED_KEY] = [] - chrome.storage.sync.get(storage_key, obj => { - const hostnames = obj[PAUSED_KEY] - const was_paused = hostnames.indexOf(hostname) !== -1 - var new_hostnames; - - if (was_paused) { - new_hostnames = hostnames.filter(h => h !== hostname) - } else { - new_hostnames = hostnames - new_hostnames.push(hostname) - } - - const new_obj = {} - new_obj[PAUSED_KEY] = new_hostnames - chrome.storage.sync.set(new_obj) - - chrome.tabs.reload() - window.close() - }) - }) -} +// DEACTIVATE_KEY = 'deactivate-this-extension-pls-interactive-fics-yalla-bina'; +// MUTATION_OBSERVER_KEY = 'observe-this-dom-pls-interactive-fics-yalla-bina'; +// +// +// document.addEventListener('DOMContentLoaded', function () { +// // event listeners +// document.getElementById('change-name-form').addEventListener('submit', changeName) +// document.getElementById('replace-other-words-form').addEventListener('submit', replaceOther) +// document.getElementById('show-saved').addEventListener('click', loadSaved) +// document.getElementById('refresh-replacements').addEventListener('click', refreshReplacements) +// document.getElementById('enable-observer').addEventListener('click', toggleMutationObserver) +// document.getElementById('toggle').addEventListener('click', togglePauseDomain) +// +// // set settings buttons +// setMutationObserverKey() +// setPauseDomainKey() +// }); +// +// +// const changeName = () => { +// const person = document.getElementById('change-name-form-text').value +// if (person) { +// chrome.storage.sync.set({'person': person}, chrome.tabs.reload()) +// } +// } +// +// const replaceOther = () => { +// const input_word = document.getElementById('replace-word').value +// const replacement = document.getElementById('replace-with').value +// const is_case_sensitive = document.getElementById('is-case-sensitive').checked +// if (input_word && replacement) { +// if (document.getElementById('is-perm').checked) { +// const obj = {} +// obj[input_word] = replacement +// obj[`${input_word}_case_sensitive`] = is_case_sensitive +// chrome.storage.sync.set(obj) +// } +// +// chrome.tabs.query({ active: true, currentWindow: true }, tabs => { +// chrome.tabs.sendMessage( +// tabs[0].id, +// { +// input_word: input_word, +// replace_value: replacement, +// case_sensitive: is_case_sensitive +// }) +// }) +// } +// } +// +// const refreshReplacements = () => { +// chrome.tabs.query({ active: true, currentWindow: true }, tabs => { +// chrome.tabs.sendMessage( +// tabs[0].id, +// { +// refresh: true +// }) +// }) +// } +// +// const loadSaved = () => { +// const list = document.getElementById('saved-items-list') +// list.innerHTML = '' +// chrome.storage.sync.get(null, loadSavedItemsWrapper(false)) +// chrome.storage.local.get(null, loadSavedItemsWrapper(true)) +// } +// +// const loadSavedItemsWrapper = isLocal => items => loadSavedItems(items, isLocal) +// +// const loadSavedItems = (items, isLocal) => { +// const list = document.getElementById('saved-items-list') +// for (var key in items) { +// if (key !== DEACTIVATE_KEY && key !== MUTATION_OBSERVER_KEY && key !== PAUSED_KEY && !key.endsWith('_case_sensitive')) { +// const label = key === 'person' ? 'Y/N' : key +// const case_sensitive = !!items[`${key}_case_sensitive`] +// const case_sensitive_string = case_sensitive ? 'case sensitive' : 'not case sensitive' +// const representative = `${label} -> ${items[key]} (${case_sensitive_string})` +// const list_item = createListItem(key, representative, 'one-saved-item', isLocal) +// list.appendChild(list_item) +// } +// } +// } +// +// const createListItem = (id, text, className, isLocal) => { +// const text_node = document.createTextNode(text) +// const list_node = document.createElement('LI') +// list_node.appendChild(text_node) +// list_node.className = className +// list_node.id = id +// list_node.addEventListener('click', () => { +// if (isLocal) { +// chrome.storage.local.remove(id) +// } else { +// chrome.storage.sync.remove(id) +// } +// list_node.className += ' strikethrough' +// }) +// return list_node +// } +// +// +// const setDeactivateKey = () => { +// chrome.storage.sync.get(DEACTIVATE_KEY, obj => { +// const is_deactivated = obj[DEACTIVATE_KEY] +// toggleDeactivateLabel(is_deactivated) +// +// if (is_deactivated) { +// const other_elements = document.getElementsByClassName('fade-when-deactivate') +// const deactivate_only_elements = document.getElementsByClassName('fade-when-deactivate-only') +// Array.from([...other_elements, ...deactivate_only_elements]).forEach(element => { +// element.style.opacity = '0.5' +// }) +// const input_elements = document.getElementsByTagName('INPUT') +// Array.from(input_elements).forEach(input => { +// if (input.id !== 'deactivate') { +// input.disabled = 'disabled' +// } +// }) +// } +// }) +// } +// +// const setMutationObserverKey = () => { +// chrome.storage.sync.get(MUTATION_OBSERVER_KEY, obj => { +// const is_enabled = obj[MUTATION_OBSERVER_KEY] +// toggleMutationObserverLabel(is_enabled) +// }) +// } +// +// const setPauseDomainKey = () => { +// chrome.tabs.query({ active: true, currentWindow: true }, tabs => { +// const hostname = new URL(tabs[0].url).hostname +// document.getElementById('this-url').innerHTML = hostname +// +// const storage_key = {} +// storage_key[PAUSED_KEY] = [] +// chrome.storage.sync.get(storage_key, obj => { +// const hostnames = obj[PAUSED_KEY] +// const is_paused = hostnames.indexOf(hostname) !== -1 +// togglePauseDomainLabel(is_paused) +// +// if (is_paused) { +// const other_elements = document.getElementsByClassName('fade-when-deactivate') +// const pause_only_other_elements = document.getElementsByClassName('fade-when-pause') +// Array.from([...other_elements, ...pause_only_other_elements]).forEach(element => { +// element.style.opacity = '0.5' +// }) +// const input_elements = document.getElementsByTagName('INPUT') +// Array.from(input_elements).forEach(input => { +// if (input.id !== 'pause' && input.id !== 'deactivate') { +// input.disabled = 'disabled' +// } +// }) +// } +// }) +// }) +// } +// +// const toggleDeactivateLabel = (isDeactivated) => { +// document.getElementById('deactivate').checked = isDeactivated; +// +// } +// +// const toggleMutationObserverLabel = (isEnabled) => { +// document.getElementById('enable-observer').checked = isEnabled; +// } +// +// const togglePauseDomainLabel = (isPaused) => { +// document.getElementById('pause').checked = isPaused; +// } +// +// const toggleMutationObserver = () => { +// chrome.storage.sync.get(MUTATION_OBSERVER_KEY, obj => { +// const was_enabled = obj[MUTATION_OBSERVER_KEY] +// +// if (was_enabled) { +// chrome.storage.sync.remove(MUTATION_OBSERVER_KEY) +// } else { +// const new_object = {} +// new_object[MUTATION_OBSERVER_KEY] = true +// chrome.storage.sync.set(new_object) +// } +// +// chrome.tabs.reload() +// }) +// } +// +// const togglePauseDomain = () => { +// chrome.tabs.query({ active: true, currentWindow: true }, tabs => { +// const hostname = new URL(tabs[0].url).hostname +// +// const storage_key = {} +// storage_key[PAUSED_KEY] = [] +// chrome.storage.sync.get(storage_key, obj => { +// const hostnames = obj[PAUSED_KEY] +// const was_paused = hostnames.indexOf(hostname) !== -1 +// var new_hostnames; +// +// if (was_paused) { +// new_hostnames = hostnames.filter(h => h !== hostname) +// } else { +// new_hostnames = hostnames +// new_hostnames.push(hostname) +// } +// +// const new_obj = {} +// new_obj[PAUSED_KEY] = new_hostnames +// chrome.storage.sync.set(new_obj) +// +// chrome.tabs.reload() +// window.close() +// }) +// }) +// } diff --git a/src/content_script.js b/src/replace-words.js similarity index 70% rename from src/content_script.js rename to src/replace-words.js index 67a9893..22e3777 100644 --- a/src/content_script.js +++ b/src/replace-words.js @@ -1,32 +1,40 @@ -PAUSED_KEY = 'pause-this-domain-pls-interactive-fics-yalla-bina'; +//PAUSED_KEY = 'pause-this-domain-pls-interactive-fics-yalla-bina'; + +const verbsHelper = require('english-verbs-helper'); browser.runtime.onMessage.addListener((message, sender, sendResponse) => { if ('input_word' in message){ - escapeAndReplace(message.input_word, message.replace_value, message.case_sensitive) + escapeAndReplace(message.input_word, message.replace_value, message.case_sensitive); } else { - replaceAll() + replaceAll(); } }); -const replaceAll = () => { - browser.storage.local.get(null, replaceAllInStorage) +function replaceAll() { + browser.storage.local.get(null, replaceAllInStorage); // TODO this is bad } -const replaceAllInStorage = (options) => { - const hostname = window.location.hostname - const is_paused = options[PAUSED_KEY] && options[PAUSED_KEY].indexOf(hostname) !== -1 +function replaceAllInStorage(options) { + //const hostname = window.location.hostname + //const is_paused = options[PAUSED_KEY] && options[PAUSED_KEY].indexOf(hostname) !== -1 if (true) { // change paused later to only care about hostname replaceName(options); replacePronouns(options); replacePov(options); replacePlv(options); replaceAlso(options); + replaceVerbs(options); } } function replaceName(options) { const regexp = /\by\/n\b|\(y\/n\)|\[y\/n\]/ig; - replace(regexp, options["name"]); + walk(document.body, regexp, options["name"], directMethod); +} + +function replaceVerbs(options) { + const regexp = /vrb\/([\w\s]+)\/([\w\s]+)\//; + walk(document.body, regexp, options, verbMethod); } // TODO case sensitivity, premade regexp @@ -182,7 +190,7 @@ function replaceAlso(options) { } function escapeAndReplace(input_word, replace_value, case_sensitive) { - let input_word_escaped = escapeRegExp(input_word.trim()) + let input_word_escaped = input_word.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); const flags = case_sensitive ? "g" : "ig" if (input_word_escaped[0].match(/[a-z]/i)) { input_word_escaped = `\\b${input_word_escaped}` @@ -191,51 +199,64 @@ function escapeAndReplace(input_word, replace_value, case_sensitive) { input_word_escaped = `${input_word_escaped}\\b` } const regexp_input_word = new RegExp(input_word_escaped, flags) - replace(regexp_input_word, replace_value) + walk(document.body, regexp_input_word, replace_value, directMethod); } -const escapeRegExp = (str) => str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&") - -const replace = (input_word, replace_value) => { - browser.storage.local.get(obj => { - if (replace_value) { - walk(document.body, input_word, replace_value) - } - }) -} - -const replaceText = (textNode, input_word, replace_value) => { - let node_value = textNode.nodeValue - node_value = node_value.replace(input_word, replace_value) - textNode.nodeValue = node_value -} - - -function walk(node, v, p){ - // I stole the base to this function from here: - // https://stackoverflow.com/questions/5904914/javascript-regex-to-replace-text-not-in-html-attributes/5904945 - if (node.contentEditable != 'true' && node.type != 'textarea' && node.type != 'input') { - var child, next; - switch (node.nodeType){ - case 1: // Element - case 9: // Document - case 11: // Document fragment - child = node.firstChild; - while (child){ - next = child.nextSibling; - walk(child, v, p); - child = next; - } - break; - case 3: // Text node - replaceText(node, v, p); - break; - } +function walk(node, input_word, replace_value, replaceMethod) { + if (node.contentEditable == "true" || node.type == "textarea" || node.type == "input") { return; } + var child, next; + switch (node.nodeType) { + case 1: /* ELEMENT_NODE */ + case 9: /* DOCUMENT_NODE */ + case 11: /* DOCUMENT_FRAGMENT_NODE */ + child = node.firstChild; + while (child) { + next = child.nextSibling; + walk(child, input_word, replace_value, replaceMethod); + child = next; + } + break; + case 3: /* TEXT_NODE */ + replaceMethod(node, input_word, replace_value); } } +function directMethod(node, input_word, replace_value) { + node.nodeValue = node.nodeValue.replace(input_word, replace_value); // TODO might replaceall work better here?; +} + +// TODO do something about options being not input_word +function verbMethod(node, regexp, options) { + var match = node.nodeValue.match(regexp); + if (match == null) { return; } + var verb = match[1]; + var tense = match[2]; + const replace_value = verbsHelper.getConjugation(null, verb, tense, getPovIndex(options)); + node.nodeValue = node.nodeValue.replace(regexp, replace_value); +} + function capitalize(word) { return word.charAt(0).toUpperCase() + word.slice(1); } -replaceAll() +// TODO figure out plv for this +function getPovIndex(options) { + switch (options.pov) { + case "first": + return 0; + case "second": + return 1; + case "third": + if (options.preset == "he" || options.preset == "she") { + return 2; + } else if (options.preset == "they") { + return 5; + } else if (options.other.plurality == "singular") { + return 2; + } else { + return 5; + } + } +} + +replaceAll();