Load string as views than from file system
eGust opened this issue · comments
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.
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]);
});
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.
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.