Skip to content

Commit

Permalink
Allow disabling template parsing per-value using $! prefix
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulSD committed Feb 18, 2025
1 parent 1de1643 commit 24aa95d
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 11 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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.

Expand All @@ -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

Expand Down
29 changes: 21 additions & 8 deletions src/config-template-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,15 +206,15 @@ 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);
}

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`;
Expand All @@ -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;
}

Expand Down

0 comments on commit 24aa95d

Please sign in to comment.