From f15e91c9d42e960156226c7b1f8a6e6aa891be0b Mon Sep 17 00:00:00 2001 From: svrnm Date: Tue, 27 Sep 2022 20:52:17 +0200 Subject: [PATCH] fix: prettier & linter use the same config. --- .babelrc | 5 +- .commitlintrc.js | 34 +- .eslintrc.json | 35 +- .markdownlint.jsonc | 10 +- .prettierrc.json | 5 + CONTRIBUTE.md | 20 +- README.md | 2 +- SHORTCUTS.md | 186 +- USAGE.md | 114 +- manifest.json | 34 +- pages/backup.html | 44 +- pages/template.html | 45 +- pages/test.html | 2008 ++- src/app.js | 150 +- src/background.js | 173 +- src/backup.js | 127 +- src/commands/AddScript.js | 2 +- src/commands/Command.js | 18 +- src/commands/CommandBuilder.js | 111 +- src/commands/CommandRegistry.js | 1808 ++- src/commands/Eval.js | 14 +- src/commands/Hide.js | 45 +- src/commands/If.js | 10 +- src/commands/InsertHTML.js | 32 +- src/commands/InterceptWebRequest.js | 23 +- src/commands/OverwriteHTML.js | 19 +- src/commands/PatchAjaxResponse.js | 5 +- src/commands/Protect.js | 14 +- src/commands/QuerySelector.js | 10 +- src/commands/RecolorImage.js | 17 +- src/commands/ReplaceAjaxResponse.js | 6 +- src/commands/ReplaceImage.js | 42 +- src/commands/ReplaceNeighbor.js | 46 +- src/commands/SearchAndReplace.js | 45 +- src/commands/Stage.js | 10 +- src/commands/Style.js | 7 +- src/commands/UndoElement.js | 2 +- src/commands/appdynamics/AddFlowmapNode.js | 337 +- src/commands/appdynamics/RecolorDashboard.js | 183 +- src/commands/appdynamics/RemoveFlowmapNode.js | 21 +- .../appdynamics/ReplaceFlowmapConnection.js | 181 +- .../appdynamics/ReplaceFlowmapIcon.js | 21 +- src/commands/appdynamics/ReplaceGeoStatus.js | 39 +- .../appdynamics/SetDashboardBackground.js | 48 +- src/components/options/Help.js | 9 +- src/components/options/Logs.js | 66 +- src/components/options/OptionsPageApp.js | 351 +- src/components/options/editor/CodeEditor.js | 81 +- src/components/options/editor/Editor.js | 319 +- .../options/editor/ace/autocomplete.js | 379 +- src/components/options/editor/ace/mnky.js | 467 +- src/components/options/editor/ace/vim.js | 11474 +++++++++------- .../options/navigation/ItemHeader.js | 85 +- .../options/navigation/Navigation.js | 76 +- .../options/navigation/NavigationHeader.js | 70 +- .../options/settings/GlobalVariables.js | 65 +- src/components/options/settings/Settings.js | 192 +- src/components/popup/ConfigurationList.js | 162 +- src/components/popup/PopupPageApp.js | 98 +- src/components/shared/ConfigurationUpload.js | 126 +- src/components/shared/DropDownMenu.js | 37 +- src/components/shared/ErrorBox.js | 16 +- src/components/shared/Page.js | 6 +- src/components/shared/Pane.js | 6 +- src/components/shared/Popup.js | 46 +- src/components/shared/Tabs.js | 23 +- src/components/shared/ToggleConfiguration.js | 26 +- src/components/shared/Variable.js | 160 +- src/components/shared/WarningBox.js | 24 +- src/helpers/arrayMerge.js | 9 +- src/helpers/extractParameters.js | 10 +- src/helpers/logger.js | 7 +- src/helpers/match.js | 13 +- src/inline.js | 63 +- src/models/Badge.js | 13 +- src/models/Configuration.js | 147 +- src/models/ElementPicker.js | 44 +- src/models/InlineRuleManager.js | 13 +- src/models/LiveModeAlarm.js | 14 +- src/models/Manifest.js | 18 +- src/models/MatchRule.js | 8 +- src/models/ModeManager.js | 356 +- src/models/Monkey.js | 264 +- src/models/NetRequestManager.js | 76 +- src/models/OptionalFeature.js | 78 +- src/models/ProtocolHandler.js | 58 +- src/models/Settings.js | 36 +- src/models/UrlManager.js | 6 +- src/models/Variable.js | 77 +- src/monkey.js | 118 +- src/reducers/configurations.js | 46 +- src/reducers/log.js | 31 +- src/reducers/settings.js | 9 +- src/test.js | 18 +- styles/main.less | 6 +- styles/popup.less | 8 +- test/commands/CommandBuilder.js | 197 +- test/commands/Eval.js | 27 +- test/commands/Group.js | 35 +- test/commands/Hide.js | 56 +- test/commands/If.js | 45 +- test/commands/OverwriteHTML.js | 33 +- test/commands/ReplaceImage.js | 26 +- test/commands/ReplaceNeighbor.js | 14 +- test/commands/SearchAndReplace.js | 14 +- test/commands/Stage.js | 8 +- test/commands/appdynamics/RecolorDashboard.js | 90 +- .../appdynamics/ReplaceFlowmapConnection.js | 22 +- .../appdynamics/ReplaceFlowmapIcon.js | 11 +- test/helpers/match.js | 7 +- test/models/Badge.js | 12 +- test/models/Configuration.js | 167 +- test/models/Ini.js | 16 +- test/models/Json2Ini.js | 10 +- test/models/MatchRule.js | 14 +- test/models/Monkey.js | 149 +- test/models/Variable.js | 67 +- test/selenium/UI.js | 14 +- test/selenium/base.js | 42 +- test/selenium/integration-simple.js | 5 +- test/selenium/integration.js | 51 +- webpack.config.js | 31 +- 122 files changed, 14730 insertions(+), 8451 deletions(-) create mode 100644 .prettierrc.json diff --git a/.babelrc b/.babelrc index 7b87203..02b40ff 100644 --- a/.babelrc +++ b/.babelrc @@ -1,4 +1,7 @@ { "presets": ["@babel/preset-react", "@babel/preset-env"], - "plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-transform-runtime"] + "plugins": [ + "@babel/plugin-proposal-class-properties", + "@babel/plugin-transform-runtime" + ] } diff --git a/.commitlintrc.js b/.commitlintrc.js index 492f76b..2bb69de 100644 --- a/.commitlintrc.js +++ b/.commitlintrc.js @@ -1,13 +1,25 @@ module.exports = { - extends: ['@commitlint/config-conventional'], - rules: { - 'header-max-length': [1, 'always', 72], - 'header-full-stop': [2, 'always'], - 'subject-full-stop': [0, 'always'], - 'type-enum': [ - 2, - 'always', - ['build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'style', 'test', 'revert', 'version'] - ] - } + extends: ['@commitlint/config-conventional'], + rules: { + 'header-max-length': [1, 'always', 72], + 'header-full-stop': [2, 'always'], + 'subject-full-stop': [0, 'always'], + 'type-enum': [ + 2, + 'always', + [ + 'build', + 'ci', + 'docs', + 'feat', + 'fix', + 'perf', + 'refactor', + 'style', + 'test', + 'revert', + 'version' + ] + ] + } } diff --git a/.eslintrc.json b/.eslintrc.json index 09b112b..37ef882 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -15,13 +15,7 @@ "plugin:import/errors", "plugin:import/warnings" ], - "plugins": [ - "promise", - "json", - "react", - "import", - "header" - ], + "plugins": ["promise", "json", "react", "import", "header"], "env": { "browser": true, "node": true, @@ -29,15 +23,24 @@ }, "rules": { "react/jsx-uses-vars": 1, - "space-before-function-paren": ["error", { - "anonymous": "always", - "named": "ignore", - "asyncArrow": "ignore" - }], - "header/header": [2, "block", [{ - "pattern": "\\* Licensed under the Apache License, Version 2\\.0 \\(the \"License\"\\);[\\r\\n]+ \\* you may not use this file except in compliance with the License\\.[\\r\\n]+ \\* You may obtain a copy of the License at[\\r\\n]+ \\*[\\r\\n]+ \\* https:\\/\\/www\\.apache\\.org\\/licenses\\/LICENSE-2\\.0[\\r\\n]+ \\*[\\r\\n]+ \\* Unless required by applicable law or agreed to in writing, software[\\r\\n]+ \\* distributed under the License is distributed on an \"AS IS\" BASIS,[\\r\\n]+ \\* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\\.[\\r\\n]+ \\* See the License for the specific language governing permissions and[\\r\\n]+ \\* limitations under the License\\.", - "template": "*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n " - }]] + "space-before-function-paren": [ + "error", + { + "anonymous": "always", + "named": "ignore", + "asyncArrow": "ignore" + } + ], + "header/header": [ + 2, + "block", + [ + { + "pattern": "\\* Licensed under the Apache License, Version 2\\.0 \\(the \"License\"\\);[\\r\\n]+ \\* you may not use this file except in compliance with the License\\.[\\r\\n]+ \\* You may obtain a copy of the License at[\\r\\n]+ \\*[\\r\\n]+ \\* https:\\/\\/www\\.apache\\.org\\/licenses\\/LICENSE-2\\.0[\\r\\n]+ \\*[\\r\\n]+ \\* Unless required by applicable law or agreed to in writing, software[\\r\\n]+ \\* distributed under the License is distributed on an \"AS IS\" BASIS,[\\r\\n]+ \\* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\\.[\\r\\n]+ \\* See the License for the specific language governing permissions and[\\r\\n]+ \\* limitations under the License\\.", + "template": "*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n " + } + ] + ] }, "settings": { "react": { diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc index a2039fe..439efe7 100644 --- a/.markdownlint.jsonc +++ b/.markdownlint.jsonc @@ -1,6 +1,6 @@ { - "default": true, - "MD013": { - "line_length": 120 - } -} \ No newline at end of file + "default": true, + "MD013": { + "line_length": 120 + } +} diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..49955e2 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,5 @@ +{ + "semi": false, + "singleQuote": true, + "trailingComma": "none" +} diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md index f68624e..b930012 100644 --- a/CONTRIBUTE.md +++ b/CONTRIBUTE.md @@ -9,7 +9,7 @@ It also provides a step by step guide to add custom commands. ## Setup Environment -Before you start, make sure you have *nodejs*, *webpack* and *mocha* installed. +Before you start, make sure you have _nodejs_, _webpack_ and _mocha_ installed. To get started, you need to checkout the latest development version via git: @@ -18,7 +18,7 @@ git clone https://github.com/svrnm/demomonkey.git cd demomonkey ``` -Now, you need to download and install all dependencies for your development environment: +Now, you need to download and install all dependencies for your development environment: ```shell npm install @@ -46,7 +46,7 @@ Likely, the first thing you want to do, is adding a custom command to DemoMonkey customisations for your demo. In the following you will learn how to build such a custom command step by step. Let's start with a helloworld example. The goal of this first exercise is creating a command `!helloworld()` that just -replaces *all* text on the website with `hello world`. +replaces _all_ text on the website with `hello world`. First, create an empty file called `HelloWorld.js` in the folder `src/commands`. Next add the following code: @@ -55,9 +55,9 @@ import Command from './Command' class HelloWorld extends Command { apply(target, key) { - target[key] = 'hello world' + target[key] = 'hello world' return false - } + } } export default HelloWorld @@ -71,7 +71,7 @@ import HelloWorld from './HelloWorld' ``` Afterward add the following within the method body of `_buildCustomCommand` right before the comment -`// Add new commands above this line.`: +`// Add new commands above this line.`: ```javascript if (command === 'helloWorld') { @@ -112,7 +112,6 @@ First, adding parameters to your command is easy. Just add a constructor to your import Command from './Command' class HelloWorld extends Command { - constructor(hello, world) { super() this.hello = hello @@ -122,7 +121,7 @@ class HelloWorld extends Command { apply(target, key) { target[key] = this.hello + ' ' + this.world return false - } + } } export default HelloWorld @@ -143,7 +142,7 @@ Reload your extension and update your demo configuration to !helloWorld(hallo) = welt ``` -Now, reloading your demo page, you should see *hallo welt* everywhere instead of *hello world*. +Now, reloading your demo page, you should see _hallo welt_ everywhere instead of _hello world_. If you need further parameters `parameters[1], ..., parameters[n]`, just add them to your constructor and to the `CommandBuilder.js` as needed. @@ -155,7 +154,6 @@ import Command from './Command' import UndoElement from './UndoElement' class HelloWorld extends Command { - constructor(hello, world) { super() this.hello = hello @@ -170,7 +168,7 @@ class HelloWorld extends Command { return new UndoElement(target, key, original, replacement) } return false - } + } } export default HelloWorld diff --git a/README.md b/README.md index dc389a0..1573f4b 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ flight booking service. ## Usage -DemoMonkey is driven by __configurations__, that contain replace patterns in the following format: +DemoMonkey is driven by **configurations**, that contain replace patterns in the following format: ```ini eCommerce = Booking Service diff --git a/SHORTCUTS.md b/SHORTCUTS.md index 995d02f..3032abe 100644 --- a/SHORTCUTS.md +++ b/SHORTCUTS.md @@ -1,118 +1,118 @@ # Shortcuts -DemoMonkey uses the [Ace](https://ace.c9.io/) as editor component for the *Configuration* view. Ace comes with a +DemoMonkey uses the [Ace](https://ace.c9.io/) as editor component for the _Configuration_ view. Ace comes with a predefined [set of shortcuts](https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts) you can use, while editing your configurations. Below you will find a complete list. Please be aware, that not all commands might work with -DemoMonkey as expected. Additionally you can use *Ctrl+s / Command+s* to save your current configuration on every screen. +DemoMonkey as expected. Additionally you can use _Ctrl+s / Command+s_ to save your current configuration on every screen. ## Line Operations -| Windows/Linux | Mac | Action | -|:-------------------------------|:-------------------------------|:-------------------------------| -| Ctrl-D | Command-D | Remove line | -| Alt-Shift-Down | Command-Option-Down | Copy lines down | -| Alt-Shift-Up | Command-Option-Up | Copy lines up | -| Alt-Down | Option-Down | Move lines down | -| Alt-Up | Option-Up | Move lines up | -| Alt-Delete | Ctrl-K | Remove to line end | -| Alt-Backspace | Command-Backspace | Remove to linestart | -| Ctrl-Backspace | Option-Backspace, Ctrl-Option-Backspace | Remove word left | -| Ctrl-Delete | Option-Delete | Remove word right | -| --- | Ctrl-O | Split line | +| Windows/Linux | Mac | Action | +| :------------- | :-------------------------------------- | :------------------ | +| Ctrl-D | Command-D | Remove line | +| Alt-Shift-Down | Command-Option-Down | Copy lines down | +| Alt-Shift-Up | Command-Option-Up | Copy lines up | +| Alt-Down | Option-Down | Move lines down | +| Alt-Up | Option-Up | Move lines up | +| Alt-Delete | Ctrl-K | Remove to line end | +| Alt-Backspace | Command-Backspace | Remove to linestart | +| Ctrl-Backspace | Option-Backspace, Ctrl-Option-Backspace | Remove word left | +| Ctrl-Delete | Option-Delete | Remove word right | +| --- | Ctrl-O | Split line | ## Selection -| Windows/Linux | Mac | Action | -|:-------------------------------|:-------------------------------|:-------------------------------| -| Ctrl-A | Command-A | Select all | -| Shift-Left | Shift-Left | Select left | -| Shift-Right | Shift-Right | Select right | -| Ctrl-Shift-Left | Option-Shift-Left | Select word left | -| Ctrl-Shift-Right | Option-Shift-Right | Select word right | -| Shift-Home | Shift-Home | Select line start | -| Shift-End | Shift-End | Select line end | -| Alt-Shift-Right | Command-Shift-Right | Select to line end | -| Alt-Shift-Left | Command-Shift-Left | Select to line start | -| Shift-Up | Shift-Up | Select up | -| Shift-Down | Shift-Down | Select down | -| Shift-PageUp | Shift-PageUp | Select page up | -| Shift-PageDown | Shift-PageDown | Select page down | -| Ctrl-Shift-Home | Command-Shift-Up | Select to start | -| Ctrl-Shift-End | Command-Shift-Down | Select to end | -| Ctrl-Shift-D | Command-Shift-D | Duplicate selection | -| Ctrl-Shift-P | --- | Select to matching bracket | +| Windows/Linux | Mac | Action | +| :--------------- | :------------------ | :------------------------- | +| Ctrl-A | Command-A | Select all | +| Shift-Left | Shift-Left | Select left | +| Shift-Right | Shift-Right | Select right | +| Ctrl-Shift-Left | Option-Shift-Left | Select word left | +| Ctrl-Shift-Right | Option-Shift-Right | Select word right | +| Shift-Home | Shift-Home | Select line start | +| Shift-End | Shift-End | Select line end | +| Alt-Shift-Right | Command-Shift-Right | Select to line end | +| Alt-Shift-Left | Command-Shift-Left | Select to line start | +| Shift-Up | Shift-Up | Select up | +| Shift-Down | Shift-Down | Select down | +| Shift-PageUp | Shift-PageUp | Select page up | +| Shift-PageDown | Shift-PageDown | Select page down | +| Ctrl-Shift-Home | Command-Shift-Up | Select to start | +| Ctrl-Shift-End | Command-Shift-Down | Select to end | +| Ctrl-Shift-D | Command-Shift-D | Duplicate selection | +| Ctrl-Shift-P | --- | Select to matching bracket | ## Multicursor -| Windows/Linux | Mac | Action | -|:-------------------------------|:-------------------------------|:-------------------------------| -| Ctrl-Alt-Up | Ctrl-Option-Up | Add multi-cursor above | -| Ctrl-Alt-Down | Ctrl-Option-Down | Add multi-cursor below | -| Ctrl-Alt-Right | Ctrl-Option-Right | Add next occurrence to multi-selection | -| Ctrl-Alt-Left | Ctrl-Option-Left | Add previous occurrence to multi-selection | -| Ctrl-Alt-Shift-Up | Ctrl-Option-Shift-Up | Move multicursor from current line to the line above | -| Ctrl-Alt-Shift-Down | Ctrl-Option-Shift-Down | Move multicursor from current line to the line below | -| Ctrl-Alt-Shift-Right | Ctrl-Option-Shift-Right | Remove current occurrence from multi-selection and move to next | -| Ctrl-Alt-Shift-Left | Ctrl-Option-Shift-Left | Remove current occurrence from multi-selection and move to previous | -| Ctrl-Shift-L | Ctrl-Shift-L | Select all from multi-selection | +| Windows/Linux | Mac | Action | +| :------------------- | :---------------------- | :------------------------------------------------------------------ | +| Ctrl-Alt-Up | Ctrl-Option-Up | Add multi-cursor above | +| Ctrl-Alt-Down | Ctrl-Option-Down | Add multi-cursor below | +| Ctrl-Alt-Right | Ctrl-Option-Right | Add next occurrence to multi-selection | +| Ctrl-Alt-Left | Ctrl-Option-Left | Add previous occurrence to multi-selection | +| Ctrl-Alt-Shift-Up | Ctrl-Option-Shift-Up | Move multicursor from current line to the line above | +| Ctrl-Alt-Shift-Down | Ctrl-Option-Shift-Down | Move multicursor from current line to the line below | +| Ctrl-Alt-Shift-Right | Ctrl-Option-Shift-Right | Remove current occurrence from multi-selection and move to next | +| Ctrl-Alt-Shift-Left | Ctrl-Option-Shift-Left | Remove current occurrence from multi-selection and move to previous | +| Ctrl-Shift-L | Ctrl-Shift-L | Select all from multi-selection | ## Go to -| Windows/Linux | Mac | Action | -|:-------------------------------|:-------------------------------|:-------------------------------| -| Left | Left, Ctrl-B | Go to left | -| Right | Right, Ctrl-F | Go to right | -| Ctrl-Left | Option-Left | Go to word left | -| Ctrl-Right | Option-Right | Go to word right | -| Up | Up, Ctrl-P | Go line up | -| Down | Down, Ctrl-N | Go line down | -| Alt-Left, Home | Command-Left, Home, Ctrl-A | Go to line start | -| Alt-Right, End | Command-Right, End, Ctrl-E | Go to line end | -| PageUp | Option-PageUp | Go to page up | -| PageDown | Option-PageDown, Ctrl-V | Go to page down | -| Ctrl-Home | Command-Home, Command-Up | Go to start | -| Ctrl-End | Command-End, Command-Down | Go to end | -| Ctrl-L | Command-L | Go to line | -| Ctrl-Down | Command-Down | Scroll line down | -| Ctrl-Up | --- | Scroll line up | -| Ctrl-P | --- | Go to matching bracket | -| --- | Option-PageDown | Scroll page down | -| --- | Option-PageUp | Scroll page up | +| Windows/Linux | Mac | Action | +| :------------- | :------------------------- | :--------------------- | +| Left | Left, Ctrl-B | Go to left | +| Right | Right, Ctrl-F | Go to right | +| Ctrl-Left | Option-Left | Go to word left | +| Ctrl-Right | Option-Right | Go to word right | +| Up | Up, Ctrl-P | Go line up | +| Down | Down, Ctrl-N | Go line down | +| Alt-Left, Home | Command-Left, Home, Ctrl-A | Go to line start | +| Alt-Right, End | Command-Right, End, Ctrl-E | Go to line end | +| PageUp | Option-PageUp | Go to page up | +| PageDown | Option-PageDown, Ctrl-V | Go to page down | +| Ctrl-Home | Command-Home, Command-Up | Go to start | +| Ctrl-End | Command-End, Command-Down | Go to end | +| Ctrl-L | Command-L | Go to line | +| Ctrl-Down | Command-Down | Scroll line down | +| Ctrl-Up | --- | Scroll line up | +| Ctrl-P | --- | Go to matching bracket | +| --- | Option-PageDown | Scroll page down | +| --- | Option-PageUp | Scroll page up | ## Find/Replace -| Windows/Linux | Mac | Action | -|:-------------------------------|:-------------------------------|:-------------------------------| -| Ctrl-F | Command-F | Find | -| Ctrl-H | Command-Option-F | Replace | -| Ctrl-K | Command-G | Find next | -| Ctrl-Shift-K | Command-Shift-G | Find previous | +| Windows/Linux | Mac | Action | +| :------------ | :--------------- | :------------ | +| Ctrl-F | Command-F | Find | +| Ctrl-H | Command-Option-F | Replace | +| Ctrl-K | Command-G | Find next | +| Ctrl-Shift-K | Command-Shift-G | Find previous | ## Folding -| Windows/Linux | Mac | Action | -|:-------------------------------|:-------------------------------|:-------------------------------| -| Alt-L, Ctrl-F1 | Command-Option-L, Command-F1 | Fold selection | -| Alt-Shift-L, Ctrl-Shift-F1 | Command-Option-Shift-L, Command-Shift-F1 | Unfold | -| Alt-0 | Command-Option-0 | Fold all | -| Alt-Shift-0 | Command-Option-Shift-0 | Unfold all | +| Windows/Linux | Mac | Action | +| :------------------------- | :--------------------------------------- | :------------- | +| Alt-L, Ctrl-F1 | Command-Option-L, Command-F1 | Fold selection | +| Alt-Shift-L, Ctrl-Shift-F1 | Command-Option-Shift-L, Command-Shift-F1 | Unfold | +| Alt-0 | Command-Option-0 | Fold all | +| Alt-Shift-0 | Command-Option-Shift-0 | Unfold all | ## Other -| Windows/Linux | Mac | Action | -|:-------------------------------|:-------------------------------|:-------------------------------| -| Tab | Tab | Indent | -| Shift-Tab | Shift-Tab | Outdent | -| Ctrl-Z | Command-Z | Undo | -| Ctrl-Shift-Z, Ctrl-Y | Command-Shift-Z, Command-Y | Redo | -| Ctrl-, | Command-, | Show the settings menu | -| Ctrl-/ | Command-/ | Toggle comment | -| Ctrl-T | Ctrl-T | Transpose letters | -| Ctrl-Enter | Command-Enter | Enter full screen | -| Ctrl-Shift-U | Ctrl-Shift-U | Change to lower case | -| Ctrl-U | Ctrl-U | Change to upper case | -| Insert | Insert | Overwrite | -| Ctrl-Shift-E | Command-Shift-E | Macros replay | -| Ctrl-Alt-E | --- | Macros recording | -| Delete | --- | Delete | -| --- | Ctrl-L | Center selection | +| Windows/Linux | Mac | Action | +| :------------------- | :------------------------- | :--------------------- | +| Tab | Tab | Indent | +| Shift-Tab | Shift-Tab | Outdent | +| Ctrl-Z | Command-Z | Undo | +| Ctrl-Shift-Z, Ctrl-Y | Command-Shift-Z, Command-Y | Redo | +| Ctrl-, | Command-, | Show the settings menu | +| Ctrl-/ | Command-/ | Toggle comment | +| Ctrl-T | Ctrl-T | Transpose letters | +| Ctrl-Enter | Command-Enter | Enter full screen | +| Ctrl-Shift-U | Ctrl-Shift-U | Change to lower case | +| Ctrl-U | Ctrl-U | Change to upper case | +| Insert | Insert | Overwrite | +| Ctrl-Shift-E | Command-Shift-E | Macros replay | +| Ctrl-Alt-E | --- | Macros recording | +| Delete | --- | Delete | +| --- | Ctrl-L | Center selection | diff --git a/USAGE.md b/USAGE.md index 6479849..1f160ec 100644 --- a/USAGE.md +++ b/USAGE.md @@ -6,47 +6,47 @@ into a personalized experience for your audience.** **Curious how this works? Read on to learn how you can use DemoMonkey, to tamper your web application to demo almost anything.** -* [Configurations](#configurations) -* [Options](#options) - * [Include and Exclude sites](#include-and-exclude-sites) - * [Namespaces](#namespaces) - * [Block- and Allowlist tags](#block--and-allowlist-tags) - * [Text Attributes](#text-attributes) - * [Deprecate configuration](#deprecate-configuration) - * [Tags](#tags) - * [Authors and more](#authors-and-more) -* [Variables](#variables) - * [Global Variables](#global-variables) - * [Variables with random value](#variables-with-random-value) -* [Imports: Reuse existing configurations](#imports-reuse-existing-configurations) -* [Snippets](#snippets) -* [Generic Commands](#generic-commands) - * [Run regular expressions](#run-regular-expressions) - * [Replace with filters](#replace-with-filters) - * [Replace Attribute](#replace-attribute) - * [Search and Hash](#search-and-hash) - * [Protect text from replacements](#protect-text-from-replacements) - * [Hide Elements](#hide-elements) - * [Replace Images](#replace-images) - * [Recolor images](#recolor-images) - * [Block, Delay, Redirect URLs](#block-delay-redirect-urls) - * [Conditional Replacements](#conditional-replacements) - * [Modify CSS](#modify-css) - * [Overwrite HTML](#overwrite-html) - * [Replace based on CSS selector](#replace-based-on-css-selector) - * [Add Javascript](#add-javascript) - * [Replace Neighbor](#replace-neighbor) - * [Insert before and after a DOM element](#insert-before-and-after-a-dom-element) - * [Replace and patch response of AJAX requests](#replace-and-patch-response-of-ajax-requests) - * [Demo Stages](#demo-stages) -* [Commands in Namespaces](#commands-in-namespaces) - * [AppDynamics](#appdynamics) - * [Replace Flowmap Icons](#replace-flowmap-icons) - * [Hide Applications, Databases, BTs](#hide-applications-databases-bts) - * [Replace Flowmap Connections](#replace-flowmap-connections) - * [Replace Flowmap Node Count](#replace-flowmap-node-count) - * [Replace EUM Geo Status](#replace-eum-geo-status) -* [Learn More](#learn-more) +- [Configurations](#configurations) +- [Options](#options) + - [Include and Exclude sites](#include-and-exclude-sites) + - [Namespaces](#namespaces) + - [Block- and Allowlist tags](#block--and-allowlist-tags) + - [Text Attributes](#text-attributes) + - [Deprecate configuration](#deprecate-configuration) + - [Tags](#tags) + - [Authors and more](#authors-and-more) +- [Variables](#variables) + - [Global Variables](#global-variables) + - [Variables with random value](#variables-with-random-value) +- [Imports: Reuse existing configurations](#imports-reuse-existing-configurations) +- [Snippets](#snippets) +- [Generic Commands](#generic-commands) + - [Run regular expressions](#run-regular-expressions) + - [Replace with filters](#replace-with-filters) + - [Replace Attribute](#replace-attribute) + - [Search and Hash](#search-and-hash) + - [Protect text from replacements](#protect-text-from-replacements) + - [Hide Elements](#hide-elements) + - [Replace Images](#replace-images) + - [Recolor images](#recolor-images) + - [Block, Delay, Redirect URLs](#block-delay-redirect-urls) + - [Conditional Replacements](#conditional-replacements) + - [Modify CSS](#modify-css) + - [Overwrite HTML](#overwrite-html) + - [Replace based on CSS selector](#replace-based-on-css-selector) + - [Add Javascript](#add-javascript) + - [Replace Neighbor](#replace-neighbor) + - [Insert before and after a DOM element](#insert-before-and-after-a-dom-element) + - [Replace and patch response of AJAX requests](#replace-and-patch-response-of-ajax-requests) + - [Demo Stages](#demo-stages) +- [Commands in Namespaces](#commands-in-namespaces) + - [AppDynamics](#appdynamics) + - [Replace Flowmap Icons](#replace-flowmap-icons) + - [Hide Applications, Databases, BTs](#hide-applications-databases-bts) + - [Replace Flowmap Connections](#replace-flowmap-connections) + - [Replace Flowmap Node Count](#replace-flowmap-node-count) + - [Replace EUM Geo Status](#replace-eum-geo-status) +- [Learn More](#learn-more) ## Configurations @@ -105,7 +105,7 @@ This protects you from having a monkey on every website: ; The configuration only works on sites that include demomonkey @include[] = /demomonkey/ ; The configuration does not work on demomonkey.net -@exclude[] = /demomonkey.net/ +@exclude[] = /demomonkey.net/ ``` If your configuration is a template or snippet (see below), you can disable the warning that an **@include** or **@exclude** @@ -409,20 +409,20 @@ If you want to hook only into certain types of requests, you can provide a type The available types are: -* `*` -* `main_frame` -* `sub_frame` -* `stylesheet` -* `script` -* `image` -* `font` -* `object` -* `xmlhttprequest` -* `ping` -* `csp_report` -* `media` -* `websocket` -* `other` +- `*` +- `main_frame` +- `sub_frame` +- `stylesheet` +- `script` +- `image` +- `font` +- `object` +- `xmlhttprequest` +- `ping` +- `csp_report` +- `media` +- `websocket` +- `other` ### Conditional Replacements @@ -553,7 +553,7 @@ and turn on `Hook into Ajax`. Now you can replace a response or you can apply a ```ini ; replace the whole response with the given replacement !replaceAjaxResponse(/v1/items) = '[{"name": "Demo"}, {"name": "Monkey"}]' -; apply a search and replace on the response, +; apply a search and replace on the response, ; here every occurrence of "Example" is replaced with "DemoMonkey" !replaceAjaxResponse(/v1/items, Example) = DemoMonkey ; apply a json patch on the given response diff --git a/manifest.json b/manifest.json index 37f0bde..f1031ea 100644 --- a/manifest.json +++ b/manifest.json @@ -8,20 +8,22 @@ "content_security_policy": { "sandbox": "sandbox allow-scripts; script-src 'self' 'unsafe-eval'; object-src 'self'" }, - "icons": { + "icons": { "16": "icons/monkey_16.png", "48": "icons/monkey_48.png", "128": "icons/monkey_128.png" }, - "web_accessible_resources": [{ - "resources": [ - "manifest.json", - "COMMITHASH", - "js/inline.js", - "js/index.js.map" - ], - "matches": [""] - }], + "web_accessible_resources": [ + { + "resources": [ + "manifest.json", + "COMMITHASH", + "js/inline.js", + "js/index.js.map" + ], + "matches": [""] + } + ], "background": { "service_worker": "js/background.js" }, @@ -35,11 +37,15 @@ "default_popup": "popup.html" }, "permissions": [ - "storage", "unlimitedStorage", "activeTab", "contextMenus", "scripting", "declarativeNetRequest", "alarms" - ], - "optional_host_permissions": [ - "" + "storage", + "unlimitedStorage", + "activeTab", + "contextMenus", + "scripting", + "declarativeNetRequest", + "alarms" ], + "optional_host_permissions": [""], "commands": { "live-mode": { "suggested_key": { diff --git a/pages/backup.html b/pages/backup.html index b04d2a3..399e18b 100644 --- a/pages/backup.html +++ b/pages/backup.html @@ -1,24 +1,34 @@ - + - - - - - - + + + + + +

Backup

-

If you would ever run into issues with DemoMonkey and need to reinstall you can download all your - configurations using the following links. If you want to copy them into a TamperMonkey script use - the json download. Pay attention, that you have to fix variables, commands, imports, ...

-

- If your storage is not well-formatted, you can edit it here. Please use this with caution! - This page will reload, when you click on 'Save Storage'. Also, you will need to "reset" the extension - via the extension manager to get your changes applied. + If you would ever run into issues with DemoMonkey and need to reinstall you + can download all your configurations using the following links. If you want + to copy them into a TamperMonkey script use the json download. Pay + attention, that you have to fix variables, commands, imports, ... +

+
    +

    + If your storage is not well-formatted, you can edit it here. Please use this + with caution! This page will reload, when you click on 'Save Storage'. Also, + you will need to "reset" the extension via the extension manager to get your + changes applied.

    -
    - +
    + +
    +
    - diff --git a/pages/template.html b/pages/template.html index 3f199da..7d47129 100644 --- a/pages/template.html +++ b/pages/template.html @@ -1,17 +1,38 @@ -class="<%= htmlWebpackPlugin.options.htmlClass %>"<% } %>> - - - <%= htmlWebpackPlugin.options.title %> - + + class="<%= htmlWebpackPlugin.options.htmlClass %>"<% } %>> + + + <%= htmlWebpackPlugin.options.title %> + - <% if (htmlWebpackPlugin.options.appname) { %> + <% if (htmlWebpackPlugin.options.appname) { %>
    - If you see this message, DemoMonkey is broken. You can access your scripts to backup by opening the backup page. -
    If you want to fix this issue, open the console of the developer toolbar for this page and the background script to check for JavaScript errors. + If you see this message, DemoMonkey is broken. You can access your scripts + to backup by opening the backup page.
    + If you want to fix this issue, open the console of the developer toolbar + for this page and the background script to check for JavaScript errors.
    -
    -
    - <% } %> +
    +
    + <% } %> - \ No newline at end of file + diff --git a/pages/test.html b/pages/test.html index 2a523d3..853bb7c 100644 --- a/pages/test.html +++ b/pages/test.html @@ -1,561 +1,1519 @@ - + - - - - - - -
    -

    DemoMonkey Test Page

    -
    - + + + + + +
    +

    DemoMonkey Test Page

    +
    -
    - - - +
    + + + -
    Test
    -
    - -
    -

    AJAX

    -
    San Francisco
    -
    - -
    +
    + +
    +

    AJAX

    +
    San Francisco
    +
    - -
    + + - - - - - - - - - - - - - - 17 calls / min, 1.1 s - 17 calls / min, 1.1 s - - JDBC - JDBC - - - - - 3 calls / min, 2 ms (async) - 3 calls / min, 2 ms (async) - - JMS - JMS - - - - - 13 calls / min, 2.1 s - 13 calls / min, 2.1 s - - MODULE - MODULE - - - - - 6 calls / min, 734 ms (async) - 6 calls / min, 734 ms (async) - - HTTP - HTTP - - - - - 9 calls / min, 3 ms (async) - 9 calls / min, 3 ms (async) - - JMS - JMS - - - - - 22 calls / min, 2.7 s - 22 calls / min, 2.7 s - - HTTP - HTTP - - - - - 22 calls / min, - (async) - 22 calls / min, - (async) - - JMS - JMS - - - - - 6 calls / min, 642 ms (async) - 6 calls / min, 642 ms (async) - - HTTP - HTTP - - - - - 203 calls / min, 2 ms - 203 calls / min, 2 ms - - JDBC - JDBC - - - - - 3 calls / min, 392 ms - 3 calls / min, 392 ms - - HTTP - HTTP - - - - - 9 calls / min, - (async) - 9 calls / min, - (async) - - JMS - JMS - - - - - 40 calls / min, 534 ms - 40 calls / min, 534 ms - - (multiple) - (multiple) - - - - - 273 calls / min, 1 ms - 273 calls / min, 1 ms - - JDBC - JDBC - - - - - 36 calls / min, 373 ms - 36 calls / min, 373 ms - - JDBC - JDBC - - - - - 14 calls / min, 4 ms (async) - 14 calls / min, 4 ms (async) - - JMS - JMS - - - ECommerce-Services - - - - - - - 2Nodes - - + + + + + + + + + + + + + + + + 17 calls / min, 1.1 s + + + 17 calls / min, 1.1 s + + + + JDBC + JDBC + - - 119 calls / min - 119 calls / min - - 1.2 s - 1.2 s - - 18 errors / min - 18 errors / min - - - ECommerce-Services - ECommerce-Services - - - - Inventory-Services - - - - - - - 1Node - - + + + + + + 3 calls / min, 2 ms (async) + + + 3 calls / min, 2 ms (async) + + + + JMS + JMS + - - 39 calls / min - 39 calls / min - - 549 ms - 549 ms - - - Inventory-Services - Inventory-Services - - - - Order-Processing-Services - - - - - - - 1Node - - + + + + + + 13 calls / min, 2.1 s + + + 13 calls / min, 2.1 s + + + + MODULE + MODULE + - - 31 calls / min - 31 calls / min - - 1.9 s - 1.9 s - - - Order-Processing-Services - Order-Processing-Services - - - - Web-Tier-Services - - - - - - - 1Node - - + + + + + + 6 calls / min, 734 ms (async) + + + 6 calls / min, 734 ms (async) + + + + HTTP + HTTP + - - 13 calls / min - 13 calls / min - - 2.1 s - 2.1 s - - 9 errors / min - 9 errors / min - - - Web-Tier-Services - Web-Tier-Services - - - - Active MQ-OrderQueue - - - Active MQ-OrderQueue - Active MQ-OrderQueue - - - - Active MQ-CustomerQueue - - - Active MQ-CustomerQueue - Active MQ-CustomerQueue - - - - Active MQ-fulfillmentQueue - - - Active MQ-fulfillmentQueue - Active MQ-fulfillmentQueue - - - - XE-Oracle-ORACLE-DB-Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production - - - XE-Oracle-ORACL...4bit Production - XE-Oracle-ORACL...4bit Production - - - - APPDY-MySQL-DB-5.5.5-10.1.38-MariaDB - - - APPDY-MySQL-DB-...10.1.38-MariaDB - APPDY-MySQL-DB-...10.1.38-MariaDB - - - - api.shipping.com - - - api.shipping.com - api.shipping.com - - - - INVENTORY-MySQL DB-DB-5.5.5-10.1.38-MariaDB - - - INVENTORY-MySQL...10.1.38-MariaDB - INVENTORY-MySQL...10.1.38-MariaDB - - - - api.secondarysupplier.com - - - api.secondarysupplier.com - api.secondarysupplier.com - - - - api.mainsupplier.com - - - api.mainsupplier.com - api.mainsupplier.com - - - - ECommerce-Fulfillment - - - - - - - - - - - 1TIER1NODE - + + + + + + 9 calls / min, 3 ms (async) + + + 9 calls / min, 3 ms (async) + + + + JMS + JMS + + + + + + + + 22 calls / min, 2.7 s + + + 22 calls / min, 2.7 s + + + + HTTP + HTTP + + + + + + + + 22 calls / min, - (async) + + + 22 calls / min, - (async) + + + + JMS + JMS + + + + + + + + 6 calls / min, 642 ms (async) + + + 6 calls / min, 642 ms (async) + + + + HTTP + HTTP + + + + + + + + 203 calls / min, 2 ms + + + 203 calls / min, 2 ms + + + + JDBC + JDBC + + + + + + + + 3 calls / min, 392 ms + + + 3 calls / min, 392 ms + + + + HTTP + HTTP + + + + + + + + 9 calls / min, - (async) + + + 9 calls / min, - (async) + + + + JMS + JMS + + + + + + + + 40 calls / min, 534 ms + + + 40 calls / min, 534 ms + + + + (multiple) + (multiple) + + + + + + + + 273 calls / min, 1 ms + + + 273 calls / min, 1 ms + + + + JDBC + JDBC + + + + + + + + 36 calls / min, 373 ms + + + 36 calls / min, 373 ms + + + + JDBC + JDBC + + + + + + + + 14 calls / min, 4 ms (async) + + + 14 calls / min, 4 ms (async) + + + + JMS + JMS + + + + ECommerce-Services + + + + + + + + + 2 + + + Nodes + + + + + + + + + 119 calls / min + + + 119 calls / min + + + + 1.2 s + 1.2 s + + + + 18 errors / min + + + 18 errors / min + + + + + + + ECommerce-Services + + + ECommerce-Services + + + + + + Inventory-Services + + + + + + + + + 1 + + + Node + + + + + + + + + 39 calls / min + + 39 calls / min + + + 549 ms + 549 ms + + + + + + Inventory-Services + + + Inventory-Services + + + + + + Order-Processing-Services + + + + + + + + + 1 + + + Node + + + + + + + + + 31 calls / min + + 31 calls / min + + + 1.9 s + 1.9 s + + + + + + Order-Processing-Services + + + Order-Processing-Services + + + + + + Web-Tier-Services + + + + + + + + + 1 + + + Node + + + + + + + + + 13 calls / min + + 13 calls / min + + + 2.1 s + 2.1 s + + + + 9 errors / min + + 9 errors / min + + + + + + Web-Tier-Services + + + Web-Tier-Services + + + + + + Active MQ-OrderQueue + + + + + Active MQ-OrderQueue + + + Active MQ-OrderQueue + + + + + + Active MQ-CustomerQueue + + + + + Active MQ-CustomerQueue + + + Active MQ-CustomerQueue + + + + + + Active MQ-fulfillmentQueue + + + + + Active MQ-fulfillmentQueue + + + Active MQ-fulfillmentQueue + + + + + + + XE-Oracle-ORACLE-DB-Oracle Database 11g Express Edition Release + 11.2.0.2.0 - 64bit Production + + + + + + XE-Oracle-ORACL...4bit Production + + + XE-Oracle-ORACL...4bit Production + + + + + + APPDY-MySQL-DB-5.5.5-10.1.38-MariaDB + + + + + APPDY-MySQL-DB-...10.1.38-MariaDB + + + APPDY-MySQL-DB-...10.1.38-MariaDB + + + + + + api.shipping.com + + + + + api.shipping.com + + + api.shipping.com + + + + + + INVENTORY-MySQL DB-DB-5.5.5-10.1.38-MariaDB + + + + + INVENTORY-MySQL...10.1.38-MariaDB + + + INVENTORY-MySQL...10.1.38-MariaDB + + + + + + api.secondarysupplier.com + + + + + api.secondarysupplier.com + + + api.secondarysupplier.com + + + + + + api.mainsupplier.com + + + + + api.mainsupplier.com + + + api.mainsupplier.com + + + + + + ECommerce-Fulfillment + + + + + + + + + + + + + 1 + + + TIER + + + 1 + + + NODE + + + + + + + 22 calls / min + + 22 calls / min + + + 2.7 s + 2.7 s + + + + + + ECommerce-Fulfillment + + + ECommerce-Fulfillment + + + - - 22 calls / min - 22 calls / min - - 2.7 s - 2.7 s - - - ECommerce-Fulfillment - ECommerce-Fulfillment - - + - -
    -
    - - - - +
    +
    + + + diff --git a/src/app.js b/src/app.js index 2759bcd..613a23d 100644 --- a/src/app.js +++ b/src/app.js @@ -35,19 +35,32 @@ function updateCurrentView(v) { function renderOptionsPageApp(root, store) { window.chrome.permissions.getAll(function (permissions) { - root.render( + root.render( + updateCurrentView(v)} permissions={permissions} /> - ) + + ) }) - window.chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { - if (request.receiver && request.receiver === 'dashboard' && typeof request.logMessage !== 'undefined') { + window.chrome.runtime.onMessage.addListener(function ( + request, + sender, + sendResponse + ) { + if ( + request.receiver && + request.receiver === 'dashboard' && + typeof request.logMessage !== 'undefined' + ) { console.log('Message received', request.logMessage) - const msg = typeof request.logMessage === 'string' ? request.logMessage : JSON.stringify(request.logMessage) + const msg = + typeof request.logMessage === 'string' + ? request.logMessage + : JSON.stringify(request.logMessage) const mbox = document.getElementById('message-box') mbox.className = 'fade-to-visible' mbox.innerHTML = '(' + new Date().toLocaleTimeString() + ') ' + msg @@ -63,15 +76,21 @@ function renderOptionsPageApp(root, store) { } function renderPopupPageApp(root, store, manifest) { - window.chrome.tabs.query({ active: true, lastFocusedWindow: true }, function (tabs) { - const currentUrl = tabs.length > 0 ? tabs[0].url : '' - root.render( - ) - // The following is required to fix https://bugs.chromium.org/p/chromium/issues/detail?id=428044 - window.setTimeout(() => { - document.body.style.minHeight = (document.body.clientHeight + 1) + 'px' - }, 200) - }) + window.chrome.tabs.query( + { active: true, lastFocusedWindow: true }, + function (tabs) { + const currentUrl = tabs.length > 0 ? tabs[0].url : '' + root.render( + + + + ) + // The following is required to fix https://bugs.chromium.org/p/chromium/issues/detail?id=428044 + window.setTimeout(() => { + document.body.style.minHeight = document.body.clientHeight + 1 + 'px' + }, 200) + } + ) } const store = new Store({ @@ -79,55 +98,76 @@ const store = new Store({ }) let commitHash = '' -fetch(window.chrome.runtime.getURL('COMMITHASH')).then((r) => { - return r.text() -}).then(r => { - commitHash = r -}).catch((e) => { - // Could not fetch COMMITHASH, that should never happen, but we have a safeguard here. - console.log(e) -}).finally(() => { - store.ready().then(() => { - document.getElementById('backup-message').remove() - const rootElement = document.getElementById('app') +fetch(window.chrome.runtime.getURL('COMMITHASH')) + .then((r) => { + return r.text() + }) + .then((r) => { + commitHash = r + }) + .catch((e) => { + // Could not fetch COMMITHASH, that should never happen, but we have a safeguard here. + console.log(e) + }) + .finally(() => { + store.ready().then(() => { + document.getElementById('backup-message').remove() + const rootElement = document.getElementById('app') - window.store = store + window.store = store - const app = rootElement.getAttribute('data-app') + const app = rootElement.getAttribute('data-app') - const root = createRoot(rootElement) + const root = createRoot(rootElement) - if (store.getState().settings.optionalFeatures.writeLogs) { - connectLogger(store, { source: 'monkey.js' }) - } + if (store.getState().settings.optionalFeatures.writeLogs) { + connectLogger(store, { source: 'monkey.js' }) + } - // updateCurrentPage() + // updateCurrentPage() - const manifest = new Manifest(window.chrome, commitHash) + const manifest = new Manifest(window.chrome, commitHash) - logger('debug', `DemoMonkey ${manifest.version()}`).write() + logger('debug', `DemoMonkey ${manifest.version()}`).write() - const protocolHandler = new ProtocolHandler('web+mnky:') - protocolHandler.handle(window.location.search).catch(error => { - logger('error', error).write() - window.history.replaceState({}, document.title, window.location.pathname + window.location.hash) - }).then((configuration) => { - if (configuration) { - const configurations = store.getState().configurations - store.dispatch({ type: 'ADD_CONFIGURATION', configuration }).then(() => { - const latest = configurations[configurations.length - 1] - store.dispatch({ type: 'SET_CURRENT_VIEW', view: `configuration/${latest.id}` }) + const protocolHandler = new ProtocolHandler('web+mnky:') + protocolHandler + .handle(window.location.search) + .catch((error) => { + logger('error', error).write() + window.history.replaceState( + {}, + document.title, + window.location.pathname + window.location.hash + ) + }) + .then((configuration) => { + if (configuration) { + const configurations = store.getState().configurations + store + .dispatch({ type: 'ADD_CONFIGURATION', configuration }) + .then(() => { + const latest = configurations[configurations.length - 1] + store.dispatch({ + type: 'SET_CURRENT_VIEW', + view: `configuration/${latest.id}` + }) + }) + window.history.replaceState( + {}, + document.title, + window.location.pathname + window.location.hash + ) + } + }) + .finally(() => { + switch (app) { + case 'OptionsPageApp': + renderOptionsPageApp(root, store) + break + default: + renderPopupPageApp(root, store, manifest) + } }) - window.history.replaceState({}, document.title, window.location.pathname + window.location.hash) - } - }).finally(() => { - switch (app) { - case 'OptionsPageApp': - renderOptionsPageApp(root, store) - break - default: - renderPopupPageApp(root, store, manifest) - } }) }) -}) diff --git a/src/background.js b/src/background.js index fa3d78a..a42f5aa 100644 --- a/src/background.js +++ b/src/background.js @@ -23,7 +23,7 @@ import { logger, connectLogger } from './helpers/logger' import LiveModeAlarm from './models/LiveModeAlarm' try { - (function (scope) { + ;(function (scope) { 'use strict' let enabledHotkeyGroup = -1 @@ -31,28 +31,45 @@ try { scope.chrome.storage.session.set({ badgeData: { timer, tabs } }) }) - const netRequestManager = new NetRequestManager(scope.chrome.declarativeNetRequest, logger) - - const liveModeAlarm = new LiveModeAlarm(scope.chrome.alarms, logger, badge, ({ startTime }) => { - scope.chrome.storage.session.set({ liveModeAlarmData: { startTime } }) - }) + const netRequestManager = new NetRequestManager( + scope.chrome.declarativeNetRequest, + logger + ) + + const liveModeAlarm = new LiveModeAlarm( + scope.chrome.alarms, + logger, + badge, + ({ startTime }) => { + scope.chrome.storage.session.set({ liveModeAlarmData: { startTime } }) + } + ) // recover states - scope.chrome.storage.session.get({ - badgeData: { - timer: -1, tabs: [] - }, - liveModeAlarmData: { - startTime: -1 + scope.chrome.storage.session.get( + { + badgeData: { + timer: -1, + tabs: [] + }, + liveModeAlarmData: { + startTime: -1 + }, + hotKeyGroupData: { + enabledHotkeyGroup: -1 + } }, - hotKeyGroupData: { - enabledHotkeyGroup: -1 + ({ + badgeData, + netRequestManagerData, + liveModeAlarmData, + hotKeyGroupData + }) => { + badge.load(badgeData.tabs, badgeData.timer) + liveModeAlarm.load(liveModeAlarmData.startTime) + enabledHotkeyGroup = hotKeyGroupData.enabledHotkeyGroup } - }, ({ badgeData, netRequestManagerData, liveModeAlarmData, hotKeyGroupData }) => { - badge.load(badgeData.tabs, badgeData.timer) - liveModeAlarm.load(liveModeAlarmData.startTime) - enabledHotkeyGroup = hotKeyGroupData.enabledHotkeyGroup - }) + ) liveModeAlarm.registerAlarmListener() @@ -75,9 +92,9 @@ try { }) /* - * The following replaces the declarative content scripts, which require - * high host permissions. - */ + * The following replaces the declarative content scripts, which require + * high host permissions. + */ scope.chrome.tabs.onUpdated.addListener(function (tabId, changeInfo) { if (changeInfo.status !== 'loading') { return @@ -85,22 +102,34 @@ try { scope.chrome.tabs.get(tabId, (tab) => { if (tab.url) { logger('debug', 'Trying to inject for', tabId, tab.url).write() - scope.chrome.scripting.executeScript({ - target: { tabId, allFrames: true }, - files: ['js/monkey.js'], - injectImmediately: true - }, () => { - logger('debug', 'Injection completed for', tabId, tab.url).write() - }) + scope.chrome.scripting.executeScript( + { + target: { tabId, allFrames: true }, + files: ['js/monkey.js'], + injectImmediately: true + }, + () => { + logger('debug', 'Injection completed for', tabId, tab.url).write() + } + ) } else { - logger('warn', 'Did not inject into tab ', tabId, ': Permission denied').write() + logger( + 'warn', + 'Did not inject into tab ', + tabId, + ': Permission denied' + ).write() badge.updateDemoCounter('!') } }) }) scope.chrome.tabs.onRemoved.addListener(function (tabId) { - logger('debug', 'Tab closed, cleaning up badge & netRequestManager', tabId).write() + logger( + 'debug', + 'Tab closed, cleaning up badge & netRequestManager', + tabId + ).write() badge.removeTab(tabId) netRequestManager.removeTab(tabId) }) @@ -113,15 +142,31 @@ try { scope.chrome.tabs.sendMessage(tab.tabId, { active: tab.tabId }) }) - scope.chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { + scope.chrome.runtime.onMessage.addListener(function ( + request, + sender, + sendResponse + ) { if (request.receiver && request.receiver === 'background') { - if (typeof request.count === 'number' && typeof sender.tab === 'object' && typeof sender.tab.id === 'number') { + if ( + typeof request.count === 'number' && + typeof sender.tab === 'object' && + typeof sender.tab.id === 'number' + ) { badge.updateDemoCounter(request.count, sender.tab.id) } - if (request.task && request.task === 'addUrl' && typeof request.description === 'object') { + if ( + request.task && + request.task === 'addUrl' && + typeof request.description === 'object' + ) { netRequestManager.add(request.description, sender.tab.id) } - if (request.task && request.task === 'removeUrl' && typeof request.description === 'object') { + if ( + request.task && + request.task === 'removeUrl' && + typeof request.description === 'object' + ) { netRequestManager.remove(request.description, sender.tab.id) } if (request.task && request.task === 'clearUrls') { @@ -137,21 +182,24 @@ try { let isInitialized = false const persistentStates = { - configurations: [{ - name: 'Example', - content: require('../examples/one.mnky'), - test: 'Inventory-Services\nCart\nCART\nSan Francisco', - enabled: false, - values: {}, - id: uuidV4() - }, { - name: 'templates/Cities', - content: require('../examples/cities.mnky'), - test: 'San Francisco\nSeattle\nLondon', - enabled: false, - values: {}, - id: uuidV4() - }], + configurations: [ + { + name: 'Example', + content: require('../examples/one.mnky'), + test: 'Inventory-Services\nCart\nCART\nSan Francisco', + enabled: false, + values: {}, + id: uuidV4() + }, + { + name: 'templates/Cities', + content: require('../examples/cities.mnky'), + test: 'San Francisco\nSeattle\nLondon', + enabled: false, + values: {}, + id: uuidV4() + } + ], settings: { baseTemplate: require('../examples/baseTemplate.mnky'), analyticsSnippet: '', @@ -163,7 +211,8 @@ try { }, { key: 'dmLogo', - value: 'data:image/png;base64,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ZQp79uzBNE0Op7XmACEEhwoEAhQVFck5c+akb9iwoaR///7poVCIJPAnT54sNm7cSD1rCvwEeNOyrL2O4/ADg8NYltUKeBcIUY927thJZmbmlp49e2ZxlIqKipg4cWLgk08+kYFAgAO01kSjUbKzs+nRowcFBQX06NGDjp06ktM8hxYtWlRVVFSUFRcXh4QQCCEwDEN888036fPmzasaOHBgcUZGRjpHYc2aNeVTpkwxRAz1LwwMBP7bcZxKDhIcQimVDnwInE0DiEQivPHGG+Tn55OokpISbrjher75ZhMHaK1Rqs/+Cy+4UF9w4YVpmZmZRnp6OkfgR6NRLxqNBubOncvcuXNZtmwZZWVlSClp2aolr77yKllZWSSirKyUq0eOZMf2HTSwx4EHbNvmAIODlFLE3AmMpYFUVVWxfv36nZdddpmICRAnrbV/9913i7Vr/4HvewweMoQnpz3JmDFjAt179AhGIhEZCASohjBigsEgnTp1YvDgwVx++eWelMJbs2aNUbKvhA0bNjBkyBCEEMRr0qRfsXLlKoQQJIsQAiEEcVLAC47jlBFjcJBlWdnAX4AQDaikpCQyatSoQAzxWrBggfv0008b7du358knn4yOGT3GyMrKIlHhcFj27dvXGDp0KJ9/voHFixfTtWtX2rZtS7xsewVr1qxBSsnR0FqjtaZr167eWWedJdu1a+cWFRVRXFwsDMOgDgLAPsuyFjiOg8mPxgBZ1EFVVRXl5eWkpaURjUbJyMggGbTWTJ06lfT0dOLlui7Tpk0LXHvttdx2221EIpEgSWJZFs888ywvv/wyv/3tbznnnHMwTZN43HrrraxYYfP55xtJlNaanj178uCDv6B16zbSNE1ijMrKSjFnzhymTJlCNBqlDu60bftXxBjEKKUE8DyQRw1c10WdoXjggQd45JFHmDBhAiNHjsT3fdavX4/WmkRprfm3fxvDlVf+K4lYtWol6enp/PznPycUCpFsUkr69OlDTNR1Xa9FixYGcTAMg/79z6mYMWOG9H1fECetNRdffHH5tGnT/JycXFNKKfieME2TLl26MGjQIN5++22qqqqoRdCyrELHcb4wiLEsSwH3A4JqeJ7v33LLz7j//gdE27ZtCQQCBAIBsrKy6N+/P/369ePDDz+sjEajJglo3rx55ZQpU81AIEAidu/e411yySUyhlTq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' + value: + 'data:image/png;base64,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ZQp79uzBNE0Op7XmACEEhwoEAhQVFck5c+akb9iwoaR///7poVCIJPAnT54sNm7cSD1rCvwEeNOyrL2O4/ADg8NYltUKeBcIUY927thJZmbmlp49e2ZxlIqKipg4cWLgk08+kYFAgAO01kSjUbKzs+nRowcFBQX06NGDjp06ktM8hxYtWlRVVFSUFRcXh4QQCCEwDEN888036fPmzasaOHBgcUZGRjpHYc2aNeVTpkwxRAz1LwwMBP7bcZxKDhIcQimVDnwInE0DiEQivPHGG+Tn55OokpISbrjher75ZhMHaK1Rqs/+Cy+4UF9w4YVpmZmZRnp6OkfgR6NRLxqNBubOncvcuXNZtmwZZWVlSClp2aolr77yKllZWSSirKyUq0eOZMf2HTSwx4EHbNvmAIODlFLE3AmMpYFUVVWxfv36nZdddpmICRAnrbV/9913i7Vr/4HvewweMoQnpz3JmDFjAt179AhGIhEZCASohjBigsEgnTp1YvDgwVx++eWelMJbs2aNUbKvhA0bNjBkyBCEEMRr0qRfsXLlKoQQJIsQAiEEcVLAC47jlBFjcJBlWdnAX4AQDaikpCQyatSoQAzxWrBggfv0008b7du358knn4yOGT3GyMrKIlHhcFj27dvXGDp0KJ9/voHFixfTtWtX2rZtS7xsewVr1qxBSsnR0FqjtaZr167eWWedJdu1a+cWFRVRXFwsDMOgDgLAPsuyFjiOg8mPxgBZ1EFVVRXl5eWkpaURjUbJyMggGbTWTJ06lfT0dOLlui7Tpk0LXHvttdx2221EIpEgSWJZFs888ywvv/wyv/3tbznnnHMwTZN43HrrraxYYfP55xtJlNaanj178uCDv6B16zbSNE1ijMrKSjFnzhymTJlCNBqlDu60bftXxBjEKKUE8DyQRw1c10WdoXjggQd45JFHmDBhAiNHjsT3fdavX4/WmkRprfm3fxvDlVf+K4lYtWol6enp/PznPycUCpFsUkr69OlDTNR1Xa9FixYGcTAMg/79z6mYMWOG9H1fECetNRdffHH5tGnT/JycXFNKKfieME2TLl26MGjQIN5++22qqqqoRdCyrELHcb4wiLEsSwH3A4JqeJ7v33LLz7j//gdE27ZtCQQCBAIBsrKy6N+/P/369ePDDz+sjEajJglo3rx55ZQpU81AIEAidu/e411yySUyhlTq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' } ], debugMode: false, @@ -200,7 +249,10 @@ try { settings, monkeyID: store.getState().monkeyID }) - if (settings.optionalFeatures.webRequestHook && configurations.filter(c => c.enabled).length > 0) { + if ( + settings.optionalFeatures.webRequestHook && + configurations.filter((c) => c.enabled).length > 0 + ) { netRequestManager.enable() } else { netRequestManager.disable() @@ -223,7 +275,10 @@ try { // Persist monkey ID. Shouldn't change after first start. scope.chrome.storage.local.set({ monkeyID: store.getState().monkeyID }) - if (settings.optionalFeatures.webRequestHook && store.getState().configurations.filter(c => c.enabled).length > 0) { + if ( + settings.optionalFeatures.webRequestHook && + store.getState().configurations.filter((c) => c.enabled).length > 0 + ) { netRequestManager.enable() } else { netRequestManager.disable() @@ -251,16 +306,22 @@ try { enabledHotkeyGroup = toggle ? group : -1 // Persist enabled hotkey group. - scope.chrome.storage.session.set({ hotKeyGroupData: { enabledHotkeyGroup } }) + scope.chrome.storage.session.set({ + hotKeyGroupData: { enabledHotkeyGroup } + }) store.getState().configurations.forEach(function (c) { - const config = (new Configuration(c.content, null, false, c.values)) + const config = new Configuration(c.content, null, false, c.values) if (config.isTemplate() || !config.isRestricted()) { return } if (Array.isArray(c.hotkeys) && c.hotkeys.includes(group)) { - store.dispatch({ type: 'TOGGLE_CONFIGURATION', id: c.id, enabled: toggle }) + store.dispatch({ + type: 'TOGGLE_CONFIGURATION', + id: c.id, + enabled: toggle + }) } else if (c.enabled) { store.dispatch({ type: 'TOGGLE_CONFIGURATION', id: c.id }) } diff --git a/src/backup.js b/src/backup.js index b6c0572..4700e07 100644 --- a/src/backup.js +++ b/src/backup.js @@ -4,13 +4,19 @@ This also includes capabilities to directly manipulate the chrome storage. */ -(function () { +;(function () { window.chrome.storage.local.get(null, function (storage) { var list = document.getElementById('configurations') storage.configurations.forEach(function (configuration, index) { - list.innerHTML += '
  • ' + - configuration.name + '' + - ' (JSON)
  • ' + list.innerHTML += + '
  • ' + + configuration.name + + '' + + ' (JSON)
  • ' }) document.querySelectorAll('.config').forEach(function (link) { @@ -30,7 +36,9 @@ var config = storage.configurations[link.href.split('#')[1]] console.log(tojson(config.content)) window.chrome.downloads.download({ - url: 'data:text/octet-stream;base64,' + window.btoa(tojson(config.content)), + url: + 'data:text/octet-stream;base64,' + + window.btoa(tojson(config.content)), filename: config.name + '.json' // Optional }) } @@ -38,7 +46,11 @@ var loaded = false document.getElementById('load-storage').onclick = function () { - document.getElementById('storage-box').value = JSON.stringify(storage, null, 1) + document.getElementById('storage-box').value = JSON.stringify( + storage, + null, + 1 + ) document.getElementById('save-storage').style.display = 'inline-block' loaded = true } @@ -75,10 +87,13 @@ /* COPY AND PASTE FROM ini.js */ function dotSplit(str) { - return str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002') + return str + .replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002') .replace(/\\\./g, '\u0001') - .split(/\./).map(function (part) { - return part.replace(/\1/g, '\\.') + .split(/\./) + .map(function (part) { + return part + .replace(/\1/g, '\\.') .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001') }) } @@ -87,9 +102,8 @@ var out = {}, p = out, section = null, - state = "START" + state = 'START', // section |key = value - , re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i, lines = str.split(/[\r\n]+/g), section = null @@ -104,16 +118,16 @@ return }*/ var key = unsafe(match[2]), - value = match[3] ? unsafe((match[4] || "")) : true + value = match[3] ? unsafe(match[4] || '') : true switch (value) { - case 'true': - case 'false': - case 'null': - value = JSON.parse(value) + case 'true': + case 'false': + case 'null': + value = JSON.parse(value) } // Convert keys with '[]' suffix to an array - if (key.length > 2 && key.slice(-2) === "[]") { + if (key.length > 2 && key.slice(-2) === '[]') { key = key.substring(0, key.length - 2) if (!p[key]) { p[key] = [] @@ -133,74 +147,77 @@ // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}} // use a filter to return the keys that have to be deleted. - Object.keys(out).filter(function (k, _, __) { - if (!out[k] || typeof out[k] !== "object" || Array.isArray(out[k])) return false - // see if the parent section is also an object. - // if so, add it to that, and mark this one for deletion - var parts = dotSplit(k), - p = out, - l = parts.pop(), - nl = l.replace(/\\\./g, '.') - parts.forEach(function (part, _, __) { - if (!p[part] || typeof p[part] !== "object") p[part] = {} - p = p[part] + Object.keys(out) + .filter(function (k, _, __) { + if (!out[k] || typeof out[k] !== 'object' || Array.isArray(out[k])) + return false + // see if the parent section is also an object. + // if so, add it to that, and mark this one for deletion + var parts = dotSplit(k), + p = out, + l = parts.pop(), + nl = l.replace(/\\\./g, '.') + parts.forEach(function (part, _, __) { + if (!p[part] || typeof p[part] !== 'object') p[part] = {} + p = p[part] + }) + if (p === out && nl === l) return false + p[nl] = out[k] + return true + }) + .forEach(function (del, _, __) { + delete out[del] }) - if (p === out && nl === l) return false - p[nl] = out[k] - return true - }).forEach(function (del, _, __) { - delete out[del] - }) return out } function isQuoted(val) { - return (val.charAt(0) === "\"" && val.slice(-1) === "\"") || + return ( + (val.charAt(0) === '"' && val.slice(-1) === '"') || (val.charAt(0) === "'" && val.slice(-1) === "'") + ) } function safe(val) { - return (typeof val !== "string" || - val.match(/[=\r\n]/) || - val.match(/^\[/) || - (val.length > 1 && - isQuoted(val)) || - val !== val.trim()) ? - JSON.stringify(val) : - val.replace(/;/g, '\\;').replace(/#/g, "\\#") + return typeof val !== 'string' || + val.match(/[=\r\n]/) || + val.match(/^\[/) || + (val.length > 1 && isQuoted(val)) || + val !== val.trim() + ? JSON.stringify(val) + : val.replace(/;/g, '\\;').replace(/#/g, '\\#') } function unsafe(val, doUnesc) { - val = (val || "").trim() + val = (val || '').trim() if (isQuoted(val)) { // remove the single quotes before calling JSON.parse if (val.charAt(0) === "'") { - val = val.substr(1, val.length - 2); + val = val.substr(1, val.length - 2) } - try { val = JSON.parse(val) } catch (_) {} + try { + val = JSON.parse(val) + } catch (_) {} } else { // walk the val to find the first not-escaped ; character var esc = false - var unesc = ""; + var unesc = '' for (var i = 0, l = val.length; i < l; i++) { var c = val.charAt(i) if (esc) { - if ("\\;#".indexOf(c) !== -1) - unesc += c - else - unesc += "\\" + c + if ('\\;#'.indexOf(c) !== -1) unesc += c + else unesc += '\\' + c esc = false - } else if (";#".indexOf(c) !== -1) { + } else if (';#'.indexOf(c) !== -1) { break - } else if (c === "\\") { + } else if (c === '\\') { esc = true } else { unesc += c } } - if (esc) - unesc += "\\" + if (esc) unesc += '\\' return unesc } return val diff --git a/src/commands/AddScript.js b/src/commands/AddScript.js index b26b7f8..6be4d1f 100644 --- a/src/commands/AddScript.js +++ b/src/commands/AddScript.js @@ -39,7 +39,7 @@ class QuerySelector extends Command { const scriptTag = target.createElement('script') scriptTag.innerHTML = this.body scriptTag.dataset.demoMonkeyId = this.demoMonkeyId - this.attributes.forEach(attribute => { + this.attributes.forEach((attribute) => { const [key, value] = attribute.split('=') if (key && value) { scriptTag.setAttribute(key, value) diff --git a/src/commands/Command.js b/src/commands/Command.js index afa2a70..cd7b285 100644 --- a/src/commands/Command.js +++ b/src/commands/Command.js @@ -41,7 +41,10 @@ class Command { return node } - if (node.parentElement !== null && typeof node.parentElement !== 'undefined') { + if ( + node.parentElement !== null && + typeof node.parentElement !== 'undefined' + ) { return this._walk(node.parentElement, count - 1) } @@ -75,12 +78,17 @@ class Command { 'ad-pink': Color('#e38ead'), 'ad-red': Color('#ff3333') } - if (Object.prototype.hasOwnProperty.call(magicColors, value.toLowerCase())) { + if ( + Object.prototype.hasOwnProperty.call(magicColors, value.toLowerCase()) + ) { return magicColors[value.toLowerCase()] } // We want to accept colors from hex 'xxxxxx(aa)' and 'xxx(a)' - if (value.match(/^(?:[0-9a-f]{3,4}|(?:[0-9a-f]{6}(?:[0-9a-f]{2})?))$/i) !== null) { + if ( + value.match(/^(?:[0-9a-f]{3,4}|(?:[0-9a-f]{6}(?:[0-9a-f]{2})?))$/i) !== + null + ) { value = '#' + value } let color = false @@ -138,7 +146,9 @@ class Command { toString() { // We need to apply "protection" so demo monkey does not run over this itself ;-) - return this.sourceString ? this.sourceString.split('').join(String.fromCharCode(0x200B)) : '' + return this.sourceString + ? this.sourceString.split('').join(String.fromCharCode(0x200b)) + : '' } } diff --git a/src/commands/CommandBuilder.js b/src/commands/CommandBuilder.js index 071c4b1..e5d1edc 100644 --- a/src/commands/CommandBuilder.js +++ b/src/commands/CommandBuilder.js @@ -17,7 +17,15 @@ import registry from './CommandRegistry' import extractParameters from '../helpers/extractParameters' class CommandBuilder { - constructor(namespaces = [], includeRules, excludeRules, featureFlags = {}, logger = () => { return { write: () => {} } }) { + constructor( + namespaces = [], + includeRules, + excludeRules, + featureFlags = {}, + logger = () => { + return { write: () => {} } + } + ) { this.namespaces = namespaces this.includeRules = includeRules this.excludeRules = excludeRules @@ -25,25 +33,29 @@ class CommandBuilder { this.logger = logger - this.commands = registry.reduce((result, current) => { - // handle namespace - if (current.registry) { - result['_' + current.name] = {} - current.registry.forEach(command => { - result['_' + current.name][command.name] = command - command.aliases && command.aliases.forEach(alias => { - result.__[alias] = command + this.commands = registry.reduce( + (result, current) => { + // handle namespace + if (current.registry) { + result['_' + current.name] = {} + current.registry.forEach((command) => { + result['_' + current.name][command.name] = command + command.aliases && + command.aliases.forEach((alias) => { + result.__[alias] = command + }) }) - }) - } - if (current.command) { - result.__[current.name] = current - current.aliases.forEach(alias => { - result.__[alias] = current - }) - } - return result - }, { __: {} }) + } + if (current.command) { + result.__[current.name] = current + current.aliases.forEach((alias) => { + result.__[alias] = current + }) + } + return result + }, + { __: {} } + ) } _buildRegex(search, modifiers, replace) { @@ -61,8 +73,12 @@ class CommandBuilder { if (match.toLowerCase() === match) { replace = replace.toLowerCase() } - return match.replace(new RegExp(search, modifiers.replace('p', '')), replace) - }) + return match.replace( + new RegExp(search, modifiers.replace('p', '')), + replace + ) + } + ) } return new SearchAndReplace(new RegExp(search, modifiers), replace) } catch (e) { @@ -74,19 +90,43 @@ class CommandBuilder { const location = typeof window === 'undefined' ? '' : window.location // Run namespaced command - if (this.commands['_' + namespace] && this.commands['_' + namespace][name]) { - return this.commands['_' + namespace][name].command.bind(this)(value, parameters, location, this.includeRules, this.excludeRules, this) + if ( + this.commands['_' + namespace] && + this.commands['_' + namespace][name] + ) { + return this.commands['_' + namespace][name].command.bind(this)( + value, + parameters, + location, + this.includeRules, + this.excludeRules, + this + ) } // Run command without namespace if (this.commands.__[name]) { - return this.commands.__[name].command.bind(this)(value, parameters, location, this.includeRules, this.excludeRules, this) + return this.commands.__[name].command.bind(this)( + value, + parameters, + location, + this.includeRules, + this.excludeRules, + this + ) } for (let i = 0; i < this.namespaces.length; i++) { const ns = this.namespaces[i] if (this.commands['_' + ns] && this.commands['_' + ns][name]) { - return this.commands['_' + ns][name].command.bind(this)(value, parameters, location, this.includeRules, this.excludeRules, this) + return this.commands['_' + ns][name].command.bind(this)( + value, + parameters, + location, + this.includeRules, + this.excludeRules, + this + ) } } @@ -105,7 +145,9 @@ class CommandBuilder { if (command.substr(-1) !== ')') { return { extracted: false } } - parameters = extractParameters(command.slice(command.indexOf('(') + 1, -1)) + parameters = extractParameters( + command.slice(command.indexOf('(') + 1, -1) + ) command = command.split('(')[0] } @@ -128,7 +170,12 @@ class CommandBuilder { const rawCommand = this._extractForCustomCommand(key) if (rawCommand.extracted) { - return this._buildCustomCommand(rawCommand.namespace, rawCommand.command, rawCommand.parameters, value) + return this._buildCustomCommand( + rawCommand.namespace, + rawCommand.command, + rawCommand.parameters, + value + ) } return new ErrorCommand('Could not build command') } @@ -162,8 +209,14 @@ class CommandBuilder { const cmd = this._innerBuild(key, value) if (!cmd.isAvailable(this.featureFlags)) { - this.logger('warn', `Command requires the following feature flags: ${cmd.getRequiredFlags()}`).write() - return new ErrorCommand(`Command requires the following feature flags: ${cmd.getRequiredFlags()}`, 'warning') + this.logger( + 'warn', + `Command requires the following feature flags: ${cmd.getRequiredFlags()}` + ).write() + return new ErrorCommand( + `Command requires the following feature flags: ${cmd.getRequiredFlags()}`, + 'warning' + ) } cmd.setSource(key, value) diff --git a/src/commands/CommandRegistry.js b/src/commands/CommandRegistry.js index 0206a23..65d6dda 100644 --- a/src/commands/CommandRegistry.js +++ b/src/commands/CommandRegistry.js @@ -47,7 +47,14 @@ export default [ name: 'addScript', signature: '(${1}) = ${2}', aliases: [], - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { return new AddScript(parameters, value) } }, @@ -55,7 +62,14 @@ export default [ name: 'replaceAjaxResponse', aliases: ['replaceAjax', 'replaceResponse'], signature: '(${1}, ${2}) = ${3}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { return new ReplaceAjaxResponse(parameters[0], parameters[1], value) } }, @@ -63,7 +77,14 @@ export default [ name: 'patchAjaxResponse', aliases: ['patchAjax', 'patchResponse'], signature: '(${1}) = ${2}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { return new PatchAjaxResponse(parameters[0], value) } }, @@ -71,67 +92,170 @@ export default [ name: 'if', aliases: [], signature: '(${1}, ${2}, ${3}) = ${4}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { const locationFilter = parameters.shift() const cssFilter = parameters.shift() - return new If(locationFilter, cssFilter, cmdBuilder.build(parameters.join(','), value), location) + return new If( + locationFilter, + cssFilter, + cmdBuilder.build(parameters.join(','), value), + location + ) } }, { name: 'ifLocation', aliases: [], signature: '(${1}, ${2}) = ${3}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { const locationFilter = parameters.shift() - return new If(locationFilter, '', cmdBuilder.build(parameters.join(','), value), location) + return new If( + locationFilter, + '', + cmdBuilder.build(parameters.join(','), value), + location + ) } }, { name: 'ifSelector', aliases: ['ifQuery', 'ifCss'], signature: '(${1}, ${2}) = ${3}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { const cssFilter = parameters.shift() - return new If('', cssFilter, cmdBuilder.build(parameters.join(','), value), location) + return new If( + '', + cssFilter, + cmdBuilder.build(parameters.join(','), value), + location + ) } }, { name: 'replace', aliases: [], signature: '(${1}, ${2}, ${3}, ${4}, ${5}) = ${6}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { - return new SearchAndReplace(parameters[0], value, parameters[1], parameters[2], parameters[3], parameters[4], location) + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { + return new SearchAndReplace( + parameters[0], + value, + parameters[1], + parameters[2], + parameters[3], + parameters[4], + location + ) } }, { name: 'replaceAttribute', aliases: [], signature: '(${1}, ${2}, ${3}, ${4}, ${5}) = ${6}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { - return new SearchAndReplace(parameters[0], value, parameters[2], parameters[3], parameters[1], parameters[4], location) + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { + return new SearchAndReplace( + parameters[0], + value, + parameters[2], + parameters[3], + parameters[1], + parameters[4], + location + ) } }, { name: 'replaceFunction', aliases: [], signature: '(${1}, ${2}) = ${3}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { - return new SearchAndReplace(parameters[0], value, parameters[2], parameters[3], parameters[4], parameters[1], location) + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { + return new SearchAndReplace( + parameters[0], + value, + parameters[2], + parameters[3], + parameters[4], + parameters[1], + location + ) } }, { name: 'hash', aliases: [], signature: '(${1}, ${2})', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { - return new SearchAndReplace(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], 'hash', location) + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { + return new SearchAndReplace( + parameters[0], + parameters[1], + parameters[2], + parameters[3], + parameters[4], + 'hash', + location + ) } }, { name: 'protect', aliases: [], signature: '(${1})', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { return new Protect(parameters[0], parameters[1], parameters[2], location) } }, @@ -139,31 +263,81 @@ export default [ name: 'replaceNeighbor', aliases: [], signature: '(${1}, ${2}, ${3}, ${4}) = ${5}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { - return new ReplaceNeighbor(parameters[0], value, parameters[1], parameters[2], parameters[3], parameters[4], location) + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { + return new ReplaceNeighbor( + parameters[0], + value, + parameters[1], + parameters[2], + parameters[3], + parameters[4], + location + ) } }, { name: 'insertBefore', aliases: [], signature: '(${1}, ${2}, ${3}) = ${4}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { - return new InsertHTML('afterbegin', parameters[0], value, parameters[1], parameters[2], location) + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { + return new InsertHTML( + 'afterbegin', + parameters[0], + value, + parameters[1], + parameters[2], + location + ) } }, { name: 'insertAfter', aliases: [], signature: '(${1}, ${2}, ${3}) = ${4}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { - return new InsertHTML('beforeend', parameters[0], value, parameters[1], parameters[2], location) + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { + return new InsertHTML( + 'beforeend', + parameters[0], + value, + parameters[1], + parameters[2], + location + ) } }, { name: 'style', aliases: [], signature: '(${1}, ${2}, ${3}) = ${4}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { return new Style(parameters[0], parameters[1], parameters[2], value) } }, @@ -171,7 +345,14 @@ export default [ name: 'querySelector', aliases: ['query'], signature: '(${1}, ${2}) = ${3}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { return new QuerySelector(parameters[0], parameters[1], value) } }, @@ -179,15 +360,36 @@ export default [ name: 'hide', aliases: [], signature: '(${1}, ${2}, ${3}, ${4})', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { - return new Hide(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], location) + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { + return new Hide( + parameters[0], + parameters[1], + parameters[2], + parameters[3], + parameters[4], + location + ) } }, { name: 'replaceImage', aliases: [], signature: '(${1}) = ${2}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { return new ReplaceImage(value, parameters) } }, @@ -195,7 +397,14 @@ export default [ name: 'recolorImage', aliases: ['recolourImage'], signature: '(${1}) = ${2}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { return new RecolorImage(parameters[0], value) } }, @@ -204,7 +413,14 @@ export default [ aliases: [], signature: '(${1}) = ${2}', deprecated: true, - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { return new QuerySelector(`a[href="${parameters[0]}"]`, 'href', value) } }, @@ -212,23 +428,58 @@ export default [ name: 'blockUrl', aliases: [], signature: '(${1})', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { - return new InterceptWebRequest(parameters[0], value, 'block', parameters[1], includeRules, excludeRules) + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { + return new InterceptWebRequest( + parameters[0], + value, + 'block', + parameters[1], + includeRules, + excludeRules + ) } }, { name: 'replaceUrl', aliases: ['redirectUrl'], signature: '(${1}) = ${2}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { - return new InterceptWebRequest(parameters[0], value, 'redirect', parameters[1], includeRules, excludeRules) + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { + return new InterceptWebRequest( + parameters[0], + value, + 'redirect', + parameters[1], + includeRules, + excludeRules + ) } }, { name: 'overwriteHTML', aliases: ['overwrite'], signature: '(${1}, ${2}) = ${3}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { + command: function ( + value, + parameters, + location, + includeRules, + excludeRules, + cmdBuilder + ) { return new OverwriteHTML(parameters[0], parameters[1], value, location) } }, @@ -236,8 +487,20 @@ export default [ name: 'overwritePage', aliases: [], signature: '(${1}, ${2}) = ${3}', - command: function (value, parameters, location, includeRules, excludeRules, cmdBuilder) { - const iframeCode = '' + parameters[1] + '