# generate-weblabels-webpack-plugin

This plugin for webpack >= 4 enables to generate an HTML page stating the licenses of every source files bundled in the JavaScript assets generated by webpack. Such a page is called [Web Labels](https://www.gnu.org/licenses/javascript-labels.html) and is intended to be consumed by the [GNU LibreJS](https://www.gnu.org/software/librejs/) Firefox plugin whose purpose is, quoting its documentation:

> GNU LibreJS aims to address the JavaScript problem described in Richard Stallman's article [The JavaScript Trap](http://www.gnu.org/philosophy/javascript-trap.html). LibreJS is a free add-on for GNU IceCat and other Mozilla-based browsers. It blocks nonfree nontrivial JavaScript while allowing JavaScript that is free and/or trivial.

So, without the Web Labels page, the loading of JavaScript assets generated by webpack in client browsers will be blocked by the LibreJS Firefox plugin. Usually, most of the bundled JavaScript source files are retrieved through `npm` or `yarn` and their associated licenses are compatible with those allowed by LibreJS. If your webpack project is also released under a free license, you can use this plugin to ensure LibreJS will detect the licenses of your bundled source files and allow the loading of the webpack generated Javascript assets.

In order to be compliant with the LibreJS specifications, the Web Labels page must contain the following information. For each JavaScript asset generated by webpack, all bundled source files in it need to be referenced along with their licenses but also a link to their non-minified source code.

The plugin works by processing the compilation statistics available after the whole webpack processing and currently does the following:
  - For each bundled JavaScript source files, it will try to find its associated LibreJS compatible license by parsing the corresponding [SPDX License Expression](https://spdx.org/licenses/) (usually located in `package.json` files)
  <br/>
  - It copies all non-minified source files, bundled into the generated JavaScript assets, into a directory located into the webpack output folder. Also if a license file can be found for a source file it will also be copied.
  <br/>
  - It generates either a Web Labels HTML page named `jslicenses.html` or a JSON file named `jslicenses.json`, into a directory located into the webpack output folder. The JSON file should then be used with an HTML template engine to generate the Web Labels page. Its structure is the following:

```json
  {
    "<js_asset_static_path>": [
      {
        "id": "<bundled_source_file_identifier>",
        "licenses": [
          {
            "name": "<librejs_compliant_license_name>",
            "url": "<librejs_compliant_license_text_url>",
            "copy_url": "<original_license_text_url>"
          },
          ...
        ]
        "src_url": "<non_minified_source_code_url>"
      },
      {
        ...
      }
    ],
    "<other_js_asset_static_path>": [
      ...
    ],
    ...
  }
```

In order for LibreJS to consume the Web Labels, a link to it must be added in the relevant HTML pages of your web application, more details in the relevant [section](https://www.gnu.org/software/librejs/free-your-javascript.html#step3) of the LibreJS documentation.

## Usage

To begin, you will need to install `generate-weblabels-webpack-plugin` (**WARNING: wip, this is currently not published on the npm registry**)

```shell
$ npm install generate-weblabels-webpack-plugin --save-dev
```

or

```shell
$ yarn add generate-weblabels-webpack-plugin --dev
```

Then add the plugin to your webpack configuration, for example:

```js
const GenerateWebLabelsPlugin = require('generate-weblabels-webpack-plugin');

module.exports = {
  // ...
  plugins: [
    new GenerateWebLabelsPlugin(options)
  ]
};
```

Also, when compiling your assets in production mode, the following webpack option must be adjusted:
```js
module.exports = {
  // ...
  optimization: {
    concatenateModules: false
  }
};
```
This will prevent webpack to concatenate some modules into a single one, which makes license and original source files detection impossible.

Please also note that the plugin will not remove the previously copied Web Labels related files into the webpack output folder. You should use the [`clean-webpack-plugin`](https://github.com/johnagan/clean-webpack-plugin) to perform that task.

## Options

The following options can be provided

### `outputDir`
type: `String`
default: `'jssources'`

Specify the directory inside the webpack output folder in which the Web Labels related files will be emitted.

### `outputType`
type: `Enum`
default: `'html'`

Specify which type of output the plugin generates. Possible values are:

  - `'html'`: generate an HTML page named "jslicenses.html" containing the Web Labels
  - `'json'`: generate a JSON file named "jslicenses.json" containing all relevant info to generate the Web Labels page through an HTML template engine.

### `exclude`
type: `Array`
default: `[]`

An array of module name or source file path prefixes to exclude from the plugin processing. If the prefix does not start with `./`, it is considered as a node module.
This can be used to exclude some special modules processed by webpack that do not generate any JavaScript that will be bundled in the generated assets (for instance the scripts associated to [`mini-css-extract-plugin`](https://github.com/webpack-contrib/mini-css-extract-plugin)).

### `srcReplace`
type: `Object`
default: `{}`

An object mapping source files to replace in the generated output.
This should be used when a node module points to its minified version by default.

### `licenseOverride`
type: `Object`
default: `{}`

An object mapping source files or node modules to their corresponding SPDX license expressions.
This should be used when you have source files inside your webpack project source tree with licenses different from the one of your project. It can also be used when you have a node module with an invalid SPDX license expression in its `package.json`.
This object must have the following structure:

```json
{
  "<src_file_path_or_node_module>": {
    "spdxLicenseExpression": "<spdx_license_expression>",
    "licenseFilePath": "<path_to_license_file>"
  },
  ...
}
```

The keys of this object can correspond either to a source file path relative to the webpack root folder or a node module identifier.
The path of the license file must be relative to the webpack project root folder.

### `additionalScripts`
type: `Object`
default: `{}`

An object declaring additional JavaScript assets loaded by your web application but not generated by webpack. It must have the following structure:

```json
{
  "<js_asset_static_path>": [
    {
      "id": "<bundled_source_file_identifier>",
      "path": "<path_to_non_minified_source_file>",
      "spdxLicenseExpression": "<spdx_license_expression>",
      "licenseFilePath": "<path_to_license_file>"
    },
    {
      ...
    }
  ],
  ...
}
```

If the path for a Javascript asset or a license file does not correspond to an url or does not start with '/', it is considered to be relative to the webpack project root folder.