eta-dev / eta

Embedded JS template engine for Node, Deno, and the browser. Lighweight, fast, and pluggable. Written in TypeScript

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

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Load string as views than from file system

eGust opened this issue · comments

commented

Is your feature request related to a problem? Please describe.
In 2.x it was ok to load ETA files as string, then I compile the string as views and render them later. With this approach I could compile the whole project into a single JS file. My code looks like this:

// eta.d.ts
declare module '*.eta' {
  const text: string;
  export default text;
}
import { compile, render } from 'eta';

import './eta.d';
import fooTemplate from './foo.eta';

const compiledFoo = compile(fooTemplate);

console.log(render(compiledFoo, { bar: 42 }, { autoEscape: false, autoTrim: false, rmWhitespace: false }));
esbuild src/main.ts --bundle --loader:.eta=text --outfile=dist/main.js

Now the dist/main.js is just a single file to deploy.

Describe the solution you'd like
Keep the same API or provide an easy way to compile/render string as template, rather than have to load files from file system.

Describe alternatives you've considered
Please keep the same API or update the docs how to do it in 3.x.

Additional context
Can you please be more carefully when you want to break the API? I appreciate your work as open-source lib. However I'm sort of regret now. I should have chosen a big lib that the maintainers dare to break their API.

@eGust you can still do the same thing. Here's some example code.

import { Eta } from "eta"
import "./eta.d"
import fooTemplate from "./foo.eta"

const eta = new Eta({ autoEscape: false, autoTrim: false, rmWhitespace: false })

const compiledFoo = eta.compile(fooTemplate)

console.log(eta.render(compiledFoo, { bar: 42 }))

Eta follows semantic versioning, which is common practice. I only changed the API in a new major release.

commented

@nebrelbug

How to achieve this functionality in v3?

import type { EtaConfig } from 'eta/dist/types/config.d';
import {
  compile,
  getConfig,
  render,
  templates,
} from 'eta';

const etaXmlConfig: EtaConfig = getConfig({
    autoEscape: true,
    autoTrim: false,
    filepathCache: false,
    rmWhitespace: false,
    templates,
  });

const compiledTemplates: Record<string, ReturnType<typeof compile>> = {};

// I can use `<%~ E.include('my-partial-view-key', { ... }) %>` in my views later
partialViewKeys.forEach((key) => {
  templates.define(key, compiledTemplates[key]);
});
commented

With

eta.loadTemplate(key, compiledTemplates[key]);

It raises

undefined:17
__eta.res+=E.include('foo', { table: it.table, context: it.context })
           ^

ReferenceError: E is not defined
    at Eta.eval (eval at compile (file://xxx/node_modules/.pnpm/eta@3.0.1/node_modules/eta/src/compile.ts:29:12), <anonymous>:17:12)

Without E it raises

file://xxx/node_modules/.pnpm/eta@3.0.1/node_modules/eta/dist/eta.module.mjs:578
    throw new EtaError("Views directory is not defined");
          ^

EtaError [Eta Error]: Views directory is not defined
    at Eta.resolvePath (file:///xxx/node_modules/.pnpm/eta@3.0.1/node_modules/eta/src/file-handling.ts:39:11)

Has this functionality removed?

@eGust will you provide me with a more concrete example?

I think the problem is in your templates themselves. With eta@3, you just write <%~ include("template-name") %> rather than E.include.

You should name all of your templates that aren't on the filesystem with an "@" at the beginning, e.g. <%~ include("@my-partial") %>. Otherwise, Eta will assume it's a filepath and attempt to resolve it from the filesystem.

commented

Managed to get it work with prefixed partial name
https://stackblitz.com/edit/stackblitz-starters-ohl9zk

I just checked the docs again. Nowhere in v3 mentioned with loadTemplate nor @ for partial views. In v2 the example did not show I should name it with @ https://eta.js.org/docs/2.x.x/api/templates-partials

@eGust this behavior was only implemented in v3. I'll update the docs to make it more clear.