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 posthtmlRequires Node.js ^20.19.0 || >=22.12.0, matching the synchronous loading requirements of posthtml-parser and its htmlparser2 backend.
npm i -D posthtmlThe 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 posthtmlnpm i -D gulp-posthtmlimport 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-posthtmlposthtml: {
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-loaderwebpack.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 configwebpack.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: {
94F3
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 |