nebbia
v2.0.3
Published
JavaScript Template literals (Template strings) compiler
Downloads
3
Readme
Nebbia
Nebbia
is a JavaScript Template literals (Template strings) compiler. Make the templates more expressive.
To improve reliability and maintainability the code is migrated to TypeScript.
How it works?
Template literals are enclosed by the back-tick `
character instead of double or single quotes. Template literals can contain placeholders. These are indicated by the dollar sign and curly braces `${expression}`
. The expressions in the placeholders and the text between them get passed to a function. The default function just concatenates the parts into a single string.
This is a very useful feature. The expression can only be used to interpolate strings. The following example demonstrates the problem of string interpolation.
`${1 + 1}` // '2'
`${}` // SyntaxError: Unexpected token }
`${if (true) {}}` // SyntaxError: Unexpected token if
Nebbia
was created to help solve this problem. The compiler extends the capabilities of Template literals (Template strings) with the capabilities of standard JavaScript
statements and declarations.
List of supported statements:
NOTE The
break
statement is a prisoner in blocksfor
,for..in
,for ...of
,while
does not support interrupt inside iterations.
Nebbia
created by to make template strings more loyal. An empty expression ${}
will not throw
an exception. Supports closures and multiple nesting of expressions.
The compiled pattern does not use regular expressions.
Getting Started
Installation
To use Nebbia
in your project, run:
npm i nebbia
Browser-compatible Node.js® module, implemented by following the ECMAScript® 2018 Language Specification standard.
API docs
Table of Contents
nebbia(template)
template
<String> The template inside the ad must be in the block{}
. By default,'__string__'
is the name of a variable used to concatenate strings. You can change a keyword by assigning a value to thenebbia.unity
property.- returns: <String> Represents the
compiled
template strings of a node and its descendants. Template literals are enclosed by the back-tick`
(grave accent).
template.html
<!DOCTYPE html>
<html>
<head>
<title>Nebbia</title>
</head>
<body>
<h1>${h1}</h1>
${if (list instanceof Array) {
<header></header>
${for (let i of list) {
<div>${i}</div>
}}
}
if (footer) {
<footer></footer>
}}
</body>
</html>
template.txt
${if (user === 'admin') {
📆 To-do list
for (let i of list) {
- ${i.date} ${i.note}
}
}
else {
Offer a cup of coffee!
}}
Strings are enclosed by the back-tick `
character is processed by the parser as is.
${if (arg === `;)`) {
<p>Maybe it's a smile</p>
}}
This is useful when you need to escape arguments in a statement. Otherwise, the parser will read the statement like arg === ;
.
Statements by category
The Nebbia
uses JavaScript with an appropriate syntax to create a compilation of template strings. Several instructions can be in the same expression. The spaces and tabs is not taken into account by the parser.
if
import nebbia from 'nebbia';
const template = '${if (arg === true) {<p>${arg}</p>}}';
const invoke = new Function('arg', 'return ' + nebbia(template));
invoke(true); // <p>true</p>
if...else
import nebbia from 'nebbia';
const template = '${if (arg === true) {<p>${arg}</p>} else {<p>else</p>}}';
const invoke = new Function('arg', 'return ' + nebbia(template));
invoke(false); // <p>else</p>
NOTE Multiple
if...else
statements not support be nested to create anelse if
clause. Planned to be implemented in the future.
for
import nebbia from 'nebbia';
const template = '${for (let i = 0; i < count; i++) {<p>${i}</p>}}';
const invoke = new Function('count', 'return ' + nebbia(template));
invoke(2); // <p>0</p><p>1</p>
for...in
import nebbia from 'nebbia';
const template = '${for (let i in obj) {<p>${i}</p>}}';
const invoke = new Function('obj', 'return ' + nebbia(template));
invoke({
fruit: 'apple',
cart: 1
}); // <p>fruit</p><p>cart</p>
for...of
import nebbia from 'nebbia';
const template = '${for (let i of list) {<p>${i}</p>}}';
const invoke = new Function('list', 'return ' + nebbia(template));
invoke([ 0, 1 ]); // <p>0</p><p>1</p>
while
import nebbia from 'nebbia';
const template = '${while (list.pop() > -1) {<p>${i.length}</p>}}';
const invoke = new Function('list', 'return ' + nebbia(template));
invoke([ 0, 1 ]); // <p>1</p><p>0/p>
NOTE The
do...while
statement not implemented. Planned to be implemented in the future.
class Node
Node
is an interface from which a number of Tree
object types inherit. It allows those types to be treated similarly; for example, inheriting the same set of methods, or being tested in the same way.
The following interfaces all inherit from Node
’s methods and properties: Expression, Statement and Text.
static: Node.unity
<String> Returns the string concatenation keyword. Default: '__string__'
.
constructor: new Node()
Sets default node instance values.
node.append(child)
Adds the specified node
argument as the last child to the current node.
node.build()
- returns: <String> Represents the
compiled
template strings of a node and its descendants. Template literals are enclosed by the back-tick`
(grave accent).
node.childs
- <Array> Contains all the children of this
node
.
node.name
- <String|null> Contains the name of the
node
. The structure of the name will differ with thenode
type. E.g. An Statement will contain the name of the corresponding statement, a Text node will have the#text
string. Default:null
.
node.parent
- <Node|null> Returns a
node
that is the parent of thisnode
. If there is no suchnode
, like if this node is the top of the tree or if doesn't participate in a tree, this property returnsnull
.
node.type
<Number|null> Returns an unsigned short representing the type of the node. Default: null
.
Possible values are:
| Name | Value | |---------------------------------|:-----:| | Expression | 0 | | Text | 1 | | Statement | 2 |
node.value
<String> Returns value of the current node
.
class Expression
Represents a group of nodes resulting from parsing an expression on Statement and Text.
class Text
Represents the textual content.
class Statement
Contains the name
of the statement, the condition is stored in the value
of the node
.
parse(template)
template
<String> The template inside the ad must be in the block{}
. By default,'__string__'
is the name of a variable used to concatenate strings. You can change a keyword by assigning a value to thenebbia.unity
property.- returns: <Expression> Each branch of the tree ends in a
node
, and eachnode
contains objects. Methods provides programmatic access to the tree; with them you can change the template strings structure.
An example of parsing the template:
template.html
<div>
${if (typeof value === 'string') {
<p>${value}</p>
}}
</div>
index.js
import fs from 'fs';
import { parse } from 'nebbia';
const content = fs.readFileSync('./template.html');
const ast = parse(content);
const template = ast.build();
const ast:
const template:
`<div>
${((__string__)=>{if(typeof value === 'string')__string__+=`
<p>${value}</p>
`;return __string__})(``)}
</div>
`
Development
Planed:
- Measure benchmark.
- To introduce:
do...while
,else...if
statement.break
,continue
statement is a prisoner in blocksfor
andwhile
inside iterations.