For example, you have some html file with <table> tag with rich markup and you need it in another file but without some buttons, different classes and labels, or even worse, you will need to wrap some tag. You can solve it with dozens of parameters and if's but you markup will become unreadable.
Extend origin html file using es6 like module system and annotations.
npm install html-extend
- API
- Annotations
- export
- global
- import
- Tags
- Attributes
- Text
- Annotations
- Contribute
/** * @param {String} filePath * @returns {HtmlString} */render(filePath)/** * @param {String} filePath * @returns {HtmlModule} */htmlFileToDom(filePath){HtmlModule} is dom object of simple-html-dom-parser with imports and exports properties
/** * @param {String} html * @param {String} filePath - needed to resolve import path * @returns {HtmlModule} */htmlToDom(html,filePath)/** * @param {DomObject} dom * @returns {String} */domToHtml(dom)/** * @property {Object} */require('html-extend').globalTagsIt's hash where keys are names of global tags and values should be DomObject or html string or function (which will take DomObject and should return string or new DomObject).
/** * @param {Array<String>|String} fileExtensions * @param {Function} handler */functionsetExtension(fileExtensions,handler)handler will take file path and should return hash with exported tag names, which values should be DomObject or html string or function (which will take DomObject and should return string or new DomObject).
Example
component.xhtml
<div><h1>{label}</h1><inputtype="{type}"/></div>varsetExtension=require('html-extend').setExtension;setExtension('xhtml',functionhandler(file){varhtml=fs.readFileSync(file).toString();return{"default": function(tag){varresult=html;for(varnameintag.shadowAttr){result=result.replace('{'+name+'}',tag.shadowAttr[name]);}returnresult;}};});import Component from './component'
<div><Component~label="Some Title" ~type="number" class="test"/></div><div><divclass="test"><h1>Some Title</h1><inputtype="number"/></div></div>With setExtension you can even rewrite default html extension handler.
To remove extension just set null
setExtension('xhtml',null);Annotations is text or comment like @annotationName before tags which describes how tag should be modified.
Annotation which used to export tags. The only option is the name of exported tag. It's same as in CommonJS when you write exports.TagName or in es6 export TagName will be @export TagName. Also as in es6 export default you can write @export default or just @export and this tag will be default for current module. You can export any tag from file, not just root tags. You can use dots and dashes in tag name. You can use as many export names as you wish.
@export default
@export Layout
<divclass="layout">
@export ButtonXS
<buttonclass="btn btn-xs">OK</button><!-- @export Button.SM --><buttonclass="btn btn-sm">OK</button><!-- | @export btn-lg | @export Btn.lg | @export Bootstrap.btn-lg +--><buttonclass="btn btn-lg">OK</button></div>This annotation same as @export only it will export to global scope
import is a keyword, not annotation, because it's not binded to any tag, it should be only on top of file or after <!DOCTYPE ...>. Syntax is same as for es6.
import{TagAlias1,TagAlias2asItem}from'./path/to/file'importLayoutfrom'/absolute/path/to/file'import*asBootstrapfrom'name-of-npm-package'Then you can use those tags.
<TagAlias1></TagAlias1><Item/><Layout/><Bootstrap.ButtonXS></Bootstrap.ButtonXS>As you can see you can share your html modules through npm and import will find it just like native require().
You have two options to point on tag which you want to modify.
First is write same tags tree to tag.
@export Item
<div><ulclass="list"><liclass="item"><spanclass="h2">Title 1</span></li><liclass="item"><spanclass="h2">Title 2</span></li><liclass="item"><spanclass="h2">Title 3</span></li></ul></div>import {Item} from './module1'
<Item><ul><li>
@prepend
<h1>Title</h1>
@append
<button>OK</button></li></ul></Item>=
<div><ulclass="list"><liclass="item"><h1>Title</h1><spanclass="h2">Title</span><button>OK</button></li></ul></div>If you don't want or don't know tags names, simply write <tag>
<Item><tag><tag>
...
</tag></tag></Item>To point to third tag
<Item><ul><tag/><tag/><tag>
...
</tag></ul></Item>Second is to use @find
If in parent tag only one child and you write two then second will be added.
@export Item
<div><ulclass="list"><liclass="item"></li></ul></div>import {Item} from './module1'
<Item><tag><tag/><liclass="second-item"></li></tag></Item>=
<div><ulclass="list"><liclass="item"></li><liclass="second-item"></li></ul></div>Also annotations like @prepend and @append can add tags.
See @remove
Just point to needed tag and write new name
@export Item
<div><ulclass="list"><liclass="item"></li></ul></div>import {Item} from './module1'
<Item><tag><div/></tag></Item>=
<div><ulclass="list"><divclass="item"></li></ul></div>Any attribute (except class) will be rewrited if it not exist in parent, it will be added.
@export Item
<div><h1id="title">Title</h1></div>import {Item} from './module1'
<Item><tagid="header" title="Header"/></Item>=
<div><h1id="header" title="Header">Title</h1></div>To remove attribute just write ! before it
@export Item
<div><h1title="Header">Title</h1></div>import {Item} from './module1'
<Item><h1!title/></Item>=
<div><h1>Title</h1></div>When attribute name starts with ~ it means it's shadow attribute and it needed only to pass some value to extended module. This type of attribute will not add, remove or rewrite parent attribute. See example of setExtension function.
All class names will be added (not rewrited) to parent tag.
@export Item
<div><h1class="header">Title</h1></div>import {Item} from './module1'
<Item><h1class="pull-left"/></Item>=
<div><h1class="header pull-left">Title</h1></div>To remove class name write ! before it
@export Item
<div><h1class="header">Title</h1></div>import {Item} from './module1'
<Item><h1class="!header"/></Item>=
<div><h1class="">Title</h1></div>Any text will rewrite parent text.
@export Item
<div><h1><spanclass="icon"></span> Title</h1><h2>Title <spanclass="icon"></span></h2><h3><spanclass="icon"></span></h3><h4><spanclass="icon"></span></h4><h5></h5></div>import {Item} from './module1'
<Item><h1><tag/> Main title</h1><tag>Sub title </tag><tag><tag/> Title</tag><tag>Title</tag><tag>
Title
<spanclass="icon"></span></tag></Item>=
<div><h1><spanclass="icon"></span> Main title</h1><h2>Sub title <spanclass="icon"></span></h2><h3><spanclass="icon"></span> Title</h3><h4>Title<spanclass="icon"></span></h4><h5>
Title
<spanclass="icon"></span></h5></div>To remove text you need write some html entity like or if you no need space then ​ or similar.
With this annotation you can point to tag with css selector.
@export Item
<div><divclass="wrapper"><divclass="header"><h1>Title</h1></div><divclass="content"><p>Description</p></div></div></div>import {Item} from './module1'
<Item>
@find .header
<tag>
@append
<span>Sub title</span></tag><tagclass="wrapper"><tag/><tagclass="content">
@append
<p>Text</p></tag></tag></Item>=
<div><divclass="wrapper"><divclass="header"><h1>Title</h1><span>Sub title</span></div><divclass="content"><p>Description</p><p>Text</p></div></div></div>It will add tag to the end of current tag parent.
@export Item
<div><span>Title</span></div>import {Item} from './module1'
<Item>
@append
<button>OK</button><span>Title</span></Item>=
<div><span>Title</span><button>OK</button></div>If you want to add several tags then you need to write @append before each of them.
Will add tag on first place of current parent
@export Item
<div><span>Title</span></div>import {Item} from './module1'
<Item>
@prepend
<button>OK</button><spanclass="header"/></Item>=
<div><button>OK</button><spanclass="header">Title</span></div>Will add tag on current place.
@export Item
<div><h1>Title</h1><p>Description</p><button>Ok</button></div>import {Item} from 'module1'
<Item><h1/><p/>
@insert
<inputtype="text"/></Item>=
<div><h1>Title</h1><p>Description</p><inputtype="text"/><button>Ok</button></div>Will remove current tag
@export Item
<div><divclass="content"><inputtype="text"/><button>OK</button></div></div>import {Item} from './module1'
<Item><tagclass="content">
@remove
<input/></tag></Item>=
<div><divclass="content"><button>OK</button></div></div>Will remove children of current tag.
@export Item
<div><divclass="content"><p>Description</p><button>OK</button></div></div>import {Item} from './module1'
<Item>
@empty
<tagclass="content"><h1>Title</h1></tag></Item>=
<div><divclass="content"><h1>Title</h1></div></div>Will add tag to another tag by css selector.
@export Item
<div><divclass="content"><pclass="description">Description</p></div></div>import {Item} from './module1'
<Item>
@appendTo .description
<span>Read more</span></Item>=
<div><divclass="content"><pclass="description">Description<span>Read more</span></p></div></div>Will add tag to the beginig of another tag by css selector
@export Item
<div><divclass="content"><pclass="description">Description</p></div></div>import {Item} from './module1'
<Item>
@prependTo .content
<h1>Title</h1></Item>=
<div><divclass="content"><h1>Title</h1><pclass="description">Description</p></div></div>Will add tag before another tag by css selector
@export Item
<div><divclass="content"><h1>Title</h1><pclass="description">Description</p></div></div>import {Item} from './module1'
<Item>
@insertBefore .description
<h2>Sub title</h2></Item>=
<div><divclass="content"><h1>Title</h1><h2>Sub title</h2><pclass="description">Description</p></div></div>Will add tag after another tag by css selector
@export Item
<div><divclass="content"><h1>Title</h1><pclass="description">Description</p></div></div>import {Item} from './module1'
<Item>
@insertAfter .content h1
<h2>Sub title</h2></Item>=
<div><divclass="content"><h1>Title</h1><h2>Sub title</h2><pclass="description">Description</p></div></div>Help me improve this doc and any comments are welcome in issues.