From 80a0d9334ddb7d77342e33b62198e2c9d71dd5d5 Mon Sep 17 00:00:00 2001 From: Wiktor Owczarek Date: Fri, 27 Feb 2026 13:38:21 +0000 Subject: [PATCH] Add suport for custom tag types --- src/compile-string.ts | 6 +++++- src/config.ts | 4 ++++ src/parse.ts | 21 ++++++++++----------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/compile-string.ts b/src/compile-string.ts index aab453b5..64808b72 100644 --- a/src/compile-string.ts +++ b/src/compile-string.ts @@ -95,7 +95,7 @@ export function compileBody(this: Eta, buff: Array): string { // we know string exists returnStr += "__eta.res+='" + str + "';\n"; } else { - const type = currentBlock.t; // "r", "e", or "i" + const type = currentBlock.t; // "r", "e", "i" or custom tag name let content = currentBlock.val || ""; if (config.debug) returnStr += "__eta.line=" + currentBlock.lineNo + "\n"; @@ -123,6 +123,10 @@ export function compileBody(this: Eta, buff: Array): string { } else if (type === "e") { // execute returnStr += content + "\n"; + + } else if (type in config.customTags) { + const customTag = config.customTags[type]; + returnStr += `__eta.res += this.config.customTags['${type}']('${content}', ${config.varName});\n`; } } } diff --git a/src/config.ts b/src/config.ts index af436109..f7ba7b61 100644 --- a/src/config.ts +++ b/src/config.ts @@ -27,6 +27,9 @@ export interface EtaConfig { /** Holds cache of resolved filepaths. Set to `false` to disable. */ cacheFilepaths: boolean; + /** Object specifying custom tags. Keys are tag prefixes, values are functions which take tag content and return a string. */ + customTags: Record string>; + /** Whether to pretty-format error messages (introduces runtime penalties) */ debug: boolean; @@ -89,6 +92,7 @@ const defaultConfig: EtaConfig = { autoTrim: [false, "nl"], cache: false, cacheFilepaths: true, + customTags: {}, debug: false, escapeFunction: XMLEscape, // default filter function (not used unless enables) just stringifies the input diff --git a/src/parse.ts b/src/parse.ts index bb74db77..028ceead 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -2,10 +2,8 @@ import { ParseErr } from "./err.ts"; import type { Eta } from "./internal.ts"; import { trimWS } from "./utils.ts"; -export type TagType = "r" | "e" | "i" | ""; - export interface TemplateObject { - t: TagType; + t: string; val: string; lineNo?: number; } @@ -40,6 +38,8 @@ export function parse(this: Eta, str: string): Array { let lastIndex = 0; const parseOptions = config.parse; + const customTagPrefixes = Object.keys(config.customTags) + if (config.plugins) { for (let i = 0; i < config.plugins.length; i++) { const plugin = config.plugins[i]; @@ -90,6 +90,7 @@ export function parse(this: Eta, str: string): Array { parseOptions.exec, parseOptions.interpolate, parseOptions.raw, + ...customTagPrefixes, ].reduce((accumulator, prefix) => { if (accumulator && prefix) { return accumulator + "|" + escapeRegExp(prefix); @@ -138,14 +139,12 @@ export function parse(this: Eta, str: string): Array { trimLeftOfNextStr = closeTag[2]; - const currentType: TagType = - prefix === parseOptions.exec - ? "e" - : prefix === parseOptions.raw - ? "r" - : prefix === parseOptions.interpolate - ? "i" - : ""; + let currentType = ""; + if(prefix === config.parse.exec) currentType = "e"; + else if(prefix === config.parse.interpolate) currentType = "i"; + else if(prefix === config.parse.raw) currentType = "r"; + // custom tags + else if(customTagPrefixes.includes(prefix)) currentType = prefix; currentObj = { t: currentType, val: content }; break;