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

htb

v0.0.1

Published

Htb.js — a 50-line HTML template engine that uses JavaScript syntax.

Downloads

10

Readme

htb-js-logo

HTML Template Builder   latest version badge license badge downloads badge

HTML Template Builder (Htb.js) is a 50-line HTML template engine that uses JavaScript syntax.

Htb.js was not invented. Htb.js was discovered at the intersection of HTML and JavaScript. Htb.js takes inspiration from Ruby's Jbuilder and JavaScript's json2html, and can be seen as a synthesis of the two, or a 'what if Jbuilder and json2html were combined'.

Examples

Getting started

const htb = Htb
  ('!DOCTYPE', { html: true })
  ('html', {}, () => [
    Htb('head', {}, () => [
      Htb('title', {}, 'Simple Example'),
      Htb('meta', { name: 'viewport', content: 'width=device-width, initial-scale=1' }),
      Htb('style', { type: 'text/css' }, 'p { font-family: Arial, Helvetica, sans-serif; }')
    ]),
    Htb('body', {}, () => [
      Htb('h1', {}, () => 
        'Hello, John Doe!'
      ),
      Htb('p', {}, () => [
        Htb('b', {}, 'This is bold text. '),
        Htb('i', {}, 'This is italic text. '),
        Htb('u', {}, 'This is underlined text.')
      ])
    ])
  ]);
console.log(htb.html)
<!DOCTYPE html>
<html>
  <head>
    <title>Simple Example</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style type="text/css">
      p {
        font-family: Arial, Helvetica, sans-serif;
      }
    </style>
  </head>
  <body>
    <h1>Hello, John Doe!</h1>
    <p><b>This is bold text.</b><i>This is italic text.</i><u>This is underlined text.</u></p>
  </body>
</html>

Conditionals & variables

const user = {
  isAdmin: false,
  isMember: true,
  name: 'John Doe'
};
const htb = Htb
  ('!DOCTYPE', { html: true })
  ('html', {}, () => [
    Htb('head', {}, () => [
      Htb('title', {}, 'Conditionals Example'),
      Htb('meta', { name: 'viewport', content: 'width=device-width, initial-scale=1' }),
      Htb('style', { type: 'text/css' }, 'p { font-family: Arial, Helvetica, sans-serif; }')
    ]),
    Htb('body', {}, () => [
      Htb('h1', {}, 'User Profile'),
      user.isAdmin
        ? Htb('p', {}, `Welcome, Admin ${user.name}!`)
        : user.isMember
          ? Htb('p', {}, `Welcome, Member ${user.name}!`)
          : Htb('p', {}, 'Welcome, Guest!')
    ])
  ]);
console.log(htb.html)
<!DOCTYPE html>
<html>
  <head>
    <title>Conditionals Example</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style type="text/css">
      p {
          font-family: Arial, Helvetica, sans-serif;
      }
    </style>
  </head>
  <body>
    <h1>User Profile</h1>
    <p>Welcome, Member John Doe!</p>
  </body>
</html>

Nested Loops

const categories = [
  { name: 'Fruits', items: ['Apple', 'Banana', 'Orange'] },
  { name: 'Vegetables', items: ['Carrot', 'Broccoli', 'Spinach'] }
];
const htb = Htb
  ('!DOCTYPE', { html: true })
  ('html', {}, () => [
    Htb('head', {}, () => [
      Htb('title', {}, 'Nested Loops Example'),
      Htb('meta', { name: 'viewport', content: 'width=device-width, initial-scale=1' }),
      Htb('style', { type: 'text/css' }, 'p { font-family: Arial, Helvetica, sans-serif; }')
    ]),
    Htb('body', {}, () => {
      const elements = [Htb('h1', {}, 'Categories and Items')];
      for (const category of categories) {
        elements.push(Htb('h2', {}, category.name)
          ('ul', {}, () =>
            category.items.map(item =>
              Htb('li', {}, item)
            )
          ));
      }
      return elements;
    })
  ]);
console.log(htb.html)
<!DOCTYPE html>
<html>
  <head>
    <title>Nested Loops Example</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style type="text/css">
      p {
          font-family: Arial, Helvetica, sans-serif;
      }
    </style>
  </head>
  <body>
    <h1>Categories and Items</h1>
    <h2>Fruits</h2>
    <ul>
      <li>Apple</li>
      <li>Banana</li>
      <li>Orange</li>
    </ul>
    <h2>Vegetables</h2>
    <ul>
      <li>Carrot</li>
      <li>Broccoli</li>
      <li>Spinach</li>
    </ul>
  </body>
</html>

Partial Templates

const headerTemplate = Htb
  ('header', {}, () => [
    Htb('h1', {}, 'My Website'),
    Htb('nav', {}, () => [
      Htb('a', { href: '/' }, 'Home'),
      Htb('a', { href: '/about' }, 'About'),
      Htb('a', { href: '/contact' }, 'Contact')
    ])
  ]);
const footerTemplate = Htb
  ('footer', {}, () => [
    Htb('p', {}, 'Made with <3 and coffee.')
  ]);
const htb = Htb
  ('!DOCTYPE', { html: true })
  ('html', {}, () => [
    Htb('head', {}, () => [
      Htb('title', {}, 'Partial Templates Example'),
      Htb('meta', { name: 'viewport', content: 'width=device-width, initial-scale=1' }),
      Htb('style', { type: 'text/css' }, 'p { font-family: Arial, Helvetica, sans-serif; }')
    ]),
    Htb('body', {}, () => [
      headerTemplate,
      Htb('main', {}, () => [
        Htb('h2', {}, 'Page Content'),
        Htb('p', {}, 'Welcome to the page!')
      ]),
      footerTemplate
    ])
  ]);
console.log(htb.html)
<!DOCTYPE html>
<html>
  <head>
    <title>Partial Templates Example</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style type="text/css">
      p {
          font-family: Arial, Helvetica, sans-serif;
      }
    </style>
  </head>
  <body>
    <header>
      <h1>My Website</h1>
      <nav><a href="/">Home</a><a href="/about">About</a><a href="/contact">Contact</a></nav>
    </header>
    <main>
      <h2>Page Content</h2>
      <p>Welcome to the page!</p>
    </main>
    <footer>
      <p>Made with &lt;3 and coffee.</p>
    </footer>
  </body>
</html>

Numbers

const htb = Htb
  ('!DOCTYPE', { html: true })
  ('html', {}, () => [
    Htb('head', {}, () => [
      Htb('title', {}, 'Arithmetic Operations Example'),
      Htb('meta', { name: 'viewport', content: 'width=device-width, initial-scale=1' }),
      Htb('style', { type: 'text/css' }, 'p { font-family: Arial, Helvetica, sans-serif; }')
    ]),
    Htb('body', {}, () => [
      Htb('h1', {}, 'Basic Arithmetic'),
      Htb('p', {}, [
        'Sum of ', Htb('span', {}, '10'), ' and ', Htb('span', {}, '5'), ': ',
        Htb('span', {}, `${10 + 5}`) // a number
      ]),
      Htb('p', {}, [
        'Product of ', Htb('span', {}, '7'), ' and ', Htb('span', {}, '3'), ': ',
        Htb('span', {}, `${7 * 3}`) // a number
      ]),
      Htb('p', {}, [
        'Division of ', Htb('span', {}, '20'), ' by ', Htb('span', {}, '4'), ': ',
        Htb('span', {}, `${20 / 4}`) // a number
      ])
    ])
  ]);
console.log(htb.html)
<!DOCTYPE html>
<html>
  <head>
    <title>Arithmetic Operations Example</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style type="text/css">
      p {
          font-family: Arial, Helvetica, sans-serif;
      }
    </style>
  </head>
  <body>
    <h1>Basic Arithmetic</h1>
    <p>Sum of <span>10</span> and <span>5</span>: <span>15</span></p>
    <p>Product of <span>7</span> and <span>3</span>: <span>21</span></p>
    <p>Division of <span>20</span> by <span>4</span>: <span>5</span></p>
  </body>
</html>

FAQ

1. Is this JSX?

JSX is a syntactic extension of JavaScript. Htb.js is closer to React.createElement(), although without the React part.

2. Is JSX to Htb.js compiler planned?

No.

3. Should I use this in production?

Fortune favours the brave.

4. How to use this in my project?

It's best to copy paste the htb.ts file into your repo. Although an NPM package is also available.

5. Is there a way to generate Htb.js code from HTML?

Use this LLM prompt: llm-prompt.txt