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

telesy

v1.1.3

Published

Telesy - Type Safe HTML Templating Library using Template Literals

Downloads

248

Readme

Telesy - Type Safe HTML Templating Library using Template Literals

Node.js CI npm version

  • We love TypeScript. Telesy gives the type safe for HTML templates.
  • No compilation build phase needed. Telesy just works natively on any ES6 compliant web browsers and Node.js.
  • 10 times faster than ReactDomServer.renderToString() to generate static HTML code.
  • Lightweight. Less than 1KB when minified. No additional dependencies.

SYNOPSIS

TypeScript

import {$$, $$$} from "telesy";

interface Context {
    name: string;
    options: Option[];
}

interface Option {
    value: string;
    selected: string;
    label: string;
}

// language=HTML
const selectRender = (ctx: Context) => $$`
    <select name="${ctx.name}">
        ${ctx.options.map(v => $$$`<option value="${v.value}" ${v.selected}>${v.label}</option>`)}
    </select>
`;

document.querySelector<HTMLElement>("#here").innerHTML = selectRender(context);

JavaScript (ES6)

const {$$, $$$} = require("telesy");

// language=HTML
const selectRender = (ctx) => $$`
    <select name="${ctx.name}">
        ${ctx.options.map(v => $$$`<option value="${v.value}" ${v.selected}>${v.label}</option>`)}
    </select>
`;

document.querySelector("#here").innerHTML = selectRender(context);

USAGE

See telesy.d.ts for detail.

Template variables:

const render = (ctx) => $$`<p>Hello, ${ctx.name}!</p>`;

render({name: "Ken"}); // => '<p>Hello, Ken!</p>'

HTML special characters escaped per default for safe:

const render = (ctx) => $$`<p>${ctx.html}</p>`;

render({html: 'first line<br>second line'}); // => '<p>first line&lt;br&gt;second line</p>'

HTML special characters unescaped with $$$ filter function like dangerouslySetInnerHTML does:

const render = (ctx) => $$`<p>${$$$(ctx.html)}</p>`;

render({html: 'first line<br>second line'}) // => '<p>first line<br>second line</p>'

Conditional section for plain string:

const render = (ctx) => $$`<div class="${(ctx.value >= 10) && 'is-many'}">${ctx.value}</div>`;

render({value: 10}); // => '<div class="is-many">10</div>'

Conditional section with $$$ tag template literals for HTML elements:

const render = (ctx) => $$`<div>${!ctx.hidden && $$$`<img src="${ctx.src}">`}</div>`;

render({src: "image.png", hidden: false}); // => '<div><img src="image.png"></div>'

Loop sections with nested $$$ tag template literals:

// language=HTML
const render = (ctx) => $$`
    <table>
        ${ctx.rows.map(row => $$$`
            <tr class="${row.className}">
                ${row.cols.map(col => $$$`
                    <td class="${col.className}">${col.v}</td>
                `)}
            </tr>
        `)}
    </table>
`;

FRAGMENT

  • Template literal with $$ tag returns a plain string.
  • Template literal with $$$ tag returns an encapsulated Fragment object as below.
  • Function call $$(string) returns an HTML escaped string.
  • Function call $$(fragment) returns a raw string for the Fragment object given.
  • Function call $$$(string) returns a Fragment object for the string given, vice versa.
interface Fragment {
    outerHTML: string;
}

EMPTY VALUES

Telesy accepts string, number values and Fragments within the template literals. It outputs empty string "" when one of null, undefined or false value is given. Note that it doesn't accept the primitive true value, on the other hand. Specify strings to output explicitly, instead.

// DON'T
const render = (ctx) => $$`<span>${ctx.bool}</span>`;
render({bool: false}); // => '<span></span>' (the false value cause an empty string)

// DO
const render = (ctx) => $$`<span>${ctx.bool ? "YES" : "NO"}</span>`;
render({bool: true}); // => '<span>YES</span>'
render({bool: false}); // => '<span>NO</span>'
// DON'T
const render = (ctx) => $$`<span>${ctx.bool || "it is falsy"}</span>`;
render({bool: false}); // => '<span>it is falsy</span>'

// DO
const render = (ctx) => $$`<span>${!ctx.bool && "it is falsy"}</span>`;
const render = (ctx) => $$`<span>${ctx.bool ? "" : "it is falsy"}</span>`;
render({bool: true}); // => '<span></span>'
render({bool: false}); // => '<span>it is falsy</span>'

BENCHMARKS

Telesy is fast enough but type safe.

| Library | Type Safe | Ops/Sec | Note | |-----------------------------------------------------------|------------|---------|-------------------------------------------| | Telesy | ✅ Safe | 42,389 | Backed by the native template literals | | common-tags | ✅ Safe | 8,323 | Nested safeHtml causes trouble | | React | ✅ Safe | 4,278 | ReactDomServer.renderToString() is slow | | Mustatte | ❌ N/A | 82,442 | Fastest but type safe NOT supported | | Hogan.js | ❌ N/A | 74,087 | Last publish: 8 years ago | | Handlebars.js | ❌ N/A | 54,129 | A popular Mustache library |

The benchmark result above is on node v18.12.0, Apple Silicon M1.

MUSTACHE MIGRATION

If your project has good old Mustache templates, use the bundled CLI command mustache2telesy to migrate from Mustache to Telesy.

# combine multiple template files to a single TypeScript file
./node_modules/.bin/mustache2telesy --trim --guess templates/*.html > templates.ts

# give some hints of property types to get more simple code generated
./node_modules/.bin/mustache2telesy --trim --guess --array="items,itemList" --bool="isHidden,selected" --func="getText" templates/*.html > templates.ts

# if you need a plain CommonJS file instead of ES Module or TypeScript file
./node_modules/.bin/mustache2telesy --trim --guess --cjs templates/*.html > templates.js

The author is a Mustache user for more than 10 years. His Mustache-based project was migrated to Telesy/TypeScript just in minutes.

Most of Mustache's basic features would just get transformed by mustache2telesy CLI. You may need to fix the rest by hand. But don't be afraid. TypeScript's type checking would help you to fix them easily, anyway.

LINKS

  • https://github.com/kawanet/telesy
  • https://www.npmjs.com/package/telesy