Skip to content

Commit

Permalink
chore: add @rollup/plugin-html (#57)
Browse files Browse the repository at this point in the history
* chore: add @rollup/plugin-html

* docs: add attribution

* chore: fix ci:lint script

* chore: nuke rollup.config.js, was a leftover from tests

* Update packages/html/README.md

* Update packages/html/README.md

* test: test output formats, warnings. update docs for formats

* chore: add bundle to template params, no-write tests

* chore: remove --u from test script
  • Loading branch information
shellscape committed Nov 29, 2019
1 parent 2e96f61 commit 144b4a4
Show file tree
Hide file tree
Showing 14 changed files with 1,738 additions and 43 deletions.
10 changes: 5 additions & 5 deletions packages/auto-install/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ npm install @rollup/plugin-inject --save-dev
Create a `rollup.config.js` [configuration file](https://www.rollupjs.org/guide/en/#configuration-files) and import the plugin:

```js
import auto from "@rollup/plugin-auto-install";
import resolve from "rollup-plugin-node-resolve";
import auto from '@rollup/plugin-auto-install';
import resolve from 'rollup-plugin-node-resolve';

export default {
input: "src/index.js",
input: 'src/index.js',
output: {
dir: "output",
format: "cjs"
dir: 'output',
format: 'cjs'
},
plugins: [auto(), resolve()]
};
Expand Down
153 changes: 153 additions & 0 deletions packages/html/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
[npm]: https://img.shields.io/npm/v/@rollup/plugin-html
[npm-url]: https://www.npmjs.com/package/@rollup/plugin-html
[size]: https://packagephobia.now.sh/badge?p=@rollup/plugin-html
[size-url]: https://packagephobia.now.sh/result?p=@rollup/plugin-html

[![npm][npm]][npm-url]
[![size][size]][size-url]
[![libera manifesto](https://img.shields.io/badge/libera-manifesto-lightgrey.svg)](https://liberamanifesto.com)

# @rollup/plugin-html

🍣 A Rollup plugin which creates HTML files to serve Rollup bundles.

Please see [Supported Output Formats](#supported-output-formats) for information about using this plugin with output formats other than `esm` (`es`), `iife`, and `umd`.

## Requirements

This plugin requires an [LTS](https://github.com/nodejs/Release) Node version (v8.0.0+) and Rollup v1.20.0+.

## Install

Using npm:

```console
npm install @rollup/plugin-html --save-dev
```

## Usage

Create a `rollup.config.js` [configuration file](https://www.rollupjs.org/guide/en/#configuration-files) and import the plugin:

```js
const html = require('@rollup/plugin-html');

module.exports = {
input: 'src/index.js',
output: {
dir: 'output',
format: 'cjs'
},
plugins: [html()]
};
```

Then call `rollup` either via the [CLI](https://www.rollupjs.org/guide/en/#command-line-reference) or the [API](https://www.rollupjs.org/guide/en/#javascript-api).

Once run successfully, an HTML file should be written to the bundle output destination.

## Options

### `attributes`

Type: `Object`<br>
Default: `{ html: { lang: 'en' }, link: null, script: null }`

Specifies additional attributes for `html`, `link`, and `script` elements. For each property, provide an object with key-value pairs that represent an HTML element attribute name and value. By default, the `html` element is rendered with an attribute of `lang="en"`.

_Note: If using the `es` / `esm` output format, `{ type: 'module'}` is automatically added to `attributes.script`._

### `fileName`

Type: `String`<br>
Default: `'index.html'`

Specifies the name of the HTML to emit.

### `publicPath`

Type: `String`<bri3ty3
Default: `''`

Specifies a path to prepend to all bundle assets (files) in the HTML output.

### `template`

Type: `Function`<br>
Default: `internal function`
Returns: `String`

Specifies a function that provides the rendered source for the HTML output. The function should be in the form of:

```js
const template = ({ attributes, bundle, files, publicPath, title }) => { ... }
```

- `attributes`: Corresponds to the `attributes` option passed to the plugin
- `bundle`: An `Object` containing key-value pairs of [`AssetInfo` or `ChunkInfo`](https://rollupjs.org/guide/en/#generatebundle)
- `files`: An `Array` of `AssetInfo` or `ChunkInfo` containing any entry (`isEntry: true`) files, and any asset (`isAsset: true`) files in the bundle that will be emitted
- `publicPath`: Corresponds to the `publicPath` option passed to the plugin
- `title`: Corresponds to the `title` option passed to the plugin

By default this is handled internally and produces HTML in the following format:

```html
<!DOCTYPE html>
<html ${attributes}>
<head>
<meta charset="utf-8" />
<title>${title}</title>
${links}
</head>
<body>
${scripts}
</body>
</html>
```

Where `${links}` represents all `<link ..` tags for CSS and `${scripts}` represents all `<script...` tags for JavaScript files.

### `title`

Type: `String`<br>
Default: `'Rollup Bundle'`

Specifies the HTML document title.

## Exports

### `makeHtmlAttributes(attributes)`

Parameters: `attributes`, Type: `Object`<br>
Returns: `String`

Consumes an object with key-value pairs that represent an HTML element attribute name and value. The function returns all pairs as a space-separated string of valid HTML element attributes. e.g.

```js
const { makeHtmlAttributes } = require('@rollup/plugin-html');

makeHtmlAttributes({ lang: 'en', 'data-batcave': 'secret' });
// -> 'lang="en" data-batcave="secret"'
```

## Supported Output Formats

By default, this plugin supports the `esm` (`es`), `iife`, and `umd` [output formats](https://rollupjs.org/guide/en/#outputformat), as those are most commonly used as browser bundles. Other formats can be used, but will require using the [`template`](#template) option to specify a custom template function which renders the unique requirements of other formats.

### `amd`

Will likely require use of RequireJS semantics, which allows only for a single entry `<script>` tag. If more entry chunks are emitted, these need to be loaded via a proxy file. RequireJS would also need to be a dependency and added to the build: https://requirejs.org/docs/start.html.

### `system`

Would require a separate `<script>` tag first that adds the `s.js` minimal loader. Loading modules might then resemble: `<script>System.import('./batman.js')</script>`.

## Attribution

This plugin was inspired by and is based upon [mini-html-webpack-plugin](https://github.com/styleguidist/mini-html-webpack-plugin) by Juho Vepsäläinen and Artem Sapegin, with permission.

## Meta

[CONTRIBUTING](/.github/CONTRIBUTING.md)

[LICENSE (MIT)](/LICENSE)
106 changes: 106 additions & 0 deletions packages/html/lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
const { extname } = require('path');

const getFiles = (bundle) => {
const files = Object.values(bundle).filter(
(file) => file.isEntry || file.type === 'asset' || file.isAsset
);
const result = {};
for (const file of files) {
const { fileName } = file;
const extension = extname(fileName).substring(1);
result[extension] = (result[extension] || []).concat(file);
}

return result;
};

const makeHtmlAttributes = (attributes) => {
if (!attributes) {
return '';
}

const keys = Object.keys(attributes);
// eslint-disable-next-line no-param-reassign
return keys.reduce((result, key) => (result += ` ${key}="${attributes[key]}"`), '');
};

const defaultTemplate = async ({ attributes, files, publicPath, title }) => {
const scripts = (files.js || [])
.map(({ fileName }) => {
const attrs = makeHtmlAttributes(attributes.script);
return `<script src="${publicPath}${fileName}"${attrs}></script>`;
})
.join('\n');

const links = (files.css || [])
.map(({ fileName }) => {
const attrs = makeHtmlAttributes(attributes.link);
return `<link href="${publicPath}${fileName}" rel="stylesheet"${attrs}>`;
})
.join('\n');

return `
<!doctype html>
<html${makeHtmlAttributes(attributes.html)}>
<head>
<meta charset="utf-8">
<title>${title}</title>
${links}
</head>
<body>
${scripts}
</body>
</html>`;
};

const supportedFormats = ['es', 'esm', 'iife', 'umd'];

const defaults = {
attributes: {
link: null,
html: { lang: 'en' },
script: null
},
fileName: 'index.html',
publicPath: '',
template: defaultTemplate,
title: 'Rollup Bundle'
};

const html = (opts = {}) => {
const { attributes, fileName, publicPath, template, title } = Object.assign({}, defaults, opts);
return {
name: 'html',

async generateBundle(output, bundle) {
if (!supportedFormats.includes(output.format) && !opts.template) {
this.warn(
`plugin-html: The output format '${
output.format
}' is not directly supported. A custom \`template\` is probably required. Supported formats include: ${supportedFormats.join(
', '
)}`
);
}

if (output.format === 'esm' || output.format === 'es') {
attributes.script = Object.assign({}, attributes.script, { type: 'module' });
}

const files = getFiles(bundle);
const source = await template({ attributes, bundle, files, publicPath, title });

const htmlFile = {
type: 'asset',
source,
name: 'Rollup HTML Asset',
fileName
};

this.emitFile(htmlFile);
}
};
};

module.exports = html;
module.exports.makeHtmlAttributes = makeHtmlAttributes;
56 changes: 56 additions & 0 deletions packages/html/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"name": "@rollup/plugin-html",
"version": "0.1.0",
"publishConfig": {
"access": "public"
},
"description": "Creates HTML files to serve Rollup bundles",
"license": "MIT",
"repository": "rollup/plugins",
"author": "Andrew Powell <andrew@shellscape.org>",
"homepage": "https://github.com/rollup/plugins/packages/beep",
"bugs": "https://github.com/rollup/plugins/issues",
"main": "lib/index.js",
"engines": {
"node": ">= 8.0.0"
},
"scripts": {
"ci:coverage": "nyc pnpm run test && nyc report --reporter=text-lcov > coverage.lcov",
"ci:lint": "pnpm run lint && pnpm run security",
"ci:lint:commits": "commitlint --from=${CIRCLE_BRANCH} --to=${CIRCLE_SHA1}",
"ci:test": "pnpm run test -- --verbose",
"lint": "pnpm run lint:js && pnpm run lint:docs && pnpm run lint:package",
"lint:docs": "prettier --single-quote --write *.md",
"lint:js": "eslint --fix --cache lib test",
"lint:package": "prettier --write package.json --plugin=prettier-plugin-package",
"prepublishOnly": "pnpm run lint",
"security": "echo 'pnpm needs `npm audit` support'",
"test": "ava"
},
"files": [
"lib",
"README.md",
"LICENSE"
],
"keywords": [
"rollup",
"plugin",
"html",
"template"
],
"peerDependencies": {
"rollup": "^1.20.0"
},
"devDependencies": {
"rollup": "^1.27.5",
"rollup-plugin-postcss": "^2.0.3"
},
"ava": {
"files": [
"!**/fixtures/**",
"!**/helpers/**",
"!**/recipes/**",
"!**/types.ts"
]
}
}
Empty file.
1 change: 1 addition & 0 deletions packages/html/test/fixtures/joker.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* { width: 100%; }
2 changes: 2 additions & 0 deletions packages/html/test/fixtures/joker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line
import style from './joker.css';
2 changes: 2 additions & 0 deletions packages/html/test/fixtures/robin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line
import * as batman from './batman.js';
Loading

0 comments on commit 144b4a4

Please sign in to comment.