@memberjunction/templates 6.2.0-edge.4 → 6.2.0-edge.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -1
- package/dist/NunjucksSandbox.js +39 -14
- package/dist/NunjucksSandbox.js.map +1 -1
- package/dist/TemplateEngine.d.ts +53 -10
- package/dist/TemplateEngine.d.ts.map +1 -1
- package/dist/TemplateEngine.js +142 -27
- package/dist/TemplateEngine.js.map +1 -1
- package/dist/TemplateRenderUser.d.ts +8 -0
- package/dist/TemplateRenderUser.d.ts.map +1 -0
- package/dist/TemplateRenderUser.js +15 -0
- package/dist/TemplateRenderUser.js.map +1 -0
- package/dist/TemplateVariableAnalysis.d.ts +27 -0
- package/dist/TemplateVariableAnalysis.d.ts.map +1 -0
- package/dist/TemplateVariableAnalysis.js +140 -0
- package/dist/TemplateVariableAnalysis.js.map +1 -0
- package/dist/extensions/AIPrompt.extension.d.ts +15 -0
- package/dist/extensions/AIPrompt.extension.d.ts.map +1 -1
- package/dist/extensions/AIPrompt.extension.js +100 -70
- package/dist/extensions/AIPrompt.extension.js.map +1 -1
- package/dist/extensions/TemplateEmbed.extension.d.ts +13 -1
- package/dist/extensions/TemplateEmbed.extension.d.ts.map +1 -1
- package/dist/extensions/TemplateEmbed.extension.js +16 -8
- package/dist/extensions/TemplateEmbed.extension.js.map +1 -1
- package/dist/extensions/TemplateExtensionBase.d.ts +12 -1
- package/dist/extensions/TemplateExtensionBase.d.ts.map +1 -1
- package/dist/extensions/TemplateExtensionBase.js +13 -1
- package/dist/extensions/TemplateExtensionBase.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/operations/TemplateRunOperation.d.ts.map +1 -1
- package/dist/operations/TemplateRunOperation.js +1 -1
- package/dist/operations/TemplateRunOperation.js.map +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -85,6 +85,10 @@ if (result.Success) {
|
|
|
85
85
|
}
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
+
Stored templates are HTML-escaped by default. For plain text a model reads (AI prompt templates), pass
|
|
89
|
+
`{ autoescape: false }` as the sixth argument: `Affineur & Owner` then stays `Affineur & Owner`. The raw render keeps
|
|
90
|
+
the registered extensions, and a `{% template %}` embed inside it renders raw too.
|
|
91
|
+
|
|
88
92
|
### Simple Template Rendering
|
|
89
93
|
|
|
90
94
|
For ad-hoc templates not stored in the database:
|
|
@@ -109,6 +113,23 @@ const subject = await engine.RenderTemplateSimple(
|
|
|
109
113
|
// subject.Output: "Acme & Co — your invite" (no entity encoding)
|
|
110
114
|
```
|
|
111
115
|
|
|
116
|
+
### Variables a Template Reads
|
|
117
|
+
|
|
118
|
+
`GetReferencedVariables()` parses a template's text and returns the top-level variable names it reads:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
const result = engine.GetReferencedVariables('{% for r in rows %}{{ r.name }}{% endfor %}{{ user.email }}');
|
|
122
|
+
// result.Names: rows, r, user
|
|
123
|
+
// result.Complete: true
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- `Names` holds top-level names only: `{{ user.email }}` gives `user`. It also holds loop, `set`, filter and keyword-argument names, so treat it as a superset of the data keys the template reads.
|
|
127
|
+
- The analysis follows stored templates named by a string literal in `{% include %}`, `{% import %}`, `{% from %}`, `{% extends %}` and `{% template %}`, and reads every content of each one. It does not follow a template named by an expression.
|
|
128
|
+
- Of the custom tags, the analysis follows `{% template %}` and reads the arguments and body of `{% AIPrompt %}`. A tag from any other extension makes the result incomplete, because the extension's code can read data that the template text does not show.
|
|
129
|
+
- `Complete: false` means "unknown", not "none". `Reason` tells why: a template is named by an expression, a named template does not exist or cannot be loaded, the text does not parse, or a tag comes from an extension the analysis does not know. A caller that keeps only the referenced data must keep all of it when the result is incomplete.
|
|
130
|
+
- The engine returns the same frozen result for the same template text until `ClearTemplateCache()`. It does not cache a result with `ParseFailed: true` (the text, or a template it pulls in, does not parse).
|
|
131
|
+
- The method sets up the Nunjucks environment and the registered extensions first, so it gives the same answer before and after the first `Config()`.
|
|
132
|
+
|
|
112
133
|
### Custom Nunjucks Filters
|
|
113
134
|
|
|
114
135
|
The engine provides built-in filters for JSON operations:
|
|
@@ -215,9 +236,10 @@ graph LR
|
|
|
215
236
|
| `Config()` | method | Load metadata and initialize Nunjucks environment |
|
|
216
237
|
| `RenderTemplate()` | method | Render a stored template with validation |
|
|
217
238
|
| `RenderTemplateSimple()` | method | Render an ad-hoc template string |
|
|
239
|
+
| `GetReferencedVariables()` | method | List the top-level variables a template's text reads |
|
|
218
240
|
| `AddTemplate()` | method | Add a template to the Nunjucks loader |
|
|
219
241
|
| `SetupNunjucks()` | method | Re-initialize the Nunjucks environment |
|
|
220
|
-
| `ClearTemplateCache()` | method | Clear cached compiled templates |
|
|
242
|
+
| `ClearTemplateCache()` | method | Clear cached compiled templates and variable analysis results |
|
|
221
243
|
|
|
222
244
|
### Rendering Process
|
|
223
245
|
|
package/dist/NunjucksSandbox.js
CHANGED
|
@@ -195,10 +195,11 @@ function guardRegistryLookup(registry) {
|
|
|
195
195
|
}
|
|
196
196
|
/**
|
|
197
197
|
* `obj.key` and `obj[key]`. The key is converted to a string once, so a computed key cannot change
|
|
198
|
-
* between the check and the read. The member is
|
|
199
|
-
*
|
|
198
|
+
* between the check and the read. The member is read once (`memberVal`), checked against restricted/nunjucks
|
|
199
|
+
* values, and returned directly (or bound to `obj` when it is a method, matching nunjucks' `memberLookup`
|
|
200
|
+
* without evaluating `obj[key]` a second time).
|
|
200
201
|
*/
|
|
201
|
-
function guardMemberLookup(
|
|
202
|
+
function guardMemberLookup(_original) {
|
|
202
203
|
return (obj, val) => {
|
|
203
204
|
if (obj === undefined || obj === null || typeof val === 'symbol') {
|
|
204
205
|
return undefined;
|
|
@@ -210,9 +211,19 @@ function guardMemberLookup(original) {
|
|
|
210
211
|
if (RESTRICTED_MEMBER_NAMES.has(key) && !isOwnDataValue(obj, key)) {
|
|
211
212
|
return undefined;
|
|
212
213
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
if (RESTRICTED_VALUES.has(obj)) {
|
|
215
|
+
throw new TemplateSandboxError(`Templates may not access members of a restricted value (reading "${key}")`);
|
|
216
|
+
}
|
|
217
|
+
const memberVal = readMember(obj, key);
|
|
218
|
+
if (isRestrictedOrNunjucksValue(memberVal)) {
|
|
219
|
+
throw new TemplateSandboxError(`Templates may not access the member "${key}"`);
|
|
220
|
+
}
|
|
221
|
+
if (typeof memberVal === 'function') {
|
|
222
|
+
return function (...args) {
|
|
223
|
+
return memberVal.apply(obj, args);
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
return memberVal;
|
|
216
227
|
};
|
|
217
228
|
}
|
|
218
229
|
/**
|
|
@@ -229,16 +240,22 @@ function guardContextOrFrameLookup() {
|
|
|
229
240
|
if (value === undefined || (RESTRICTED_MEMBER_NAMES.has(name) && typeof value === 'function')) {
|
|
230
241
|
return undefined;
|
|
231
242
|
}
|
|
232
|
-
|
|
243
|
+
if (isRestrictedOrNunjucksValue(value, context)) {
|
|
244
|
+
throw new TemplateSandboxError(`Templates may not access the name "${name}"`);
|
|
245
|
+
}
|
|
233
246
|
return value;
|
|
234
247
|
};
|
|
235
248
|
}
|
|
236
249
|
/** A call such as `{{ fn(x) }}`. nunjucks passes the render context as `this`, so a call may not return it. */
|
|
237
250
|
function guardCallWrap(original) {
|
|
238
251
|
return (obj, name, context, args) => {
|
|
239
|
-
|
|
252
|
+
if (isRestrictedOrNunjucksValue(obj, context)) {
|
|
253
|
+
throw new TemplateSandboxError(`Templates may not access the function "${name}"`);
|
|
254
|
+
}
|
|
240
255
|
const result = original(obj, name, context, args);
|
|
241
|
-
|
|
256
|
+
if (isRestrictedOrNunjucksValue(result, context)) {
|
|
257
|
+
throw new TemplateSandboxError(`Templates may not access the value returned by "${name}"`);
|
|
258
|
+
}
|
|
242
259
|
return result;
|
|
243
260
|
};
|
|
244
261
|
}
|
|
@@ -271,7 +288,14 @@ function isNunjucksObject(value) {
|
|
|
271
288
|
if (typeof value !== 'object' || value === null) {
|
|
272
289
|
return false;
|
|
273
290
|
}
|
|
274
|
-
|
|
291
|
+
if (NUNJUCKS_MODULES.has(value)) {
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
const proto = Object.getPrototypeOf(value);
|
|
295
|
+
if (proto === Object.prototype || proto === Array.prototype || proto === null) {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
return NUNJUCKS_OBJECT_PROTOTYPES.some((prototype) => prototype.isPrototypeOf(value));
|
|
275
299
|
}
|
|
276
300
|
/** Reads a member the way a template does, including members of primitive strings and numbers. */
|
|
277
301
|
function readMember(obj, key) {
|
|
@@ -283,10 +307,11 @@ function pairKeyName(pair) {
|
|
|
283
307
|
const value = typeof key === 'object' && key !== null ? readMember(key, 'value') : undefined;
|
|
284
308
|
return typeof value === 'string' ? value : undefined;
|
|
285
309
|
}
|
|
286
|
-
/**
|
|
287
|
-
function
|
|
288
|
-
if (
|
|
289
|
-
|
|
310
|
+
/** Returns true when a lookup or call would give a template a restricted value, the render context or another nunjucks object. */
|
|
311
|
+
function isRestrictedOrNunjucksValue(value, context) {
|
|
312
|
+
if (value === null || (typeof value !== 'object' && typeof value !== 'function')) {
|
|
313
|
+
return false;
|
|
290
314
|
}
|
|
315
|
+
return RESTRICTED_VALUES.has(value) || isNunjucksObject(value) || (context !== undefined && value === context);
|
|
291
316
|
}
|
|
292
317
|
//# sourceMappingURL=NunjucksSandbox.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NunjucksSandbox.js","sourceRoot":"","sources":["../src/NunjucksSandbox.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"NunjucksSandbox.js","sourceRoot":"","sources":["../src/NunjucksSandbox.ts"],"names":[],"mappings":"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"}
|
package/dist/TemplateEngine.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { IMetadataProvider, UserInfo } from "@memberjunction/core";
|
|
|
2
2
|
import { MJTemplateCategoryEntity, MJTemplateContentEntity, MJTemplateContentTypeEntity, MJTemplateEntityExtended, MJTemplateParamEntity } from "@memberjunction/core-entities";
|
|
3
3
|
import nunjucks from 'nunjucks';
|
|
4
4
|
import { BaseSingleton } from "@memberjunction/global";
|
|
5
|
-
import {
|
|
5
|
+
import { ReferencedVariablesResult } from "./TemplateVariableAnalysis.js";
|
|
6
|
+
import { TemplateRenderOptions, TemplateRenderResult } from '@memberjunction/templates-base-types';
|
|
6
7
|
/**
|
|
7
8
|
* This class extends the nunjucks loader to allow adding templates directly to the loader
|
|
8
9
|
*/
|
|
@@ -54,8 +55,13 @@ export declare class TemplateEngineServer extends BaseSingleton<TemplateEngineSe
|
|
|
54
55
|
* not ours, so we drive the render-layer init explicitly here after the cache is loaded.
|
|
55
56
|
*/
|
|
56
57
|
Config(forceRefresh?: boolean, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<void>;
|
|
57
|
-
/** One-time nunjucks environment + registered-extension setup
|
|
58
|
+
/** One-time nunjucks environment + registered-extension setup. {@link Config} and {@link GetReferencedVariables} call it. */
|
|
58
59
|
private ensureNunjucksInitialized;
|
|
60
|
+
/**
|
|
61
|
+
* Registers every {@link TemplateExtensionBase} subclass with the given environment.
|
|
62
|
+
* @returns the extension instances registered on `env`
|
|
63
|
+
*/
|
|
64
|
+
private registerExtensions;
|
|
59
65
|
/** True once the underlying TemplateEngineBase cache has loaded. */
|
|
60
66
|
get Loaded(): boolean;
|
|
61
67
|
get ContextUser(): UserInfo;
|
|
@@ -66,6 +72,7 @@ export declare class TemplateEngineServer extends BaseSingleton<TemplateEngineSe
|
|
|
66
72
|
get TemplateContents(): MJTemplateContentEntity[];
|
|
67
73
|
get TemplateParams(): MJTemplateParamEntity[];
|
|
68
74
|
FindTemplate(templateName: string): MJTemplateEntityExtended;
|
|
75
|
+
FindTemplateByID(templateId: string): MJTemplateEntityExtended | undefined;
|
|
69
76
|
SetupNunjucks(): void;
|
|
70
77
|
private _nunjucksEnv;
|
|
71
78
|
/**
|
|
@@ -76,7 +83,11 @@ export declare class TemplateEngineServer extends BaseSingleton<TemplateEngineSe
|
|
|
76
83
|
* renders, not the stored-Template extension surface. Reset to `undefined` whenever the loader is rebuilt.
|
|
77
84
|
*/
|
|
78
85
|
private _nunjucksEnvNoAutoescape?;
|
|
86
|
+
/** Environment with autoescape off and the registered extensions, for {@link RenderTemplate} with `autoescape: false`. Created lazily. */
|
|
87
|
+
private _nunjucksEnvRawTemplates?;
|
|
79
88
|
private _templateLoader;
|
|
89
|
+
/** The extension instances registered on {@link _nunjucksEnv}. The variable analysis parses their custom tags. */
|
|
90
|
+
private _registeredExtensions;
|
|
80
91
|
/**
|
|
81
92
|
* Builds a Nunjucks environment bound to the shared template loader with our custom filters applied.
|
|
82
93
|
* Single source of truth for env construction so the autoescape and no-autoescape environments never drift.
|
|
@@ -89,9 +100,18 @@ export declare class TemplateEngineServer extends BaseSingleton<TemplateEngineSe
|
|
|
89
100
|
*/
|
|
90
101
|
private addCustomFilters;
|
|
91
102
|
/**
|
|
92
|
-
*
|
|
103
|
+
* Compiled templates per environment, then per template content ID, so a raw compile is never served to an
|
|
104
|
+
* escaping render. Tracks `sourceText` so in-place `AutoRefresh` updates to `TemplateText` recompile automatically.
|
|
93
105
|
*/
|
|
94
106
|
private _templateCache;
|
|
107
|
+
/**
|
|
108
|
+
* Bounded LRU cache for ad-hoc templates rendered via {@link RenderTemplateSimple}.
|
|
109
|
+
* Keyed by `${autoescape ? '1:' : '0:'}${templateText}`.
|
|
110
|
+
*/
|
|
111
|
+
private static readonly MAX_SIMPLE_TEMPLATE_CACHE_SIZE;
|
|
112
|
+
private _simpleTemplateCache;
|
|
113
|
+
/** {@link GetReferencedVariables} results by template text. */
|
|
114
|
+
private _referencedVariablesCache;
|
|
95
115
|
AddTemplate(templateEntity: MJTemplateEntityExtended): void;
|
|
96
116
|
/**
|
|
97
117
|
* Renders a template with the given data.
|
|
@@ -100,8 +120,10 @@ export declare class TemplateEngineServer extends BaseSingleton<TemplateEngineSe
|
|
|
100
120
|
* @param data
|
|
101
121
|
* @param SkipValidation if true, validation is skipped entirely (or reduced to warnings depending on SuppressWarnings)
|
|
102
122
|
* @param SuppressWarnings if true AND SkipValidation is true, no validation warnings are logged. When SkipValidation is true but SuppressWarnings is false, validation issues are logged as non-fatal warnings. Defaults to false.
|
|
123
|
+
* @param options `autoescape` (default `true`) toggles HTML escaping; pass `false` when the output is plain text for
|
|
124
|
+
* a model, where `Affineur & Owner` must not become `Affineur & Owner`
|
|
103
125
|
*/
|
|
104
|
-
RenderTemplate(templateEntity: MJTemplateEntityExtended, templateContent: MJTemplateContentEntity, data: any, SkipValidation?: boolean, SuppressWarnings?: boolean): Promise<TemplateRenderResult>;
|
|
126
|
+
RenderTemplate(templateEntity: MJTemplateEntityExtended, templateContent: MJTemplateContentEntity, data: any, SkipValidation?: boolean, SuppressWarnings?: boolean, options?: TemplateRenderOptions): Promise<TemplateRenderResult>;
|
|
105
127
|
/**
|
|
106
128
|
* Simple rendering utilty method. Use this to render any valid Nunjucks Template within the Nunjucks environment created by the Template Engine
|
|
107
129
|
* without having to use the stored metadata (Templates/Template Contents/Template Params/etc) within the MJ database. This is useful when you have
|
|
@@ -112,37 +134,58 @@ export declare class TemplateEngineServer extends BaseSingleton<TemplateEngineSe
|
|
|
112
134
|
* `false` for plain-text contexts such as email subject lines, where `Acme & Co` must not become `Acme & Co`.
|
|
113
135
|
* @returns
|
|
114
136
|
*/
|
|
115
|
-
RenderTemplateSimple(templateText: string, data: any, options?:
|
|
116
|
-
|
|
117
|
-
|
|
137
|
+
RenderTemplateSimple(templateText: string, data: any, options?: TemplateRenderOptions): Promise<TemplateRenderResult>;
|
|
138
|
+
/**
|
|
139
|
+
* Returns the top-level variable names a template's text reads, following stored templates it
|
|
140
|
+
* pulls in by literal name (`{% include %}`, `{% import %}`, `{% from %}`, `{% extends %}`,
|
|
141
|
+
* `{% template %}`). It sets up the Nunjucks environment first, so the registered extensions' tags
|
|
142
|
+
* parse before the first {@link Config} too. The result is frozen and cached per template text until
|
|
143
|
+
* {@link ClearTemplateCache}; a result whose text does not parse is not cached.
|
|
144
|
+
*/
|
|
145
|
+
GetReferencedVariables(templateText: string): ReferencedVariablesResult;
|
|
118
146
|
/**
|
|
119
147
|
* This method is responsible for creating a new Nunjucks template, caching it, and returning it.
|
|
120
148
|
* If the templateContentId already had a template created, it will return that template from the cache.
|
|
121
149
|
* @param templateId - must be provided if you want to cache the template, if not provided the template will not be cached
|
|
122
150
|
* @param templateText
|
|
123
151
|
* @param cacheTemplate - if true, the template will be cached, otherwise it will not be cached
|
|
152
|
+
* @param env the environment to compile against; defaults to the shared autoescape environment
|
|
124
153
|
*/
|
|
125
|
-
protected getNunjucksTemplate(templateContentId: string, templateText: string, cacheTemplate: boolean):
|
|
154
|
+
protected getNunjucksTemplate(templateContentId: string, templateText: string, cacheTemplate: boolean, env?: nunjucks.Environment): nunjucks.Template;
|
|
126
155
|
/**
|
|
127
156
|
* Simple utility method to create a new Nunjucks template object and bind it to a Nunjucks environment.
|
|
128
157
|
* @param templateText
|
|
129
158
|
* @param env the environment to bind to; defaults to the shared autoescape environment
|
|
130
159
|
* @returns
|
|
131
160
|
*/
|
|
132
|
-
protected createNunjucksTemplate(templateText: string, env?: nunjucks.Environment):
|
|
161
|
+
protected createNunjucksTemplate(templateText: string, env?: nunjucks.Environment): nunjucks.Template;
|
|
133
162
|
/**
|
|
134
163
|
* Resolves the Nunjucks environment for an ad-hoc {@link RenderTemplateSimple} render. The autoescape:false
|
|
135
164
|
* variant is created lazily on first use and cached, so callers that never opt out pay nothing.
|
|
136
165
|
* @param autoescape whether the returned environment HTML-escapes output
|
|
137
166
|
*/
|
|
138
167
|
private getSimpleRenderEnv;
|
|
168
|
+
/** The environment for {@link RenderTemplate} with `autoescape: false`, built on first use with the registered extensions. */
|
|
169
|
+
private getRawTemplateEnv;
|
|
170
|
+
/** Clears the compiled-template cache and the cached {@link GetReferencedVariables} results. */
|
|
139
171
|
ClearTemplateCache(): void;
|
|
172
|
+
/**
|
|
173
|
+
* The user a render runs as: the one the caller passed, else the user of the render this one is
|
|
174
|
+
* nested in. There is no fallback to this engine's context user: that is whoever last configured
|
|
175
|
+
* the process-wide engine, so it may be another request's user. A render with no user runs its
|
|
176
|
+
* extensions with no user, and an extension that needs one fails the render with an error rather
|
|
177
|
+
* than run as nobody (an `{% AIPrompt %}` tag does). Every server caller should pass `ContextUser`.
|
|
178
|
+
*/
|
|
179
|
+
private resolveRenderUser;
|
|
140
180
|
/**
|
|
141
181
|
* Promisifies the Nunjucks template rendering process.
|
|
142
182
|
* @param template the Nunjucks template object
|
|
143
183
|
* @param data the data to render the template with
|
|
184
|
+
* @param renderUser the user registered extensions act for during this render
|
|
144
185
|
*/
|
|
145
|
-
protected renderTemplateAsync(template: nunjucks.Template, data: any): Promise<string>;
|
|
186
|
+
protected renderTemplateAsync(template: nunjucks.Template, data: any, renderUser?: UserInfo): Promise<string>;
|
|
187
|
+
/** Renders `template` with `data`, inside the caller's render-user scope. */
|
|
188
|
+
private renderInCurrentScope;
|
|
146
189
|
/**
|
|
147
190
|
* Merges default values from template parameters with the provided data.
|
|
148
191
|
* Content-specific parameters take precedence over global parameters when both define the same parameter name.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TemplateEngine.d.ts","sourceRoot":"","sources":["../src/TemplateEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAY,QAAQ,EAAuB,MAAM,sBAAsB,CAAC;AAClG,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAChL,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,aAAa,EAAwB,MAAM,wBAAwB,CAAC;AAG7E,OAAO,EAAE,oBAAoB,EAAsB,MAAM,sCAAsC,CAAA;
|
|
1
|
+
{"version":3,"file":"TemplateEngine.d.ts","sourceRoot":"","sources":["../src/TemplateEngine.ts"],"names":[],"mappings":"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"}
|
package/dist/TemplateEngine.js
CHANGED
|
@@ -3,6 +3,8 @@ import nunjucks from 'nunjucks';
|
|
|
3
3
|
import { BaseSingleton, MJGlobal, UUIDsEqual } from "@memberjunction/global";
|
|
4
4
|
import { TemplateExtensionBase } from "./extensions/TemplateExtensionBase.js";
|
|
5
5
|
import { HardenNunjucksRuntime } from "./NunjucksSandbox.js";
|
|
6
|
+
import { CollectReferencedVariables } from "./TemplateVariableAnalysis.js";
|
|
7
|
+
import { CurrentTemplateRenderUser, RunAsTemplateRenderUser } from "./TemplateRenderUser.js";
|
|
6
8
|
import { TemplateEngineBase } from '@memberjunction/templates-base-types';
|
|
7
9
|
// Stored templates are user-editable, so nunjucks is guarded as soon as the engine loads. The guard
|
|
8
10
|
// is process-wide: it also covers nunjucks environments that other packages create.
|
|
@@ -60,10 +62,16 @@ export class TemplateEngineServer extends BaseSingleton {
|
|
|
60
62
|
constructor() {
|
|
61
63
|
super(...arguments);
|
|
62
64
|
this._oneTimeLoadingComplete = false;
|
|
65
|
+
/** The extension instances registered on {@link _nunjucksEnv}. The variable analysis parses their custom tags. */
|
|
66
|
+
this._registeredExtensions = [];
|
|
63
67
|
/**
|
|
64
|
-
*
|
|
68
|
+
* Compiled templates per environment, then per template content ID, so a raw compile is never served to an
|
|
69
|
+
* escaping render. Tracks `sourceText` so in-place `AutoRefresh` updates to `TemplateText` recompile automatically.
|
|
65
70
|
*/
|
|
66
|
-
this._templateCache = new
|
|
71
|
+
this._templateCache = new WeakMap();
|
|
72
|
+
this._simpleTemplateCache = new Map();
|
|
73
|
+
/** {@link GetReferencedVariables} results by template text. */
|
|
74
|
+
this._referencedVariablesCache = new Map();
|
|
67
75
|
}
|
|
68
76
|
static get Instance() {
|
|
69
77
|
return super.getInstance();
|
|
@@ -95,7 +103,7 @@ export class TemplateEngineServer extends BaseSingleton {
|
|
|
95
103
|
this.ClearTemplateCache(); // base templates (re)loaded — drop any stale compiled templates
|
|
96
104
|
this.ensureNunjucksInitialized(contextUser);
|
|
97
105
|
}
|
|
98
|
-
/** One-time nunjucks environment + registered-extension setup
|
|
106
|
+
/** One-time nunjucks environment + registered-extension setup. {@link Config} and {@link GetReferencedVariables} call it. */
|
|
99
107
|
ensureNunjucksInitialized(contextUser) {
|
|
100
108
|
if (this._oneTimeLoadingComplete) {
|
|
101
109
|
return;
|
|
@@ -104,17 +112,27 @@ export class TemplateEngineServer extends BaseSingleton {
|
|
|
104
112
|
this._templateLoader = new TemplateEntityLoader();
|
|
105
113
|
this._nunjucksEnv = this.createConfiguredNunjucksEnv(true);
|
|
106
114
|
this._nunjucksEnvNoAutoescape = undefined; // rebound lazily against the fresh loader on next no-autoescape render
|
|
107
|
-
|
|
115
|
+
this._nunjucksEnvRawTemplates = undefined;
|
|
116
|
+
this._registeredExtensions = this.registerExtensions(this._nunjucksEnv, contextUser);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Registers every {@link TemplateExtensionBase} subclass with the given environment.
|
|
120
|
+
* @returns the extension instances registered on `env`
|
|
121
|
+
*/
|
|
122
|
+
registerExtensions(env, contextUser) {
|
|
123
|
+
const registered = [];
|
|
108
124
|
const extensions = MJGlobal.Instance.ClassFactory.GetAllRegistrations(TemplateExtensionBase);
|
|
109
125
|
if (extensions && extensions.length > 0) {
|
|
110
126
|
for (const ext of extensions) {
|
|
111
127
|
const SubClassConstructor = ext.SubClass;
|
|
112
128
|
const instance = new SubClassConstructor(contextUser);
|
|
113
129
|
if (ext.Key) {
|
|
114
|
-
|
|
130
|
+
env.addExtension(ext.Key, instance);
|
|
131
|
+
registered.push(instance);
|
|
115
132
|
}
|
|
116
133
|
}
|
|
117
134
|
}
|
|
135
|
+
return registered;
|
|
118
136
|
}
|
|
119
137
|
/** True once the underlying TemplateEngineBase cache has loaded. */
|
|
120
138
|
get Loaded() { return this.base.Loaded; }
|
|
@@ -127,10 +145,13 @@ export class TemplateEngineServer extends BaseSingleton {
|
|
|
127
145
|
get TemplateContents() { return this.base.TemplateContents; }
|
|
128
146
|
get TemplateParams() { return this.base.TemplateParams; }
|
|
129
147
|
FindTemplate(templateName) { return this.base.FindTemplate(templateName); }
|
|
148
|
+
FindTemplateByID(templateId) { return this.base.FindTemplateByID(templateId); }
|
|
130
149
|
SetupNunjucks() {
|
|
131
150
|
this._templateLoader = new TemplateEntityLoader();
|
|
132
151
|
this._nunjucksEnv = this.createConfiguredNunjucksEnv(true);
|
|
133
152
|
this._nunjucksEnvNoAutoescape = undefined; // rebound lazily against the fresh loader on next no-autoescape render
|
|
153
|
+
this._nunjucksEnvRawTemplates = undefined;
|
|
154
|
+
this._simpleTemplateCache.clear();
|
|
134
155
|
}
|
|
135
156
|
/**
|
|
136
157
|
* Builds a Nunjucks environment bound to the shared template loader with our custom filters applied.
|
|
@@ -178,6 +199,11 @@ export class TemplateEngineServer extends BaseSingleton {
|
|
|
178
199
|
}
|
|
179
200
|
});
|
|
180
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Bounded LRU cache for ad-hoc templates rendered via {@link RenderTemplateSimple}.
|
|
204
|
+
* Keyed by `${autoescape ? '1:' : '0:'}${templateText}`.
|
|
205
|
+
*/
|
|
206
|
+
static { this.MAX_SIMPLE_TEMPLATE_CACHE_SIZE = 2000; }
|
|
181
207
|
AddTemplate(templateEntity) {
|
|
182
208
|
this._templateLoader.AddTemplate(templateEntity.ID, templateEntity);
|
|
183
209
|
}
|
|
@@ -188,8 +214,10 @@ export class TemplateEngineServer extends BaseSingleton {
|
|
|
188
214
|
* @param data
|
|
189
215
|
* @param SkipValidation if true, validation is skipped entirely (or reduced to warnings depending on SuppressWarnings)
|
|
190
216
|
* @param SuppressWarnings if true AND SkipValidation is true, no validation warnings are logged. When SkipValidation is true but SuppressWarnings is false, validation issues are logged as non-fatal warnings. Defaults to false.
|
|
217
|
+
* @param options `autoescape` (default `true`) toggles HTML escaping; pass `false` when the output is plain text for
|
|
218
|
+
* a model, where `Affineur & Owner` must not become `Affineur & Owner`
|
|
191
219
|
*/
|
|
192
|
-
async RenderTemplate(templateEntity, templateContent, data, SkipValidation, SuppressWarnings) {
|
|
220
|
+
async RenderTemplate(templateEntity, templateContent, data, SkipValidation, SuppressWarnings, options) {
|
|
193
221
|
try {
|
|
194
222
|
if (!templateContent) {
|
|
195
223
|
return {
|
|
@@ -233,8 +261,9 @@ export class TemplateEngineServer extends BaseSingleton {
|
|
|
233
261
|
}
|
|
234
262
|
// Merge default values from parameters applicable to this content
|
|
235
263
|
const mergedData = this.mergeDefaultValues(templateEntity, templateContent.ID, data);
|
|
236
|
-
const
|
|
237
|
-
const
|
|
264
|
+
const env = options?.autoescape === false ? this.getRawTemplateEnv() : this._nunjucksEnv;
|
|
265
|
+
const template = this.getNunjucksTemplate(templateContent.ID, templateContent.TemplateText, true, env);
|
|
266
|
+
const result = await this.renderTemplateAsync(template, mergedData, this.resolveRenderUser(options));
|
|
238
267
|
return {
|
|
239
268
|
Success: true,
|
|
240
269
|
Output: result,
|
|
@@ -261,9 +290,26 @@ export class TemplateEngineServer extends BaseSingleton {
|
|
|
261
290
|
*/
|
|
262
291
|
async RenderTemplateSimple(templateText, data, options) {
|
|
263
292
|
try {
|
|
264
|
-
const
|
|
265
|
-
const
|
|
266
|
-
|
|
293
|
+
const autoescape = options?.autoescape ?? true;
|
|
294
|
+
const cacheKey = `${autoescape ? '1:' : '0:'}${templateText}`;
|
|
295
|
+
let template = this._simpleTemplateCache.get(cacheKey);
|
|
296
|
+
if (template) {
|
|
297
|
+
// Refresh LRU order
|
|
298
|
+
this._simpleTemplateCache.delete(cacheKey);
|
|
299
|
+
this._simpleTemplateCache.set(cacheKey, template);
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
const env = this.getSimpleRenderEnv(autoescape);
|
|
303
|
+
template = this.createNunjucksTemplate(templateText, env);
|
|
304
|
+
if (this._simpleTemplateCache.size >= TemplateEngineServer.MAX_SIMPLE_TEMPLATE_CACHE_SIZE) {
|
|
305
|
+
const oldestKey = this._simpleTemplateCache.keys().next().value;
|
|
306
|
+
if (oldestKey !== undefined) {
|
|
307
|
+
this._simpleTemplateCache.delete(oldestKey);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
this._simpleTemplateCache.set(cacheKey, template);
|
|
311
|
+
}
|
|
312
|
+
const result = await this.renderTemplateAsync(template, data, this.resolveRenderUser(options));
|
|
267
313
|
return {
|
|
268
314
|
Success: true,
|
|
269
315
|
Output: result,
|
|
@@ -279,26 +325,61 @@ export class TemplateEngineServer extends BaseSingleton {
|
|
|
279
325
|
};
|
|
280
326
|
}
|
|
281
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Returns the top-level variable names a template's text reads, following stored templates it
|
|
330
|
+
* pulls in by literal name (`{% include %}`, `{% import %}`, `{% from %}`, `{% extends %}`,
|
|
331
|
+
* `{% template %}`). It sets up the Nunjucks environment first, so the registered extensions' tags
|
|
332
|
+
* parse before the first {@link Config} too. The result is frozen and cached per template text until
|
|
333
|
+
* {@link ClearTemplateCache}; a result whose text does not parse is not cached.
|
|
334
|
+
*/
|
|
335
|
+
GetReferencedVariables(templateText) {
|
|
336
|
+
const cached = this._referencedVariablesCache.get(templateText);
|
|
337
|
+
if (cached) {
|
|
338
|
+
return cached;
|
|
339
|
+
}
|
|
340
|
+
this.ensureNunjucksInitialized(this.ContextUser);
|
|
341
|
+
const result = Object.freeze(CollectReferencedVariables(templateText, {
|
|
342
|
+
Extensions: this._registeredExtensions,
|
|
343
|
+
ResolveTemplateTexts: (name) => {
|
|
344
|
+
const template = this.FindTemplate(name);
|
|
345
|
+
return template ? template.Content.map((c) => c.TemplateText).filter((t) => !!t) : null;
|
|
346
|
+
},
|
|
347
|
+
}));
|
|
348
|
+
if (!result.ParseFailed) {
|
|
349
|
+
this._referencedVariablesCache.set(templateText, result);
|
|
350
|
+
}
|
|
351
|
+
return result;
|
|
352
|
+
}
|
|
282
353
|
/**
|
|
283
354
|
* This method is responsible for creating a new Nunjucks template, caching it, and returning it.
|
|
284
355
|
* If the templateContentId already had a template created, it will return that template from the cache.
|
|
285
356
|
* @param templateId - must be provided if you want to cache the template, if not provided the template will not be cached
|
|
286
357
|
* @param templateText
|
|
287
358
|
* @param cacheTemplate - if true, the template will be cached, otherwise it will not be cached
|
|
359
|
+
* @param env the environment to compile against; defaults to the shared autoescape environment
|
|
288
360
|
*/
|
|
289
|
-
getNunjucksTemplate(templateContentId, templateText, cacheTemplate) {
|
|
361
|
+
getNunjucksTemplate(templateContentId, templateText, cacheTemplate, env = this._nunjucksEnv) {
|
|
290
362
|
if (templateContentId && cacheTemplate) {
|
|
291
|
-
let
|
|
292
|
-
if (!
|
|
293
|
-
|
|
294
|
-
this._templateCache.set(
|
|
363
|
+
let envCache = this._templateCache.get(env);
|
|
364
|
+
if (!envCache) {
|
|
365
|
+
envCache = new Map();
|
|
366
|
+
this._templateCache.set(env, envCache);
|
|
367
|
+
}
|
|
368
|
+
const cached = envCache.get(templateContentId);
|
|
369
|
+
if (cached && cached.sourceText === templateText) {
|
|
370
|
+
return cached.template;
|
|
295
371
|
}
|
|
372
|
+
if (cached && cached.sourceText !== templateText) {
|
|
373
|
+
this._referencedVariablesCache.clear();
|
|
374
|
+
}
|
|
375
|
+
const template = this.createNunjucksTemplate(templateText, env);
|
|
376
|
+
envCache.set(templateContentId, { template, sourceText: templateText });
|
|
296
377
|
return template;
|
|
297
378
|
}
|
|
298
379
|
else {
|
|
299
380
|
// we don't have a template ID which means this is a dyanmic template, and so we don't want to do
|
|
300
381
|
// anything with the cache, we just create a new nunjucks template and return it
|
|
301
|
-
return this.createNunjucksTemplate(templateText);
|
|
382
|
+
return this.createNunjucksTemplate(templateText, env);
|
|
302
383
|
}
|
|
303
384
|
}
|
|
304
385
|
/**
|
|
@@ -324,16 +405,42 @@ export class TemplateEngineServer extends BaseSingleton {
|
|
|
324
405
|
}
|
|
325
406
|
return this._nunjucksEnvNoAutoescape;
|
|
326
407
|
}
|
|
408
|
+
/** The environment for {@link RenderTemplate} with `autoescape: false`, built on first use with the registered extensions. */
|
|
409
|
+
getRawTemplateEnv() {
|
|
410
|
+
if (!this._nunjucksEnvRawTemplates) {
|
|
411
|
+
this._nunjucksEnvRawTemplates = this.createConfiguredNunjucksEnv(false);
|
|
412
|
+
this.registerExtensions(this._nunjucksEnvRawTemplates, this._contextUser);
|
|
413
|
+
}
|
|
414
|
+
return this._nunjucksEnvRawTemplates;
|
|
415
|
+
}
|
|
416
|
+
/** Clears the compiled-template cache and the cached {@link GetReferencedVariables} results. */
|
|
327
417
|
ClearTemplateCache() {
|
|
328
|
-
this._templateCache
|
|
418
|
+
this._templateCache = new WeakMap();
|
|
419
|
+
this._simpleTemplateCache.clear();
|
|
420
|
+
this._referencedVariablesCache.clear();
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* The user a render runs as: the one the caller passed, else the user of the render this one is
|
|
424
|
+
* nested in. There is no fallback to this engine's context user: that is whoever last configured
|
|
425
|
+
* the process-wide engine, so it may be another request's user. A render with no user runs its
|
|
426
|
+
* extensions with no user, and an extension that needs one fails the render with an error rather
|
|
427
|
+
* than run as nobody (an `{% AIPrompt %}` tag does). Every server caller should pass `ContextUser`.
|
|
428
|
+
*/
|
|
429
|
+
resolveRenderUser(options) {
|
|
430
|
+
return options?.ContextUser ?? CurrentTemplateRenderUser();
|
|
329
431
|
}
|
|
330
432
|
/**
|
|
331
433
|
* Promisifies the Nunjucks template rendering process.
|
|
332
434
|
* @param template the Nunjucks template object
|
|
333
435
|
* @param data the data to render the template with
|
|
436
|
+
* @param renderUser the user registered extensions act for during this render
|
|
334
437
|
*/
|
|
335
|
-
async renderTemplateAsync(template, data) {
|
|
438
|
+
async renderTemplateAsync(template, data, renderUser) {
|
|
336
439
|
HardenNunjucksRuntime(); // no-op unless something replaced a guarded nunjucks hook
|
|
440
|
+
return RunAsTemplateRenderUser(renderUser ?? this.resolveRenderUser(), () => this.renderInCurrentScope(template, data));
|
|
441
|
+
}
|
|
442
|
+
/** Renders `template` with `data`, inside the caller's render-user scope. */
|
|
443
|
+
renderInCurrentScope(template, data) {
|
|
337
444
|
return new Promise((resolve, reject) => {
|
|
338
445
|
template.render(data, (err, result) => {
|
|
339
446
|
if (err) {
|
|
@@ -364,16 +471,24 @@ export class TemplateEngineServer extends BaseSingleton {
|
|
|
364
471
|
const mergedData = { ...data };
|
|
365
472
|
// Get all parameters applicable to this content
|
|
366
473
|
const params = templateEntity.GetParametersForContent(contentId);
|
|
474
|
+
if (!params || params.length === 0) {
|
|
475
|
+
return mergedData;
|
|
476
|
+
}
|
|
367
477
|
// Group parameters by name to handle precedence
|
|
368
478
|
const paramsByName = new Map();
|
|
369
|
-
// First add global parameters
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
479
|
+
// First add global parameters, then override with content-specific parameters
|
|
480
|
+
for (let i = 0; i < params.length; i++) {
|
|
481
|
+
const p = params[i];
|
|
482
|
+
if (!p.TemplateContentID) {
|
|
483
|
+
paramsByName.set(p.Name, p);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
for (let i = 0; i < params.length; i++) {
|
|
487
|
+
const p = params[i];
|
|
488
|
+
if (p.TemplateContentID && UUIDsEqual(p.TemplateContentID, contentId)) {
|
|
489
|
+
paramsByName.set(p.Name, p);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
377
492
|
// Apply default values for missing parameters
|
|
378
493
|
paramsByName.forEach((param, name) => {
|
|
379
494
|
// Only apply default if the parameter is not already provided
|