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

tatlrt

v0.1.0

Published

Runtime for TATL, a templating language that compiles to Python or Javascript

Downloads

3

Readme

#TATL: Tag & Attribute Template Language ##A templating system thats good for outputting HTML, for Javascript and Python.

TATL templates are expressive, easy to learn, and cross easily from server to client. TATL uses the natural block structure in your HTML code, resulting in less repetition and more natural indentation.

Templates are precompiled into either Python or Javascript and then loaded as modules.

There are 2 special tags and 6 special attributes:

<do>
<else>
def=
set=
for=
if=
param=
use=

Extended attributes:

for="var in expr"
    Repeats tag, with {var} now available elsewhere in tag contents.
for="expr"
    Same, var assumed to be . (dot).
for
    Same, var and expr assumed to be . (dot).
for="key, value in expr"
    When iterating over a map, gives key and value (sorted by key). When iterating over
    a list, gives index, value where index is 0-based.
for="key, value in expr #unsorted"
    As above, but the keys and value are unsorted.
for="var = expr; var2 = expr; key in expr"
    Set some variables before evaluating the expr

if="expr"
    If the expression is false, do not include or the tag or the content or execute any
    substitions within. When <else> is present in tag, include the tag and content before
    the else if the expression is false, or the tag and content after the else if the
    expression is true.
if
    If any variable substitutions are empty, elide this whole tag. Empty values are null
    and false. Also allows else as above.
if="var = expr; var2 = expr; expr"
    Set some variables before evaluating the expr

def="name(arg, arg)"
    Define a macro. Calling the macro will return the tag and its contents. The tag won't
    be included in the output at this location. Note that functions can be defined after
    they are called by a template. Functions do not have access to any variables defined
    thus far, only parameters.
def="name(arg, arg, arg='default') |filter1|filter2"
    Like python decorators, name will be set to filter1(filter2(foo)). A primary use of
    filters is caching.
def="name()"
    Macro with no args. You still have to call it.
def="name(*)"
    Macro with args placeholder. Any variables defined by param="" or free variables
    (undefined variables) will become parameters.
def="name(arg) = expr"
    Macro with result defined by expr. Can reference "." in expr, which is what would have
    been returned

set="var"
    Sets variable to be the tag with all substitutions executed.
set="var|filter"
    Sets var to be `filter(_tag_)`.
set
    For `<do>` tag, same as set="inner". For other tags, same as set="_tagname_|contents"

param="var"
    Define a parameter, scoped to the nearest def=. The parameter can be accessed anywhere
    in the scope; even if the tag itself isnt included/processed due to an if=. Within the
    tag, the parameter can be accessed by {.}.
param
    Defines a parameter with the tag name, or for the <do> tag, named "inner".
param="var, var"
    Defines multiple paramters. {.} is not set.

use="template::html(expr, expr)"
    Set "inner" to be the tag with all substitutions executed, then call the given macro,
    passing in arguments as specified. The result is then used in place of the current tag.
use="template::html"
    Call the given macro, automatically finding parameters from local variables.
use="var = expr; var2 = expr; template::html"
    Same as above, but with some variables already set.

Variable substitution

Variable substitution occurs in text nodes, and in normal attributes. In special
attributes, where expr is called for, just use the {var} syntax but remove the parens
(eg if="x", not if="{x}").

{var}
    Simple variable substitution. Value is inserted in document, with context-sensitive
    quoting.
{var.attr}
    Looks up attribute or key from object or map.
{template::var}
    Access macro from template, or function from external module.
{.}
    Within a for= or with=
{var[0]}
{.[0]}
{var[var]}
    Can index with numbers or variables

{macro(var, var)}
    Call macro

{1...5}
    The numbers 1 up to and including 5 ie inclusive range (1, 2, 3, 4, 5)
{0..5}
    The numbers 0 up to 5 ie exclusive range (0, 1, 2, 3, 4)

{[var, "val", 3]}
    A list of three values. Would be outputted with one space between contents, eg
    "var val 3".
{[var, "val", 3, *0..9]}
    A list of three values with inline splice.
{{name: var1, "a key": "value"}}
    A map with keys "name" and "a key". Any value can be stored in a map; only numbers
    and strings can be keys. Would be outputted in JSON format.
{{name: var1, name2: "value", *foo, name3: "value"}}
    A map, with inline splice. This creates a new map (foo is not modified) where the keys
    "name" and "name2" override the values in foo and foo overrides "name3".

{expr |afilter}
    After evaluating expression, look up the filter function and call it. If there is no
    filter function, look up a locally defined function.
{expr |module::func}
    Look up func in module and call it.

{test ? value1 : value2}
    Ternary. Valid tests are a eq b, a ne b, a lt b, a lt b lt c, etc, (and le gt ge)
    a ~ /regex/, and a truthy test, with just the expression.
{test ? value1}
    Ternary, value2 assumed to be empty
{expr ?: default}
    Use the value of expr or default if not defined.
{test ?}
    Either true or false. tests are not allowed in other places where expressions are
    allowed so this is useful to either do a boolean comparison elewhere or to coerce an
    expression to true/false.

{var = "value"}
{var = expr}
    expression or assignment. Value is not inserted into doc
{var = expr; var}
    Same, but then a value is inserted.

{var ?= value}
    Same as {var = var ?: value}

Special tags / quoting

<do>
    Without attrs, this tag just disappears in the output. Which is useful to do with some
    of the special attributes above.

<else/>
    No content (like <br>). Only allowed tags are if="". This should be used within a <do>
    only, otherwise the compiler will have to synthesize
    tags.

{{ }}
    Doubled braces insert a single brace.

<!-- -->
    Content within comments is not processed, and is not included in the document.
<!--[ ]-->
    Content within comments beginning with [ is included in the document.
<!--{ }-->
    Comments beginning with { are parsed as JSON to form front matter.
# comment
    Comments starting with a hash sign can also appear at the end of special attributes
    and substitutions ({}).
{# Another comment}


<html param= use= def=>
    Only a few attrs are allow on the <html> root tag. There is an implied def="html(*)".

<style>, <script>
    No substition occurs in <style> or <script>

<label>, <output>
    for= does not have extended meaning.

Builtins

len(x) -- return length of list
true
false
null
sum(nums) -- return sum of list of numbers (null if any arent numbers)
forloop(iter, opts) -- swiss army knife of looping
contents(inner) -- strip outer tag
tag(name, attrs, inner) -- wrap with tag
attrs(attrmap, inner) -- add attributes to outer tag

Built in filters

url
safe
trim

###Compatibility

|Environment|Min version|Runtime?|Compiler?|Package?| |-----------|-----------|--------|---------|--------| |Python 2 |2.7 |Yes |Yes |Soon | |Python 3 |3.4 |Yes |No |No | |node |??? |Yes |No |No | |Chrome |??? |Yes |No |No | |Firefox |??? |Yes |No |No | |IE |??? |Yes |No |No | |Safari |??? |Yes |No |No |

###Needed and Possible changes

0.1.0 changes

  • package.json for tatlrt module
  • Faster code for JS compiled templates
  • split tatlrt into submodules for leaner javascript runtime (only forloop for now)
  • module::func() lookup will detect whether to use rquire('./module') or require('module')

Planned 0.2.0 changes

  • tatlify (browserfy support) -- own repo
  • |noquote (or |nq) as a "safer" |safe
  • document |safe optimization as being unsafe

Future

  • More contextual quoting
  • Placeholders -- need fixes
  • Limit loading to specified modules?
  • Watch compiler -- lean on browserfy?
  • Client code to reload changes
  • Generate shadow dom code eg mithril
  • The parser. bs4 + lxml adds and loses line info. HTMLParsers() requires sax rewrite but seems more reliable.
  • Pure python3 compiler?
  • PyPy, Jython - check speed?
  • Babel? Whats the JS solution?
  • any and all -- boolean quantifiers
  • Expand front matter to use built-in value syntax, (which is basically JSON5). // and /* */ Comments
  • Further builtins... min, max, reversed, sorted, zip... groupby, batch...