1.0.9 • Published 3 years ago

nebbia v1.0.9

Weekly downloads
182
License
MIT
Repository
github
Last release
3 years ago

Nebbia

License Build Status Coverage Status Known Vulnerabilities

npm

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?

yuml diagram

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 blocks for, 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)

nebbia(template)

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 an else 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.

yuml diagram

The following interfaces all inherit from Node’s methods and properties: Expression, Statement and Text.

static: Node.unity

[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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()

node.childs

node.name

node.parent

node.type

[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)|[null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null) Returns an unsigned short representing the type of the node. Default: null.

Possible values are:

NameValue
Expression0
Text1
Statement2

node.value

[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) Returns value of the current node.

class Expression

Represents a group of nodes resulting from parsing an expression on Statement and Text.

yuml diagram

class Text

Represents the textual content.

class Statement

Contains the name of the statement, the condition is stored in the value of the node.

nebbia.parse(template)

An example of parsing the template:

template.html

<div>
${if (typeof value === 'string') {
  <p>${value}</p>
}}
</div>

index.js

import fs from 'fs';
import nebbia from 'nebbia';

const content = fs.readFileSync('./template.html');
const ast = nebbia.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 blocks for and while inside iterations.
1.0.9

3 years ago

1.0.8

3 years ago

1.0.7

3 years ago

1.0.6

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

0.0.7

4 years ago

0.0.6

5 years ago

0.0.5

5 years ago

0.0.4

5 years ago

0.0.3

6 years ago

0.0.2

6 years ago

0.0.1

6 years ago