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 🙏

© 2025 – Pkg Stats / Ryan Hefner

attr2json

v0.1.1

Published

An utility library for extracting JSON data from HTML attributes.

Readme

attr2json

An utility library for extracting JSON data from HTML attributes.

Motivation

When using setups where you are mostly rendering static HTML pages on the server, you often want to pass some sort of data to your JavaScript, which is often either done via an API endpoint or somehow dumping JSON into the DOM. Both of these approaches are quite cumbersome which is what this library tries to solve:

Lets see this example where we'll create a solution to render chart.js charts using HTML attributes:

<!-- this site is using daisyui -->
<div class="card bg-base-200 my-4">
    <div class="card-body">
        <h2 class="card-title">
            Pie Chart
        </h2>

        <canvas
            chartjs <!-- this is used as a marker to init the thing later you could use something else though like an id -->
            chartjs:type="pie"
            chartjs:data.labels[0]="40%"
            chartjs:data.labels[1]="60%"
            chartjs:data.datasets[0].data[0]="40"
            chartjs:data.datasets[0].backgroundColor[0]="red"
            chartjs:data.datasets[0].data[1]="60"
            chartjs:data.datasets[0].backgroundColor[1]="blue"
        ></canvas>
    </div>
</div>

<!-- this is the JS we use to initialize chartjs -->
<script type="module">
    import { Chart } from "chart.js";
    import extractJson from "attr2json";

    // for every element that has the marker we defined here "chartjs"
    document.querySelectorAll("[chartjs]").forEach(elem => {
        const data = extractJson(elem, "chartjs");

        /*
         * Representation of what "data" is right now:
         *
         * {
         *     type: "pie",
         *     data: {
         *         labels: ["40%", "60%"],
         *         datasets: [{
         *             data: [40, 60],
         *             backgroundColor: ["red", "blue"],
         *         }
         *     }
         * }
         */

        // init chart.js
        new Chart(elem, data);
    });
</script>

Syntax

The syntax of attr2json parse syntax contains always a prefix, a colon, a path and a value

for example

<div prefix:path="value"></div>

this is equivalent with

{
    "path": "value"
}

The prefix can generally be whatever you want it to be just make sure its unique and doesn't collide with other things.

The path however is a bit special, here are a few example on how it might be parsed:

  • prefix:path -> key is path
  • prefix:very.nested.path -> This will create a JSON object like this: { very: nested: path: ... }
  • prefix:numbers[3] -> This will create an array, the index gets used to determine the order of the element inside the array, e.g. prefix:numbers[3]="5" will create [5] and not [undefined, undefined, 5]
  • prefix:start-at-zero -> since it's common to use camel case in JS names and HTML attributes are case insensitive, we parse kebab case into camel case e.g. prefix:start-at-zero becomes startAtZero

The value also has some special parsing rules:

  • if it can be parsed as a number it will be e.g. "1337" becomes 1337, "13.37" becomes 13.37
  • if it is "true" or "false" (or "TRUE", "FALSE") it will be parsed as a boolean
  • if none of the above rules match it will be a string

License

MIT