squirrellyjs / squirrelly

Semi-embedded JS template engine that supports helpers, filters, partials, and template inheritance. 4KB minzipped, written in TypeScript ⛺

Home Page:https://squirrelly.js.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Squirrelly version 8: layouts, plugins, new parser, and new language features

nebrelbug opened this issue · comments

Squirrelly version 8 is underway!

Feel free to comment with suggestions or requests!

Syntax and Code Changes

  • Bundling with Rollup instead of Webpack
    • I've been experimenting with this, and right now squirrelly.runtime.js is down to 995 Bytes, without being gzipped!
    • In addition, I'll add a Babel transpiler to make sure everything is compatible.
  • runtime.js will have a separate entry point (with Rollup) so it will be compiled better
  • All files that deal with file-handling will be in a separate file not imported by runtime.js, so it will be even smaller.
  • Helpers will be prefixed with ~, so {{~if(options.stuff}}
  • 'Interpolate syntax': {{=4+3}}
  • Native Code: what was previously {{js(var x = 0)/}} will become: {{!var x = 0}}

New Features

  • Support for layouts!
  • Caching for partials and layouts
  • Options for developers like cache refreshing
  • Brand new parser that works without RegExp to create a more performant, reliable, and maintainable experience
  • Saving the cache and loading it later
  • Saving all Helpers, nativeHelpers, Filters, Partials, and Layouts and loading them later
    • The two features above mean that developers will be able to create libraries of helpers, partials, nativeHelpers, and layouts that can be loaded!
  • Support for middleware.
    • This means that you'll be able to use middleware that, for example, minifies HTML before compiling it, or minifies the template function before saving it.
    • Middleware could also be used to write custom language features.
  • 'Template Tree' exposure, allowing middleware to transform syntax before a template is compiled into a function

File Stuff

  • You will be able to register an entire directory of partials/layouts with one command, loadPartialsDir or loadLayoutsDir

I'm also considering writing packages that will allow Squirrelly to work with:

  • Fastify
  • Koa
  • Metalsmith

And more!

Having the option to hide "undefined" for variable might be a good idea. Maybe production vs debug setting?

  • Saving the cache and loading it later

As in session / local storage caching? That is what i currently do with templates. I found keeping them in the session storage, is a good balance between keeping "up to date" and being able to update on changes.

Another technique i have experimented with, is including in the local scope by adding the templates into a local div ( in the main document ). It works but its "tricky". And more prone to conflicts.

  • The two features above mean that developers will be able to create libraries of helpers, partials, nativeHelpers, and layouts that can be loaded!

As in single request or multi http requests?

I'm also considering writing packages that will allow Squirrelly to work with:

General tip: KISS ...

A few more tips:

On the website: Overview > options.somevalue ... Add on the top a real example of data. This allows people to see the flow of the code and not pseudo code.

PS:

https://github.com/nebrelbug/squirrelly-benchmarks
https://github.com/marko-js/templating-benchmarks

I think your benchmarks may be out of date?

Yours...
squirrelly » 9,756 op/s (fastest)
marko » 2,335 op/s (76.07% slower)
dust » 745 op/s (92.36% slower)

Marko
marko » 4,780 op/s (fastest)
dust » 868 op/s (81.84% slower)

Notice how Marko has almost double to performance on the Friends. Or how if-expression Marko was slower then Pug but in the new tests Makro is way faster. If these results hold, the gap between Marko and squirrelly is smaller then the old results?

@Indribell thanks for the feedback!

Having the option to hide "undefined" for variable might be a good idea. Maybe production vs debug setting?

Maybe we should add a production flag that would add hiding undefined to the default filter.

As in session / local storage caching?

Right now, I think I'll just add a way to export as a JS/JSON object. That way, you could save it in a separate file, in local or session storage, etc., and then load it when needed.

General tip: KISS ...

Always a good thing to keep in mind 😄. I should have clarified, I'm going to build separate packages that rely on Squirrelly for those cases, probably called squirrelly-koa and so on, and then publish them separately on NPM. That way, it doesn't complicate the source code.

As in single request or multi http requests?

One request will load the entire library, including helpers, partials, native helpers, layouts, filters, etc., that will be stored in a JS object or JSON file.

I think your benchmarks may be out of date?

Actually, my branch is based on the very newest version of the benchmarks. I think they have different results because the times are based on the local computer. Whoever owns the markojs repository probably has a nicer computer than me 😉
In all of my tests, though there was some variation in the times, Squirrelly came out either as the fastest or almost the fastest, so I think the tests still show that Squirrelly is faster.

On the website: Overview > options.somevalue ... Add on the top a real example of data. This allows people to see the flow of the code and not pseudo code.

I'm trying to add working Runkit examples to the docs, but the styling is broken. Hopefully I'll get this working soon 😃

Version 8 Update

Don't worry if you haven't seen any recent development on GitHub--right now, I'm working on my local computer.

After a lot of thought, I'm currently handwriting a parser that I think will make Squirrelly more reliable and functional.

The basic template syntax will probably stay the same, except helpers will be prefixed with ~ (so {{~if(options.something)}} instead of {{if(options.something)}}, and the compile function will probably return a string (which will be turned into a function by the Render() function) rather than a function.

@nebrelbug When are you planning to release version 8?

@raydenx I just finished the new parser (probably the most difficult part) and I've tested out Rollup. Currently, the main thing I need to do is add aysnc support to templates, and I'm hoping I'll have that done by mid-July, and a full release by the end of July.

commented

@nebrelbug this is really great work!

Thanks @4hm3d! Let me know if you have any suggestions!

When is v8 coming out?

Hi @michaelguild13! I'm shooting for a release by the end of 2019.

So its out ;)
I wonder how to do layouts with it? Coming from Jekyll layouts are very helpful.

Hi @pke! It's not officially released yet, I just finally got a basic working version. As far as layouts, here's how to do them with the current version: https://stackblitz.com/edit/squirrelly-layouts

And here's what they will probably look like in the next version (example modified from Nunjucks docs):

layout.sqrl

{{~block("header")}}
<h1>This is the default header</h1>
{{/block}}

<section class="left">
  {{~block("left")}}{{/block}}
</section>

<main>
{{~block("content")}}{{/block}}
</main>

<section class="right">
  {{~block("right")}}
  This is more content
  {{/block}}
</section>

template.sqrl

{~extends("layout.sqrl")}}
Squirrelly is a super awesome template engine
{{# left}}
This is the left side!
{{# right}}
This is the right side!
{{/extends}}

Rendering template.sqrl would output:

<h1>This is the default header</h1>

<section class="left">
  This is the left side!
</section>

<main>
Squirrelly is a super awesome template engine
</main>

<section class="right">
  This is the right side!
</section>

This is only one possible syntax, though, based on Nunjuck's model. Squirrelly is designed so that you could easily design your own layout model.

JUST PUBLISHED SQUIRRELLY 8 BETA!