-
-
Notifications
You must be signed in to change notification settings - Fork 85
feat: Add suport for custom tag types #364
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -95,7 +95,7 @@ export function compileBody(this: Eta, buff: Array<AstObject>): 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<AstObject>): string { | |
| } else if (type === "e") { | ||
| // execute | ||
| returnStr += content + "\n"; | ||
|
|
||
| } else if (type in config.customTags) { | ||
| const customTag = config.customTags[type]; | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security: Code injection via template content The returnStr += `__eta.res += this.config.customTags['${type}']('${content}', ${config.varName});\n`;If a template contains something like
Generated by Claude Code
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also worth noting: there's no validation that Generated by Claude Code |
||
| returnStr += `__eta.res += this.config.customTags['${type}']('${content}', ${config.varName});\n`; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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. */ | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Making Generated by Claude Code |
||
| customTags: Record<string, (content: string, data: unknown) => 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 | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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 { | ||||||||||||||||||||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing the Consider keeping the named type and extending it instead: export type TagType = "r" | "e" | "i" | "" | (string & {});This preserves autocomplete for the built-in types while still allowing arbitrary custom tag strings. Generated by Claude Code |
||||||||||||||||||||||||||
| t: TagType; | ||||||||||||||||||||||||||
| t: string; | ||||||||||||||||||||||||||
| val: string; | ||||||||||||||||||||||||||
| lineNo?: number; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
@@ -40,6 +38,8 @@ export function parse(this: Eta, str: string): Array<AstObject> { | |||||||||||||||||||||||||
| let lastIndex = 0; | ||||||||||||||||||||||||||
| const parseOptions = config.parse; | ||||||||||||||||||||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no validation that custom tag prefixes don't collide with the built-in prefixes ( Generated by Claude Code |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| 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<AstObject> { | |||||||||||||||||||||||||
| 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<AstObject> { | |||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| 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; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
Comment on lines
+142
to
148
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: missing spaces after
Suggested change
Generated by Claude Code |
||||||||||||||||||||||||||
| currentObj = { t: currentType, val: content }; | ||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
customTagis assigned but never used. This line can be removed.Generated by Claude Code