You are not logged in.
Pages: 1
Part of our mORMot framework, we implemented an optimized Mustache template engine in the SynMustache unit:
- It is the first Delphi implementation of Mustache;
- It has a separate parser and renderer (so you can compile your templates ahead of time);
- The parser features a shared cache of compiled templates;
- It passes all official Mustache specification tests, as defined at http://github.com/mustache/spec - including all weird whitespace process;
- External partials can be supplied as TSynMustachePartials dictionaries;
- {{.}}, {{-index}} and {{"some text}} pseudo-variables were added to the standard Mustache syntax;
- {{#-first}}, {{#-last}} and {{#-odd}} pseudo-sections were added to the standard Mustache syntax;
- Internal partials can be defined via <partial - also a nice addition to the standard Mustache syntax;
- It allows the data context to be supplied as JSON or our TDocVariant custom type;
- Almost no memory allocation is performed during the rendering;
- It is natively UTF-8, from the ground up, with optimized conversion of any string data;
- Performance has been tuned and grounded in SynCommons's optimized code;
- Each parsed template is thread-safe and re-entrant;
- It follows the Open/Close principle so that any aspect of the process can be customized and extended (e.g. for any kind of data context);
- It is perfectly integrated with the other bricks of our mORMot framework, ready to implement dynamic web sites with true 10 design, and full separation of concerns in the views written in Mustache, the controllers being e.g. interface-based services;
- API is flexible and easy to use.
This is the forum thread for a series of blog articles.
See http://blog.synopse.info/post/2014/04/2 … phi-part-1
Online
great job ab! Maybe get this Delphi wrapper listed here: http://mustache.github.io/
Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.
Offline
This looks amazing! I'll start replacing some of our (sometimes awful) DIY template implementation with this as standard. I will update with any issues. Thanks
Offline
@berndvf
Thanks for the feedback!
@edwinsn
Our SynMustache is already listed to the official page http://mustache.github.io/
Online
@edwinsn
Our SynMustache is already listed to the official page http://mustache.github.io/
Great! And I wish start to love github - although on my computer I only do git-clones, github's web interface is really helpful for people checking out the source without using any version controlling systems.
Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.
Offline
ab, actually, maybe you should also create separate repository for other detach-able bits of in the synopses library, such as the BSON implementation, the mongodb client library, the standalone http servers, etc. Nowadays single-purpose libraries is a trend - just check the node.js/python libraries, and I always liked it.
Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.
Offline
... yes, but all will use SynCommons.pas, SynLZ.pas and Synopse.inc...
All is available within mORMot source code repository, but the units are decoupled.
Several web sites may help, but only for marketing purpose, IMHO.
Online
ab, it's good to see you took this step!
Well, in a perfect world, we'll have small, standalone but interface-able libraries, like how node.js mange its modules.
In a perfect world, we'll have:
1 - SynpseFundamentals, which includes SynCommons.pas, Synnopse.inc, etc.
2 - SynpseSpiderMonkeyWrapper...
3 - SynpseMongoDbClient...
4 - SynpseHttpClient...
5 - SynpseHttpServer...
6 - SynpseORM...
And so on...
So it's not only good for marketing, but also good for managing the dependency, good for people who only want to use parts of the framework.
We all know the JVCL framework, which was heading to another direction over ten years ago. I saw people want to use some of it's components, but were afraid of it's huge size.
... yes, but all will use SynCommons.pas, SynLZ.pas and Synopse.inc...
All is available within mORMot source code repository, but the units are decoupled.
Several web sites may help, but only for marketing purpose, IMHO.
Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.
Offline
Isn't it already almost like that?
Most units are already uncoupled.
The only coupling is about SynCommons.pas, Synnopse.inc, etc...
Each unit, in fact, is most of the time stand-alone, or has clear dependencies.
For instance, you would never link any UI unit when you write a mORMot server.
Thanks to Delphi smart-linking (i.e. it puts only what is used in the exe), having huge units is not a problem.
On the contrary, it tends to make compilation faster, and use less resources (when compared to a lot of small units).
For a framework, I think it does make sense to have huge general-purpose units (as the VCL/RTL do).
Online
Arnaud, yes, the Synopse framework is very well organized already!
And I didn't describe that 'perfect world' well. Simply put it, in a perfect world, we'll have a dependency/package manager like Maven for Java (http://stackoverflow.com/a/3589974), and all Delphi libs are comply with it... Well, just a dream
Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.
Offline
A package manager is what https://www.meteor.com/ or http://rubyonrails.org/ offer.
But if our server is compiled, those dependencies become in fact simply Delphi units.
The Delphi compiler is your package manager...
Online
in my templates I want to generate interfaces and thus need to provided GUIDs. I'd like my generator program to automatically create these GUIDs.
i.e. my template should be
Ixx1 = interface
['{{GUID}}']
end;
Ixx2 = interface
['{{GUID}}']
end;
and the output e.g.
Ixx1 = interface
['{46DBA8EB-E9E3-4811-A2AF-B07895981A85}']
end;
Ixx2 = interface
['{C9CB4B0A-EC28-49E8-9CC6-B549B3CCB354}']
end;
What is be the best way to do this?
i.e. I think as a last resort, I could misuse the Internationalization feature..
Offline
Just define a custom expression helper.
See http://synopse.info/files/html/Synopse% … #TITLE_431
Online
Hello, I have a question on how to iterate objects instead of array. I used to have Mustache friendly JSON context, example:
{
"reviews": [
{
"user_id": 1,
"user_name": "u1",
"product_id": 1,
"product_name": "p1",
"content": "c1",
"rating": 1,
"stars": "★☆☆☆☆",
"approved": true,
"is_new": true
},
{
"user_id": 1,
"user_name": "u1",
"product_id": 2,
"product_name": "p2",
"content": "c2",
"rating": 4,
"stars": "★★★★☆",
"approved": true,
"is_new": false
},
{
"user_id": 2,
"user_name": "u2",
"product_id": 1,
"product_name": "p1",
"content": "c3",
"rating": 3,
"stars": "★★★☆☆",
"approved": false,
"is_new": false
}
],
}
However, that turns out to be difficult to be used as API response as well based on the service consumer feedback, so I change it to:
{
"result": {
"1": {
"product_name": "p1",
"reviews": {
"1": {
"user_name": "u1",
"content": "c1",
"rating": 1,
"stars": "★☆☆☆☆",
"approved": true,
"is_new": true
},
"2": {
"user_name": "u2",
"content": "c2",
"rating": 3,
"stars": "★★★☆☆",
"approved": false,
"is_new": false
}
}
},
"2": {
"product_name": "p2",
"reviews": {
"1": {
"user_name": "u1",
"content": "c3",
"rating": 4,
"stars": "★★★★☆",
"approved": true,
"is_new": false
}
}
}
}
}
Essentially turning the ids into object key instead of part of an object inside an array. However, not I have problem implementing the front end because I can't (or don't know how to) iterate the objects like arrays. Is it possible to do that or is there any alternative way?
Offline
Pages: 1