npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

html-extend

v1.5.0

Published

html-extend ===========

Downloads

55

Readme

html-extend

Build Status

Issue

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.

My solution

Extend origin html file using es6 like module system and annotations.

Install

npm install html-extend

Contents

API

/**
 * @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').globalTags

It'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
 */
function setExtension(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>
    <input type="{type}"/>
</div>
var setExtension = require('html-extend').setExtension;

setExtension('xhtml', function handler(file) {
    var html = fs.readFileSync(file).toString();

    return {
        "default": function (tag) {
            var result = html;

            for (var name in tag.shadowAttr) {
                result = result.replace('{' + name + '}', tag.shadowAttr[name]);
            }

            return result;
        }
    };
});
import Component from './component'

<div>
    <Component ~label="Some Title" ~type="number" class="test"/>
</div>
<div>
    <div class="test">
        <h1>Some Title</h1>
        <input type="number"/>
    </div>
</div>

With setExtension you can even rewrite default html extension handler.

To remove extension just set null

setExtension('xhtml', null);

Annotations

Annotations is text or comment like @annotationName before tags which describes how tag should be modified.

@export

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
<div class="layout">
  @export ButtonXS
  <button class="btn btn-xs">OK</button>
  <!-- @export Button.SM -->
  <button class="btn btn-sm">OK</button>
  <!--
   | @export btn-lg
   | @export Btn.lg
   | @export Bootstrap.btn-lg
   +-->
  <button class="btn btn-lg">OK</button>
</div>

@global

This annotation same as @export only it will export to global scope

import

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, TagAlias2 as Item} from './path/to/file'
import Layout from '/absolute/path/to/file'
import * as Bootstrap from '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().

Path to tag

You have two options to point on tag which you want to modify.

First is write same tags tree to tag.

@export Item
<div>
  <ul class="list">
    <li class="item">
      <span class="h2">Title 1</span>
    </li>
    <li class="item">
      <span class="h2">Title 2</span>
    </li>
    <li class="item">
      <span class="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>
  <ul class="list">
    <li class="item"><h1>Title</h1>
      <span class="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

Add tag

If in parent tag only one child and you write two then second will be added.

@export Item
<div>
  <ul class="list">
    <li class="item"></li>
  </ul>
</div>
import {Item} from './module1'

<Item>
  <tag>
    <tag/>
    <li class="second-item"></li>
  </tag>
</Item>

=

<div>
  <ul class="list">
    <li class="item"></li>
    <li class="second-item"></li>
  </ul>
</div>

Also annotations like @prepend and @append can add tags.

Remove tag

See @remove

Rename tag

Just point to needed tag and write new name

@export Item
<div>
  <ul class="list">
    <li class="item"></li>
  </ul>
</div>
import {Item} from './module1'

<Item>
  <tag>
    <div/>
  </tag>
</Item>

=

<div>
  <ul class="list">
    <div class="item"></li>
  </ul>
</div>

Add/rewrite attribute

Any attribute (except class) will be rewrited if it not exist in parent, it will be added.

@export Item
<div>
  <h1 id="title">Title</h1>
</div>
import {Item} from './module1'

<Item>
  <tag id="header" title="Header"/>
</Item>

=

<div>
  <h1 id="header" title="Header">Title</h1>
</div>

Remove attribute

To remove attribute just write ! before it

@export Item
<div>
  <h1 title="Header">Title</h1>
</div>
import {Item} from './module1'

<Item>
  <h1 !title/>
</Item>

=

<div>
  <h1>Title</h1>
</div>

Shadow attribute

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.

Add class

All class names will be added (not rewrited) to parent tag.

@export Item
<div>
  <h1 class="header">Title</h1>
</div>
import {Item} from './module1'

<Item>
  <h1 class="pull-left"/>
</Item>

=

<div>
  <h1 class="header pull-left">Title</h1>
</div>

Remove class

To remove class name write ! before it

@export Item
<div>
  <h1 class="header">Title</h1>
</div>
import {Item} from './module1'

<Item>
  <h1 class="!header"/>
</Item>

=

<div>
  <h1 class="">Title</h1>
</div>

Rewrite text in tag

Any text will rewrite parent text.

@export Item
<div>
  <h1><span class="icon"></span> Title</h1>
  <h2>Title <span class="icon"></span></h2>
  <h3><span class="icon"></span></h3>
  <h4><span class="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
    <span class="icon"></span>
  </tag>
</Item>

=

<div>
  <h1><span class="icon"></span> Main title</h1>
  <h2>Sub title <span class="icon"></span></h2>
  <h3><span class="icon"></span> Title</h3>
  <h4>Title<span class="icon"></span></h4>
  <h5>
    Title
    <span class="icon"></span>
  </h5>
</div>

Remove text

To remove text you need write some html entity like &nbsp; or if you no need space then &ZeroWidthSpace; or similar.

@find

With this annotation you can point to tag with css selector.

@export Item
<div>
  <div class="wrapper">
    <div class="header">
      <h1>Title</h1>
    </div>
    <div class="content">
      <p>Description</p>
    </div>
  </div>
</div>
import {Item} from './module1'

<Item>
  @find .header
  <tag>
    @append
    <span>Sub title</span>
  </tag>
  
  <tag class="wrapper">
    <tag/>
    <tag class="content">
      @append
      <p>Text</p>
    </tag>
  </tag>
</Item>

=

<div>
  <div class="wrapper">
    <div class="header">
      <h1>Title</h1>
    <span>Sub title</span></div>
    <div class="content">
      <p>Description</p>
    <p>Text</p></div>
  </div>
</div>

@append

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.

@prepend

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>
  
  <span class="header"/>
</Item>

=

<div><button>OK</button>
  <span class="header">Title</span>
</div>

@insert

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
  <input type="text"/>
</Item>

=

<div>
  <h1>Title</h1>
  <p>Description</p>
  <input type="text"/>
  <button>Ok</button>
</div>

@remove

Will remove current tag

@export Item
<div>
  <div class="content">
    <input type="text"/>
    <button>OK</button>
  </div>
</div>
import {Item} from './module1'

<Item>
  <tag class="content">
    @remove
    <input/>
  </tag>
</Item>

=

<div>
  <div class="content">
    <button>OK</button>
  </div>
</div>

@empty

Will remove children of current tag.

@export Item
<div>
  <div class="content">
    <p>Description</p>
    <button>OK</button>
  </div>
</div>
import {Item} from './module1'

<Item>
  @empty
  <tag class="content">
    <h1>Title</h1>
  </tag>
</Item>

=

<div>
  <div class="content">
    <h1>Title</h1>
  </div>
</div>

@appendTo

Will add tag to another tag by css selector.

@export Item
<div>
  <div class="content">
    <p class="description">Description</p>
  </div>
</div>
import {Item} from './module1'

<Item>
  @appendTo .description
  <span>Read more</span>
</Item>

=

<div>
  <div class="content">
    <p class="description">Description<span>Read more</span></p>
  </div>
</div>

@prependTo

Will add tag to the beginig of another tag by css selector

@export Item
<div>
  <div class="content">
    <p class="description">Description</p>
  </div>
</div>
import {Item} from './module1'

<Item>
  @prependTo .content
  <h1>Title</h1>
</Item>

=

<div>
  <div class="content"><h1>Title</h1>
    <p class="description">Description</p>
  </div>
</div>

@insertBefore

Will add tag before another tag by css selector

@export Item
<div>
  <div class="content">
    <h1>Title</h1>
    <p class="description">Description</p>
  </div>
</div>
import {Item} from './module1'

<Item>
  @insertBefore .description
  <h2>Sub title</h2>
</Item>

=

<div>
  <div class="content">
    <h1>Title</h1>
    <h2>Sub title</h2><p class="description">Description</p>
  </div>
</div>

@insertAfter

Will add tag after another tag by css selector

@export Item
<div>
  <div class="content">
    <h1>Title</h1>
    <p class="description">Description</p>
  </div>
</div>
import {Item} from './module1'

<Item>
  @insertAfter .content h1
  <h2>Sub title</h2>
</Item>

=

<div>
  <div class="content">
    <h1>Title</h1><h2>Sub title</h2>
    <p class="description">Description</p>
  </div>
</div>

Contribute

Help me improve this doc and any comments are welcome in issues.