slam-js

A pure js library for HTML templates without any dependencies.

Usage no npm install needed!

<script type="module">
  import slamJs from 'https://cdn.skypack.dev/slam-js';
</script>

README

Slam-js

A Javascript library for generating static HTML on the client or server. Slam-js is meant to be a complete replacement to HTML templating engines such as Pug, Handlebars, or EJS.

Features

  • Easy templating
  • Component friendly
  • No need to learn a new language/syntax
  • Accurate type declarations
  • Good performance and speed
  • SVG tag support.

Installation

If using on the server:

npm install --save-dev slam-js

If using on the client or as part of a library:

npm install slam-js

Code Example

The function Document in this example returns a string constructed based on the tag functions used.

import { html, head, title, meta, link, body, h1, p } from "slam-js";

export const Document = () =>
  html({ lang: "en" },
    head(
      title("Slam-js"),
      meta({ name: "viewport", content: "width=device-width initial-scale=1, minimum-scale=1" }),
      link({ rel: "icon", href: "assets/favicon.ico" })
    ),
    body(
            h1("Slam-js"), 
            p("A Javascript library for generating static HTML on the server side.")
        )
  );

API

Each element function has the same parameters, with the exception of void elements which won't accept children (e.g. br, meta, link, etc.):

Parameter Type Default Required Example(s) Details
attributes Object undefined False { class: "card", tabindex: 0 } The key used should be in the exact form used in HTML. Keys with hyphens will need to be quoted, e.g. "aria-details".
...children string undefined False "Slam-js", div("Slam-js"), fs.readFileSync("./partial.html") Any function returning a string can be placed inline. Strings will not be checked whether they are valid HTML or not, so be careful.

All Slam-js functions return a string with the tag, its attributes, and children:

import { div, p } from "slam-js";

export const Card = () => 
  div({ class: "card" }, 
        p("Slam-js")
    );

console.log(Card());

//Console logs '<div class="card"><p>Slam-js</p></div>'

Examples & Usage

Components

Reusable components can easily be created and then imported into an index file:

//Head.js
import { head, title, meta, link } from "slam-js";

export const Head = () =>
    head(
        title("Slam-js"),
        meta({ name: "viewport", content: "width=device-width initial-scale=1, minimum-scale=1" }),
        link({ rel: "icon", href: "assets/favicon.ico" })
    );
//A template for an "index" page:
import { html, body } from "slam-js";
import { Head } from "./Head.js";

export const indexPage = () => 
  html(
        Head(), 
        body("Index")
    );
//A template for an "about" page:
import { html, body } from "slam-js";
import { Head } from "./Head.js";

export const aboutPage = () => 
    html(
        Head(), 
        body("About")
    );

Components with Variables

Just make sure to return a string.

//Card.js

import { div, img, h4, p } from "slam-js";

export const Card = (imgSrc, imgAlt, header, description) => 
  div({ class: "card" }, 
        img({ src: imgSrc, alt: imgAlt }), 
        h4(header), 
        p(description)
    );
//index.js

import { html, body } from "slam-js";
import { Card } from "slam-js";

const document = () => 
  html(
    body(
      Card("./assets/dog.jpg", "A cute brown dog", "Sparky", "Sparky likes to play fetch an run around"),
      Card("./assets/cat.jpg", "An ugly gray cat", "Sleezy", "Sleezy likes to tear up furniture."),
      Card("./assets/lizard.jpg", "A plain green lizard.", "Plainola", "Plainola just hangs around.")
    )
  );

Inlining SVGs

SVGs can be constructed manually, or they can be easily inlined:

//hamburgerIcon.js

export function HamburgerIcon() {
  return `
    <svg viewBox="0 0 100 80">
      <rect width="100" height="20" rx="8"></rect>
      <rect y="30" width="100" height="20" rx="8"></rect>
      <rect y="60" width="100" height="20" rx="8"></rect>
    </svg>
  `;
}

FAQs

What about the reserved words var and switch?

These functions have an underscore after them:

import { var_, switch_ } from "slam-js";

What about inline styles?

The style attribute takes an object of attribute/value pairs:

import { div } from "slam-js";
export const WideRedBox = () => div({ style: { backgroundColor: "red", width: "100%" } });

How do I integrate with Webpack?

Export the template, and use it with HtmlWebpackPlugin.

//index.js

import { html, body } from "slam-js";

const Document = () => 
    html(
        body("Slam-js")
    );

export default Document;
//webpack.js
{
  plugins: [
    new HtmlWebpackPlugin({
      template: "./index.js",
      filename: index.html,
      chunks: [name],
    }),
  ];
}