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 🙏

© 2026 – Pkg Stats / Ryan Hefner

runesmith

v0.0.8

Published

Parse and compile html files

Downloads

63

Readme

Runesmith v0.0.8

Parse and compile html files

Install


npm install runesmith

Usage


const Runesmith = require('runesmith');

Runesmith(file/path/to/some/file.html)
.then(html => ... ); // returns compiled html as a String

Parsing HTML


Use special html tags to modify parsing behavior

Import

Import html files as partials or as templates

<import src="a/path/to/file.html"></import>

Absolute filepaths are resolved to the project root directory.

When the parser identifies an import tag, it will read the contents of src and then replace the tag with src's content. Furthermore, the children of the import tag will be appended into the src if it contains a content tag:

// file.html
<import src="template.html">
    <p>import example</p>
    <import src="import.html"></import>
</import>

// import.html
<p>This is a partial</p>

// template.html
<section>
    <h1>this is a template</h1>
    <content></content>
</section>

>> Runesmith(file.html);

Compiles into:

<section>
    <h1>this is a template</h1>
    <p>import example</p>
    <p>this is a partial</p>
</section>

Namespace

Create a namespace environment for the parser

<namespace>
    foo: bar
    bar: baz
</namespace>

namespace elements can have three attributes: delimiter, pair, and overwrite

  1. delimiter: modifies how namespace interprets the key-value set
    • By default, the parser recognizes newlines, semicolons and commas as delimiters
  2. pair: modifies how namespace interprets a single key-value pair
    • By default, the parser recognizes colons as the pair separator
  3. overwrite: modifies namespace overwriting. Namespace scopes are maintains from start to end of compilation. When many namespaces are introduced, this attribute will tell the parser how to interpret conflicting keys
    • By default, the parser will overwrite key-value pairs
<namespace delimiter=";" pair="@">
    foo@bar;
    bar@baz;
</namespace>
<namespace ovewrite="false">
    bar: bax
</namespace>

Compiles to this map:

{
    foo: bar,
    bar: baz
}

Var

Replace var tags with its namespace equivalent

<namespace>
    foo: bar
</namespace>
<p>this is <var>foo</var></p>

Compiles to:

<p>this is bar</p>

Expanding parse behavior

Extend Runesmith by implementing your own parsers:

Runesmith.rune((document) => {
    // modify the html document in some way
});

A single argument is passed into a rune, an instance of ParsedHTMLDocument. ParsedHTMLDocuments can be modified similarly to how the web browser document object can be modified. (https://github.com/jikurata/html-parser to see what is currently supported).

// Convert all p elements to span
Runesmith.rune((document) => {
    const elements = document.getElementsByTagName('p');
    for ( let i = 0; i < elements.length; ++i ) {
        elements[i].tagName = 'span';
    }
});

To implement asynchronous parsers, simply return a Promise for the rune handler:

    Runesmmith.rune((document) => new Promise((resolve, reject) => {
        // async operations here...
    }));

The special namespace, var, and import tags all have priority over other parsers, so those tags will be resolved first before any custom parsers are executed.

Putting it all together


// main.html
<!DOCTYPE html>
<import src="head.html"></import>
<body>
    <import src="navigation.html"></import>
    <h1><var>title</var></h1>
    <content></content>
</body>

// head.html
<head>
    <meta charset="utf8">
    <title><var>title</var></title>
</head>

// navigation.html
<ul>
    <li><a>home</a></li>
    <li><a>about</a></li>
</ul>

// compile.html
<namespace>
    title: Example
</namespace>
<import src="main.html">
    <section>
        stuff
    </section>
</import>

>> Runesmith(compile.html)

Result:

    
<!DOCTYPE html>
<head>
    <meta charset="utf8">
    <title>Example</title>
</head>
<body>
    <ul>
        <li><a>home</a></li>
        <li><a>about</a></li>
    </ul>
    <h1>Example</h1>
    <section>
        stuff
    </section>
</body>

Version History

v0.0.8

  • Parser now utilizes a tree-like data structure instead of an array, which should improve compile speed
  • Modified filepath parsing behavior within the import tags:
    • Filepaths that start with a directory or text are now treated as a filepath relative to the project root.
      • Ex. a/b/c => project root/a/b/c
    • Absolute file paths are now treated as true absolute filepaths, to enable access to files outside the project root
      • Ex. /a/b/c => /a/b/c

v0.0.7

  • Runesmith now clears the compile map before each compilation

v0.0.6

  • Refactor cache emptying to a separate function in module.exports

v0.0.5

  • Fixed misreference for the cache in main module.exports

v0.0.4

  • Implement async compability for runes
  • Expose Runesmith.map to allow users to retrieve stats on the most recent compile
  • The file cache can now be emptied by passing {emptyCache: true} as an argument

v0.0.3

  • Merging paths now account for partial matches

v0.0.2

  • Absolute filepaths are resolved to the project root directory

v0.0.1

  • Path resolution between the current directory and current filepath accounts for sequential "sameness" in the filepaths

v0.0.0

  • TODO: Implement configurations to make Runesmith more flexible