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 🙏

© 2026 – Pkg Stats / Ryan Hefner

ltsr

v0.0.10

Published

Literal Template String Render - Use JS literal templates strings for file templates

Readme

LTSR

Literal Template String Render

Use Javascript Literal Template String syntax for file templates.

ltsr = new LTSR({root: , layout: }) : create a renderer at a specific root, optionally with a default layout.

ltsr.render(file, { locals:, collection:, sep:, keyName:, valueName:, keepWhitespace, layout:})

render second argument defaults:

  • locals = {}
  • collection = null
  • sep = '': String to place between collection elements
  • keyName = 'index': When collection is a Set or an Array.
  • keyName = 'key': Otherwise.
  • valueName = 'value'
  • keepWhitespace = false: set to true to keep trailing whitespace from the template file
  • layout = undefined: see Layout section below

ltsr.raw(file, keepWhitespace = false) may be used to render the template without interpolation, useful for including javascript files which have string templates in them.

It also allows the file (on disk) to not include the .lt extension. ltsr.raw("style.css") (or render.raw from within a template) will first attempt to render style.css.lt, if that fails it will attempt to render style.css.

Single render:

render(file, { locals: {} }) : render template at root/file making the keys in locals available as arguments to the template

Iterative render, with an Array or a Set:

With collection: (Array or Set) : repetitively render template at root/file making the keys in locals available as arguments to the template. Collection is iterated and the index and values are sent as the valueName and keyName respectively.

Effectively making these lines equivalent:

['a', 'b', 'c'].map((value, index) => ltsr.render('template', { locals: { content: value, position: index } })).join('');

ltsr.render('template', {collection: ['a', 'b', 'c'], valueName: 'content', keyName: 'position'}));

The following are also equivalent, using the default value and key names for arrays:

['a', 'b', 'c'].map((value, index) => ltsr.render('template', { locals: { value, index } })).join('');

ltsr.render('template', { collection: ['a', 'b', 'c'] }));

Iterative render, with a Map or an Object:

With collection: (Map or Object) : as above, but the key is passed where the index would have been above.

Example: partial.lt

<div>Hello ${name} of ${place}</div>

Simple call

Called with render('partial', {locals: {name: 'Hooky', place: 'Earth'}}):

<div>Hello Hooky of Earth</div>

Iterative call with and Array

Called with render('partial', {collection: ['Hooky', 'TJ'], locals: {place: 'Earth'}, valueName: 'name'}):

<div>Hello Hooky of Earth</div>
<div>Hello TJ of Earth</div>
  • Note: the array index is passed to the partial (with the default key 'index'), but is not used in this case.

Iterative call with an Object

Called with render('partial', {collection: {Hooky: 'Earth', TJ: 'Earth', Marvin: 'Mars'}, keyName: 'name', valueName: 'place'}):

<div>Hello Hooky of Earth</div>
<div>Hello TJ of Earth</div>
<div>Hello Marvin of Mars</div>

partials at depth

The render and render.raw methods are available to templates, enabling partial renders:

With outer.lt

<html>
  <body>
    ${ render('partial', {locals: user}) }
  </body>
</html>

Calling with render('outer', {locals: {user: {name: 'Hooky', place: 'Earth'}}}):

<html>
  <body>
    <div>Hello Hooky of Earth</div>
  </body>
</html>

Layouts

Providing a layout template to render will wrap the target rendered file in the layout at the point of a yield. render and raw may be called within the layout file, but note that none of the values sent to the template which invoked the layout are provided. (you may get them using the yield 'name' technique shown below).

With layout.lt

<html>
  <head><title>${yield 'title'}</title></head>
  <body>${yield}</body>
</html>

And content.lt

This is the body

Calling with render('content', {layout: 'layout', locals: {title: 'This is the title'}}):

<html>
  <head><title>This is the title</title></head>
  <body>This is the body</body>
</html>

Unlike rendering a partial, if a value yielded for (such as yield 'title' in this case) is not provided, LTSR will not raise an error. No arguments are passed to the layout, but can be provided in the locals field of the render options. Note that they must be yielded for.

If render is called with a layout while rendering a collection, each item is wrapped in the layout.

Using sep

When rendering a collection, you can provided an element separator string to place between items.

With partial.lt

<div>${name}</div>

Calling with render('partial', { collection: ['me', 'you', 'her', 'him'], valueName: 'name', sep: '<hr/>\n'}):

<div>me</div><hr/>
<div>you</div><hr/>
<div>her</div><hr/>
<div>him</div>

File search

Calling ltsr.render and ltsr.raw will only load the provided file from the provided root.

Calling render or render.raw from within a template will attempt to load the file first from {root}/partial/{template}.lt, then {root}/{template}.lt. Calling raw will also attempt to load (in the same order) files without the .lt extension after trying with.

Using the layout option will attempt to load first from {root}/layout/{template}.lt then {root}/{template}.lt. Note that calling render or render.raw from within a layout will use the same paths described above, even if the layout was found in the layout/ sub-directory.