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

abs-template

v1.2.0

Published

Parse and compile template partials in static HTMLs

Downloads

10

Readme

Abs-Template

npm version Install size

Introduction:

This module offers a static class that can preprocess HTML <template> nodes and print them in a somewhat dynamic way following an object with data inside it.

CDN:

Typescript: https://abstractn.github.io/lib/abs-template.ts

Javascript (with export): https://abstractn.github.io/lib/abs-template.js

Javascript (without export): https://abstractn.github.io/lib/abs-template.nx.js

Browser iclusion: <script src="https://abstractn.github.io/lib/abs-template.nx.js"></script>

The Config object

There are two main methods to use from this class: the first one would be .build(). This method takes a config object with all the necessary parameters inside it. Here's a deep example:

AbsTemplate.build({
  // node reference to the template to build
  templateNode: document.querySelector('template#my-template'),

  // a data object to compile the template with
  templateData: {
    myField: 'lorem ipsum'
  },

  // the output node to where the compiled template needs to be printed
  printTargetNode: document.querySelector('.dynamic-template-container'),

  // the position relative to `printTargetNode`
  printMethod: AbsTemplatePrintMethod.BEFORE_END,
})

NOTE on printMethod: I've created a custom enum to group all possible values but not that these are in reality the same ones used by the native method Element.insertAdjacentElement() (see MDN's documentation here for more details)

Underneath build()'s logic there's compile(): if you need to just parse your template node and get the result without printing it immediately this will return the compiled HTML as a string.

Template Syntax

You can write double curly brackets to write a couple of neat things inside your HTML to make minimal logic and print data with it.

1) Data

Starting with an object defined from our code:

const myData = {
  greeting: 'Hello',
  user: {
    firstName: 'John',
    lastName: 'Doe'
  }
};

use it in HTML with

<template id="my-data-template">
  <span>{{greeting}} {{user.firstName}} {{user.lastName}}</span>
</template>

and after compilation it will turn into

<span>Hello John Doe</span>

2) Conditions

{{if condition}}...{{/if}} and {{if condition}}...{{else}}...{{/if}} are the syntaxes that can decide wether the content of the condition will be printed or not for the first case and print either one content block or the other depending on the condition.

The accepted format for conditions are both a single variable that will be implicitly interpreted as a boolean check (much like a common if() from JS/TS code) or a set of two variables to evaluate with an operator in between them.

The list of all available operators is the following:

  • ==
  • ==
  • ===
  • !=
  • !==
  • >
  • >=
  • <
  • <=
  • &&
  • ||
  • %
  • ^

For the example we'll change the data object a little:

const myData = {
  visible: true
};

and make a debug-like test template

<template id="my-data-template">
  status:

  {{if visible}}
    <span>true</span>
  {{else}}
    <span>false</span>
  {{/if}}
</template>

The output will be

status:
<span>true</span>

NOTE: full condition syntax strictly accepts only the following format: <parameter_1> <operator> <parameter_2>. Using parenthesis for grouping and/or multiple operators will not work.

3) Loops

If our data object contains arrays inside it we can iterate on them using a {{forEach item in array}}...{{/forEach}}. Here's a simple list:

const myData = {
  users: [
    {
      firstName: 'John',
      lastName: 'Doe'
    },
    {
      firstName: 'Alex',
      lastName: 'Rodriguez'
    },
    {
      firstName: 'Emily',
      lastName: 'Turner'
    }
  ]
};

and whatever HTML is contained inside the loop statement will be repeated for each item

<template id="list-template">
  <h4>List of users</h4>
  <ol>
    {{forEach user in users}}
      <li>
        <div>First name: {{user.firstName}}</div>
        <div>Last name: {{user.lastName}}</div>
      </li>
    {{/forEach}}
  </ol>
</template>

And this is how the list turned out after parsing:

<h4>List of users</h4>
<ol>
  <li>
    <div>First name: John</div>
    <div>Last name: Doe</div>
  </li>
  <li>
    <div>First name: Alex</div>
    <div>Last name: Rodriguez</div>
  </li>
  <li>
    <div>First name: Emily</div>
    <div>Last name: Turner</div>
  </li>
</ol>

An important note to point out is that if you use an identifier for the list iterable that is already present inside the first level of the data object, the object outside of the list will not be accessible since the identifiers overlap and forEach's scope takes priority.

const myData = {
  item: 'OUTSIDE LIST',
  list: [ 'INSIDE LIST' ]
}
1. {{item}}

{{forEach item in list}}
  2. {{item}}
{{/forEach}}

3. {{item}}

The output will be:

1. OUTSIDE LIST
2. INSIDE LIST
3. OUTSIDE LIST

KNOWN BUGS

  • ~~Same statements consecutively inside each other are probably not parsed correctly~~ Fixed in 1.2