| LEFT | RIGHT | 
|    1 Shared Adblock Plus UI code |    1 Shared Adblock Plus UI code | 
|    2 =========================== |    2 =========================== | 
|    3  |    3  | 
|    4 The user interface elements defined in this repository will be used by various |    4 The user interface elements defined in this repository will be used by various | 
|    5 Adblock Plus products like Adblock Plus for Firefox. Their functionality can be |    5 Adblock Plus products like Adblock Plus for Firefox. Their functionality can be | 
|    6 tested within this repository, even though they might not work exactly the same |    6 tested within this repository, even though they might not work exactly the same | 
|    7 as they will do in the final product. |    7 as they will do in the final product. | 
 |    8  | 
 |    9 Installing dependencies | 
 |   10 ----------------------- | 
 |   11  | 
 |   12 Both [python 2](https://www.python.org/downloads/) and [node](https://nodejs.org
     /en/), as well as [npm](https://www.npmjs.com), are required to contribute to th
     is repository. | 
 |   13  | 
 |   14 If you are installing `node` in ArchLinux, please remember to install `npm` too. | 
 |   15  | 
 |   16 After cloning this repository, enter into its folder and run: `npm install`. | 
 |   17  | 
 |   18 This should create and populate, both `./node_modules` folder and the `./buildto
     ols` one. | 
 |   19  | 
 |   20 **Note:** [devDependencies](https://docs.npmjs.com/files/package.json#devdepende
     ncies) are not preinstalled during extension build, use [dependencies](https://d
     ocs.npmjs.com/files/package.json#dependencies) instead. | 
|    8  |   21  | 
|    9 Directory structure |   22 Directory structure | 
|   10 ------------------- |   23 ------------------- | 
|   11  |   24  | 
|   12 * Top-level files: |   25 * Top-level files: | 
|   13   * `firstRun.html` and `firstRun.js`: First-run page, see below |   26   * `firstRun.html` and `firstRun.js`: First-run page, see below | 
|   14   * `i18n.js`: Localization functions, should be included by all pages. |   27   * `i18n.js`: Localization functions, should be included by all pages. | 
|   15   * `messageResponder.js`: Script to be used on the background page to respond |   28   * `messageResponder.js`: Script to be used on the background page to respond | 
|   16     to messages sent by UI code. |   29     to messages sent by UI code. | 
|   17   * `background.html`, `background.js`: Test implementation of the background |   30   * `background.html`, `background.js`: Test implementation of the background | 
|   18     page, should *not be imported*. |   31     page, should *not be imported*. | 
|   19   * `desktop-options.html`, `desktop-options.js`: Options page, see below |   32   * `desktop-options.html`, `desktop-options.js`: Options page, see below | 
|   20   * `subscriptions.xml`: Test subscription data, should *not be imported* |   33   * `subscriptions.xml`: Test subscription data, should *not be imported* | 
|   21   * `polyfill.js`: Browser API polyfills, should *not be imported* |   34   * `polyfill.js`: Browser API polyfills, should *not be imported* | 
 |   35 * `js` directory: new CommonJS modules/entry-points bundled to produce | 
 |   36   top level pages. As example, `js/desktop-options.js` produces | 
 |   37   `./desktop-options.js` [IIFE](https://developer.mozilla.org/en-US/docs/Glossar
     y/IIFE) | 
 |   38   deployed within the extension. | 
 |   39 * `lib` directory: Modules to be used on the background page to expose | 
 |   40   UI-related functionality. | 
|   22 * `locale` directory: Localized strings, with one directory per locale. The |   41 * `locale` directory: Localized strings, with one directory per locale. The | 
|   23   Firefox format for locale identifiers is used (xx-YY where xx is the language |   42   Firefox format for locale identifiers is used (xx-YY where xx is the language | 
|   24   code and YY the optional region code). The localization strings themselves are |   43   code and YY the optional region code). The localization strings themselves are | 
|   25   stored in the JSON format, like the one used by Chrome extensions. There is |   44   stored in the JSON format, like the one used by Chrome extensions. There is | 
|   26   one JSON file per HTML page, file names of HTML page and JSON file should |   45   one JSON file per HTML page, file names of HTML page and JSON file should | 
|   27   match. |   46   match. | 
|   28 * `skin` directory: CSS files and any additional resources (images and fonts) |   47 * `skin` directory: CSS files and any additional resources (images and fonts) | 
|   29   required for these. |   48   required for these. | 
|   30 * `ext` directory: Test implementation of the abstraction layer. This one should |   49 * `ext` directory: Test implementation of the abstraction layer. This one should | 
|   31   *not to be imported*, these files should rather be replaced by |   50   *not to be imported*, these files should rather be replaced by | 
|   32   product-specific versions providing the same interface. |   51   product-specific versions providing the same interface. | 
|   33  |   52  | 
|   34 Testing |   53 Testing | 
|   35 ------- |   54 ------- | 
|   36  |   55  | 
|   37 In Firefox the HTML pages can be opened directly from the file system |   56 In Firefox the HTML pages can be opened directly from the file system | 
|   38 and should be fully functional. Due to security restrictions in Chrome, there |   57 and should be fully functional. Due to security restrictions in Chrome, there | 
|   39 you need to pass in the `--allow-file-access-from-files` command line flag when |   58 you need to pass in the `--allow-file-access-from-files` command line flag when | 
|   40 starting the application. Alternatively, you can run `test_server.py` (requires |   59 starting the application. Alternatively, you can run `npm start` and open | 
|   41 Python 2.7) and open the HTML pages under URLs like |   60 the HTML pages under URL shown shown in the terminal (example: http://127.0.0.1:
     8080). | 
|   42 `http://127.0.0.1:5000/firstRun.html`. |   61  | 
|   43  |   62 You can pass along to underlying [http-server](https://www.npmjs.com/package/htt
     p-server) | 
|   44 Various aspects of the pages can be tested by setting parameters in the URL. The |   63 program any arguments via `--` as in: | 
|   45 only universal parameter is `locale`, e.g. `?locale=es-AR`. This parameter |   64 ```sh | 
 |   65 npm start -- -p 5000 -c-1 | 
 |   66 ``` | 
 |   67  | 
 |   68 Various aspects of the pages can be tested by setting parameters in the URL. | 
 |   69 The only universal parameter is `locale`, e.g. `?locale=es-AR`. This parameter | 
|   46 overrides browser's locale which will be used by default. |   70 overrides browser's locale which will be used by default. | 
 |   71  | 
 |   72 Smoke Testing UI | 
 |   73 ---------------- | 
 |   74  | 
 |   75 The `./tests` folder contains essential files to test our Custom Elements | 
 |   76 in isolation. As it is done for the `io-element` one, you need to add | 
 |   77 at least an `io-element.js` test file and its `io-element.html` related page. | 
 |   78  | 
 |   79 A package script entry such `"test:io-element.js"` should bundle the | 
 |   80 resulting page/component inside the `./smoke` folder. | 
 |   81  | 
 |   82 Please read how it's done for `io-element` to know more. | 
 |   83  | 
 |   84 Linting | 
 |   85 ------- | 
 |   86  | 
 |   87 You can lint all options via `npm run lint`. | 
 |   88  | 
 |   89 You can also run specific target linting via `npm run lint:js` or, once availabl
     e, via `npm run lint:css`. | 
 |   90  | 
 |   91 Remember, both `eslint` and `stylelint` can help fixing issues via `--fix` flag. | 
 |   92  | 
 |   93 You can try as example via [npx](https://medium.com/@maybekatz/introducing-npx-a
     n-npm-package-runner-55f7d4bd282b) | 
 |   94 which should be provided automatically when you install `npm`. | 
 |   95  | 
 |   96 ```sh | 
 |   97 npx stylelint --fix skin/real-file-name.css | 
 |   98 ``` | 
 |   99  | 
 |  100 Bundling JS | 
 |  101 ----------- | 
 |  102  | 
 |  103 As it is for the `desktop-options.js` case, bundling is done via `package.json` | 
 |  104 script entries. | 
 |  105  | 
 |  106 A dedicated script entry, such `bundle:desktop-options.js`, | 
 |  107 should simply use the `bash:js` script, passing along | 
 |  108 the source file and the target. | 
 |  109  | 
 |  110 ```js | 
 |  111 { | 
 |  112   // example of a new bundle for the ./js/source.js file | 
 |  113   "bundle:target.js": "npm run bash:js ./js/source.js ./target.js" | 
 |  114 } | 
 |  115 ``` | 
 |  116  | 
 |  117 The main `bundle` script should include each sub-bundle operation too. | 
 |  118  | 
 |  119 Bundling CSS | 
 |  120 ------------ | 
 |  121  | 
 |  122 As it is for the `desktop-options.css` case, bundling is done via `package.json` | 
 |  123 script entries. | 
 |  124  | 
 |  125 A dedicated script entry, such `bundle:desktop-options.css`, | 
 |  126 should simply use the `bash:css` script, passing along | 
 |  127 the source file and the target. | 
 |  128  | 
 |  129 ```js | 
 |  130 { | 
 |  131   // example of a new bundle for the ./css/source.scss file | 
 |  132   "bundle:target.css": "npm run bash:css ./css/source.scss ./skin/target.css" | 
 |  133 } | 
 |  134 ``` | 
 |  135  | 
 |  136 In case there are dependencies, please ensure these are | 
 |  137 imported via `@import "dep.scss"` and not via `url(...)` syntax. | 
 |  138  | 
 |  139 As it is for JS bundles, the main `bundle` script should include each | 
 |  140 CSS bundle too. | 
 |  141  | 
 |  142 Watching | 
 |  143 -------- | 
 |  144  | 
 |  145 While developing, it is convenient to bundle automatically | 
 |  146 each time a source file is changed. | 
 |  147  | 
 |  148 As a team, we agreed on restructuring JS code inside the js folder, | 
 |  149 so that is watched, and each bundled created, every time there is a changes. | 
 |  150  | 
 |  151 Similarly done for bundles, watches follow the following convention: | 
 |  152  | 
 |  153 a named script entry such `watch:desktop-option` that | 
 |  154 points at the following command: | 
 |  155  | 
 |  156 ```sh | 
 |  157 watch 'npm run bundle:desktop-options' ./js | 
 |  158 ``` | 
 |  159  | 
 |  160 The main `watch` script should include each sub-watch operation. | 
 |  161  | 
|   47  |  162  | 
|   48 Translations |  163 Translations | 
|   49 ------------ |  164 ------------ | 
|   50  |  165  | 
|   51 Translations for the strings in this project are managed using the online |  166 Translations for the strings in this project are managed using the online | 
|   52 [Crowdin platform][crowdin]. To synchronise with Crowdin you can use the build |  167 [Crowdin platform][crowdin]. To synchronise with Crowdin you can use the build | 
|   53 script. To get a list of the possible commands type `./build.py help` at |  168 script. To get a list of the possible commands type `./build.py help` at | 
|   54 the command line. (You will also need the Crowdin API key for the project.) |  169 the command line. (You will also need the Crowdin API key for the project.) | 
|   55  |  170  | 
|   56 Before updating translations in the crowdin eyeo send strings to translation |  171 Translations CSV exporter | 
|   57 agencies, in order to get high quality translations before updating crowdin. |  172 ------------------------- | 
|   58 Translation agencies are using CSV files, so in order to optimize import and |  173  | 
|   59 export process use csv-export.js, run `node csv-export.js -h` for instructions. 
       |  174 Translation agencies are using CSVs for translating the strings. CSV exporter | 
 |  175 helps keeping that files in sync with the project. To learn more about the | 
 |  176 script usage run `node build/csv-export.js -h`. | 
 |  177  | 
 |  178 Format of the exported CSV files: | 
 |  179  | 
 |  180 | Filename     | StringID | Description          | Placeholders                |
          en_US      | af         | am   | ... | | 
 |  181 |--------------|----------|----------------------|-----------------------------|
     ----------------|------------|------|-----| | 
 |  182 | options.json | cancel   | Cancel button label  |                             |
       Cancel        | Kanselleer | ይቅር | ... | | 
 |  183 | options.json | domain   | Domain input example | {"domain":{"content":"$1"}} |
       e.g. $domain$ |            |      | ... | | 
 |  184  | 
|   60  |  185  | 
|   61 firstRun.html |  186 firstRun.html | 
|   62 ------------- |  187 ------------- | 
|   63  |  188  | 
|   64 This is the implementation of the Adblock Plus first-run page that will show up |  189 This is the implementation of the Adblock Plus first-run page that will show up | 
|   65 whenever changes are applied automatically to user's Adblock Plus configuration. |  190 whenever changes are applied automatically to user's Adblock Plus configuration. | 
|   66 This will usually happen when the user first installs Adblock Plus (initial |  191 This will usually happen when the user first installs Adblock Plus (initial | 
|   67 setup), but it can also happen in case the user's settings get lost. |  192 setup), but it can also happen in case the user's settings get lost. | 
|   68  |  193  | 
|   69 To aid testing, the behavior of this page is affected by a number of URL |  194 To aid testing, the behavior of this page is affected by a number of URL | 
|   70 parameters: |  195 parameters: | 
|   71  |  196  | 
|   72 * `platform`, `platformVersion`, `application`, `applicationVersion`: sets |  197 * `platform`, `platformVersion`, `application`, `applicationVersion`: sets | 
|   73   application parameters that are normally determined by Adblock Plus. |  198   application parameters that are normally determined by Adblock Plus. | 
|   74 * `filterlistsReinitialized`: setting these parameters to `true` should |  199 * `dataCorrupted`, `filterlistsReinitialized`: setting these parameters to | 
|   75   trigger warnings referring to issues detected by Adblock Plus. |  200   `true` should trigger warnings referring to issues detected by Adblock Plus. | 
|   76 * `blockedURLs`: a comma-separated list of URLs that should be considered |  201 * `blockedURLs`: a comma-separated list of URLs that should be considered | 
|   77   blocked (necessary to test the check for blocked scripts in sharing buttons). |  202   blocked (necessary to test the check for blocked scripts in sharing buttons). | 
|   78  |  203  | 
|   79 mobile-options.html |  204 mobile-options.html | 
|   80 ------------ |  205 ------------ | 
|   81  |  206  | 
|   82 This is a web extension implementation of the Adblock Plus for Firefox Mobile |  207 This is a web extension implementation of the Adblock Plus for Firefox Mobile | 
|   83 options page. |  208 options page. | 
|   84  |  209  | 
|   85 To aid testing, the behavior of this page is affected by a number of URL |  210 To aid testing, the behavior of this page is affected by a number of URL | 
|   86 parameters: |  211 parameters: | 
|   87  |  212  | 
|   88 * `addSubscription=true`: this parameter should trigger a dialog for adding |  213 * `addSubscription=true`: this parameter should trigger a dialog for adding | 
|   89   subscriptions as initiated by clicking on an "abp:subscribe" link |  214   subscriptions as initiated by clicking on an "abp:subscribe" link | 
|   90 * `showPageOptions=true`: shows page-specific options |  215 * `showPageOptions=true`: shows page-specific options | 
|   91  |  216  | 
|   92 desktop-options.html |  217 desktop-options.html | 
|   93 ------------ |  218 ------------ | 
|   94  |  219  | 
|   95 This is the implementation of the Adblock Plus options page which is |  220 This is the implementation of the Adblock Plus options page which is | 
|   96 the primary UI for changing settings and for managing filter lists. |  221 the primary UI for changing settings and for managing filter lists. | 
|   97  |  222  | 
|   98 To aid testing, the behavior of this page is affected by a number of URL |  223 To aid testing, the behavior of this page is affected by a number of URL | 
|   99 parameters: |  224 parameters: | 
|  100  |  225  | 
|  101 * `addonVersion`: sets addon version application parameter that is used for |  226 * `addonVersion`: sets addon version application parameter that is used for | 
|  102   creating the link to the version-specific release notes |  227   creating the link to the version-specific release notes | 
|  103 * `addSubscription=true`: this parameter should trigger a dialog for adding |  228 * `addSubscription=true`: this parameter should trigger a dialog for adding | 
|  104   subscriptions as initiated by clicking on an "abp:subscribe" link |  229   subscriptions as initiated by clicking on an "abp:subscribe" link | 
 |  230 * `additionalSubscriptions`: A comma-separated list of subscription URLs that | 
 |  231   simulates scenario of persistent filter lists preinstalled by administrators. | 
|  105 * `filterError=true`: causes filter validation to fail, showing validation |  232 * `filterError=true`: causes filter validation to fail, showing validation | 
|  106   errors when adding new filters on the options page |  233   errors when adding new filters on the options page | 
|  107 * `blockedURLs`: a comma-separated list of URLs that should be considered |  234 * `blockedURLs`: a comma-separated list of URLs that should be considered | 
|  108   blocked (necessary to test the check for blocked scripts in sharing buttons). |  235   blocked (necessary to test the check for blocked scripts in sharing buttons). | 
|  109 * `downloadStatus`: sets downloadStatus parameter for filter lists, can be used |  236 * `downloadStatus`: sets downloadStatus parameter for filter lists, can be used | 
|  110   to trigger various filter list download errors |  237   to trigger various filter list download errors | 
|  111 * `platform=chromium`: shows the opt-out for the developer tools panel |  238 * `platform=chromium`: shows the opt-out for the developer tools panel | 
|  112 * `showNotificationUI=true`: simulates user having opted-out of notifications |  239 * `showNotificationUI=true`: simulates user having opted-out of notifications | 
|  113  |  240  | 
|  114  |  241  | 
|  115 [crowdin]: https://crowdin.com |  242 [crowdin]: https://crowdin.com | 
|  116  |  | 
|  117 Linting |  | 
|  118 ------- |  | 
|  119  |  | 
|  120 You can lint the code using [ESLint](http://eslint.org). |  | 
|  121  |  | 
|  122     eslint *.js lib ext |  | 
|  123  |  | 
|  124 You will need to set up ESLint and our configuration first, see |  | 
|  125 [eslint-config-eyeo](https://hg.adblockplus.org/codingtools/file/tip/eslint-conf
     ig-eyeo) |  | 
|  126 for more information. |  | 
| LEFT | RIGHT |