Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
### 3.2.0

* Support for "template inheritance" (partials with parameters)
`{{<foo}} {{$param1}}...{{/param1}} {{$param2}}...{{/param2}} {{/foo}`
following the widely-implemented semi-official specification
https://github.com/mustache/spec/pull/75
(@gasche, 58)
* Partials are now supported in the `mustache` command-line tool (@gasche, #57)
They are interpreted as template inclusion: "{{>foo/bar}}" will include
"foo/bar.mustache", relative to the current working directory.
Expand Down
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,18 @@ let rendered =
exit 2
```

Spec compliance
-----------
Supported template language
---------------------------

ocaml-mustache accepts the whole Mustache template language, except:
- it does not support setting delimiter tags to something else than '{{' and '}}'.
- it does not support lambdas inside the provided data

ocaml-mustache complies¹ to the latest [mustache specification](https://github.com/mustache/spec/tree/v1.1.3), and is automatically tested against it.
It is automatically tested against the latest
[mustache specification testsuite](https://github.com/mustache/spec/tree/v1.1.3).

¹: except for lambdas and set delimiters tags.
ocaml-mustache also supports template inheritance / partials with parameters,
tested against the [semi-official specification](https://github.com/mustache/spec/pull/75).

Todo/Wish List
-----------
Expand Down
59 changes: 58 additions & 1 deletion bin/mustache_cli.ml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,19 @@ let manpage = Cmdliner.[
(leftmost $(b,-I) option) has precedence, and the current working directory has precedence
over include directories.";

`S "TEMPLATE INHERITANCE / PARTIALS WITH PARAMETERS";

`P "$(i,ocaml-mustache) supports a common extension to the original Mustache specification,
called 'template inheritance' or 'parent partials', or here 'partials with parameters'.
In addition to usual partials '{{>foo}}', which include a partial template, one can use
the syntax '{{<bar}} {{\\$param1}}...{{/param1}} {{\\$param2}}...{{/param2}} {{/bar}}' to
pass parameters to the included partial template. Inside this included template, parameters
are used as '{{\\$param}}...{{/param}}', with the inner content being used by default
if this parameter was not specified by the caller.";

`P "This is typically used to define page layouts that are wrapped 'around' the current template.
See our EXAMPLES.";

`S Manpage.s_examples;
`Pre {|
## Simple usage.
Expand All @@ -172,7 +185,7 @@ Mustache is:
- fun


## Using a partial to include a subpage; see $(b,PARTIALS).
## Including a subpage; see $(b,PARTIALS).

\$ cat page.mustache
<html>
Expand All @@ -189,6 +202,47 @@ Mustache is:
- simple
- fun
</body>
</html>


## Including a layount around a page; see $(b,PARTIALS WITH PARAMETERS).

\$ cat new-post.json
{
"title": "New Post",
"authors": "Foo and Bar",
"date": "today",
"content": "Shiny new content."
}

\$ cat post.mustache
{{<post-layout}}
{{\$page-title}}Post: {{title}}{{/page-title}}
{{\$content}}
<h1>{{title}}</h1>
<p>{{content}}</p>
{{/content}}
{{/post-layout}}

\$ cat post-layout.mustache
<html>
<head>
<title>{{\$page-title}}Default Title{{/page-title}}</title>
</head>
<body>
{{\$content}}{{/content}}
</body>
</html>

\$ $(tname) new-post.json post.mustache
<html>
<head>
<title>Post: New Post</title>
</head>
<body>
<h1>New Post</h1>
<p>Shiny new content.</p>
</body>
</html>|};

`S "CONFORMING TO";
Expand All @@ -200,6 +254,9 @@ Mustache is:
`I ("Mustache specification testsuite",
"https://github.com/mustache/spec");

`I ("Semi-official specification of PARTIALS WITH PARAMETERS",
"https://github.com/mustache/spec/pull/75");

`S "REPORTING BUGS";
`P "Report bugs on https://github.com/rgrinberg/ocaml-mustache/issues";
]
Expand Down
21 changes: 18 additions & 3 deletions bin/test/errors/parsing-errors.t
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Delimiter problems:
$ PROBLEM=eof-before-section-end.mustache
$ echo "{{#foo}} {{.}} {{/" > $PROBLEM
$ mustache foo.json $PROBLEM
File "eof-before-section-end.mustache", line 2, character 0: ident expected.
File "eof-before-section-end.mustache", line 2, character 0: '}}' expected.
[3]

$ PROBLEM=eof-before-inverted-section.mustache
Expand Down Expand Up @@ -84,7 +84,7 @@ Mismatch between section-start and section-end:
$ echo "{{#foo}} {{.}} {{/bar}}" > $PROBLEM
$ mustache foo.json $PROBLEM
File "foo-bar.mustache", line 1, characters 0-23:
Section mismatch: {{#foo}} is closed by {{/bar}}.
Open/close tag mismatch: {{# foo }} is closed by {{/ bar }}.
[3]

$ PROBLEM=foo-not-closed.mustache
Expand All @@ -97,9 +97,24 @@ Mismatch between section-start and section-end:
$ echo "{{#bar}} {{#foo}} {{.}} {{/bar}} {{/foo}}" > $PROBLEM
$ mustache foo.json $PROBLEM
File "wrong-nesting.mustache", line 1, characters 9-32:
Section mismatch: {{#foo}} is closed by {{/bar}}.
Open/close tag mismatch: {{# foo }} is closed by {{/ bar }}.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this style not apply to variables? E.g. {{$ foo }}..{{/ foo}}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does, I just added test cases for {{$foo}} and {{<foo}}. Feel free to recommend improvements to the wording.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, what I meant was that pp_partial_param isn't consistent with this printing style. It's still printing {{$foo}} instead of {{$ foo }}.

[3]

$ PROBLEM=wrong-nesting-variable.mustache
$ echo '{{#bar}} {{$foo}} {{.}} {{/bar}} {{/foo}}' > $PROBLEM
$ mustache foo.json $PROBLEM
File "wrong-nesting-variable.mustache", line 1, characters 9-32:
Open/close tag mismatch: {{$ foo }} is closed by {{/ bar }}.
[3]

$ PROBLEM=wrong-nesting-partial.mustache
$ echo "{{#foo}} {{<foo-bar}} {{/foo}} {{/foo-bar}}" > $PROBLEM
$ mustache foo.json $PROBLEM
File "wrong-nesting-partial.mustache", line 1, characters 9-30:
Open/close tag mismatch: {{< foo-bar }} is closed by {{/ foo }}.
[3]



Weird cases that may confuse our lexer or parser:

Expand Down
6 changes: 6 additions & 0 deletions bin/test/inheritance.t/base.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<html>
{{$header}}{{/header}}
<body>
{{$content}}{{/content}}
</body>
</html>
3 changes: 3 additions & 0 deletions bin/test/inheritance.t/header.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<head>
<title>{{$title}}Default title{{/title}}</title>
</head>
10 changes: 10 additions & 0 deletions bin/test/inheritance.t/mypage.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{{<base}}
{{$header}}
{{<header}}
{{$title}}My page title{{/title}}
{{/header}}
{{/header}}
{{$content}}
<h1>Hello world</h1>
{{/content}}
{{/base}}
31 changes: 31 additions & 0 deletions bin/test/inheritance.t/run.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
$ echo "{}" > data.json

This test is the reference example from the template-inheritance specification:
https://github.com/mustache/spec/pull/75

$ mustache data.json mypage.mustache
<html>
<head>
<title>My page title</title>
</head>
<body>
<h1>Hello world</h1>
</body>
</html>


We also test the indentation of parameter blocks.

$ mustache data.json test-indent-more.mustache
<p>
The test below should be indented in the same way as this line.
This text is not indented in the source,
it should be indented naturally in the output.
</p>

$ mustache data.json test-indent-less.mustache
<p>
The test below should be indented in the same way as this line.
This text is very indented in the source,
it should be indented naturally in the output.
</p>
6 changes: 6 additions & 0 deletions bin/test/inheritance.t/test-indent-less.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{{<test-indentation}}
{{$indented-block}}
This text is very indented in the source,
it should be indented naturally in the output.
{{/indented-block}}
{{/test-indentation}}
6 changes: 6 additions & 0 deletions bin/test/inheritance.t/test-indent-more.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{{<test-indentation}}
{{$indented-block}}
This text is not indented in the source,
it should be indented naturally in the output.
{{/indented-block}}
{{/test-indentation}}
4 changes: 4 additions & 0 deletions bin/test/inheritance.t/test-indentation.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<p>
The test below should be indented in the same way as this line.
{{$indented-block}}{{/indented-block}}
</p>
2 changes: 2 additions & 0 deletions bin/test/manpage-examples.t/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{ "name": "OCaml",
"qualities": [{"name": "simple"}, {"name": "fun"}] }
5 changes: 5 additions & 0 deletions bin/test/manpage-examples.t/hello.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Hello {{name}}!
Mustache is:
{{#qualities}}
- {{name}}
{{/qualities}}
4 changes: 4 additions & 0 deletions bin/test/manpage-examples.t/new-post.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"title": "New Post",
"content": "Shiny new content."
}
8 changes: 8 additions & 0 deletions bin/test/manpage-examples.t/page-layout.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<html>
<head>
<title>{{$page-title}}Default Title{{/page-title}}</title>
</head>
<body>
{{$content}}{{/content}}
</body>
</html>
5 changes: 5 additions & 0 deletions bin/test/manpage-examples.t/page.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
{{>hello}}
</body>
</html>
7 changes: 7 additions & 0 deletions bin/test/manpage-examples.t/post.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{{<page-layout}}
{{$page-title}}Post: {{title}}{{/page-title}}
{{$content}}
<h1>{{title}}</h1>
<p>{{content}}</p>
{{/content}}
{{/page-layout}}
77 changes: 77 additions & 0 deletions bin/test/manpage-examples.t/run.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
Simple usage:

$ cat data.json
{ "name": "OCaml",
"qualities": [{"name": "simple"}, {"name": "fun"}] }

$ cat hello.mustache
Hello {{name}}!
Mustache is:
{{#qualities}}
- {{name}}
{{/qualities}}

$ mustache data.json hello.mustache
Hello OCaml!
Mustache is:
- simple
- fun


Using a partial to include a subpage:

$ cat page.mustache
<html>
<body>
{{>hello}}
</body>
</html>

$ mustache data.json page.mustache
<html>
<body>
Hello OCaml!
Mustache is:
- simple
- fun
</body>
</html>


Using a partial with parameters to include a layout around a page:

$ cat new-post.json
{
"title": "New Post",
"content": "Shiny new content."
}

$ cat post.mustache
{{<page-layout}}
{{$page-title}}Post: {{title}}{{/page-title}}
{{$content}}
<h1>{{title}}</h1>
<p>{{content}}</p>
{{/content}}
{{/page-layout}}

$ cat page-layout.mustache
<html>
<head>
<title>{{$page-title}}Default Title{{/page-title}}</title>
</head>
<body>
{{$content}}{{/content}}
</body>
</html>

$ mustache new-post.json post.mustache
<html>
<head>
<title>Post: New Post</title>
</head>
<body>
<h1>New Post</h1>
<p>Shiny new content.</p>
</body>
</html>
2 changes: 1 addition & 1 deletion dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ Contains the `mustache` command line utility for driving logic-less templates.
(ezjsonm :with-test)
(menhir (>= 20180703))
(cmdliner (>= 1.0.4))
(ocaml (>= 4.06))))
(ocaml (>= 4.08))))
Loading