Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Text templating processor for SWI-Prolog.

License

NotificationsYou must be signed in to change notification settings

rla/simple-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

73 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Text (HTML) template processor for SWI-Prolog. Worksbest for cases when you have mainly static HTML.

Build Status

Visual Code syntax support:https://marketplace.visualstudio.com/items?itemName=rlaanemets.simple-template-syntax

Example

Input markup (test.html file):

<h1>{{= title }}</h1>{{ each items, item }}    <h2>{{= item.title }}</h2>    <div>{{- item.content }}</div>{{ end }}

rendering with data:

use_module(library(st/st_render)).current_output(Out),st_render_file(test, _{    title: 'Hello',    items: [        _{ title: 'Item 1', content: 'Abc 1' },        _{ title: 'Item 1', content: 'Abc 2' }    ]}, Out, []).

output:

<h1>Hello</h1><h2>Item 1</h2><div>Abc 1</div><h2>Item 1</h2><div>Abc 2</div>

Alternate syntax: semblance

If you find your tools work better with a template tag syntax thatmore closely resembles other web templating engines, such as Django(Python) / Djula (Common Lisp) / Twig (PHP), you can also use analternate frontend syntax called semblance:

Input markup (test.html file):

<h1>{{ title }}</h1>{% each items, item %}    <h2>{{ item.title }}</h2>    <div>{% unescape item.content %}</div>{% end %}

rendering with data:

use_module(library(st/st_render)).current_output(Out),st_render_file(test, _{    title: 'Hello',    items: [        _{ title: 'Item 1', content: 'Abc 1' },        _{ title: 'Item 1', content: 'Abc 2' }    ]}, Out, _{ frontend: semblance }).

output:

<h1>Hello</h1><h2>Item 1</h2><div>Abc 1</div><h2>Item 1</h2><div>Abc 2</div>

It is not possible to mix two syntaxes through a single render call.

User-Defined Syntax

Alternatively, you can specify your own templating delimiter syntax.This is useful to prevent template collision, in similar cases to semblance,but is more flexible.

Input markup (test.html file):

<h1><%= title %></h1><% each items, item %>    <h2><%= item.title %></h2>    <div><%~ item.content %></div><% end %>

rendering with data:

use_module(library(st/st_render)).current_output(Out),st_render_file(test, _{    title: 'Hello',    items: [        _{ title: 'Item 1', content: 'Abc 1' },        _{ title: 'Item 1', content: 'Abc 2' }    ]}, Out, _{    frontend: syntax_tokens(        comment("<%#", "%>"),        out("<%=", "%>"),        out_unescaped("<%~", "%>"),        statement("<%", "%>")    )}).

output:

<h1>Hello</h1><h2>Item 1</h2><div>Abc 1</div><h2>Item 1</h2><div>Abc 2</div>

Unescape Keyword in User-Defined Syntax

If you'd like to use an unescape keyword, you can use the helperkeyword_unescape_start(Token) in place of a string, whereTokenis the starting Token to unify:

use_module(library(st/st_render)).current_output(Out),st_render_file(test, _{    title: 'Hello',    items: [        _{ title: 'Item 1', content: 'Abc 1' },        _{ title: 'Item 1', content: 'Abc 2' }    ]}, Out, _{    frontend: syntax_tokens(        comment("<%#", "%>"),        out("<%=", "%>"),        out_unescaped(keyword_unescape_start("<%="), "%>"),        statement("<%", "%>")    )}).

With input markup (test.html file):

<h1><%= title %></h1><% each items, item %>    <h2><%= item.title %></h2>    <div><%= unescape item.content %></div><% end %>

output:

<h1>Hello</h1><h2>Item 1</h2><div>Abc 1</div><h2>Item 1</h2><div>Abc 2</div>

API

Render template from string:

st_render_string(String, Data, Stream, File, Options).

Render template from file:

st_render_file(File, Data, Stream, Options).

Render template from codes:

st_render_codes(Codes, Data, Stream, File, Options).

Options accept the following:

  • encoding - defaultutf8.
  • extension - file name extension, defaulthtml.
  • cache - whether to use cache, defaultfalse.
  • strip - whether to try to strip whitespace from output, defaultfalse.
  • frontend - which syntax to use, currentlysimple (default) orsemblance.
  • undefined - throw error on undefinedvariables -error (default) orfalse (evaluates to false).

Processing instructions

Processing instructions start with double opening curly braces ({{) andend with double closing curly braces (}}). Semblance syntax variationsare described below.

There are 4 types of processing instructions.

Output

There are two output instructions.{{= expression }} outputs the expressionvalue and escapes the special HTML characters.{{- expression }} outputs theexpression value but does not escape the output. There must be no spacebetween{{ and= or-.

Includes

Includes use the syntax{{ include path/to/file }}. The path should be relative.The relative path is resolved against the current file location and the currentlyset file extension is added. All values from the current scope are available tothe included file. There is also{{ include path/to/file, expression }} thatsets the scope of the included file to the value of the expression (must be a dict).

Dynamic includes use the syntax{{ dynamic_include expression }}. The value ofthe expression must be a file path specifier. There is also a variant with thescope expression.

Includes are currently processed at runtime. You should enable caching if you includeinside a loop otherwise the included file is parsed over and over again.

Conditionals

Conditional instructions have the following syntax:

{{ if cond_expression1 }}...{{ else if cond_expression2 }}...{{ else }}...{{ end }}

else if andelse parts are optional.

Each loop

The each loop allows to process lists. The syntax for each loop:

{{ each expression, item_var, index_var, len_var }}...{{ end }}

The value of expression must be a list.item_var,index_var andlen_varrefer to current item, current item index and the length of the list.index_var andlen_var are optional.

Blocks

Blocks allow to compose templates while passing around the contained template asa value. This allows to wrap templated content with another template.

General syntax (block usage):

{{ block path/to/file }}    Block content.{{ end }}

And to render the distributed block content:

{{ slot }}

Example 1: wrapping content into a panel element.

Input file:

<div></div>{{ block panel }}    <span>This will be wrapped in panel.</span>{{ end }}<div></div>

Panel file:

<div>{{ slot }}</div>

Rendering result:

<div></div><div><span>This will be wrapped in panel.</span></div><div></div>

Variable scoping inside block content is lexical. Variable scope insideblock is either the current scope or selectable with an expression similarto the{{ include file, expr }} instruction.

Example 2: layouts.

Layout file (layout.html):

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8">        <title>{{= title }}</title>    </head>    <body>        <h1>{{= title }}</h1>        {{ slot }}    </body></html>

Concrete page file:

{{ block layout }}    <span>This is the page file.</span>{{ end }}

Data:

_{ title: "A page title" }

Rendering result:

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8">        <title>A page title</title>    </head>    <body>        <h1>A page title</h1>        <span>This is the page file.</span>    </body></html>

Semblance syntax

The semblance syntax has the following differences.

Output instruction:{{ variable }}.

Unescaped output:{% unescape rawvar %}.

Conditional instructions:

{% if cond_expression1 %}...{% else if cond_expression2 %}...{% else %}...{% end %}

Each loop:

{% each expression, item_var, index_var, len_var %}...{% end %}

Comments:{# comment #}.

Expressions

Expressions are ground Prolog terms with the interpretationdescribed below.

In most contexts, atoms are interpreted as scope entries ("variables").An error is thrown when there is no suitable entry.

The following arithmetic operators and functions are supported:-, +, *, /, mod, rem, //, div, abs, sign, max, min, random, round, truncate, floor, ceiling, **, ^.

Boolean expressions include modified unification using the= operator. Theoperator provides coercion from atom to string when either of operands is an atomand the other is a string. For other types, no coercion is applied. Similarily worksthe\= operator. Supported boolean operators are:, (logical and),; (logical or)and\+ (logical negation). Supported comparison operator are:>, <, >=, =<,.

Conditional expressionif(expression, true_expr, false_expr) value is the value oftrue_expr when theexpression evaluates to anything but 0 orfalse. Otherwise thevalue is the value offalse_expr.

The+ operator is overloaded to provide string or atom concatenation whenthe left side of the operator is an atom or string. The result is string.

The. operator is used for accessing values from dicts. Internally the./3 predicate is used which means that user-defined functions on dictswill work as intended.

Compound terms that match none of the operators and constructs described above aretreated as user-defined (see below) function calls. An error is thrown when there is no such functiondefined.

A special expression isatom(something). Its value is atomsomething. Thisis added to differentiate them from other atoms which are otherwise interpretedas scope entries.

Literal lists work as expected with the elements having the interpretation asthe expressions above.

Undefined variables

The default behaviour when a variable that is not in the scope (template data dict) is encountered is to throw ano_entry error. This behaviour can be modified to set the variable value tofalse (default iserror) by setting theundefined option tofalse when rendering templates. For example:

st_render_file(test, _{    title: 'Hello',    items: [        _{ title: 'Item 1', content: 'Abc 1' },        _{ title: 'Item 1', content: 'Abc 2' }    ]}, Out, _{ undefined: false }).

This is useful in situations where a developer may want to include a block in the template based on the existence of a variable. For example:

{% if page_header %}    <h2>{{page_header}}</h2>{% end %}

Built-in functions

There are three single-argument functions to encode URI parts:encode_path,encode_query_value andencode_fragment. These calluri_encoded/3 withthe respective first argument.

Global constants

Global constants can be set with thest_set_global/2 predicate by importingthest_expr module. When a scope contains anentry with the same name as a global then the local value is preferred.

User-defined functions

User-defined functions can be set with thest_set_function(Name, Arity, Goal)predicate in thest_expr module. Arity refers to the function arity. Goal musthave arity Arity + 1.

Comments

Comment blocks start with{{% and end with}}. Comments do not appearin the output.

Caching

Template caching is enabled by setting optioncache: true during rendering. This makesthe system cache parsed templates. This is particulary useful when using includes in loops.To purge the current cache contents, use thest_cache_invalidate predicate.

Whitespace removal

Some (but not all) whitespace is removed by setting optionstrip: true during rendering. Line indents and some duplicate line endsare removed from the output. Whitespace removal is parse-time and does notincur any runtime penalty.

Encoding

Encoding for template files can be specified by setting optionencoding during rendering. Acceptedvalues are all that are accepted by theencoding option of theread_file_to_codes/3 predicate.

Installation

This package requires SWI-Prolog 7.x.

pack_install(simple_template).

API documentation

Seehttp://packs.rlaanemets.com/simple-template/doc/.

Running tests

In the package root, insert into swipl:

[tests/tests].run_tests.

Or if you cloned the repo:

make test

Bug reports/feature requests

Please send bug reports/feature request through the GitHubprojectpage.

Changelog

  • 2020-02-03 version 1.3.1. Add user-defined templating syntax.
  • 2017-11-03 version 1.2.0. Option to deal with undefined variables.
  • 2015-12-28 version 1.1.0. Add alternate syntax: semblance.
  • 2015-11-07 version 1.0.0. Removal of global options. Backwards-incompatible.
  • 2014-05-09 version 0.3.0. Provide st_cache_invalidate/0, = operator, comments.
  • 2014-05-07 version 0.2.0. Literal lists, encode_* functions.
  • 2014-03-02 version 0.1.0. Provided st_set_encoding/1.
  • 2014-01-30 version 0.0.1

License

The MIT License. See LICENSE file.

About

Text templating processor for SWI-Prolog.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp