PostHTML is a tool for transforming HTML/XML with JS plugins. PostHTML itself is very small. It includes only a HTML parser, a HTML node tree API and a node tree stringifier.
All HTML transformations are made by plugins. And these plugins are just small plain JS functions, which receive a HTML node tree, transform it, and return a modified tree.
See the documentation for the processor API, tree format and plugin guides.
For usage questions, visit Discussions. Report bugs and propose features through Issues.
| Name | Description |
|---|---|
| posthtml-parser | Parser HTML/XML to PostHTMLTree |
| posthtml-render | Render PostHTMLTree to HTML/XML |
npm init posthtml
Requires Node.js ^20.19.0 || >=22.12.0, matching the synchronous loading requirements of posthtml-parser and its htmlparser2 backend.
npm i -D posthtml
The examples below use ES modules. Save them as .mjs files or set "type": "module" in your project's package.json, and install the plugins used in each example.
Sync
import posthtml from 'posthtml' import customElements from 'posthtml-custom-elements' const html = ` <component> <title>Super Title</title> <text>Awesome Text</text> </component> ` const result = posthtml() .use(customElements()) .process(html, { sync: true }) .html console.log(result)
<div class="component"> <div class="title">Super Title</div> <div class="text">Awesome Text</div> </div>
⚠️ Async Plugins can't be used in sync mode and will throw an Error. It's recommended to use PostHTML asynchronously whenever possible.
Async
import posthtml from 'posthtml' import toSvgTags from 'posthtml-to-svg-tags' import extendAttrs from 'posthtml-extend-attrs' const html = ` <html> <body> <p class="wow">OMG</p> </body> </html> ` posthtml( [ toSvgTags(), extendAttrs({ attrsTree: { '.wow' : { id: 'wow_id', fill: '#4A83B4', 'fill-rule': 'evenodd', 'font-family': 'Verdana' } } }) ]) .process(html/*, options */) .then((result) => console.log(result.html))
<svg xmlns="http://www.w3.org/2000/svg"> <text class="wow" id="wow_id" fill="#4A83B4" fill-rule="evenodd" font-family="Verdana"> OMG </text> </svg>
Directives
import posthtml from 'posthtml' import customElements from 'posthtml-custom-elements' const php = ` <component> <title><?php echo $title; ?></title> <text><?php echo $article; ?></text> </component> ` posthtml() .use(customElements()) .process(php, { directives: [ { name: '?php', start: '<', end: '>' } ] }) .then((result) => console.log(result.html))
<div class="component"> <div class="title"><?php echo $title; ?></div> <div class="text"><?php echo $article; ?></div> </div>
npm i posthtml-cli
"scripts": { "posthtml": "posthtml -o output.html -i input.html -c config.json" }
npm run posthtml
npm i -D gulp-posthtml
import gulp from 'gulp' import posthtml from 'gulp-posthtml' import include from 'posthtml-include' const { task, src, dest } = gulp task('html', () => { const plugins = [include({ root: 'src' })] const options = {} return src('src/**/*.html') .pipe(posthtml(plugins, options)) .pipe(dest('build/')) })
Check project-stub for an example with Gulp
npm i -D grunt-posthtml
posthtml: { options: { use: [ require('posthtml-doctype')({ doctype: 'HTML 5' }), require('posthtml-include')({ root: './', encoding: 'utf-8' }) ] }, build: { files: [ { dot: true, cwd: 'html/', src: ['*.html'], dest: 'tmp/', expand: true, } ] } }
npm i -D html-loader posthtml-loader
webpack.config.js
import pug from 'posthtml-pug' import bem from 'posthtml-bem' const config = { module: { loaders: [ { test: /\.html$/, loader: 'html!posthtml' } ] }, posthtml: (ctx) => ({ parser: pug, plugins: [ bem() ] }) } export default config
webpack.config.js
import webpack from 'webpack' import pug from 'posthtml-pug' import bem from 'posthtml-bem' const { LoaderOptionsPlugin } = webpack const config = { module: { rules: [ { test: /\.html$/, use: [ { loader: 'html-loader', options: { minimize: true } }, { loader: 'posthtml-loader' } ] } ] }, plugins: [ new LoaderOptionsPlugin({ options: { posthtml(ctx) { return { parser: pug, plugins: [ bem() ] } } } }) ] } export default config
$ npm i rollup-plugin-posthtml -D
# or
$ npm i rollup-plugin-posthtml-template -Dimport posthtml from 'rollup-plugin-posthtml-template' // or // import posthtml from 'rollup-plugin-posthtml' import sugarml from 'posthtml-sugarml' // npm i posthtml-sugarml -D import include from 'posthtml-include' // npm i posthtml-include -D export default { input: 'main.js', output: { file: 'bundle.js', format: 'iife' }, plugins: [ posthtml({ parser: sugarml(), plugins: [include()], template: true // only rollup-plugin-posthtml-template }) ] }
import posthtml from 'posthtml' import pug from 'posthtml-pug' posthtml().process(html, { parser: pug(options) }).then((result) => result.html)
| Name | Description |
|---|---|
| posthtml-pug | Pug Parser |
| sugarml | SugarML Parser |
In case you want to develop your own plugin, we recommend using posthtml-plugin-starter to get started.
Use Node.js 24 from .nvmrc and run npm run check. See the contributor guide for commands and releases, and AGENTS.md for coordinated work on PostHTML, its parser and renderer.
|
Ivan Demidov |
Ivan Voischev |