Giter Club home page Giter Club logo

eta's Introduction

eta (η)

Documentation - Chat - RunKit Demo - Playground

GitHub package.json version (main) GitHub Actions Status All Contributors Coveralls Donate

You're viewing the source for Eta v3, which we just released! For v2, visit the old branch.

Summary

Eta is a lightweight and blazing fast embedded JS templating engine that works inside Node, Deno, and the browser. It's written in TypeScript and emphasizes great performance, configurability, and small bundle size.

🌟 Features

  • 📦 0 dependencies
  • 💡 Only ~3.5 KB minzipped
  • ⚡️ Written in TypeScript
  • ✨ Deno support (+ Node and browser)
  • 🚀 Super Fast
  • 🔧 Configurable
    • Plugins, custom delimiters, caching
  • 🔨 Powerful
    • Precompilation, partials, async
    • Layout support!
  • 🔥 Reliable
    • Better quotes/comments support
      • ex. <%= someval + "string %>" %> compiles correctly, while it fails with doT or EJS
    • Great error reporting
  • ⚡️ Exports ES Modules as well as UMD
  • 📝 Easy template syntax

Get Started

For more thorough documentation, visit https://eta.js.org

Install Eta

npm install eta

In the root of your project, create templates/simple.eta

Hi <%= it.name %>!

Then, in your JS file:

import { Eta } from "eta";
// import { Eta } from "https://deno.land/x/[email protected]/src/index.ts";

const eta = new Eta({ views: path.join(__dirname, "templates") });

// Render a template

const res = eta.render("./simple", { name: "Ben" });
console.log(res); // Hi Ben!

FAQs

Where did Eta's name come from?

"Eta" means tiny in Esperanto. Plus, it can be used as an acronym for all sorts of cool phrases: "ECMAScript Template Awesomeness", "Embedded Templating Alternative", etc....

Additionally, Eta is a letter of the Greek alphabet (it stands for all sorts of cool things in various mathematical fields, including efficiency) and is three letters long (perfect for a file extension).


Integrations

Visual Studio Code

@shadowtime2000 created eta-vscode.

ESLint

eslint-plugin-eta was created to provide an ESLint processor so you can lint your Eta templates.

Webpack

Currently there is no official Webpack integration but @clshortfuse shared the loader he uses:

{
  loader: 'html-loader',
  options: {
    preprocessor(content, loaderContext) {
      return eta.render(content, {}, { filename: loaderContext.resourcePath });
    },
  },
}
Node-RED

To operate with Eta templates in Node-RED: @ralphwetzel/node-red-contrib-eta

image

Projects using eta

  • Docusaurus v2: open-source documentation framework that uses Eta to generate a SSR build
  • swagger-typescript-api: Open source typescript api codegenerator from Swagger. Uses Eta as codegenerator by templates
  • html-bundler-webpack-plugin: Webpack plugin make easily to bundle HTML pages from templates, source styles and scripts
  • SmartDeno: SmartDeno is an easy to setup web template using Deno & Oak
  • stc: OpenAPI (Swagger) and Apifox documentation converted to api. Use eta templates to generate code.
  • Add yours!

Contributors

Made with ❤ by @nebrelbug and all these wonderful contributors (emoji key):

Ben Gubler
Ben Gubler

💻 💬 📖 ⚠️
Clite Tailor
Clite Tailor

🤔 💻
Ioan CHIRIAC
Ioan CHIRIAC

💻 🤔
Craig Morten
Craig Morten

💻
Rajan Tiwari
Rajan Tiwari

💡
shadowtime2000
shadowtime2000

💻 🤔 ⚠️
Hamza Hamidi
Hamza Hamidi

📖
Calum Knott
Calum Knott

🤔
nhaef
nhaef

💻
Gün
Gün

💻

This project follows the all-contributors specification. Contributions of any kind are welcome!

Credits

  • Async support, file handling, and error formatting were based on code from EJS, which is licensed under the Apache-2.0 license. Code was modified and refactored to some extent.
  • Syntax and some parts of compilation are heavily based off EJS, Nunjucks, and doT.

eta's People

Contributors

allcontributors[bot] avatar benasher44 avatar cmorten avatar dependabot[bot] avatar diegoacs0 avatar gettoarun avatar greenkeeper[bot] avatar guildenstern70 avatar gurgunday avatar hamzahamidi avatar jakubmazanec avatar joshcancode avatar js2me avatar long-woo avatar muan avatar multivoltage avatar nebrelbug avatar nhaef avatar ninanator avatar ralphwetzel avatar shadowtime2000 avatar stdword avatar tobbe avatar trojanh avatar webdiscus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eta's Issues

Complex template not working

Thanks for this lightweight library.
Not sure if this is intended to be used this way, but reporting it anyway for future readers as it's not mentioned in the docs.

Consider the following template

const template = `&lt;ApplicantFirstName&gt;{{it.firstName}}&lt;/ApplicantFirstName&gt;`

When we use the following, it.firstName is replaced by ''

Eta.render(template, { firstName: "ABC" }, { tags: ["{{", "}}"])

output is:

`&lt;ApplicantFirstName&gt;&lt;/ApplicantFirstName&gt;`

Package & Environment Details

  • Environment: Node
  • Version: latest

Browser build in cjs/es format for workers

Is your feature request related to a problem? Please describe.

I'd like to use eta from a CloudFlare worker.

Describe the solution you'd like

It would be really helpful to have a "browser" build, but in cjs/es format. Workers don't have access to fs and path.

Describe alternatives you've considered

Open to suggestions.

Provide full path to current parsing ETA template in process.env

Hello!
Firstly, thanks for this powerful tool!

I use ETA template in https://github.com/acacode/swagger-typescript-api
And currently I have a problem with using custom require() function inside ETA template

__dirname contains path where placed custom required() function
process.cwd() contains path to direction of the called script which use ETA templates

Custom raw implementation of require() function

require = (packageOrPath) => {
    const isPath = _.startsWith(packageOrPath, "./") || _.startsWith(packageOrPath, "../");

    if (isPath) {
      return require(path.resolve(process.cwd(), packageOrPath))
    }

    return require(packageOrPath);
  }

Thanks!

“import”ed Eta’s “config” does not configure.

I can’t configure Eta when importing it. What should I do?

I only imported Eta, but somehow it got require’d as well, creating another unreachable clone of the Eta.config in use.

I clearly imported Eta. Never require’d.

import * as Eta from "eta";
for(const key in Eta.defaultConfig) {
	delete Eta.defaultConfig[key];
}
app.engine("Eta", Eta.renderFile);
app.set("view engine", "Eta");

Setting the Eta.config did not affect the E at all. As if there was another clone of the Eta.config.

Tried removing every source file except for eta.es.js, which should never be used, and got:

Error: Cannot find module 'B:\……\node_modules\eta\dist\eta.cjs'
    at createEsmNotFoundErr (node:internal/modules/cjs/loader:968:15)
    at finalizeEsmResolution (node:internal/modules/cjs/loader:961:15)
    at resolveExports (node:internal/modules/cjs/loader:478:14)
    at Function.Module._findPath (node:internal/modules/cjs/loader:518:31)
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:927:27)
    at Function.Module._load (node:internal/modules/cjs/loader:774:27)
    at Module.require (node:internal/modules/cjs/loader:1013:19)
    at require (node:internal/modules/cjs/helpers:93:18)
    at new View (B:\…\node_modules\express\lib\view.js:81:14)
    at Function.render (B:\…\node_modules\express\lib\application.js:570:12) {
  code: 'MODULE_NOT_FOUND',
  path: 'B:\\……\\node_modules\\eta\\package.json'
}

It turned out Express required it.

https://github.com/expressjs/express/blob/5c4f3e7cc76fed9b42c27cebcdd9d66ef63092f9/lib/view.js#L80-L81

// default engine export
var fn = require(mod).__express

And in this new instance of Eta, you have another Eta.config that is unaffected, unaltered, and in use.

How to make data available on all partials

Hi, thank you for this amazing template engine.

My data is stored in json file

eta.renderFile(file, JSON.parse(fs.readFileSync('src/eta/data.json')))

How to make data available on all partials, so I don't have to pass data every time I includeFile

I can not and do not want to run the script below:
<%~ includeFile('include/_sidebar', JSON.parse(fs.readFileSync('src/eta/data.json'))) %>

using views in data object overwrites template path config

I've been using ETA for a little while now and today suddenly it stopped finding my template files.
After a lot of troubleshooting I noticed my data object was overwriting my default template location.

For example:

I used the following code to set my default location to look for templates
eta.configure({ views: path.join(__dirname, "templates") })

Now when trying to render a template everything is fine.
This works:
eta.renderFile("./pages/example", {example: "example"})

This doesn't:
eta.renderFile("./pages/example", {views: "example"})

It will overwrite the config and result in eta being unable to find the templates.

It might be more specific than this but just be aware of this little issue. It might save you a headache debugging

Official Command Line Tool

Is your feature request related to a problem? Please describe.
There is no official CLI for eta.

Describe the solution you'd like
A CLI preferably written in Typescript using yargs. It should be able to facilitate testing to make sure it is working properly.

Describe alternatives you've considered
Not having a CLI.

Additional context
I could work on this, I just want to see what people think.

Webpack Loader

It would be great to have a Webpack loader for .eta templates. It should have .eta files export the compiled function. Once the initial version with that is completed, we can add support for plugins and configuration for the loader.

Source maps

Is your feature request related to a problem? Please describe.
It would be useful if we could pipe Eta's output into sourcemap-aware tooling to associate things like rendered HTML linting errors with the template source code.

Describe the solution you'd like
I'd like to be able to produce a sourcemap file along with the rendered template string.

Describe alternatives you've considered
Right now I am working on a project that uses EJS, and I need to figure out a way to have transient error mapping.
Alternatives I've considered:

  • Forking EJS
  • Developing an Eta plugin (but plugins don't receive enough metadata)
  • Fork/reimplement Mustache.JS or any other compatible and embeddable platform (Lua, C + WASM), whatever is easier (but then struggle with porting over existing templates)

Additional context

Similar issue for EJS
mde/ejs#123

Async Streaming

Is your feature request related to a problem? Please describe.
No not really.

Describe the solution you'd like
A function, stream?, that creates a stream which can be sent to the browser or destination for faster TTB.

Describe alternatives you've considered
None.

Create linter for Eta templates

We should create a linter for Eta templates, similar to https://github.com/RyanZim/EJS-Lint. This would be very useful for checking the validity of Eta templates -- Eta, like EJS, uses new Function() to generate compiled template functions, and new Function() doesn't throw detailed syntax errors.

EJS-Lint replaces everything outside a scriptlet tag with whitespace (to retain line & column numbers) and then runs the resulting (hopefully) valid JS through node-syntax-error to check for errors.

We probably want to do something similar to this, but use a modified version of Eta's parser to handle multi-line comments and strings correctly.

Ideally the linter would be available as an Eta plugin using the processTemplate hook and as a command-line tool.

Denopack Bundling For Deno Dependencies

Is your feature request related to a problem? Please describe.
No it is not.

Describe the solution you'd like

  1. The exporting of dependencies from file-methods.deno.ts to only export what is actually used in file-utils.ts
  2. Using denopack to bundle file-methods.ts in the deno_dist with tree shaking so you only use what is needed keeping the total size of files loaded low.

Describe alternatives you've considered
deno bundle but that doesn't support tree shaking.

Cannot use Node ESM because `es` version contains `requires` / wrong extension for ES version

Describe the bug

When trying to import a module in a Node ESM file, it crashes. I tried making a hotfix, but it crashed due to another reason.

To Reproduce
Steps to reproduce the behavior:

  1. Create a npm project and index.mjs file
  2. Try to import: import eta from 'eta'
  3. See this:
export { renderFile as __express, compile, compileToString, config, configure, config as defaultConfig, getConfig, loadFile, parse, render, renderFile, templates };
^^^^^^

SyntaxError: Unexpected token 'export'

then I also tried:

  1. Go to node_modules/eta/package.json and append "type": "module"
  2. See this:
file:///home/v1rtl/Coding/tinyhttp/node_modules/.pnpm/[email protected]/node_modules/eta/dist/eta.es.js:586
var fs = require('fs');
         ^

ReferenceError: require is not defined
    at file:///home/v1rtl/Coding/tinyhttp/node_modules/.pnpm/[email protected]/node_modules/eta/dist/eta.es.js:586:10

Expected behavior

It should have been resolved using any of the Node resolution strategies.

Package & Environment Details

  • Environment: Node 14.11, Manjaro Linux x64
  • Version: 1.10.0

Additional context

There are different ways to make this work. The first one is fixing the build to avoid calling require in ES versions of builds and putting "type": "module" in package.json. Another way is to change the extension of es version to .mjs.

Support Deno 1.4.0 Strict Type Import / Export

Describe the bug

Deno 1.4.0 introduced stricter checks on the import and export of types for all users using the --unstable flag. These (presumably) will be integrated with Deno stable in an upcoming release.

This request is to make the necessary changes to support these stricter checks, especially given eta requires the --unstable flag to run and thus is immediately broken by this latest release.

See relevant section in release blog post: https://deno.land/posts/v1.4#stricter-type-checks-in-code--unstablecode

To Reproduce

Create a file called repro.ts with the following contents:

import "https://deno.land/x/[email protected]/mod.ts";

And run deno run --unstable repro.ts.

Note there are several errors:

error: TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { TemplateFunction } from "./compile.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/containers.ts:5:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { TemplateFunction } from "./compile.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/config.ts:7:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { Cacher } from "./storage.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/config.ts:8:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { EtaConfig } from "./config.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/utils.ts:8:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { EtaConfig } from "./config.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/parse.ts:6:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { EtaConfig } from "./config.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/compile-string.ts:5:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { AstObject } from "./parse.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/compile-string.ts:6:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { EtaConfig, PartialConfig } from "./config.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/compile.ts:7:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { CallbackFn } from "./file-handlers.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/compile.ts:8:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { EtaConfig } from "./config.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/file-utils.ts:10:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { EtaConfig, PartialConfig, EtaConfigWithFilename } from "./config.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/file-handlers.ts:12:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { TemplateFunction } from "./compile.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/file-handlers.ts:13:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { EtaConfig } from "./config.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/file-helpers.ts:5:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { EtaConfig, PartialConfig } from "./config.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/render.ts:8:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { TemplateFunction } from "./compile.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/render.ts:9:1

TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { CallbackFn } from "./file-handlers.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/render.ts:10:1

Found 16 errors.

Expected behavior

The import should work without throwing typescript errors relating to type imports and exports.

Screenshots

--

Package & Environment Details

$ deno --version
deno 1.4.0
v8 8.7.75
typescript 4.0.2

Additional context

Encountered attempting to upgrade Opine to Deno 1.4.0

Know The Codebase Contributing

Is your feature request related to a problem? Please describe.
No.

Describe the solution you'd like
A "Know the Codebase" section in the CONTRIBUTING.md

Describe alternatives you've considered
None.

Interpolation of an unset value prints "undefined"

Hello.
While trying to implement value prefilling for my inputs I encountered many "undefined" values for unset variables.

Steps to reproduce:

  1. Go to interactive examples https://eta.js.org/docs/examples/interactive
  2. Change Eta.render('Hi <%= it.name %>', {name: 'Person'}) to Eta.render('Hi <%= it.name %>', {})
  3. Press Run button. Result is "Hi undefined".

It is very inconvenient to use something like <%= it.name || "" %> for each interpolation especially for input prefilling. So I think showing "" instead of "undefined" is more correct.
EJS thinks the same way and renders "Hi " if I modify this example for it.
However if it is intended and there is another way to interpolate undefined values as "" please add it to the documentation.

Looking for a new lead maintainer

Hey everyone, this is @nebrelbug -- the lead maintainer of Eta and its companion project, Squirrelly.

On October 28, 2020, I will leave on a 2-year service opportunity. During that time, I will be unable to work on any of my open-source projects.

Since my date of departure is drawing closer, I've decided it is time to begin looking for a new lead maintainer.

Maintainer Requirements

  • Proficiency in TypeScript
  • Open-source experience. Preferably the maintainer/developer of an open-source JS/TS project with 50+ stars
  • Willing to test changes & not break anything important 😉
  • Willing to follow the Project Goals (see below)

Maintainer Jobs

  • Fix bugs
  • Answer questions

A maintainer could also update documentation, write tutorials, write plugins, write integrations (ex. for Fastify, Eleventy, Koa) etc. In case this sounds overwhelming, remember that Eta is only 2.5KB minzipped 😂

Ideally a maintainer would be willing to maintain Squirrelly as well (they share much of the same codebase) but that's definitely not a requirement.

Project Goals

  • Follow SemVer versioning guidelines
    • This means Eta's public API should remain backwards-compatible (at least within v1.x.x)
  • Remain lightweight
    • Browser build should never exceed 3KB minzipped
  • Remain stable
  • Keep parsing engine
    • Eta's parser has been optimized quite a bit for performance and reliability, and any significant changes run too high a risk of impacting either

Fallback Plan

There's always the possibility I will be unable to find a new lead maintainer before my departure. This is one of the reasons I've accelerated development so much. It's also the reason Eta and Squirrelly are so extensively tested.

I feel confident that Eta is stable enough it could continue to function, if needs be, without maintenance for several years. It has a stable API, is well tested, and has decent documentation. Many features can be added as 3rd-party plugins rather than core parts of the library. Moreover, Eta's small size reduces the likelihood that important bugs exist inside the code.

That scenario, though, would be far from ideal, so I've made several backup plans:

  • Give repository + npm access to a friend I trust to act in my behalf. This friend would not modify Eta's code, but could give access if, while I was gone, someone asked to become a maintainer
  • Add the project to https://www.codeshelter.co/

TL;DR

I'm going to be away for 2 years and unable to maintain Eta.

In case I am unable to find a maintainer before I leave, I will give repository access to a trusted friend and add the repository to https://www.codeshelter.co/ (allowing anyone to apply for maintainership).

If you want to become one of Eta's maintainers and have experience with open-source and TypeScript, message me on Gitter, email me at nebrelbug [at] gmail [dot] com, or contact me some other way!

configuration options

Have been trying to configure the Eta varName config options, but am having issues with it.

Based on the limited docs on config options, I've ended up with the following:

let compiled = Eta.compile(html)
compiled(userOptions, Eta.getConfig({varName: 'user'}))

But I am getting the following error:

ReferenceError: user is not defined

What am I missing?

Documentation is not beginner friendly

I feel the hard stuff was addressed straight away, while very basic info was omitted. What file extension do I use? What file do I link my html or eta file to in the node_modules folder? Not everyone has used EJS before. Besides that documentation (EJS's) is far from explanatory.

I'd prefer a documentation where the user is held by hand. Empathy for a beginner - like me. Thanks in advance.

Additional context
After knowing how to do this, I can assist in documentation writings and more explanations. If I can be allowed. Thanks in advance. I eagerly await a response. I need to get this template done. :)

Sharing ESLint Config

Is your feature request related to a problem? Please describe.
No, not really.

Describe the solution you'd like
The ESLint config to be shared on NPM with a name like eslint-config-eta-dev.

Describe alternatives you've considered
Copy and pasting the config everywhere.

Additional context
The reason I am suggesting this is so it is easy to lint projects relating to this (integrations).

Capture data and send to a partial?

If I had a template 'somepage.html' then I'd like to point to a 'layout' (which is a template itself with header, footer etc that renders out a passed body somewhere) and then pass/inject a body into it. Like how e.g. Jekyll works. Something along the lines of:

<% var body = %>
lots of HTML
<% ; %>
<%~ E.include('layout', {body: body}) %>

Is that possible?

Projects using Eta

There are quite a few projects using Eta, and it would be great to feature some of them.

Notably, Docusaurus 2 uses Eta for SSR generation. I'll see whether I can list them.

Great Error Reporting.

Issue here is that it doesn't have a good error reporting.
It works on my localhost but it doesn't work when deployed and the only thing i see is this error here:


Unexpected token '.'```

I don't know why you call it a great error reporting. 
I have 92 dots in my template...

EJS + EJS-LAYOUTS Replacement?

Is your feature request related to a problem? Please describe.
Hello, I just run into your project and it looks and sounds amazing. But I have a doubt. I am currently using EJS + express-ejs-layouts combined. Can this be just dropped in and it will replace both the things, if yes how? I understand that I'll need to change the syntax a bit as well (adding it and ~ in all the places).

Thanks!

includeFile not working

Describe the bug

includeFile is not working, it just throws ReferenceError: includeFile is not defined.

To Reproduce

Run await eta.Render("<%~ includeFile("./MyFile") %>", {...}); to experience the bug.

Package & Environment Details

  • Environment: Node
  • Version: v15.12.0

Additional context

It looks like it's just not in the default config:

eta/src/config.ts

Lines 111 to 129 in 7102b66

const config: EtaConfig = {
async: false,
autoEscape: true,
autoTrim: [false, 'nl'],
cache: false,
e: XMLEscape,
include: includeHelper,
parse: {
exec: '',
interpolate: '=',
raw: '~'
},
plugins: [],
rmWhitespace: false,
tags: ['<%', '%>'],
templates: templates,
useWith: false,
varName: 'it'
}

Same thing happens when running console.log(E);, it is just not defined.

Question: How to use eta as a templating engine for express?

(This is just a question and not a bug report)

Hello, so i checked the documentation and couldn't find a way to use the eta templating engine for express. So, how to use eta as a templating engine for express? Also, what is the file extension used for the eta templating engine?

v2 Proposal

This is a proposal for a breaking change in Eta. This would pretty much be a restructure of the project, restructured enough that it would be a breaking change. Here is how it would work:

We would basically unify the codebase a little more. We would use ES2015 modules with extensions and URLs for most of our code. We would use a pattern like Yargs, where we have a folder for shims (src/platform-shims/) and we inject those shims into the main code. We would use Rollup to create a Node CJS and ESM which is shimmed with node shims, have an index.mjs which injects browser shims, and a mod.ts which injects Deno shims. We wouldn't need to create a seperate browser.ts and index.ts for server and browser side because instead inside of the browser shim we could just through an Eta error that operations that use fs are unsupported.

This would require some communication with the Deno team about changing the configuration of the project with the output directory and stuff.

In the end this will do two things:

  1. Allow us to fix bugs and stuff with Deno because currently we can't fix bugs and stuff with that because we just use Denoify
  2. More easily support browser ES (Skypack, jspm, etc)

I would love to here the thoughts of users on this!

How to render a template from a file/folder?

Hi, I'm new to eta, and I'm looking at the documentation.

My goal is to render templates in NodeJS from a 'templates' folder that would contain a set of templates, e.g. 'main.html' and 'footer.html'.

I do see something about templates here https://eta.js.org/docs/api/configuration but it is not clear in the docs where to actually pass those config options, and there is also no example on how to render a template from a file.

Could you add that to the docs? Thanks!

Syntactic Sugar : renderAsync

Is your feature request related to a problem? Please describe.
async:true feels a little clunky, when added as an additional parameter for Eta.render()

let result = await Eta.render(
  '<%= it.name %>: <%= await it.asyncFunc() %>',
  { name: 'Ada Lovelace', asyncFunc: asyncFunc },
  { async: true }
)

Describe the solution you'd like
Could we have an additional function Eta.renderAsync()

let result = await Eta.renderAsync(
  '<%= it.name %>: <%= await it.asyncFunc() %>',
  { name: 'Ada Lovelace', asyncFunc: asyncFunc }
)

I think this would improve legibility.

ES6 module support

Please let me import Eta

import Eta from "eta";
       ^^^
SyntaxError: The requested module 'eta' does not provide an export named 'default'

like I do with Node.js built-in modules.

import Crypto from "crypto";

Add Eta support to Hexo

Hexo has support for EJS.

Since Eta is more powerful, faster, and has more reliable parsing than EJS, it would be great to add support for Eta to Hexo.

https://github.com/hexojs/hexo-renderer-ejs is installed by default in new Hexo projects. Since Eta imitates much of the external API of EJS, we should be able to use very similar code (the actual renderer is only 15 lines long). Then we should be able to add support for Eta-specific features, like plugins.

Inject Methods/Object with Plugins

Is your feature request related to a problem? Please describe.
Currently there isn't a nice clean way to inject methods or objects with plugins for usage in the template.

Describe the solution you'd like
Some way to inject methods for usage.

Additional context
Carrying over discussion from Gitter, we could allow modification of prototype (I don't think that works), allowing injecting into this of template, or use some scoping tricks with dynamic closures to handle this (still thinking about it).

Add documentation for webpack

Describe the solution you'd like
Add some sort of documentation somewhere that explains how to integrate with webpack.

Additional context

It works perfectly fine with html-loader if you want to compile to .html (eg: use as HTML preprocessor instead of during runtime). This is what I'm using at the moment:

{
  loader: 'html-loader',
  options: {
    preprocessor(content, loaderContext) {
      return eta.render(content, {}, { filename: loaderContext.resourcePath });
    },
  },
}

This is more to serve as a guidance for others trying to figure out how to integrate with eta.

Cache fallback to file, to behave similar to EJS 'include'

Is your feature request related to a problem? Please describe.

I am coming from EJS and noticed the include functionality doesn't behave in the same way. In ETA it expects to only get templates from the cache, so the cache needs to be pre-populated.

Describe the solution you'd like

The suggestion is to fall back to the includeFile() function and then load the result into the cache. An alternative to providing the code as part of the code base, would be to provide documentation on how the developers using the package could do the same.

Describe alternatives you've considered

Iterating through the views directory and filling the cache myself.

Additional context
Add any other context or screenshots about the feature request here.

How to add a plugin?

I'm just getting started with Eta and struggle to find an example how to plugin a custom function e.g. to add IntlMessageFormat.
Is there some context in Eta or do I have to provide all functions on window level?

VSCode extension for Eta

A common request from Eta users is VSCode syntax highlighting. We should create a VSCode extension with syntax highlighting for Eta templates! (Bonus: include snippets and/or formatting)

Theoretically, we should be able to fork https://github.com/Digitalbrainstem/ejs-grammar. It has about 200K users and seems to have quite a few features.

We could instead try to create a Language Server, which might be more powerful at the possible cost of being more complex to create. Here's one fairly minimal example: https://github.com/ebebbington/drash-markup-language.

Resources

ability to use variables directly without 'it'

Is your feature request related to a problem? Please describe.
I have a fixed set of variables that my users will use in creating their templates. Say, x and y. So, instead of having them to write the template using it.x and it.y, I am wondering if there is a way to directly use x and y as it would be natural to the end users.

Describe the solution you'd like
Perhaps at the time of compiling a template a list of variables can be provided and those will be made available directly as arguments to the compiled function rather than via the it object. At the time of rendering, these will be unpacked and applied to the function perhaps including the existing it which passes all the data as is. So the template function might compile to

function(it,x,y) { ... } instead of function(it) { ... }

Describe alternatives you've considered
At the moment, I am constrained to using it.x and it.y.

Additional context
Using this template engine in a low code environment requires it to be as easy as possible for end users.

Add Eta support to Eleventy

The Eleventy static site generator is growing increasingly popular, and it would be great to add support for the Eta template engine. See this issue in the Eleventy repository for the feature request.

https://github.com/11ty/eleventy-plugin-vue looks like a good example we could get started with. It should theoretically be easy to add Eta support, because Eta implements file handling, partials, layouts, and caching on its own.

Globally async data object and global await feature

Is your feature request related to a problem? Please describe.

No, not really.

Describe the solution you'd like

I'd like to be able to await for all async functions in my data object without having to add the "await" keyword in front of each of them (maybe an option in the config).
In my case, I don't want users to ask themselves "is this function async or not?".

But the biggest benefit of this, and this is the reason of my feature request, is that I would like eta to be able to await for all the Promises of async functions globally (using something like Promise.all()) instead of individually, to speed things up.
Right now, eta is awaiting each async function one by one.
This means that if an async function takes 1 second, another 2 seconds and another 3 seconds, eta will take a total of 6 seconds instead of 3 (maximum possible time among the 3 functions) to render the templates.

Describe alternatives you've considered

Right now I'm using a kinda ugly hack to be able to await all for async functions in my data object: I'm basically adding the "await" keyword in front of every template variable.
It works fine but as I said before, since eta awaits each function one by one, this can be very slow.

let async_content = content.replace(new RegExp("it\.", "g"), "await it\.");
content = await Eta.renderAsync(async_content, context);

Additional context

Ideally, I'd like to be able to have something like this: multiple async functions (d1, d2, d3) in my data object and have eta do something like Promise.all in the background to speed things up.

function delay(ms: number) {
    return new Promise( resolve => setTimeout(resolve, ms) );
};

let d1 = delay(1000);
let d2 = delay(2000);
let d3 = delay(3000)

Promise.all([d1, d2, d3]).then((values) => {
    console.log("FINISHED !");
});

Among the popular templating js engines I tested (nunjucks, ejs, handlebars, ...), eta is probably the best templating engine to deal with async functions in the data object (kudos for that!).
Adding this feature would really make async functions a breeze to use.

Thanks for this excellent tool.

Ability to provide a custom function to fetch templates given their path

Is your feature request related to a problem? Please describe.
In Deno, I want Eta to use Leaf.readTextFileSync instead of Deno.readTextFileSync for reading templates referenced by path. Leaf is a library for Deno which creates a kind of virtual filesystem in which files like Eta templates can be bundled and therefore included in compiled executables.

Describe the solution you'd like
To provide a custom function in config to read text files: { readFile: (path: string) => Promise<string> | string }. This would allow (path) => Leaf.readTextFileSync(path), but could also be useful with (path) => fetch(path).then(r => r.text()).

Describe alternatives you've considered
Forego using paths and use Eta.templates.define() on every template in advance, then only reference templates by their defined names.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.