Pre

2.0.0-rc2.2 • Public • Published

Pre

Advanced General-Purpose Preprocessor


🐝 Direct includes from Github (versioned) and URLs

🐧 Flexible syntax (macros, loops, expressions, etc.)

🍄 Asset filters (escape, base64, custom)

🐠 Automatic un-indentation of nested blocks

🐥 Line control statements generation

🐸 Available as cli or as npm library

🐼 Extensible and embeddable via JS API



[![Build Status](https://travis-ci.org/myurasov/Pre.svg?branch=develop)](https://travis-ci.org/myurasov/Pre)

Syntax

Directives

Directives start with @ symbol.

@set

@set <variable:identifier> <value:expression>
@set <variable:identifier> = <value:expression>

Assigns a value of an expression to a variable.

Variables are defined in a global context.

Example:

Sets SOMEVAR to 1:

@set SOMEVAR min(1, 2, 3)

@macro

@macro <name>(<arguments>)
  <body>
@endmacro

@endmacro can be replaced with @end.

Defines a code region that can take it's own parameters. Macros are declared in a global scope. Macro parameters are only available within the macro scope and override global variables with the same name (but do not affect them).

Macros can be used:

  • via @include directive:

      @include macro(a, b, c)
      
  • inline:

      @{macro(a, b, c)}
      

    When macros are used inline:

    • no line control statements are generated for the output inside the macro scope
    • trailing newline is trimmed from macro output

Examples:

@macro some_macro(a, b, c)
  Hello, @{a}!
  Roses are @{b},
  And violets are @{defined(c) ? c : "of undefined color"}.
@end

Then some_macro can be used as:

@include some_macro("username", "red")

which will produce:

Hello, username!
Roses are red,
And violets are of undefined color.

The same macro used inline:

[[[ @{some_macro("username", "red", "blue")} ]]]

will ouput:

[[[ Hello, username!
Roses are red,
And violets are blue. ]]]

@include

Includes local file, external source or a macro.

@include <source:expression>

Macro

@include some_macro("username", 123)

Local Files

@include "somefile.ext"

Remote Files

@include "http://example.com/file.ext"
@include "https://example.com/file.ext"

From GitHub

@include "github:<user>/<repo>/<path>[@<ref>]"

Where:

  • user – user/organization name
  • repo – repository name
  • ref – git reference (branch name or tag, defaults to master)

Examples:

  • Head of the default branch

    @include "github:electricimp/Promise/Promise.class.nut"
    
  • Head of the develop branch

    @include "github:electricimp/Promise/Promise.class.nut@develop"
    
  • Tag v2.0.0:

    @include "github:electricimp/Promise/Promise.class.nut@v2.0.0"
    

Authentication

When using GitHub includes, authentication is optional, however:

  • with authentication GitHub API provides much higher rate limits
  • to access private repositories authentication is required

Apart from GitHub username you need to provide either a personal access token or password (which is less secure and not recommended). More info on how to provide those parameters is in usage section.

@include once

@include once <source:expression>

Acts the same as @include but has no effect if source has already been included. Macros are always included.

@{...} (inline expressions/macros)

@{<expression>}
@{macro(a, b, c)}

Inserts the value of the enclosed expression or executes a macro.

Example:

@set name "Someone"
Hello, @{name}, the result is: @{123 * 456}.

results in the following output:

Hello, Someone, the result is: 56088.

@while

While-loop. loop variable is available in @while loops.

@while <test:expression>
  // 0-based iteration counter: @{loop.index}
  // 1-based iteration counter: @{loop.iteration}
@endwhile

@endwhile can be replaced with @end.

Example

@repeat

Loop that repeats a certain number of iterations. loop variable is available in @repeat loops.

@repeat <times:expression>
  // 0-based iteration counter: @{loop.index}
  // 1-based iteration counter: @{loop.iteration}
@endrepeat

@endrepeat can be replaced with @end.

Example:

@repeat 3
  loop.iteration: @{loop.iteration}
@end

outputs:

  loop.iteration: 1
  loop.iteration: 2
  loop.iteration: 3

@if – @elseif – @else

Conditional directive.

@if 

  // consequent code

@elseif <test:expression>

  // else if #1 code

// ...more elseifs...

@else

  // alternate code

@endif

@endif can be replaced with @end.

Example:

@if __FILE__ == 'abc.ext'
  // include something
@elseif __FILE__ == 'def.ext'
  // include something else
@else
  // something completely different
@endif

@error

@error <message:expression>

Emits an error.

Example:

@if PLATFORM == "platform1"
  // platform 1 code
@elseif PLATFORM == "platform2"
  // platform 2 code
@elseif PLATFORM == "platform3"
  // platform 3 code
@else
  @error "Platform is " + PLATFORM + " is unsupported"
@endif

Filters

"Filter" | operator allows to pass a value through any of supported functions.

@{<expression> | <filter>}

which is equivalent to:

@{<filter>(<expression>)}

Example:

// include external HTML to a string
a = "@{include('index.html')|escape}"

// include external binary file to a base64-encoded string
b = "@{include('file.bin')|base64}"

Expressions

Directives that have parameters allow usage of expression syntax.

For example:

  • @include <source:expression>
  • @set <variable:identifier> <value:expression>
  • @if <condition:expression>
  • @elseif <condition:expression>
  • @{<expression>} (inline expressions)

Types

The following types are supported in expressions:

  • numbers (eg: 1,1E6, 1e-6, 1.567)
  • strings (eg: "abc", 'abc')
  • null
  • true
  • false

Operators

Binary

|| && == != < > <= >= + - * / %

Unary

+ - !

Member Expressions

  • somevar.member
  • somevar["member"]
  • ([1, 2, 3])[1]

Conditional Expressions

test ? consequent : alternate

Variables

  • Variables defined by @set statements are available in expressions.
  • Undefined variables are evaluated as null.
  • Variable names can contain $, _, latin letters and digits and can start only with a non-digit.

__LINE__

Line number (relative to the file in which this variable appears).

Example:

Hi from line @{__LINE__}!

__FILE__

Name of the file in which this variable appears.

Example:

Hi from file @{__FILE__}!

__PATH__

Absolute path (not including file name) to the file where this variable appears. Contains url for remote includes.

Example:

Hi from file @{__PATH__}!

loop

Defined inside @while and @repeat loops.

Contains information about the current loop:

  • loop.index – 0-indexed iteration counter
  • loop.iteration – 1-indexed iteration counter

Example:

@set myvar = 12

@while myvar > 9
  @set myvar = myvar - 1
  var: @{myvar}
  loop.index: @{loop.index}
@end

outputs:

myvar: 11
loop.index: 0
myvar: 10
loop.index: 1
myvar: 9
loop.index: 2

Functions

  • defined(<variable_name>) – returns true if a variable is defined, false otherwise.
  • include(<source>) – includes external source
  • escape(<value>) – escapes special characters in string (\b, \f, \n, \r, \t, \, ', ")
  • base64(<value>) – encodes value as base64
  • min(<numbers>)
  • max(<numbers>)
  • abs(<number>)

Comments

Lines starting with @ followed by space or a line break are treated as comments and not added to the output.

Example:

@ something about platform #1
@set PLATFORM "platform1"

Usage

Please note that Pre requires Node.js 4.0 and above.

  • As npm library:

    npm i --save Pre

    then

    const Pre = require('Pre');
    
    const pre = new Pre();
    
    // (optional) provide GitHub credentials
    pre.machine.readers.github.username = "<usename>";
    pre.machine.readers.github.token = "<personal access token>";
    
    const output = pre.machine.execute(`@include "${inputFile}"`);
  • As CLI:

    Pre provides prprcss command when installed globally:

    npm i -g Pre
    pre [-D<variable> <value>...] [-l] [--github-user <usename> --github-token <token>] [-l] <input_file>
    

    where:

    • -l – generate line control statements
    • -D<variable> <value> – define a variable
    • --github-user – GitHub username
    • --github-token – GitHub personal access token or password (not recommended)

Testing

SPEC_LOGLEVEL=<debug|info|warning|error> \
SPEC_GITHUB_USERNAME=<GitHub username> \
SPEC_GITHUB_TOKEN=<GitHub password/access token> \
npm test

License

MIT. Pre is a fork of Electric Imp's Builder licensed under MIT.

Author

Mikhail Yurasov me@yurasov.me

Readme

Keywords

none

Package Sidebar

Install

npm i Pre

Weekly Downloads

1

Version

2.0.0-rc2.2

License

MIT

Last publish

Collaborators

  • mym___