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

domogen

v0.0.21

Published

Domogen is a dependency-free and lightweight library for generating HTML with support for efficient and parameterized inline styling.

Downloads

6

Readme

Domogen

Domogen is a dependency-free and lightweight library for generating HTML with support for efficient and parameterized inline styling.

Installation

Install via:

npm install domogen

Usage

We will create an HTML document by calling the Root constructor:

import { Root } from "domogen"
const root = new Root()

Basics

We can start constructing sections of the HTML document by using HTMLNode, RawNode and TextNode. HTMLNode allows you to construct an HTML element, set attributes on it and set its children. RawNode is for encapsulating raw, unescaped HTML, whilst TextNode performs escaping on the text provided. See the example below for reference:

import { HTMLNode, TextNode, RawNode } from "domogen"
const div = new HTMLNode("div")
    .addAttribute("width", "500px")
    .addChild(new TextNode("this is escaped text"))
    .addChild(new HTMLNode("span")
        .addChild(new RawNode("this is unescaped HTML"))
    )

Fragments

We can also use FragmentNode - this is similar to a ReactFragment you might find in React. It allows you to render a collection of child elements without having to wrap them in an additional HTML element:

import { FragmentNode } from "domogen"

const fragment = new FragmentNode()
    .addChild(new TextNode("h"))
    .addChild(new TextNode("i"))

// div renders to <div>hi</div>
const div = new HTMLNode("div")
    .addChild(fragment)

Components

We can use what we've learnt to construct complex, HTML components, similar in function to React components, allowing for maximal code re-use. Lets create an example "InfoBox" component below that will take a blurb of text, and present it in a padded, bordered box:

import type { INode, RenderContext } from "domogen"

export const InfoBox {
    private rootNode : INode

    constructor(text : string) {
        this.rootNode = new HTMLNode("div")
            .addAttribute("style", "padding:4px;border 1px solid black;")
            .addChild(new TexNode(text))
    }

    render(context : RenderContext ) {
        // To render this node, we simply render its root node
        this.rootNode.render(context)
    }

}

We have created a class that implements the core INode interface (specifically, the render method). Once constructed, this node can be passed into any addChild method (they accept INode implementations):

const div = new HTMLNode("div")
div.addChild(new InfoBox("hello test"))

Head

Sometimes its nice to create components that, upon render, will mutate the <head>, despite being placed in the <body>. This can be achieved by using a HeadCollectorNode:

import { HeadCollectorNode } from "domogen"

export class Title {
    private rootNode : INode
    constructor(title : string) {
        this.rootNode = new HeadCollectorNode()
            .addChild(new HTMLNode("title")
                .addChild(new RawNode(title))
            )
    }

    render(context : RenderContext) {
        this.rootNode.render(context)
    }
}

const div = new HTMLNode("div").addChild(new Title("foo"))

Now, upon render, the Title component will not render anything inside the div, but instead will append its children to the <head> tag.

Inline Styling

And now, for the pièce de résistance, inline styling. To style an HTMLNode, we first must create a StyleFactory<T>, which will take some parameters T, and return a Style which can be applied directly to an HTMLNode as follows:

import { StyleFactory } from "domogen"

const simpleStyleFactory = new StyleFactory<{ padding : number }>((clsName, params) => {
    // The StyleTemplate (that the StyleFactory takes in its constructor) 
    // generates a valid chunk of CSS for a given className and set of parameters:
    const block = [
        `padding: ${padding}px;`,
        "background-color: black;"
    ].join("")
    return `.${clsName} {${block}}`
})

const div = new HTMLNode("div")
    .addStyle(simpleStyleFactory.getStyle({ padding: 5}))

In this example, the CSS generated by the StyleFactory will be appended to the <head> and the HTML element will have a corresponding CSS class added to it such that it receives the styling. Should we re-use the exact styles:

const span = new HTMLNode("span")
    .addStyle(simpleStyleFactory.getStyle({ padding: 5}))

The generated CSS won't be redundantly added to the DOM, with the span re-using the same class name as the div above...