From 24aa95dd4ccdc4478faec1a90870b14d6f249529 Mon Sep 17 00:00:00 2001 From: Paul Donohue Date: Mon, 17 Feb 2025 22:38:59 -0500 Subject: [PATCH] Allow disabling template parsing per-value using $! prefix --- README.md | 12 +++++++++--- src/config-template-card.ts | 29 +++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 24529ce..31524f4 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ variables: # {{ states('sensor.time') }} ``` -## Defining global functions in variables +### Defining global functions in variables If you find yourself having to rewrite the same logic in multiple locations, you can define global methods inside Config Template Card's variables, which can be called anywhere within the scope of the card: @@ -185,7 +185,7 @@ type: 'custom:config-template-card' name: '${ setTempMessage("House: ", currentTemp) }' ```` -## Dashboard wide variables +### Dashboard wide variables If you need to use the same variable in multiple cards, then instead of defining it in each card's `variables` you can do that once for the entire dashboard. @@ -202,7 +202,13 @@ Both arrays and objects are supported, just like in card's local variables. It i ### Note: All templates must be enclosed by `${}`, except when defining variables. -[Troubleshooting](https://github.com/thomasloven/hass-config/wiki/Lovelace-Plugins) +`${}` is optional in variable definitions (variables will be parsed as templates even without `${}`). + +Values that begin with `$!` will not be parsed for templates. `$!` will be stripped from the beginning of the value, but any `${}` sequences within the value will be left as-is. + +## Troubleshooting + +[General HA Plugin Troubleshooting](https://github.com/thomasloven/hass-config/wiki/Lovelace-Plugins) ## Developers diff --git a/src/config-template-card.ts b/src/config-template-card.ts index 5c2e4d9..58e8185 100644 --- a/src/config-template-card.ts +++ b/src/config-template-card.ts @@ -206,7 +206,7 @@ export class ConfigTemplateCard extends LitElement { arrayVars = structuredClone(arrayVars); for (let v of arrayVars) { - if (isString(v) && !v.includes('${')) { v = this._evalWithVars(v); } + if (isString(v)) { v = this._evaluateTemplate(v, true); } else { v = this._evaluateStructure(v); } vars.push(v); } @@ -214,7 +214,7 @@ export class ConfigTemplateCard extends LitElement { namedVars = structuredClone(namedVars); for (const varName in namedVars) { let v = namedVars[varName]; - if (isString(v) && !v.includes('${')) { v = this._evalWithVars(v); } + if (isString(v)) { v = this._evaluateTemplate(v, true); } else { v = this._evaluateStructure(v); } vars[varName] = v; this._varMgr._evalInitVars += `var ${varName} = vars['${varName}'];\n`; @@ -234,23 +234,36 @@ export class ConfigTemplateCard extends LitElement { const value = entry[1]; struct[key] = this._evaluateStructure(value); }); - } else if (isString(struct) && struct.includes('${')) { + } else if (isString(struct)) { return this._evaluateTemplate(struct); } return struct; } - private _evaluateTemplate(template: string): any { + private _evaluateTemplate(template: string, withoutDelim = false): any { + if (template.startsWith('$!')) { + return template.substring(2, template.length); + } + if (template.startsWith('${') && template.endsWith('}')) { // The entire property is a template, return eval's result directly // to preserve types other than string (eg. numbers) return this._evalWithVars(template.substring(2, template.length - 1)); } - /\${[^}]+}/.exec(template)?.forEach(m => { - const repl = this._evalWithVars(m.substring(2, m.length - 1)).toString() as string; - template = template.replace(m, repl); - }); + const matches = /\${[^}]+}/.exec(template); + if (matches) { + matches.forEach(m => { + const repl = this._evalWithVars(m.substring(2, m.length - 1)).toString() as string; + template = template.replace(m, repl); + }); + return template; + } + + if (withoutDelim) { + return this._evalWithVars(template); + } + return template; }