🔍 Firefox Add-ons linter, written in JavaScript. 👁
Перейти к файлу
SagePtr 2b3156b117 Pontoon: Update Russian (ru) localization of AMO Linter
Localization authors:
- Alexander Slovesnik <unghost@mozilla-russia.org>
- SagePtr <sageptr@gmail.com>
2018-02-19 09:51:31 +00:00
bin Added build-locales script (#1705) 2018-01-17 19:36:01 +01:00
docs Merge pull request #1829 from wagnerand/ang 2018-02-12 15:32:10 +01:00
locale Pontoon: Update Russian (ru) localization of AMO Linter 2018-02-19 09:51:31 +00:00
src Merge pull request #1829 from wagnerand/ang 2018-02-12 15:32:10 +01:00
tasks Configure amo eslint config (#1451) 2017-08-11 16:49:06 +02:00
tests Async/await refactoring tests/rules/js folder (#1790) 2018-02-12 17:00:34 +01:00
tmp Update tar to 3.0.1, handle stream errors in schema import (#1278) 2017-06-01 10:44:49 -05:00
.babelrc Babel setup for async/await (#1692) 2017-12-19 16:29:01 +01:00
.eslintignore Added locale/ to .eslintignore 2018-02-13 21:00:42 +05:30
.eslintrc Babel setup for async/await (#1692) 2017-12-19 16:29:01 +01:00
.gitignore Added build-locales script (#1705) 2018-01-17 19:36:01 +01:00
.npmignore Sort ESLint rules and fix Grunt scripts 2016-05-19 12:25:07 -07:00
.npmrc Add .npmrc to remove package prefixes by default 2015-10-01 11:31:11 +01:00
.nvmrc Update nvm to use node6 2017-08-29 09:13:15 +02:00
.travis.yml Add lint to CI (#1518) 2017-09-05 12:02:28 +01:00
CODE_OF_CONDUCT.md add in code of conduct 2016-11-16 15:17:56 -08:00
CONTRIBUTING.md Update contributing docs (#1574) 2017-10-09 09:50:46 +02:00
Gruntfile.js Configure amo eslint config (#1451) 2017-08-11 16:49:06 +02:00
ISSUE_TEMPLATE.md Add ISSUE_TEMPLATE 2016-09-14 09:25:33 +01:00
LICENSE Initial commit 2015-09-14 09:34:44 +01:00
PULL_REQUEST_TEMPLATE.md Fix typo in PR template 2017-07-18 13:04:57 +01:00
README.md Add `langpack` to API usage example to avoid cli barf. 2018-02-09 14:46:47 -08:00
appveyor.yml Convert scanned and collected file paths to unix path separator (#1730) 2018-01-05 13:58:59 -06:00
config.js Added config file 2018-01-23 19:27:15 +05:30
jest.config.js Block specific content script match patterns. (#1652) 2017-11-14 18:03:32 +01:00
package.json Merge pull request #1840 from mozilla/greenkeeper/eslint-plugin-jest-21.12.1 2018-02-15 10:54:53 +01:00
webpack.config.js Initialized the yarn command for extraction (#1799) 2018-02-12 16:55:36 +01:00
webpack.l10n.config.babel.js Added the webpack configuration file to extract text (#1739) 2018-01-26 08:27:46 +01:00
yarn.lock fix(package): update eslint to version 4.17.0 (#1824) 2018-02-12 10:55:44 +01:00

README.md

Build Status Coverage Status Dependency Status devDependency Status npm version

addons-linter

The Add-ons Linter, JS edition.

Here is the canonical list of rules we're working from.

Usage

Command Line

You need node.js to use the add-ons linter.

To validate your add-on locally, install the linter from npm:

# Install globally so you can use the linter from any directory on
# your machine.
yarn global add addons-linter
# or
npm install -g addons-linter

After installation, run the linter and direct it to your add-on file:

addons-linter my-addon.zip

Alternatively you can point it at a directory:

addons-linter my/package/dir

The addons-linter will check your add-on and show you errors, warnings, and friendly messages for your add-on. If you want more info on the options you can enable/disable for the command-line app, use the --help option:

addons-linter --help

Import Linter API into another NodeJS application

import linter from 'addons-linter';

const sourceDir = process.cwd();

const linter = linter.createInstance({
  config: {
    // This mimics the first command line argument from yargs,
    // which should be the directory to the extension.
    _: [sourceDir],
    logLevel: process.env.VERBOSE ? 'debug' : 'fatal',
    stack: Boolean(process.env.VERBOSE),
    pretty: false,
    warningsAsErrors: false,
    metadata: false,
    output: 'none',
    boring: false,
    selfHosted: false,
    langpack: false,
    // Lint only the selected files
    //   scanFile: ['path/...', ...]
    //
    // Exclude files:
    shouldScanFile: (fileName) => true,
  },
  // This prevent the linter to exit the nodejs application
  runAsBinary: false,
});

linter.run()
  .then((linterResults) => ...)
  .catch((err) => console.error("addons-linter failure: ", err));

linter.output is composed by the following properties (the same of the 'json' report type):

{
  metadata: {...},
  summary: {
    error, notice, warning,
  },
  scanFile,
  count,
  error: [{
    type: "error",
    code, message, description,
    column, file, line
  }, ...],
  warning: [...],
  notice: [...]
}

Development

If you'd like to help us develop the addons-linter, that's great! It's pretty easy to get started, you just need node.js installed on your machine.

Quick Start

If you have node.js installed, here's the quick start to getting your development dependencies installed and building the binary:

git clone https://github.com/mozilla/addons-linter.git
cd addons-linter
yarn install
yarn start
# Leave running to watch for changes or cancel to stop watching.
bin/addons-linter my-addon.zip

Required node version

addons-linter requires node.js v6 or greater. Using nvm is probably the easiest way to manage multiple node versions side by side. See nvm on github for more details.

Install dependencies

Install dependencies with yarn:

yarn install

Dependencies are automatically kept up-to-date using greenkeeper.

yarn scripts and grunt tasks

Run basic automation tasks via yarn (e.g. yarn test). These don't need grunt-cli installed globally.

yarn scripts

Most of these scripts will also run with npm by substuting yarn with npm.

Script Description
yarn test Runs the tests
yarn test-coverage Runs the tests with coverage (watches for changes)
yarn test Runs the tests once
yarn lint Runs eslint
yarn test-coverage-once Runs the tests once with coverage
yarn start Builds the lib and watches for changes
yarn [run] build Builds the lib (used by Travis)

Building and watching for changes

You can run yarn start to build the library and then rebuild on file changes.

Once you build the library you can use the CLI in bin/addons-linter.

Testing

Tests use grunt but don't require global grunt. Just run yarn test or npm test.

Coverage

We're looking to maintain coverage at 100%. Use the coverage data in the test output to work out what lines aren't covered and ensure they're covered.

Testing and promises

Tests using promises should return the promise. This removes the need to call done() in your tests:

it('should do something promise-y', () => {
  return somePromiseCall()
    .then(() => {
      // Assert stuff here.
    });
})

To test for rejection you can use this pattern:

import { unexpectedSuccess } from './helpers';
...
it('should reject because of x', () => {
  return somePromiseCall()
    .then(unexpectedSuccess)
    .catch((err) => {
      // make assertions about err here.
    });
})

Assertions and testing APIs

assert, describe, it, beforeEach, and afterEach are available in tests by default–you don't need to import anything for those to work.

We're using chai for assertions see the Chai docs for the API available

Logging

We use bunyan for logging:

  • By default logging is off (level is set to 'fatal') .
  • Logging in tests can be enabled using an env var e.g: LOG_LEVEL=debug jest test
  • Logging on the cli can be enabled with --log-level [level].
  • Bunyan by default logs JSON. If you want the json to be pretty printed pipe anything that logs into bunyan e.g. LOG_LEVEL=debug jest test | node_modules/bunyan/bin/bunyan

Architecture

In a nutshell the way the linter works is to take an add-on package, extract the metadata from the xpi (zip) format and then process the files it finds through various content scanners.

Architecture diagram

Scanners

Each file-type has a scanner. For example: CSS files use CSSScanner; Javascript files use JavaScriptScanner. Each scanner looks at relevant files and passes each file through a parser which then hands off to a set of rules that look for specific things.

Rules

Rules get exported via a single function in a single file. A rule can have private functions it uses internally, but rule code should not depend on another rule file and each rule file should export one rule.

Each rule function is passed data from the scanner in order to carry out the specific checks for that rule it returns a list of objects which are then made into message objects and are passed to the Collector.

Collector

The Collector is an in-memory store for all validation message objects "collected" as the contents of the package are processed.

Messages

Each message has a code which is also its key. It has a message which is a short outline of what the message represents, and a description which is more detail into why that message was logged. The type of the message is set as messages are added so that if necessary the same message could be an error or a warning for example.

Output

Lastly when the processing is complete the linter will output the collected data as text or JSON.

Deploys

We deploy to npm automatically using TravisCI. To release a new version, increment the version in package.json and create a PR. Make sure your version number conforms to the semver format eg: 0.2.1.

After merging the PR, create a new release with the same tag name as your new version. Once the build passes it will deploy. Magic!