V project for supporting whisker, a descendent of the Mustache template language.
39
stars
150
commits
V
primary language
Jun 16, 2024
updated
whisker is inspired by Mustache but is more stable, robust and predictable. It is a fast template engine for V with a simple syntax.
{{...}}.The following blog posts provide more context:
You must have V installed. Refer to the official instructions for help with installation.
If you already have V installed, use v up to update the toolchain and standard
library.
v install hungrybluedev.whisker
This should install the package as the hungrybluedev.whisker module.
To use it, use import hungrybluedev.whisker and proceed as normal.
Run the following to install whisker from GitHub using V's package manager:
v install --git https://github.com/hungrybluedev/whisker
This should install in hungrybluedev.whisker first and then relocate it
to whisker. Now, in your project, you can import whisker and use whisker
right away!
The main struct is whisker.template.Template which can be generated either
directly from template strings or be loaded from disk from template files. A
single template should be reused for different data models to produce outputs
which differ in content but not semantic structure.
Note There might be slight white-space consistencies between the generated and expected results. For machine-verification, it is recommended to compare the parsed and reconstructed outputs for your particular file format.
template.from_strings(input: input_str, partials: partial_map)
to generate a template from direct string inputs. Here, input_str is
a string and partial_map is a map[string]string. The map's keys are the
names of the template that are replaced by the direct template strings. Leave
the partials field empty if there are none required.run(data) to generate the output string. The
data can be represented in V source code directly (refer to the spec for
examples), or it can be loaded from JSON (using
datamodel.from_json(data_string)).This is a copy-paste-able example to get started immediately:
module main
// Imports if you install from GitHub:
import whisker.datamodel
import whisker.template
// Imports if you install from VPM:
import hungrybluedev.whisker.template
import hungrybluedev.whisker.datamodel
fn main() {
simple_template := template.from_strings(input: 'Hello, {{name}}!')!
data := datamodel.from_json('{"name": "World"}')!
println(simple_template.run(data)!) // prints "Hello, World!"
}
template.load_file(input: input_str, partials: partial_map) to
generate a template from file names. The difference here is that instead of
providing content, you provide the relative file paths. The names of the
partials need to be exact though, so keep an eye on that.os.read_file(path_to_json) to read the JSON contents and then plug this
into the datamodel.from_json function.It is not necessary, but it is recommended to use filenames that
contain *.wskr.* somewhere in the file name.
Check json_test.v and html_test.v for
examples with template files.
whisker may also be used as a standalone command-line program to process template files. It does not support direct template string input for the sake of simplicity.
Build whisker with v cmd/whisker and run cmd/whisker/whisker --help for
usage instructions. You can specify a bin subdirectory as output folder and
add it to path as well:
# Create an output directory
mkdir cmd/bin
# Build the executable
v cmd/whisker -o cmd/bin/whisker
# Run the executable
cmd/bin/whisker --help
Check whisker_cli_test.v for a concrete demonstration.
Sample text
Sample text
Hello, {{name}}!
{
"name": "world"
}
Hello, world!
{{=[ ]=}}
module main
fn main() {
println('[greeting]')
}
{
"greeting": "Have a nice day!"
}
module main
fn main() {
println('Have a nice day!')
}
<nav>
<ul>
<li>Home</li>
<li>About</li>
{{-logged_in}}
<li>Log In</li>
{{/logged_in}} {{+logged_in}}
<li>Account: {{user.name}}</li>
{{/logged_in}}
</ul>
</nav>
{
"logged_in": false
}
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Log In</li>
</ul>
</nav>
{
"logged_in": true,
"user": {
"name": "whisker"
}
}
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Account: whisker</li>
</ul>
</nav>
Positive and negative sections also apply to lists and maps. An empty list or map means a negative section and a non-empty one represents a positive section.
List:
{{+vacation}}
<h1>Currently on vacation</h1>
<ul>
{{*.}}
<li>{{.}}</li>
{{/.}}
</ul>
{{/vacation}} {{-vacation}}
<p>Nobody is on vacation currently</p>
{{/vacation}}
{
"vacation": []
}
<p>Nobody is on vacation currently</p>
{
"vacation": ["Homer", "Marge"]
}
<h1>Currently on vacation</h1>
<ul>
<li>Homer</li>
<li>Marge</li>
</ul>
Map:
{{+user}}
<p>Welcome {{last_name}}, {{first_name}}</h1>
{{/user}}
{{-user}}
<p>Create account?</p>
{{/user}}
{
"user": {}
}
<p>Create account?</p>
{
"user": {
"last_name": "Simpson",
"first_name": "Homer"
}
}
<p>Welcome Simpson, Homer</h1>
Map Iteration:
<ul>
{{*user}}
<li>{{key}}: {{value}}</li>
{{/user}}
</ul>
{
"user": {
"First Name": "Homer",
"Last Name": "Simpson"
}
}
<ul>
<li>First Name: Homer</li>
<li>Last Name: Simpson</li>
</ul>
<ol>
{{*items}} {{>item}} {{/items}}
</ol>
<li>{{name}}: {{description}}</li>
{
"items": [
{
"name": "Banana",
"description": "Rich in potassium and naturally sweet."
},
{
"name": "Orange",
"description": "High in Vitamin C and very refreshing."
}
]
}
<ol>
<li>Banana: Rich in potassium and naturally sweet.</li>
<li>Orange: High in Vitamin C and very refreshing.</li>
</ol>
All the examples shown here are tested in CI in the readme_test.v file.
For the full specification, refer to the unit tests and test cases in
the spec directory.
This project is distributed under the MIT License.
Thanks to the original Mustache project for inspiration and the specification.
V
95.5%
HTML
4.5%
V project for supporting whisker, a descendent of the Mustache template language.
39
stars
150
commits
V
primary language
Jun 16, 2024
updated
whisker is inspired by Mustache but is more stable, robust and predictable. It is a fast template engine for V with a simple syntax.
{{...}}.The following blog posts provide more context:
You must have V installed. Refer to the official instructions for help with installation.
If you already have V installed, use v up to update the toolchain and standard
library.
v install hungrybluedev.whisker
This should install the package as the hungrybluedev.whisker module.
To use it, use import hungrybluedev.whisker and proceed as normal.
Run the following to install whisker from GitHub using V's package manager:
v install --git https://github.com/hungrybluedev/whisker
This should install in hungrybluedev.whisker first and then relocate it
to whisker. Now, in your project, you can import whisker and use whisker
right away!
The main struct is whisker.template.Template which can be generated either
directly from template strings or be loaded from disk from template files. A
single template should be reused for different data models to produce outputs
which differ in content but not semantic structure.
Note There might be slight white-space consistencies between the generated and expected results. For machine-verification, it is recommended to compare the parsed and reconstructed outputs for your particular file format.
template.from_strings(input: input_str, partials: partial_map)
to generate a template from direct string inputs. Here, input_str is
a string and partial_map is a map[string]string. The map's keys are the
names of the template that are replaced by the direct template strings. Leave
the partials field empty if there are none required.run(data) to generate the output string. The
data can be represented in V source code directly (refer to the spec for
examples), or it can be loaded from JSON (using
datamodel.from_json(data_string)).This is a copy-paste-able example to get started immediately:
module main
// Imports if you install from GitHub:
import whisker.datamodel
import whisker.template
// Imports if you install from VPM:
import hungrybluedev.whisker.template
import hungrybluedev.whisker.datamodel
fn main() {
simple_template := template.from_strings(input: 'Hello, {{name}}!')!
data := datamodel.from_json('{"name": "World"}')!
println(simple_template.run(data)!) // prints "Hello, World!"
}
template.load_file(input: input_str, partials: partial_map) to
generate a template from file names. The difference here is that instead of
providing content, you provide the relative file paths. The names of the
partials need to be exact though, so keep an eye on that.os.read_file(path_to_json) to read the JSON contents and then plug this
into the datamodel.from_json function.It is not necessary, but it is recommended to use filenames that
contain *.wskr.* somewhere in the file name.
Check json_test.v and html_test.v for
examples with template files.
whisker may also be used as a standalone command-line program to process template files. It does not support direct template string input for the sake of simplicity.
Build whisker with v cmd/whisker and run cmd/whisker/whisker --help for
usage instructions. You can specify a bin subdirectory as output folder and
add it to path as well:
# Create an output directory
mkdir cmd/bin
# Build the executable
v cmd/whisker -o cmd/bin/whisker
# Run the executable
cmd/bin/whisker --help
Check whisker_cli_test.v for a concrete demonstration.
Sample text
Sample text
Hello, {{name}}!
{
"name": "world"
}
Hello, world!
{{=[ ]=}}
module main
fn main() {
println('[greeting]')
}
{
"greeting": "Have a nice day!"
}
module main
fn main() {
println('Have a nice day!')
}
<nav>
<ul>
<li>Home</li>
<li>About</li>
{{-logged_in}}
<li>Log In</li>
{{/logged_in}} {{+logged_in}}
<li>Account: {{user.name}}</li>
{{/logged_in}}
</ul>
</nav>
{
"logged_in": false
}
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Log In</li>
</ul>
</nav>
{
"logged_in": true,
"user": {
"name": "whisker"
}
}
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Account: whisker</li>
</ul>
</nav>
Positive and negative sections also apply to lists and maps. An empty list or map means a negative section and a non-empty one represents a positive section.
List:
{{+vacation}}
<h1>Currently on vacation</h1>
<ul>
{{*.}}
<li>{{.}}</li>
{{/.}}
</ul>
{{/vacation}} {{-vacation}}
<p>Nobody is on vacation currently</p>
{{/vacation}}
{
"vacation": []
}
<p>Nobody is on vacation currently</p>
{
"vacation": ["Homer", "Marge"]
}
<h1>Currently on vacation</h1>
<ul>
<li>Homer</li>
<li>Marge</li>
</ul>
Map:
{{+user}}
<p>Welcome {{last_name}}, {{first_name}}</h1>
{{/user}}
{{-user}}
<p>Create account?</p>
{{/user}}
{
"user": {}
}
<p>Create account?</p>
{
"user": {
"last_name": "Simpson",
"first_name": "Homer"
}
}
<p>Welcome Simpson, Homer</h1>
Map Iteration:
<ul>
{{*user}}
<li>{{key}}: {{value}}</li>
{{/user}}
</ul>
{
"user": {
"First Name": "Homer",
"Last Name": "Simpson"
}
}
<ul>
<li>First Name: Homer</li>
<li>Last Name: Simpson</li>
</ul>
<ol>
{{*items}} {{>item}} {{/items}}
</ol>
<li>{{name}}: {{description}}</li>
{
"items": [
{
"name": "Banana",
"description": "Rich in potassium and naturally sweet."
},
{
"name": "Orange",
"description": "High in Vitamin C and very refreshing."
}
]
}
<ol>
<li>Banana: Rich in potassium and naturally sweet.</li>
<li>Orange: High in Vitamin C and very refreshing.</li>
</ol>
All the examples shown here are tested in CI in the readme_test.v file.
For the full specification, refer to the unit tests and test cases in
the spec directory.
This project is distributed under the MIT License.
Thanks to the original Mustache project for inspiration and the specification.
V
95.5%
HTML
4.5%