Installation

npm

npm i -D rollup-plugin-posthtml-amstramgram

Manually

Download the plugin in a rollup-plugin-posthtml-amstramgram folder located at the root of your project.

Dependencies

If you have chosen the manual way, install also posthtml and fast-glob.

npm i -D posthtml fast-glob

Posthtml plugins

Pick up posthtml plugins you need from here and enjoy...

Usage

Imagine a development tree like this :

src
  • html
    • common
      • head.html
      • header-aside.html
      • template.html
    • content
      • css.html
      • html.html
      • index.html
      • watcher.html
  • css.html
  • error.html
  • html.html
  • index.html
  • watcher.html

Each html file at the root of src calls src/html/common/template.html which includes some other parts...

<include src="common/template.html">
	{
		"title" : "Amstramgram Rollup Plugins - A workflow to build website",
		"description" : "An introduction to processing external HTML and CSS files with Amstramgram Rollup Plugins",
		"content" : "index",
		"style" : "" 
	}
</include>

The template should grab this information and and put it all together.

<!doctype html>
<html lang="en" class="loading">

<head>
	<!-- A specific title -->
	<title>{{ title }}</title>
	<!-- A specific description -->
	<meta name="description" content="{{ description }}">
	<include src="common/head.html"></include>
</head>

<body>
	<include src="common/header-aside.html"></include>
	<div class="content-wrapper">
		<div class="content">
			<!-- A specific content -->
			<include src="content/{{content}}.html"></include>
		</div>
	</div>
	<div class="up"></div>
	<!-- A specific style : the style of the page about the postcss plugin is originally written in scss-->
	<link rel="stylesheet" href="css/index{{style}}.css" media="print" onload="this.media='all';">
	<script type="module" src="js/index.mjs"></script>
	<script nomodule src="js/noModule/index.js"></script> 
</body> 

</html>

Let rollup and our plugin do the job :

...
//import rollup-plugin-posthtml-amstramgram from the folder where you downloaded it :
import htmlPlugin from './rollup-plugin-posthtml-amstramgram/esm/index.mjs'
//Or if you have installed it from npm :
//import htmlPlugin from 'rollup-plugin-posthtml-amstramgram'
//import posthtml plugins you want to use :
//https://github.com/posthtml/posthtml-include
import htmlinclude from 'posthtml-include'
//https://github.com/posthtml/htmlnano
import htmlnano from 'htmlnano'
...

export default = {
  input: 'src/js/index.js',
  output: {
    file: 'dist/js/index.js',
    format: ...
  },
  plugins: [
    ...
    htmlPlugin({
      jobs: { from: 'src', to: 'dist' },
      //Watch src folder if in development
      watch: process.env.BUILD === 'development',
      plugins: [
        htmlinclude({
          root: 'src/html/'
        }),
        //Minify if in production
        ...(process.env.BUILD === 'production' ? [htmlnano()] : [])
      ]
    }),
    ...
  ]
}

Options

jobs

A Job or an array of Jobs.

A Job is an object whose properties are :

- from -

Either a String or an Array of Strings.
Each element should be a valid glob or a string pointing to an existing file or folder.
If the target is a folder, all relevant files at its root will be processed.
See here if you need details about glob.

- to -

A String (or an Array of Strings) pointing to folder(s) where to put the result.

- root -

A String that sets the reference for the result tree.
By default, all processed files are placed at the root of the destination folder(s) defined by the to option.
If a directory is set as root option, the files will be placed relatively to it (see below for an illustration).
(default : undefined)

- rename -

A String or a Function that defines how the resulting file(s) should be named.
The function takes the file name and its full path as arguments and should return a string.
Example :
    rename: (name, path) => name + '.min'
will result in :
    index.html => index.min.html
If you process only one file, you can simply set :
    rename: 'index.min'
(default : undefined)

plugins

An Array of posthtml plugins.

ext

A String or an Array of Strings defining accepted extensions.
Only files with one of the listed extension will be processed.
Example : ext: 'html'
Note that, if omitted, the dot will be automatically added.
So in the example above, ext: 'html' actually becomes ext: '.html'.
(default : ['.html', '.htm'])

watch

A Boolean indicating whether folders containing files to process (including their dependencies) should be watched.
(default : false)

processHook

A String that defines the rollup hook used to process the files.
Note however that the watch option will be forced to false if you use a hook called after moduleParsed because rollup cannot call the addWatchFile function after the build has finished.
(default : "transform").

verbose

A Boolean that specifies whether messages and notifications should be sent to the terminal.
(default : false).

warnOnError

A Boolean that specifies whether warnings should be logged for process errors.
(default : true).

Examples

Basic

As already mentioned, by default, all processed files are placed at the root of the destination folder(s) set by the to option of a job.
So, if you work with a tree-structure like this :

src
  • html
    • pages
      • page-01.html
      • page-02.html
    • import
      • import-01.html
      • import-02.html
    • index.html

And if you set the plugin options like that :

...
export default = {
  ...
  plugins: [
    ...
    htmlPlugin({
      jobs: {
        from: [`src/html/**/*`, `!src/html/import`],
        to: `dist/html`
      }
    }),
    ...
  ]
}

You will get :

dist
  • html
    • index.html
    • page-01.html
    • page-02.html

Keep nested structure

If you need to keep the original nested structure of your files, you should consider taking advantage of the job's root property.
Something like below where we also use the rename feature to spice it up a bit :

...
export default = {
  ...
  plugins: [
    ...
    htmlPlugin({
      jobs: {
        from: [`src/html/**/*`, `!src/html/import`],
        to: `dist`,
        root: `src`,
        rename: (name, fullPath) => (fullPath.includes('pages') ? 'my-' : 'the-') + name
      }
    }),
    ...
  ]
}
dist
  • html
    • pages
      • my-page-01.html
      • my-page-02.html
    • the-index.html

Output plugin

The plugin can be set as an output plugin if you really need it.
However, even if the job is indeed done, you will be warned by rollup about using "transform" and "watchChange" hooks if you don't set an output generation hook for the processHook option.

...
export default = {
  input: `src/js/main.js`,
  output: {
    file: `dist/js/main.js`,
    format: 'esm',
    plugins: [
      htmlPlugin({
        jobs: { from: `src/html/index.html`, to: `dist/html`, rename: `index.min`},
        processHook: 'writeBundle',
        plugins: [htmlnano()]
      })
    ]
  },
}