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.
npm install --save-dev posthtml
Simple example
var posthtml = require('posthtml');
var html = '<myComponent><myTitle>Super Title</myTitle><myText>Awesome Text</myText></myComponent>';
posthtml()
.use(require('posthtml-custom-elements')())
.process(html/*, options */)
.then(function(result) {
console.log(result.html);
// <div class="myComponent"><div class="myTitle">Super Title</div><div class="myText">Awesome Text</div></div>
});
Сomplex example
var posthtml = require('posthtml');
var html = '<html><body><p class="wow">OMG</p></body></html>';
posthtml([
require('posthtml-to-svg-tags')(),
require('posthtml-extend-attrs')({
attrsTree: {
'.wow' : {
id: 'wow_id',
fill: '#4A83B4',
'fill-rule': 'evenodd',
'font-family': 'Verdana'
}
}
})
])
.process(html/*, options */)
.then(function(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>
});
Install gulp-posthtml
npm install --save-dev gulp-posthtml
gulp.task('html', function() {
var posthtml = require('gulp-posthtml');
return gulp.src('src/**/*.html')
.pipe(posthtml([ require('posthtml-custom-elements')() ]/*, options */))
.pipe(gulp.dest('build/'));
});
Check project-stub example with Gulp
- posthtml-bem — Support BEM naming in html structure
- posthtml-retext — Extensible system for analysing and manipulating natural language
- posthtml-textr — Modular typographic framework
- posthtml-custom-elements — Use custom elements now
- posthtml-style-to-file — Save HTML style nodes and attributes to CSS file
- posthtml-classes — Get a list of classes from HTML
- posthtml-doctype — Extend html tags doctype
- posthtml-include — Include html file
- posthtml-to-svg-tags — Convert html tags to svg equals
- posthtml-extend-attrs — Extend html tags attributes with custom data and attributes
- posthtml-modular-css — Makes css modular
- posthtml-static-react — Render custom elements as static React components
- posthtml-inline-css — Inline CSS
- posthtml-imports — Support W3C HTML imports
- posthtml-style — Include css file in HTML. Save <style>, style attrs to CSS file
- beml — HTML preprocessor for BEM
- mimic
Something more? ;)
- posthml-match-helper - Expand CSS selectors into PostHTML matcher objects.
- posthtml-parser — Parser HTML/XML to PostHTMLTree
- posthtml-render — Render PostHTMLTree to HTML/XML
<a class="animals" href="#">
<span class="animals__cat" style="background: url(cat.png)">Cat</span>
</a>
[{
tag: 'a',
attrs: {
class: 'animals',
href: '#'
},
content: [
'\n ',
{
tag: 'span',
attrs: {
class: 'animals__cat',
style: 'background: url(cat.png)'
},
content: ['Cat']
},
'\n'
]
}]
This is a simple function with a single argument
module.exports = function pluginName(tree) {
// do something for tree
tree.match({ tag: 'img' }, function(node) {
node = Object.assign(node, { attrs: { class: 'img-wrapped' } }});
return {
tag: 'span',
attrs: { class: 'img-wrapper' },
content: node
}
});
};
var request = request('request');
module.exports = function pluginName(tree, cb) {
var tasks = 0;
tree.match({ tag: 'a' }, function(node) {
// skip local anchors
if (!/^(https?:)?\/\//.test(node.attrs.href)) {
return node;
}
request.head(node.attrs.href, function (err, resp) {
if (err) return done();
if (resp.statusCode >= 400) {
node.attrs.class += ' ' + 'Erroric';
}
if (resp.headers.contentType) {
node.attrs.class += ' content-type_' + resp.headers.contentType;
}
done();
});
tasks += 1;
return node;
});
function done() {
tasks -= 1;
if (!tasks) cb(null, tree);
}
};
import { toTree } from 'posthtml/lib/api';
import request from 'request';
export default tree => {
return new Promise(resolve => {
tree.match({ tag: 'user-info' }, (node) => {
request(`/api/user-info?${node.attrs.dataUserId}`, (err, resp, body) {
if (!err && body) node.content = toTree(body);
resolve(tree);
});
});
});
};
Arguments: {String} html
Parses HTML string into a PostHTMLTree object.
Returns: {PostHTMLTree}
Arguments: {Function} plugin
Adds a plugin into the flow.
var posthtml = require('posthtml');
var ph = posthtml()
.use(function(tree) {
return { tag: 'div', content: tree };
});
Arguments: {String|PostHTMLTree} html[, {Object} options]
Applies all plugins to the incoming html
object.
Returns: {{tree: PostHTMLTree, html: String}}
(eventually) an Object with modified html and/or tree.
var ph = posthtml()
.process('<div></div>'/*, { options }*/);
Array tags for extend default list single tags
Default: []
Options { singleTags: ['rect', 'custom'] }
...
<div>
...
<rect>
<custom>
</div>
Option to specify version closing single tags.
Accepts values: default
, slash
, tag
.
Default: default
Options { closingSingleTag: 'default' }
<singletag>
Options { closingSingleTag: 'slash' }
<singletag />
Options { closingSingleTag: 'tag' }
<singletag></singletag>
Skips input html parsing process.
Default: null
posthtml()
.use(function(tree) { tree.tag = 'section'; })
.process({ tag: 'div' }, { skipParse: true })
.then(function (result) {
result.tree; // { tag: 'section' }
result.html; // <section></section>
});
Try to run plugins synchronously. Throws if some plugins are async.
Default: null
posthtml()
.use(function(tree) { tree.tag = 'section'; })
.process('<div>foo</div>', { sync: true })
.html; // <section>foo</section>
Arguments: {function(PostHTMLNode|String): PostHTMLNode|String}
Walk for all nodes in tree, run callback.
tree.walk(function(node) {
let classes = node.attrs && node.attrs.class.split(' ') || [];
if(classes.includes(className)) {
// do something for node
return node;
}
return node;
});
Arguments: {Object|String|RegExp}, {function(PostHTMLNode|String): PostHTMLNode|String}
Find subtree in tree, run callback.
tree.match({ tag: 'custom-tag' }, function(node) {
// do something for node
return Object.assign(node, {
tag: 'div',
attrs: { class: node.tag }
});
});
Support Array matchers
tree.match([{ tag: 'b' }, { tag: 'strong' }], function(node) {
var style = 'font-weight: bold;';
node.tag = 'span';
node.attrs ? (
node.attrs.style ? (
node.attrs.style += style
) : node.attrs.style = style;
) : node.attrs = { style: style };
return node
});
MIT