Package Exports
- posthtml
- posthtml/lib/api
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (posthtml) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
PostHTML
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.
Usage
Install PostHTML
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>
});
Gulp plugin for PostHTML
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
Plugins
- 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
Ideas for plugins
- 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? ;)
Helpers
- posthml-match-helper - Expand CSS selectors into PostHTML matcher objects.
Dependency
- posthtml-parser — Parser HTML/XML to PostHTMLTree
- posthtml-render — Render PostHTMLTree to HTML/XML
PostHTML JSON tree example
input HTML
<a class="animals" href="#">
<span class="animals__cat" style="background: url(cat.png)">Cat</span>
</a>
Tree in PostHTML (PostHTMLTree)
[{
tag: 'a',
attrs: {
class: 'animals',
href: '#'
},
content: [
'\n ',
{
tag: 'span',
attrs: {
class: 'animals__cat',
style: 'background: url(cat.png)'
},
content: ['Cat']
},
'\n'
]
}]
Create PostHTML plugin
This is a simple function with a single argument
Synchronous plugin example
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
}
});
};
Classic asynchronous plugin example
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);
}
};
Promised asynchronous plugin example
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);
});
});
});
};
class PostHTML
.parse()
Arguments: {String} html
Parses HTML string into a PostHTMLTree object.
Returns: {PostHTMLTree}
.use()
Arguments: {Function} plugin
Adds a plugin into the flow.
Example
var posthtml = require('posthtml');
var ph = posthtml()
.use(function(tree) {
return { tag: 'div', content: tree };
});
.process()
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.
Example
var ph = posthtml()
.process('<div></div>'/*, { options }*/);
Options
singleTags
Array tags for extend default list single tags
Default: []
Options { singleTags: ['rect', 'custom'] }
...
<div>
...
<rect>
<custom>
</div>
closingSingleTag
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>
skipParse
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>
});
sync
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>
class API
.walk()
Arguments: {function(PostHTMLNode|String): PostHTMLNode|String}
Walk for all nodes in tree, run callback.
Example
tree.walk(function(node) {
let classes = node.attrs && node.attrs.class.split(' ') || [];
if(classes.includes(className)) {
// do something for node
return node;
}
return node;
});
.match()
Arguments: {Object|String|RegExp}, {function(PostHTMLNode|String): PostHTMLNode|String}
Find subtree in tree, run callback.
Example
tree.match({ tag: 'custom-tag' }, function(node) {
// do something for node
return Object.assign(node, {
tag: 'div',
attrs: { class: node.tag }
});
});
Support Array matchers
Example
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
});
License
MIT