Browse Source

[Minor] Add lua-lupa library for Jinja2 templates

tags/1.9.1
Vsevolod Stakhov 5 years ago
parent
commit
3bf124702c
4 changed files with 2008 additions and 0 deletions
  1. 1
    0
      CMakeLists.txt
  2. 21
    0
      contrib/lua-lupa/LICENSE
  3. 179
    0
      contrib/lua-lupa/README.md
  4. 1807
    0
      contrib/lua-lupa/lupa.lua

+ 1
- 0
CMakeLists.txt View File

@@ -1376,6 +1376,7 @@ ENDFOREACH(LUA_LIB)
INSTALL(FILES "contrib/lua-fun/fun.lua" DESTINATION ${LUALIBDIR})
INSTALL(FILES "contrib/lua-argparse/argparse.lua" DESTINATION ${LUALIBDIR})
INSTALL(FILES "contrib/lua-tableshape/tableshape.lua" DESTINATION ${LUALIBDIR})
INSTALL(FILES "contrib/lua-lupa/lupa.lua" DESTINATION ${LUALIBDIR})

IF(ENABLE_TORCH MATCHES "ON")
INSTALL(FILES "contrib/lua-moses/moses.lua" DESTINATION ${LUALIBDIR})

+ 21
- 0
contrib/lua-lupa/LICENSE View File

@@ -0,0 +1,21 @@
The MIT License

Copyright (c) 2015-2018 Mitchell

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

+ 179
- 0
contrib/lua-lupa/README.md View File

@@ -0,0 +1,179 @@
# Lupa

## Introduction

Lupa is a [Jinja2][] template engine implementation written in Lua and supports
Lua syntax within tags and variables.

Lupa was sponsored by the [Library of the University of Antwerp][].

[Jinja2]: http://jinja.pocoo.org
[Library of the University of Antwerp]: http://www.uantwerpen.be/

## Requirements

Lupa has the following requirements:

* [Lua][] 5.1, 5.2, or 5.3.
* The [LPeg][] library.

[Lua]: http://www.lua.org
[LPeg]: http://www.inf.puc-rio.br/~roberto/lpeg/

## Download

Download Lupa from the project’s [download page][].

[download page]: download

## Installation

Unzip Lupa and place the "lupa.lua" file in your Lua installation's
`package.path`. This location depends on your version of Lua. Typical locations
are listed below.

* Lua 5.1: */usr/local/share/lua/5.1/* or */usr/local/share/lua/5.1/*
* Lua 5.2: */usr/local/share/lua/5.2/* or */usr/local/share/lua/5.2/*
* Lua 5.3: */usr/local/share/lua/5.3/* or */usr/local/share/lua/5.3/*

You can also place the "lupa.lua" file wherever you'd like and add it to Lua's
`package.path` manually in your program. For example, if Lupa was placed in a
*/home/user/lua/* directory, it can be used as follows:

package.path = package.path..';/home/user/lua/?.lua'

## Usage

Lupa is simply a Lua library. Its `lupa.expand()` and `lupa.expand_file()`
functions may called to process templates. For example:

lupa = require('lupa')
lupa.expand("hello {{ s }}!", {s = "world"}) --> "hello world!"
lupa.expand("{% for i in {1, 2, 3} %}{{ i }}{% endfor %}") --> 123

By default, Lupa loads templates relative to the current working directory. This
can be changed by reconfiguring Lupa:

lupa.expand_file('name') --> expands template "./name"
lupa.configure{loader = lupa.loaders.filesystem('path/to/templates')}
lupa.expand_file('name') --> expands template "path/to/templates/name"

See Lupa's [API documentation][] for more information.

[API documentation]: api.html

## Syntax

Please refer to Jinja2's extensive [template documentation][]. Any
incompatibilities are listed in the sections below.

[template documentation]: http://jinja.pocoo.org/docs/dev/templates/

## Comparison with Jinja2

While Lua and Python (Jinja2's implementation language) share some similarities,
the languages themselves are fundamentally different. Nevertheless, a
significant effort was made to support a vast majority of Jinja2's Python-style
syntax. As a result, Lupa passes Jinja2's test suite with only a handful of
modifications. The comprehensive list of differences between Lupa and Jinja2 is
described in the following sections.

### Fundamental Differences

* Expressions use Lua's syntax instead of Python's, so many of Python's
syntactic constructs are not valid. However, the following constructs
*are valid*, despite being invalid in pure Lua:

+ Iterating over table literals or table variables directly in a "for" loop:

{% for i in {1, 2, 3} %}...{% endfor %}

+ Conditional loops via an "if" expression suffix:

{% for x in range(10) if is_odd(x) %}...{% endfor %}

+ Table unpacking for list elements when iterating through a list of lists:

{% for a, b, c in {{1, 2, 3}, {4, 5, 6}} %}...{% endfor %}

+ Default values for macro arguments:

{% macro m(a, b, c='c', d='d') %}...{% endmacro %}

* Strings do not have unicode escapes nor is unicode interpreted in any way.

### Syntactic Differences

* Line statements are not supported due to parsing complexity.
* In `{% for ... %}` loops, the `loop.length`, `loop.revindex`,
`loop.revindex0`, and `loop.last` variables only apply to sequences, where
Lua's `'#'` operator applies.
* The `{% continue %}` and `{% break %}` loop controls are not supported due to
complexity.
* Loops may be used recursively by default, so the `recursive` loop modifier is
not supported.
* The `is` operator is not supported by Lua, so tests of the form `{{ x is y }}`
should be written `{{ is_y(x) }}` (e.g. `{{ is_number(42) }}`).
* Filters cannot occur after tokens within an expression (e.g.
`{{ "foo"|upper .. "bar"|upper }}`), but can only occur at the end of an
expression (e.g. `{{ "foo".."bar"|upper }}`).
* Blocks always have access to scoped variables, so the `scoped` block modifier
is not supported.
* Named block end tags are not supported since the parser cannot easily keep
track of that state information.
* Any `{% block ... %}` tags within a "false" block (e.g. `{% if a %}` where `a`
evaluates to `false`) are never read and stored due to the parser
implementation.
* Inline "if" expressions (e.g. `{% extends b if a else c %}`) are not
supported. Instead, use a Lua conditional expression
(e.g. `{% extends a and b or c %}`).
* Any `{% extends ... %}` tags within a sub-scope are not effective outside that
scope (e.g. `{% if a %}{% extends a %}{% else %}{% extends b %}{% endif %}`).
Instead, use a Lua conditional expression (e.g. `{% extends a or b %}`).
* Macros are simply Lua functions and have no metadata attributes.
* Macros do not have access to a `kwargs` variable since Lua does not support
keyword arguments.
* `{% from x import y %}` tags are not supported. Instead, you must use either
`{% import x %}`, which imports all globals in `x` into the current
environment, or use `{% import x as z %}`, which imports all globals in `x`
into the variable `z`.
* `{% set ... %}` does not support multiple assignment. Use `{% do ...%}`
instead. The catch is that `{% do ... %}` does not support filters.
* The `{% trans %}` and `{% endtrans %}` tags, `{% with %}` and `{% endwith %}`
tags, and `{% autoescape %}` and `{% endautoescape %}` tags are not supported
since they are outside the scope of this implementation.

### Filter Differences

* Only the `batch`, `groupby`, and `slice` filters return generators which
produce one item at a time when looping. All other filters that produce
iterable results generate all items at once.
* The `float` filter only works in Lua 5.3 since that version of Lua has a
distinction between floats and integers.
* The `safe` filter must appear at the end of a filter chain since its output
cannot be passed to any other filter.

### Function Differences

* The global `range(n)` function returns a sequence from 1 to `n`, inclusive,
since lists start at 1 in Lua.
* No `lipsum()`, `dict()`, or `joiner()` functions for the sake of simplicity.

### API Differences

* Lupa has a much simpler API consisting of just four functions and three
fields:

+ `lupa.expand()`: Expands a string template subject to an environment.
+ `lupa.expand_file()`: Expands a file template subject to an environment.
+ `lupa.configure()` Configures delimiters and template options.
+ `lupa.reset()`: Resets delimiters and options to their defaults.
+ `lupa.env`: The default environment for templates.
+ `lupa.filters`: The set of available filters (`escape`, `join`, etc.).
+ `lupa.tests`: The set of available tests (`is_odd`, `is_defined`, etc.).

* There is no bytecode caching.
* Lupa has no extension mechanism. Instead, modify `lupa.env`, `lupa.filters`,
and `lupa.tests` directly. However, the parser cannot be extended.
* Sandboxing is not supported, although `lupa.env` is safe by default (`io`,
`os.execute`, `os.remove`, etc. are not available).

+ 1807
- 0
contrib/lua-lupa/lupa.lua
File diff suppressed because it is too large
View File


Loading…
Cancel
Save