├── .github └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── README.md ├── package.json ├── src └── index.js ├── test ├── __snapshots__ │ └── template.test.js.snap ├── fixtures │ ├── base.js │ └── styles.css ├── helpers │ ├── compiler.js │ └── config.js └── template.test.js └── yarn.lock /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | types: [opened, synchronize] 8 | 9 | jobs: 10 | test: 11 | name: Test on Node ${{ matrix.node }} 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | node: [10, 12, 14] 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v2 20 | 21 | - name: Setup Node ${{ matrix.node }} 22 | uses: actions/setup-node@v1 23 | with: 24 | node-version: ${{ matrix.node }} 25 | 26 | - name: Install dependencies 27 | run: yarn install --frozen-lockfile --check-files 28 | 29 | - name: Run test 30 | run: yarn test 31 | 32 | release: 33 | name: Release package 34 | runs-on: ubuntu-latest 35 | needs: test 36 | if: github.event_name != 'pull_request' 37 | 38 | steps: 39 | - name: Checkout repository 40 | uses: actions/checkout@v2 41 | with: 42 | fetch-depth: 0 43 | 44 | - name: Run semantic-release 45 | run: npx semantic-release 46 | env: 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 48 | NPM_TOKEN: ${{ secrets.NPM_TOKEN}} 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode/ 3 | .DS_Store 4 | Thumbs.db 5 | *.log 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) vxna 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @vxna/mini-html-webpack-template 2 | 3 | [](https://github.com/vxna/mini-html-webpack-template/actions?query=workflow%3ACI+branch%3Amaster) [](https://www.npmjs.com/package/@vxna/mini-html-webpack-template) 4 | 5 | Template for [mini-html-webpack-plugin](https://github.com/bebraw/mini-html-webpack-plugin) that extends default features with useful subset of options 6 | 7 | ## Warning 8 | 9 | It does not work with [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) 10 | 11 | ## Common usage 12 | 13 | **webpack.config.js** 14 | 15 | ```js 16 | const MiniHtmlWebpackPlugin = require('mini-html-webpack-plugin') 17 | 18 | module.exports = { 19 | plugins: [ 20 | new MiniHtmlWebpackPlugin({ 21 | context: { 22 | title: 'common-usage', 23 | favicon: 'https://assets-cdn.github.com/favicon.ico', 24 | container: 'root', 25 | trimWhitespace: true, 26 | }, 27 | template: require('@vxna/mini-html-webpack-template'), 28 | }), 29 | ], 30 | } 31 | ``` 32 | 33 | ## Common options 34 | 35 | | Name | Type | Default | Description | 36 | | -------------------- | ----------- | -------------- | ---------------------------------- | 37 | | **`lang`** | `{String}` | `undefined` | Set document language | 38 | | **`title`** | `{String}` | `'sample-app'` | Set document title | 39 | | **`favicon`** | `{String}` | `undefined` | Set document favicon | 40 | | **`container`** | `{String}` | `undefined` | Set application mount point | 41 | | **`trimWhitespace`** | `{Boolean}` | `undefined` | Safe document whitespace reduction | 42 | 43 | ## Extended usage 44 | 45 | **webpack.config.js** 46 | 47 | ```js 48 | const MiniHtmlWebpackPlugin = require('mini-html-webpack-plugin') 49 | 50 | module.exports = { 51 | plugins: [ 52 | new MiniHtmlWebpackPlugin({ 53 | context: { 54 | title: 'extended-usage', 55 | head: { 56 | meta: [ 57 | { 58 | name: 'description', 59 | content: 'mini-html-webpack-template', 60 | }, 61 | ], 62 | }, 63 | body: { 64 | raw: '
', 65 | }, 66 | attrs: { 67 | js: { 68 | async: '', 69 | type: 'text/javascript', 70 | }, 71 | }, 72 | }, 73 | template: require('@vxna/mini-html-webpack-template'), 74 | }), 75 | ], 76 | } 77 | ``` 78 | 79 | ## Extended options 80 | 81 | | Name | Type | Default | Description | 82 | | ------------------ | ----------------- | ----------- | ----------------------------------------- | 83 | | **`head.meta`** | `{Array}` | `undefined` | Array of objects with key + value pairs | 84 | | **`head.links`** | `{Array}` | `undefined` | Array of objects with key + value pairs | 85 | | **`head.scripts`** | `{Array}` | `undefined` | Array of objects with key + value pairs | 86 | | **`head.raw`** | `{Array\|String}` | `undefined` | Generates raw document markup | 87 | | **`body.scripts`** | `{Array}` | `undefined` | Array of objects with key + value pairs | 88 | | **`body.raw`** | `{Array\|String}` | `undefined` | Generates raw document markup | 89 | | **`attrs.js`** | `{Object}` | `undefined` | Applies html attributes to webpack output | 90 | | **`attrs.css`** | `{Object}` | `undefined` | Applies html attributes to webpack output | 91 | 92 | ## Advanced minification 93 | 94 | For custom needs [html-minifier](https://github.com/kangax/html-minifier) middleware and all of it's [options](https://github.com/kangax/html-minifier#options-quick-reference) could be used 95 | 96 | **webpack.config.js** 97 | 98 | ```js 99 | const { minify } = require('html-minifier') 100 | const MiniHtmlWebpackPlugin = require('mini-html-webpack-plugin') 101 | 102 | module.exports = { 103 | plugins: [ 104 | new MiniHtmlWebpackPlugin({ 105 | context: { 106 | title: 'advanced-minification', 107 | }, 108 | template: (ctx) => 109 | minify(require('@vxna/mini-html-webpack-template')(ctx), { 110 | collapseWhitespace: true, 111 | minifyCSS: true, 112 | minifyJS: true, 113 | }), 114 | }), 115 | ], 116 | } 117 | ``` 118 | 119 | ## Complex security features 120 | 121 | [SRI](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) is out of scope of this project and it's recommended to use [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) with it's ecosystem tools. 122 | 123 | ## Inspired by 124 | 125 | [html-webpack-template](https://github.com/jaketrent/html-webpack-template) 126 | 127 | ## License 128 | 129 | MIT (http://www.opensource.org/licenses/mit-license.php) 130 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vxna/mini-html-webpack-template", 3 | "version": "0.0.0-development", 4 | "description": "Minimum viable template for mini-html-webpack-plugin", 5 | "author": "vxna", 6 | "license": "MIT", 7 | "main": "src/index.js", 8 | "files": [ 9 | "src/**/*.js" 10 | ], 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/vxna/mini-html-webpack-template.git" 14 | }, 15 | "keywords": [ 16 | "webpack", 17 | "mini-html-webpack-plugin" 18 | ], 19 | "engines": { 20 | "node": ">= 10" 21 | }, 22 | "scripts": { 23 | "pretest": "yarn lint", 24 | "lint": "eslint src/**/*.js --format codeframe --fix", 25 | "test": "jest", 26 | "format": "prettier src/**/*.{js,md} --write", 27 | "posttest": "yarn format" 28 | }, 29 | "dependencies": { 30 | "common-tags": "^1.8.0" 31 | }, 32 | "devDependencies": { 33 | "css-loader": "^4.2.2", 34 | "eslint": "^7.7.0", 35 | "eslint-config-prettier": "^6.11.0", 36 | "eslint-config-standard": "^14.1.1", 37 | "eslint-plugin-import": "^2.22.0", 38 | "eslint-plugin-node": "^11.1.0", 39 | "eslint-plugin-promise": "^4.2.1", 40 | "eslint-plugin-standard": "^4.0.1", 41 | "husky": "^4.2.5", 42 | "jest": "^26.4.2", 43 | "lint-staged": "^10.2.13", 44 | "memfs": "^3.2.0", 45 | "mini-css-extract-plugin": "^0.10.0", 46 | "mini-html-webpack-plugin": "^3.0.7", 47 | "prettier": "^2.1.1", 48 | "webpack": "^4.44.1" 49 | }, 50 | "eslintConfig": { 51 | "extends": [ 52 | "standard", 53 | "prettier" 54 | ], 55 | "env": { 56 | "jest": true 57 | } 58 | }, 59 | "jest": { 60 | "testEnvironment": "node" 61 | }, 62 | "prettier": { 63 | "singleQuote": true, 64 | "semi": false 65 | }, 66 | "husky": { 67 | "hooks": { 68 | "pre-commit": "lint-staged" 69 | } 70 | }, 71 | "lint-staged": { 72 | "*.js": [ 73 | "eslint --fix" 74 | ], 75 | "*.{js,md}": [ 76 | "prettier --write" 77 | ] 78 | }, 79 | "publishConfig": { 80 | "access": "public" 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const { 2 | html, 3 | oneLineTrim, 4 | TemplateTag, 5 | trimResultTransformer, 6 | replaceResultTransformer, 7 | } = require('common-tags') 8 | 9 | function template(ctx) { 10 | const { 11 | publicPath, 12 | css, 13 | js, 14 | lang, 15 | title, 16 | favicon, 17 | container, 18 | head = {}, 19 | body = {}, 20 | attrs = {}, 21 | trimWhitespace, 22 | } = ctx 23 | 24 | const doc = html` 25 | 26 | ${lang ? `` : ''} 27 | 28 | 29 | 30 | 31 |