ha-nunjucks 1.4.0 → 1.6.0
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 +90 -38
- package/dist/filters.js +26 -8
- package/dist/globals.js +17 -6
- package/dist/index.d.ts +8 -1
- package/dist/index.js +56 -31
- package/dist/models/interfaces/hass.d.ts +3 -0
- package/dist/utils/areas.js +12 -7
- package/dist/utils/devices.d.ts +1 -0
- package/dist/utils/devices.js +15 -0
- package/dist/utils/floors.d.ts +1 -0
- package/dist/utils/floors.js +34 -2
- package/dist/utils/json.d.ts +1 -0
- package/dist/utils/json.js +6 -0
- package/dist/utils/labels.d.ts +2 -1
- package/dist/utils/labels.js +10 -10
- package/dist/utils/state_translated.d.ts +5 -0
- package/dist/utils/state_translated.js +37 -0
- package/dist/utils/states.d.ts +1 -1
- package/dist/utils/states.js +8 -9
- package/dist/utils/string_filters.d.ts +4 -0
- package/dist/utils/string_filters.js +27 -0
- package/dist/utils/time.d.ts +1 -0
- package/dist/utils/time.js +16 -12
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -54,6 +54,34 @@ const context = {
|
|
|
54
54
|
const renderedString = renderTemplate(this.hass, templateString, context);
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
`renderTemplate` will try to validate that inputs contain valid templates by default using the exported function `hasTemplate`. You can disable this by setting the fourth argument of `renderTemplate` to `false`. This way you can perform this check yourself before any additional templating setup you perform in your code.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { hasTemplate, renderTemplate } from 'ha-nunjucks';
|
|
61
|
+
|
|
62
|
+
if (!hasTemplate(templateString)) {
|
|
63
|
+
return templateString;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const context = {
|
|
67
|
+
foo: 'bar',
|
|
68
|
+
doThing(thing: string) {
|
|
69
|
+
return `doing ${thing}!`;
|
|
70
|
+
},
|
|
71
|
+
config: {
|
|
72
|
+
entity: 'foo.bar',
|
|
73
|
+
attribute: 'baz_bah',
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const renderedString = renderTemplate(
|
|
78
|
+
this.hass,
|
|
79
|
+
templateString,
|
|
80
|
+
context,
|
|
81
|
+
false,
|
|
82
|
+
);
|
|
83
|
+
```
|
|
84
|
+
|
|
57
85
|
### Return Types
|
|
58
86
|
|
|
59
87
|
`renderTemplate` will return a string unless the result is `true` or `false` (_not_ case sensitive), in which case it will return a boolean.
|
|
@@ -115,6 +143,10 @@ Functions used to determine an entity's state or an attribute.
|
|
|
115
143
|
| state_translated | function, filter | entity_id, state (optional) | Returns the formatted and translated state of an entity or provided state using a language that is currently configured in the general settings. |
|
|
116
144
|
| attr_name_translated | function, filter | entity_id, attr_name | Returns the formatted and translated attribute name of an entity using a language that is currently configured in the general settings. |
|
|
117
145
|
| attr_value_translated | function, filter | entity_id, attr_name, attr_value (optional) | Returns the formatted and translated attribute value of an entity or provided attribute value using a language that is currently configured in the general settings. |
|
|
146
|
+
| number_translated | function, filter | value | Returns the formatted and translated input number using a language that is currently configured in the general settings. |
|
|
147
|
+
| date_translated | function, filter | value | Returns the formatted and translated input date or datetime as a date using a language that is currently configured in the general settings. |
|
|
148
|
+
| time_translated | function, filter | value | Returns the formatted and translated input time or datetime as a time using a language that is currently configured in the general settings. |
|
|
149
|
+
| datetime_translated | function, filter | value | Returns the formatted and translated input datetime using a language that is currently configured in the general settings. |
|
|
118
150
|
|
|
119
151
|
### [Groups](https://www.home-assistant.io/docs/configuration/templating/#working-with-groups)
|
|
120
152
|
|
|
@@ -136,15 +168,17 @@ Functions used to determine an entity's state or an attribute.
|
|
|
136
168
|
| device_attr | function, filter | device_or_entity_id, attr_name | Returns the value of attr_name for the given device or entity ID. |
|
|
137
169
|
| is_device_attr | function | device_or_entity_id, attr_name, attr_value | Returns whether the value of attr_name for the given device or entity ID matches attr_value. |
|
|
138
170
|
| device_id | function, filter | entity_id | Returns the device ID for a given entity ID or device name. |
|
|
171
|
+
| device_name | function, filter | device_or_entity_id | Returns the device name as defined by user or default for a give entity or device ID. |
|
|
139
172
|
|
|
140
173
|
### [Floors](https://www.home-assistant.io/docs/configuration/templating/#floors)
|
|
141
174
|
|
|
142
|
-
| Name
|
|
143
|
-
|
|
|
144
|
-
| floors
|
|
145
|
-
| floor_id
|
|
146
|
-
| floor_name
|
|
147
|
-
| floor_areas
|
|
175
|
+
| Name | Type | Arguments | Description |
|
|
176
|
+
| -------------- | ---------------- | ---------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
177
|
+
| floors | function | | Returns the full list of floor IDs that include an area. |
|
|
178
|
+
| floor_id | function, filter | lookup_value | Returns the floor ID for a given floor name or alias, device ID, entity ID, area ID, or area name or alias. |
|
|
179
|
+
| floor_name | function, filter | lookup_value | Returns the floor name for a given device ID, entity ID, area ID, area name, or floor ID. |
|
|
180
|
+
| floor_areas | function, filter | floor_name_or_id | Returns the list of area IDs tied to a given floor ID or name. |
|
|
181
|
+
| floor_entities | function, filter | floor_name_or_id | Returns the list of entity IDs tied to a given floor ID or name. |
|
|
148
182
|
|
|
149
183
|
### [Areas](https://www.home-assistant.io/docs/configuration/templating/#areas)
|
|
150
184
|
|
|
@@ -164,16 +198,17 @@ Functions used to determine an entity's state or an attribute.
|
|
|
164
198
|
|
|
165
199
|
### [Labels](https://www.home-assistant.io/docs/configuration/templating/#labels)
|
|
166
200
|
|
|
167
|
-
**NOTE**: Labels are not available in the `hass` object and must be retrieved asynchronously from the Home Assistant backend the first time `
|
|
201
|
+
**NOTE**: Labels are not available in the `hass` object and must be retrieved asynchronously from the Home Assistant backend the first time `ha-nunjucks` is imported. Since this package is otherwise synchronous, this can cause a race condition where no labels are found the first time `renderTemplate` is run. This generally resolves itself once the template re-renders.
|
|
168
202
|
|
|
169
|
-
| Name
|
|
170
|
-
|
|
|
171
|
-
| labels
|
|
172
|
-
| label_id
|
|
173
|
-
| label_name
|
|
174
|
-
|
|
|
175
|
-
|
|
|
176
|
-
|
|
|
203
|
+
| Name | Type | Arguments | Description |
|
|
204
|
+
| ----------------- | ---------------- | ----------------------- | ------------------------------------------------------------------------------------------ |
|
|
205
|
+
| labels | function, filter | lookup_value (optional) | Returns the full list of label IDs, or those for a given area ID, device ID, or entity ID. |
|
|
206
|
+
| label_id | function, filter | lookup_value | Returns the label ID for a given label name. |
|
|
207
|
+
| label_name | function, filter | lookup_value | Returns the label name for a given label ID. |
|
|
208
|
+
| label_description | function, filter | lookup_value | Returns the label description for a given label ID. |
|
|
209
|
+
| label_areas | function, filter | label_name_or_id | Returns the list of area IDs tied to a given label ID or name. |
|
|
210
|
+
| label_devices | function, filter | label_name_or_id | Returns the list of device IDs tied to a given label ID or name. |
|
|
211
|
+
| label_entities | function, filter | label_name_or_id | Returns the list of entity IDs tied to a given label ID or name. |
|
|
177
212
|
|
|
178
213
|
### [Immediate If](https://www.home-assistant.io/docs/configuration/templating/#immediate-if-iif)
|
|
179
214
|
|
|
@@ -191,21 +226,22 @@ A shorthand for an if else statement.
|
|
|
191
226
|
- JS Date is not as good at handling timezones as Python datetime. Be careful about timezone differences! You can try to account for this using the `utc` flags and/or by including a timezone offset in a datetime string to parse using `as_datetime` or `strptime`.
|
|
192
227
|
- Including time extensions in your templates does not cause them to refresh more regularly by themselves, although they will still update whenever the `hass` object does. If you are a developer, you have to implement this behavior yourself in your custom cards.
|
|
193
228
|
|
|
194
|
-
| Name | Type | Arguments | Description
|
|
195
|
-
| ---------------- | ---------------- | -------------------------------------------------------- |
|
|
196
|
-
| now | function | | Returns a datetime object that represents the current time in your time zone.
|
|
197
|
-
| utcnow | function | | Returns a datetime object of the current time in the UTC timezone.
|
|
198
|
-
| today_at | function, filter | value | Converts a string containing a military time format to a datetime object with today’s date in your time zone. Defaults to midnight (00:00).
|
|
199
|
-
| as_datetime | function, filter | value, fallback (optional), utc (default true) | Converts a string containing a timestamp, or valid UNIX timestamp, to a datetime object. If that fails, it returns the fallback value or, if omitted, raises an error. When the input is already a datetime object it will be returned as is. in case the input is a datetime.date object, midnight will be added as time.
|
|
200
|
-
| as_timestamp | function, filter | value, fallback (optional) | Converts a datetime object or string to UNIX timestamp. If that fails, returns the fallback value, or if omitted raises an error.
|
|
201
|
-
| as_local | function, filter | value | Converts a datetime object to local time.
|
|
202
|
-
| strptime | function | value, format, fallback (optional), utc (default false) | Parses a string based on a [format](https://d3js.org/d3-time-format#locale_format) and returns a datetime object. If that fails, it returns the default value or, if omitted, raises an error.
|
|
203
|
-
|
|
|
204
|
-
|
|
|
205
|
-
|
|
|
206
|
-
|
|
|
207
|
-
|
|
|
208
|
-
|
|
|
229
|
+
| Name | Type | Arguments | Description |
|
|
230
|
+
| ---------------- | ---------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
231
|
+
| now | function | | Returns a datetime object that represents the current time in your time zone. |
|
|
232
|
+
| utcnow | function | | Returns a datetime object of the current time in the UTC timezone. |
|
|
233
|
+
| today_at | function, filter | value | Converts a string containing a military time format to a datetime object with today’s date in your time zone. Defaults to midnight (00:00). |
|
|
234
|
+
| as_datetime | function, filter | value, fallback (optional), utc (default true) | Converts a string containing a timestamp, or valid UNIX timestamp, to a datetime object. If that fails, it returns the fallback value or, if omitted, raises an error. When the input is already a datetime object it will be returned as is. in case the input is a datetime.date object, midnight will be added as time. |
|
|
235
|
+
| as_timestamp | function, filter | value, fallback (optional) | Converts a datetime object or string to UNIX timestamp. If that fails, returns the fallback value, or if omitted raises an error. |
|
|
236
|
+
| as_local | function, filter | value | Converts a datetime object to local time. |
|
|
237
|
+
| strptime | function | value, format, fallback (optional), utc (default false) | Parses a string based on a [format](https://d3js.org/d3-time-format#locale_format) and returns a datetime object. If that fails, it returns the default value or, if omitted, raises an error. |
|
|
238
|
+
| relative_time | function, filter | value | Returns a human readable string indicating the differenceb between now and an input past datetime object. Only uses the largest unit (years, months, days, hours, minutes, seconds) rounded. |
|
|
239
|
+
| time_since | function, filter | value, precision (default 1) | Returns a human readable string indicating the difference between now and an input past datetime object. `precision` indicates how many units (years, months, days, hours, minutes, seconds) to use, with the last unit being rounded and 0 being the same as 6. If the input datetime is in the future it returns the input. If the input datetime is not a datetime object it returns nothing. |
|
|
240
|
+
| time_until | function, filter | value, precision (default 1) | Returns a human readable string indicating the difference between now and an input future datetime object. `precision` indicates how many units (years, months, days, hours, minutes, seconds) to use, with the last unit being rounded and 0 being the same as 6. If the input datetime is in the past it returns the input. If the input datetime is not a datetime object it returns nothing. |
|
|
241
|
+
| as_timedelta | function, filter | value | Converts a string to a timedelta object. Expects data in the format `DD HH:MM:SS.uuuuuu`, `DD HH:MM:SS,uuuuuu`, or as specified by ISO 8601 (e.g. `P4DT1H15M20S` which is equivalent to `4 1:15:20`) or PostgreSQL’s day-time interval format (e.g. `3 days 04:05:06`). |
|
|
242
|
+
| timestamp_local | filter | value, fallback (optional) | Converts a UNIX timestamp to the ISO format string representation as date/time in your local timezone. If that fails, returns the `fallback` value, or if omitted raises an error. |
|
|
243
|
+
| timestamp_utc | filter | value, fallback (optional) | Converts a UNIX timestamp to the ISO format string representation as date/time in UTC timezone. If that fails, returns the `fallback` value, or if omitted raises an error. |
|
|
244
|
+
| timestamp_custom | filter | value, format, local (default true), fallback (optional) | Converts a UNIX timestamp to its string representation based on a custom format. Uses the local timezone by default. If that fails, returns the `fallback` value, or if omitted raises an error. |
|
|
209
245
|
|
|
210
246
|
In addition to these functions, you have access to [a datetime library](https://github.com/Nerwyn/ts-py-datetime) which emulates the Python datetime module in TypeScript. You can instantiate `date`, `time`, `datetime`, and `timedelta` objects using the `dt` object. You can then access it's class methods using these objects. To use the static method and constants of these classes, you can reference them directly without prefixing them with `dt`. See the README in the datetime repository linked above for more information on how to use it.
|
|
211
247
|
|
|
@@ -228,6 +264,12 @@ In addition to these functions, you have access to [a datetime library](https://
|
|
|
228
264
|
| to_json | filter | obj, ensure_ascii, pretty_print, sort_keys | Turn an object into a JSON string. `ensure_ascii` converts unicode characters into escape sequences. `pretty_print` formats the output with new lines and an indent of two spaces. `sort_keys` sorts the keys of the JSON object. **Consider using the nunjucks `safe` filter with this, or the nunjucks `dump` filter instead.** |
|
|
229
265
|
| from_json | filter | value | Parse a string as JSON. |
|
|
230
266
|
|
|
267
|
+
### [Is Defined](https://www.home-assistant.io/docs/configuration/templating/#is-defined)
|
|
268
|
+
|
|
269
|
+
| Name | Type | Arguments | Description |
|
|
270
|
+
| ---------- | ------ | --------- | -------------------------------------------------------------- |
|
|
271
|
+
| is_defined | filter | value | Returns the value if it is defined, otherwise throws an error. |
|
|
272
|
+
|
|
231
273
|
### [Distance](https://www.home-assistant.io/docs/configuration/templating/#distance)
|
|
232
274
|
|
|
233
275
|
| Name | Type | Arguments | Description |
|
|
@@ -287,10 +329,11 @@ In addition to these functions, you have access to [a datetime library](https://
|
|
|
287
329
|
|
|
288
330
|
### [Type Conversions](https://www.home-assistant.io/docs/configuration/templating/#type-conversions)
|
|
289
331
|
|
|
290
|
-
| Name | Type
|
|
291
|
-
| ---- |
|
|
292
|
-
| set | function
|
|
293
|
-
| list | function
|
|
332
|
+
| Name | Type | Arguments | Description |
|
|
333
|
+
| ---- | ---------------- | --------- | ------------------------------------------------------ |
|
|
334
|
+
| set | function | args | Convert a list/array to a set. Removes duplicates. |
|
|
335
|
+
| list | function | args | Convert a set to an array. Does not remove duplicates. |
|
|
336
|
+
| str | function, filter | value | Return the string representation of the input. |
|
|
294
337
|
|
|
295
338
|
### [Iterating Multiple Objects](https://www.home-assistant.io/docs/configuration/templating/#iterating-multiple-objects)
|
|
296
339
|
|
|
@@ -298,6 +341,16 @@ In addition to these functions, you have access to [a datetime library](https://
|
|
|
298
341
|
| ---- | -------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
299
342
|
| zip | function | args | Use to iterate over multiple collections in one operation. If given one array will perform the opposite action and unzip the list. |
|
|
300
343
|
|
|
344
|
+
### [String filters](https://www.home-assistant.io/docs/configuration/templating/#string-filters)
|
|
345
|
+
|
|
346
|
+
| Name | Type | Arguments | Description |
|
|
347
|
+
| ------------- | ------ | ----------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
348
|
+
| urlencode | filter | value | Convert an object to a percent-encoded ASCII text string. |
|
|
349
|
+
| slugify | filter | value, separator (default \_) | Convert a given string into a "slug". |
|
|
350
|
+
| ordinal | filter | value | Convert an integer into a number defining a position in a series (e.g. `1st`, `2nd`, `3rd`, `4th`, etc). |
|
|
351
|
+
| base64_encode | filter | value | Encodes a string or bytes to a base 64 string. |
|
|
352
|
+
| base64_decode | filter | value | Decodes a base 64 string to a UTF-8 string. |
|
|
353
|
+
|
|
301
354
|
### [Regular Expressions](https://www.home-assistant.io/docs/configuration/templating/#regular-expressions)
|
|
302
355
|
|
|
303
356
|
**NOTE**: The format of regular expressions in nunjucks is different than jinja2. You may want to read the [Nunjucks](https://mozilla.github.io/nunjucks/templating.html#regular-expressions) and [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions) documentation.
|
|
@@ -315,10 +368,9 @@ In addition to these functions, you have access to [a datetime library](https://
|
|
|
315
368
|
|
|
316
369
|
Functions that are not from the Home Assistant templating documentation.
|
|
317
370
|
|
|
318
|
-
| Name | Type
|
|
319
|
-
| ----------- |
|
|
320
|
-
| match_media | function
|
|
321
|
-
| str | function, filter | value | Return the string representation of the input. |
|
|
371
|
+
| Name | Type | Arguments | Description |
|
|
372
|
+
| ----------- | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
373
|
+
| match_media | function | value | Returns the boolean result of the provided [CSS media query](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries/Using_media_queries). |
|
|
322
374
|
|
|
323
375
|
[last-commit-shield]: https://img.shields.io/github/last-commit/Nerwyn/ha-nunjucks?style=for-the-badge
|
|
324
376
|
[commits]: https://github.com/Nerwyn/ha-nunjucks/commits/main
|
package/dist/filters.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { area_devices, area_entities, area_id, area_name } from './utils/areas';
|
|
2
2
|
import { contains } from './utils/contains';
|
|
3
|
-
import { device_attr, device_entities, device_id } from './utils/devices';
|
|
3
|
+
import { device_attr, device_entities, device_id, device_name, } from './utils/devices';
|
|
4
4
|
import { closest } from './utils/distance';
|
|
5
|
-
import { floor_areas, floor_id, floor_name } from './utils/floors';
|
|
5
|
+
import { floor_areas, floor_entities, floor_id, floor_name, } from './utils/floors';
|
|
6
6
|
import { expand } from './utils/groups';
|
|
7
7
|
import { iif } from './utils/iif';
|
|
8
|
-
import { from_json, to_json } from './utils/json';
|
|
9
|
-
import { label_areas, label_devices, label_entities, label_id, label_name, labels, } from './utils/labels';
|
|
8
|
+
import { from_json, is_defined, to_json } from './utils/json';
|
|
9
|
+
import { label_areas, label_description, label_devices, label_entities, label_id, label_name, labels, } from './utils/labels';
|
|
10
10
|
import { str } from './utils/miscellaneous';
|
|
11
11
|
import { acos, add, asin, atan, atan2, average, bitwise_and, bitwise_not, bitwise_or, bitwise_xor, bool, cos, is_number, log, max, median, min, multiply, ord, sin, sqrt, statistical_mode, tan, } from './utils/numeric';
|
|
12
12
|
import { regex_findall, regex_findall_index, regex_replace, } from './utils/regexp';
|
|
13
|
-
import { attr_name_translated, attr_value_translated, state_translated, } from './utils/state_translated';
|
|
13
|
+
import { attr_name_translated, attr_value_translated, date_translated, datetime_translated, number_translated, state_translated, time_translated, } from './utils/state_translated';
|
|
14
14
|
import { has_value, state_attr, states } from './utils/states';
|
|
15
|
-
import {
|
|
15
|
+
import { base64_decode, base64_encode, ordinal, slugify, } from './utils/string_filters';
|
|
16
|
+
import { as_datetime, as_local, as_timedelta, as_timestamp, relative_time, time_since, time_until, timestamp_custom, timestamp_local, timestamp_utc, today_at, } from './utils/time';
|
|
16
17
|
export function addFilters(env) {
|
|
17
18
|
for (const func in FILTERS) {
|
|
18
19
|
env.addFilter(func, function (...args) {
|
|
@@ -41,10 +42,12 @@ const HASS_FILTERS = {
|
|
|
41
42
|
device_entities,
|
|
42
43
|
device_attr,
|
|
43
44
|
device_id,
|
|
45
|
+
device_name,
|
|
44
46
|
// Floors
|
|
45
47
|
floor_id,
|
|
46
48
|
floor_name,
|
|
47
49
|
floor_areas,
|
|
50
|
+
floor_entities,
|
|
48
51
|
// Areas
|
|
49
52
|
area_id,
|
|
50
53
|
area_name,
|
|
@@ -64,19 +67,27 @@ const FILTERS = {
|
|
|
64
67
|
// Labels
|
|
65
68
|
label_id,
|
|
66
69
|
label_name,
|
|
70
|
+
label_description,
|
|
67
71
|
// Time
|
|
68
72
|
today_at,
|
|
73
|
+
as_timedelta,
|
|
69
74
|
as_datetime,
|
|
70
75
|
as_timestamp,
|
|
71
76
|
as_local,
|
|
77
|
+
relative_time,
|
|
72
78
|
time_since,
|
|
73
79
|
time_until,
|
|
74
80
|
timestamp_local,
|
|
75
81
|
timestamp_utc,
|
|
76
82
|
timestamp_custom,
|
|
83
|
+
date_translated,
|
|
84
|
+
time_translated,
|
|
85
|
+
datetime_translated,
|
|
77
86
|
// To/From JSON
|
|
78
87
|
to_json,
|
|
79
88
|
from_json,
|
|
89
|
+
// Is Defined
|
|
90
|
+
is_defined,
|
|
80
91
|
// Distance
|
|
81
92
|
closest,
|
|
82
93
|
// Contains
|
|
@@ -107,10 +118,17 @@ const FILTERS = {
|
|
|
107
118
|
ord,
|
|
108
119
|
multiply,
|
|
109
120
|
add,
|
|
121
|
+
number_translated,
|
|
122
|
+
// Type conversions
|
|
123
|
+
str,
|
|
124
|
+
// String filters
|
|
125
|
+
// urlencode filter is built into nunjucks
|
|
126
|
+
slugify,
|
|
127
|
+
ordinal,
|
|
128
|
+
base64_encode,
|
|
129
|
+
base64_decode,
|
|
110
130
|
// Regular Expressions
|
|
111
131
|
regex_replace,
|
|
112
132
|
regex_findall,
|
|
113
133
|
regex_findall_index,
|
|
114
|
-
// Miscellaneous
|
|
115
|
-
str,
|
|
116
134
|
};
|
package/dist/globals.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { area_devices, area_entities, area_id, area_name, areas, } from './utils/areas';
|
|
2
|
-
import { device_attr, device_entities, device_id, is_device_attr, } from './utils/devices';
|
|
2
|
+
import { device_attr, device_entities, device_id, device_name, is_device_attr, } from './utils/devices';
|
|
3
3
|
import { closest, distance } from './utils/distance';
|
|
4
4
|
import { is_hidden_entity } from './utils/entities';
|
|
5
|
-
import { floor_areas, floor_id, floor_name, floors } from './utils/floors';
|
|
5
|
+
import { floor_areas, floor_entities, floor_id, floor_name, floors, } from './utils/floors';
|
|
6
6
|
import { expand } from './utils/groups';
|
|
7
7
|
import { iif } from './utils/iif';
|
|
8
8
|
import { integration_entities } from './utils/integrations';
|
|
9
|
-
import { label_areas, label_devices, label_entities, label_id, label_name, labels, } from './utils/labels';
|
|
9
|
+
import { label_areas, label_description, label_devices, label_entities, label_id, label_name, labels, } from './utils/labels';
|
|
10
10
|
import { match_media, str } from './utils/miscellaneous';
|
|
11
11
|
import { acos, asin, atan, atan2, average, bool, cos, e, float, inf, int, is_number, log, max, median, min, pi, sin, sqrt, statistical_mode, tan, tau, } from './utils/numeric';
|
|
12
|
-
import { attr_name_translated, attr_value_translated, state_translated, } from './utils/state_translated';
|
|
12
|
+
import { attr_name_translated, attr_value_translated, date_translated, datetime_translated, number_translated, state_translated, time_translated, } from './utils/state_translated';
|
|
13
13
|
import { has_value, is_state, is_state_attr, state_attr, states, } from './utils/states';
|
|
14
|
-
import {
|
|
14
|
+
import { slugify } from './utils/string_filters';
|
|
15
|
+
import { as_datetime, as_local, as_timedelta, as_timestamp, now, relative_time, strptime, time_since, time_until, today_at, utcnow, } from './utils/time';
|
|
15
16
|
import { list, set } from './utils/type_conversions';
|
|
16
17
|
import { zip } from './utils/zip';
|
|
17
18
|
import dt, { date, datetime, time, timedelta } from 'ts-py-datetime';
|
|
@@ -56,11 +57,13 @@ const HASS_GLOBALS = {
|
|
|
56
57
|
device_attr,
|
|
57
58
|
is_device_attr,
|
|
58
59
|
device_id,
|
|
60
|
+
device_name,
|
|
59
61
|
// Floors
|
|
60
62
|
floors,
|
|
61
63
|
floor_id,
|
|
62
64
|
floor_name,
|
|
63
65
|
floor_areas,
|
|
66
|
+
floor_entities,
|
|
64
67
|
// Areas
|
|
65
68
|
areas,
|
|
66
69
|
area_id,
|
|
@@ -84,6 +87,7 @@ const GLOBALS = {
|
|
|
84
87
|
// Labels
|
|
85
88
|
label_id,
|
|
86
89
|
label_name,
|
|
90
|
+
label_description,
|
|
87
91
|
// Time
|
|
88
92
|
now,
|
|
89
93
|
utcnow,
|
|
@@ -92,9 +96,13 @@ const GLOBALS = {
|
|
|
92
96
|
as_timestamp,
|
|
93
97
|
as_local,
|
|
94
98
|
strptime,
|
|
99
|
+
relative_time,
|
|
95
100
|
time_since,
|
|
96
101
|
time_until,
|
|
97
102
|
as_timedelta,
|
|
103
|
+
date_translated,
|
|
104
|
+
time_translated,
|
|
105
|
+
datetime_translated,
|
|
98
106
|
// Numeric,
|
|
99
107
|
float,
|
|
100
108
|
is_number,
|
|
@@ -114,14 +122,17 @@ const GLOBALS = {
|
|
|
114
122
|
average,
|
|
115
123
|
median,
|
|
116
124
|
statistical_mode,
|
|
125
|
+
number_translated,
|
|
117
126
|
// Type Conversions
|
|
118
127
|
set,
|
|
119
128
|
list,
|
|
129
|
+
str,
|
|
120
130
|
// Iterating Multiple Objects
|
|
121
131
|
zip,
|
|
132
|
+
// String fitlers
|
|
133
|
+
slugify,
|
|
122
134
|
// Miscellaneous
|
|
123
135
|
match_media,
|
|
124
|
-
str,
|
|
125
136
|
};
|
|
126
137
|
const CONST_GLOBALS = {
|
|
127
138
|
e,
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,13 @@ import { HomeAssistant } from './models/interfaces/hass';
|
|
|
4
4
|
* @param {HomeAssistant} hass The Home Assistant object
|
|
5
5
|
* @param {string} str The template string to render
|
|
6
6
|
* @param {object} [context] Additional context to expose to nunjucks
|
|
7
|
+
* @param {boolean} [validate=true] Validate that the input contains a template.
|
|
7
8
|
* @returns {string | boolean} The rendered template string if a string was provided, otherwise the unaltered input
|
|
8
9
|
*/
|
|
9
|
-
export declare function renderTemplate(hass: HomeAssistant, str: string, context?: object): string | boolean;
|
|
10
|
+
export declare function renderTemplate(hass: HomeAssistant, str: string, context?: object, validate?: boolean): string | boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Test if the input contains a valid template
|
|
13
|
+
* @param {any} str the variable to check
|
|
14
|
+
* @returns if the input is a string that contains a template
|
|
15
|
+
*/
|
|
16
|
+
export declare function hasTemplate(str: any): boolean;
|
package/dist/index.js
CHANGED
|
@@ -5,49 +5,74 @@ import { addTests } from './tests';
|
|
|
5
5
|
import { fetchLabelRegistry } from './utils/labels';
|
|
6
6
|
import { buildStatesObject } from './utils/states';
|
|
7
7
|
if (!window.haNunjucks) {
|
|
8
|
-
window.haNunjucks = {
|
|
8
|
+
window.haNunjucks = {
|
|
9
|
+
states: {},
|
|
10
|
+
labelRegistry: {},
|
|
11
|
+
};
|
|
12
|
+
// Async setup label registry and states object on import
|
|
13
|
+
const registrySetup = async () => {
|
|
14
|
+
const ha = document.querySelector('home-assistant');
|
|
15
|
+
if (!ha ||
|
|
16
|
+
!ha.hass ||
|
|
17
|
+
!ha.hass.connected ||
|
|
18
|
+
!ha.hass.connection ||
|
|
19
|
+
!ha.hass.connection.connected) {
|
|
20
|
+
setTimeout(registrySetup, 10);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
// Number and datetime translators
|
|
24
|
+
window.haNunjucks.numberFormat = new Intl.NumberFormat(ha.hass.language);
|
|
25
|
+
window.haNunjucks.dateFormat = new Intl.DateTimeFormat(ha.hass.language, { dateStyle: 'full' });
|
|
26
|
+
window.haNunjucks.timeFormat = new Intl.DateTimeFormat(ha.hass.language, { timeStyle: 'long' });
|
|
27
|
+
window.haNunjucks.datetimeFormat = new Intl.DateTimeFormat(ha.hass.language, { dateStyle: 'full', timeStyle: 'long' });
|
|
28
|
+
window.haNunjucks.ordinalFormat = new Intl.PluralRules('en-US', // ha.hass.language, // Use english for proper numeric suffixes
|
|
29
|
+
{ type: 'ordinal' });
|
|
30
|
+
// Label registry and states object
|
|
31
|
+
window.haNunjucks.hass = ha.hass;
|
|
32
|
+
fetchLabelRegistry();
|
|
33
|
+
buildStatesObject();
|
|
34
|
+
};
|
|
35
|
+
registrySetup();
|
|
36
|
+
// Initialize global ha-nunjucks environment
|
|
9
37
|
nunjucks.installJinjaCompat();
|
|
10
38
|
window.haNunjucks.env = addTests(addFilters(addGlobals(new nunjucks.Environment())));
|
|
11
|
-
window.haNunjucks.states = {};
|
|
12
|
-
window.hassConnection?.then((hassConnection) => {
|
|
13
|
-
const entities = hassConnection?.conn?._entityRegistryDisplay?.state
|
|
14
|
-
?.entities;
|
|
15
|
-
for (const entity of entities) {
|
|
16
|
-
const [domain, _id] = entity.ei.split('.');
|
|
17
|
-
window.haNunjucks.states[domain] ??= {};
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
39
|
}
|
|
21
40
|
/**
|
|
22
41
|
* Render a Home Assistant template string using nunjucks
|
|
23
42
|
* @param {HomeAssistant} hass The Home Assistant object
|
|
24
43
|
* @param {string} str The template string to render
|
|
25
44
|
* @param {object} [context] Additional context to expose to nunjucks
|
|
45
|
+
* @param {boolean} [validate=true] Validate that the input contains a template.
|
|
26
46
|
* @returns {string | boolean} The rendered template string if a string was provided, otherwise the unaltered input
|
|
27
47
|
*/
|
|
28
|
-
export function renderTemplate(hass, str, context) {
|
|
29
|
-
if (!
|
|
30
|
-
|
|
48
|
+
export function renderTemplate(hass, str, context, validate = true) {
|
|
49
|
+
if (validate && !hasTemplate(str)) {
|
|
50
|
+
return str;
|
|
31
51
|
}
|
|
32
52
|
window.haNunjucks.hass = hass;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (['true', 'false'].includes(lowerStr)) {
|
|
48
|
-
return lowerStr == 'true';
|
|
49
|
-
}
|
|
50
|
-
return str;
|
|
53
|
+
buildStatesObject();
|
|
54
|
+
str = window.haNunjucks.env
|
|
55
|
+
.renderString(structuredClone(str), {
|
|
56
|
+
hass,
|
|
57
|
+
_states: window.haNunjucks.states,
|
|
58
|
+
...context,
|
|
59
|
+
})
|
|
60
|
+
.trim();
|
|
61
|
+
if ([undefined, null, 'undefined', 'null', 'None'].includes(str)) {
|
|
62
|
+
return '';
|
|
63
|
+
}
|
|
64
|
+
const lowerStr = str.toLowerCase();
|
|
65
|
+
if (['true', 'false'].includes(lowerStr)) {
|
|
66
|
+
return lowerStr == 'true';
|
|
51
67
|
}
|
|
52
68
|
return str;
|
|
53
69
|
}
|
|
70
|
+
const hasTemplateRegex = /{{.*?}}|{%.*?%}/;
|
|
71
|
+
/**
|
|
72
|
+
* Test if the input contains a valid template
|
|
73
|
+
* @param {any} str the variable to check
|
|
74
|
+
* @returns if the input is a string that contains a template
|
|
75
|
+
*/
|
|
76
|
+
export function hasTemplate(str) {
|
|
77
|
+
return hasTemplateRegex.test(str);
|
|
78
|
+
}
|
|
@@ -37,3 +37,6 @@ export interface HomeAssistant {
|
|
|
37
37
|
formatEntityAttributeValue(stateObj: HassEntity, attribute: string, value?: any): string;
|
|
38
38
|
formatEntityAttributeName(stateObj: HassEntity, attribute: string): string;
|
|
39
39
|
}
|
|
40
|
+
export interface HassElement extends HTMLElement {
|
|
41
|
+
hass: HomeAssistant;
|
|
42
|
+
}
|
package/dist/utils/areas.js
CHANGED
|
@@ -20,7 +20,8 @@ export function area_id(hass, lookup_value) {
|
|
|
20
20
|
return hass.devices[lookup_value].area_id;
|
|
21
21
|
}
|
|
22
22
|
for (const areaId in hass.areas) {
|
|
23
|
-
if (hass.areas[areaId].name == lookup_value
|
|
23
|
+
if (hass.areas[areaId].name == lookup_value ||
|
|
24
|
+
hass.areas[areaId].aliases?.includes(lookup_value)) {
|
|
24
25
|
return areaId;
|
|
25
26
|
}
|
|
26
27
|
}
|
|
@@ -57,12 +58,15 @@ export function area_entities(hass, area_name_or_id) {
|
|
|
57
58
|
try {
|
|
58
59
|
const entityIds = [];
|
|
59
60
|
if (area_name_or_id) {
|
|
61
|
+
let areaId = area_name_or_id;
|
|
62
|
+
if (!hass.areas[area_name_or_id]) {
|
|
63
|
+
areaId = area_id(hass, area_name_or_id) ?? area_name_or_id;
|
|
64
|
+
}
|
|
60
65
|
const deviceIds = area_devices(hass, area_name_or_id);
|
|
61
|
-
for (const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
+
for (const entityId in hass.entities) {
|
|
67
|
+
if (deviceIds.includes(hass.entities[entityId].device_id) ||
|
|
68
|
+
hass.entities[entityId].area_id == areaId) {
|
|
69
|
+
entityIds.push(entityId);
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
72
|
entityIds.sort();
|
|
@@ -79,7 +83,8 @@ export function area_devices(hass, area_name_or_id) {
|
|
|
79
83
|
if (area_name_or_id) {
|
|
80
84
|
if (!(area_name_or_id in hass.areas)) {
|
|
81
85
|
for (const areaId in hass.areas) {
|
|
82
|
-
if (hass.areas[areaId].name == area_name_or_id
|
|
86
|
+
if (hass.areas[areaId].name == area_name_or_id ||
|
|
87
|
+
hass.areas[areaId].aliases?.includes(area_name_or_id)) {
|
|
83
88
|
area_name_or_id = areaId;
|
|
84
89
|
break;
|
|
85
90
|
}
|
package/dist/utils/devices.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export declare function device_entities(hass: HomeAssistant, device_id: string):
|
|
|
4
4
|
export declare function device_attr(hass: HomeAssistant, device_or_entity_id: string, attr_name: keyof DeviceRegistryEntry): any;
|
|
5
5
|
export declare function is_device_attr(hass: HomeAssistant, device_or_entity_id: string, attr_name: keyof DeviceRegistryEntry, attr_value: string): boolean;
|
|
6
6
|
export declare function device_id(hass: HomeAssistant, entity_id: string): string | undefined;
|
|
7
|
+
export declare function device_name(hass: HomeAssistant, lookup_value: string): string | null | undefined;
|
package/dist/utils/devices.js
CHANGED
|
@@ -55,3 +55,18 @@ export function device_id(hass, entity_id) {
|
|
|
55
55
|
return undefined;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
export function device_name(hass, lookup_value) {
|
|
59
|
+
try {
|
|
60
|
+
if (hass.entities[lookup_value]) {
|
|
61
|
+
lookup_value = hass.entities[lookup_value].device_id;
|
|
62
|
+
}
|
|
63
|
+
const device = hass.devices[lookup_value];
|
|
64
|
+
if (device) {
|
|
65
|
+
return device.name_by_user ?? device.name;
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
package/dist/utils/floors.d.ts
CHANGED
|
@@ -3,3 +3,4 @@ export declare function floors(hass: HomeAssistant): string[];
|
|
|
3
3
|
export declare function floor_id(hass: HomeAssistant, lookup_value: string): string | null | undefined;
|
|
4
4
|
export declare function floor_name(hass: HomeAssistant, lookup_value: string): string | undefined;
|
|
5
5
|
export declare function floor_areas(hass: HomeAssistant, floor_name_or_id: string): string[];
|
|
6
|
+
export declare function floor_entities(hass: HomeAssistant, floor_name_or_id: string): string[];
|
package/dist/utils/floors.js
CHANGED
|
@@ -4,25 +4,37 @@ export function floors(hass) {
|
|
|
4
4
|
export function floor_id(hass, lookup_value) {
|
|
5
5
|
try {
|
|
6
6
|
let areaId = lookup_value;
|
|
7
|
+
// Entity ID
|
|
7
8
|
if (hass.entities[lookup_value]) {
|
|
8
9
|
areaId = hass.entities[lookup_value].area_id ?? areaId;
|
|
9
10
|
lookup_value =
|
|
10
11
|
hass.entities[lookup_value].device_id ?? lookup_value;
|
|
11
12
|
}
|
|
12
13
|
if (lookup_value) {
|
|
14
|
+
// Device ID
|
|
13
15
|
if (hass.devices[lookup_value]) {
|
|
14
16
|
areaId = hass.devices[lookup_value].area_id ?? areaId;
|
|
15
17
|
}
|
|
18
|
+
// Area ID
|
|
16
19
|
if (hass.areas[areaId]) {
|
|
17
20
|
return hass.areas[areaId].floor_id;
|
|
18
21
|
}
|
|
19
22
|
else {
|
|
23
|
+
// Area name or alias
|
|
20
24
|
for (const areaId in hass.areas) {
|
|
21
|
-
if (hass.areas[areaId].name == lookup_value
|
|
25
|
+
if (hass.areas[areaId].name == lookup_value ||
|
|
26
|
+
hass.areas[areaId].aliases?.includes(lookup_value)) {
|
|
22
27
|
return hass.areas[areaId].floor_id;
|
|
23
28
|
}
|
|
24
29
|
}
|
|
25
30
|
}
|
|
31
|
+
// Floor name or alias
|
|
32
|
+
for (const floorId in hass.floors) {
|
|
33
|
+
if (hass.floors[floorId].name == lookup_value ||
|
|
34
|
+
hass.floors[floorId].aliases?.includes(lookup_value)) {
|
|
35
|
+
return floorId;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
26
38
|
}
|
|
27
39
|
return undefined;
|
|
28
40
|
}
|
|
@@ -50,7 +62,8 @@ export function floor_areas(hass, floor_name_or_id) {
|
|
|
50
62
|
}
|
|
51
63
|
else {
|
|
52
64
|
for (const id in hass.floors) {
|
|
53
|
-
if (hass.floors[id].name == floor_name_or_id
|
|
65
|
+
if (hass.floors[id].name == floor_name_or_id ||
|
|
66
|
+
hass.floors[id].aliases?.includes(floor_name_or_id)) {
|
|
54
67
|
floorId = id;
|
|
55
68
|
break;
|
|
56
69
|
}
|
|
@@ -71,3 +84,22 @@ export function floor_areas(hass, floor_name_or_id) {
|
|
|
71
84
|
return [];
|
|
72
85
|
}
|
|
73
86
|
}
|
|
87
|
+
export function floor_entities(hass, floor_name_or_id) {
|
|
88
|
+
try {
|
|
89
|
+
const res = new Set();
|
|
90
|
+
const areas = floor_areas(hass, floor_name_or_id);
|
|
91
|
+
for (const entityId in hass.entities) {
|
|
92
|
+
if (areas.includes(hass.entities[entityId].area_id)) {
|
|
93
|
+
res.add(entityId);
|
|
94
|
+
for (const subEntityId of hass.states[entityId]?.attributes
|
|
95
|
+
?.entity_id ?? []) {
|
|
96
|
+
res.add(subEntityId);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return Array.from(res);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
}
|
package/dist/utils/json.d.ts
CHANGED
package/dist/utils/json.js
CHANGED
|
@@ -21,3 +21,9 @@ export function to_json(obj, ensure_ascii = false, pretty_print = false, sort_ke
|
|
|
21
21
|
export function from_json(value) {
|
|
22
22
|
return JSON.parse(value);
|
|
23
23
|
}
|
|
24
|
+
export function is_defined(value) {
|
|
25
|
+
if (value == undefined) {
|
|
26
|
+
throw Error('UndefinedError: input is undefined');
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
package/dist/utils/labels.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { HomeAssistant } from '../models/interfaces/hass';
|
|
2
|
-
export declare function fetchLabelRegistry(
|
|
2
|
+
export declare function fetchLabelRegistry(): Promise<void>;
|
|
3
3
|
export declare function labels(hass: HomeAssistant, lookup_value?: string): string[];
|
|
4
4
|
export declare function label_id(lookup_value: string): string | undefined;
|
|
5
5
|
export declare function label_name(lookup_value: string): string;
|
|
6
|
+
export declare function label_description(lookup_value: string): string | undefined;
|
|
6
7
|
export declare function label_areas(hass: HomeAssistant, label_name_or_id: string): string[];
|
|
7
8
|
export declare function label_devices(hass: HomeAssistant, label_name_or_id: string): string[];
|
|
8
9
|
export declare function label_entities(hass: HomeAssistant, label_name_or_id: string): string[];
|
package/dist/utils/labels.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
export async function fetchLabelRegistry(
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
for (const label of labels) {
|
|
9
|
-
window.haNunjucks.labelRegistry[label.label_id] = label;
|
|
10
|
-
}
|
|
1
|
+
export async function fetchLabelRegistry() {
|
|
2
|
+
const labels = await window.haNunjucks.hass.connection.sendMessagePromise({
|
|
3
|
+
type: 'config/label_registry/list',
|
|
4
|
+
});
|
|
5
|
+
labels.sort((ent1, ent2) => ent1.name.localeCompare(ent2.name));
|
|
6
|
+
for (const label of labels) {
|
|
7
|
+
window.haNunjucks.labelRegistry[label.label_id] = label;
|
|
11
8
|
}
|
|
12
9
|
}
|
|
13
10
|
export function labels(hass, lookup_value) {
|
|
@@ -35,6 +32,9 @@ export function label_id(lookup_value) {
|
|
|
35
32
|
export function label_name(lookup_value) {
|
|
36
33
|
return window.haNunjucks.labelRegistry[lookup_value]?.name;
|
|
37
34
|
}
|
|
35
|
+
export function label_description(lookup_value) {
|
|
36
|
+
return window.haNunjucks.labelRegistry[lookup_value]?.description;
|
|
37
|
+
}
|
|
38
38
|
export function label_areas(hass, label_name_or_id) {
|
|
39
39
|
try {
|
|
40
40
|
const areaIds = [];
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
import { date, datetime, time } from 'ts-py-datetime';
|
|
1
2
|
import { HomeAssistant } from '../models/interfaces/hass';
|
|
2
3
|
export declare function state_translated(hass: HomeAssistant, entity_id: string, state?: string): string;
|
|
3
4
|
export declare function attr_name_translated(hass: HomeAssistant, entity_id: string, attr_name: string): string;
|
|
4
5
|
export declare function attr_value_translated(hass: HomeAssistant, entity_id: string, attr_name: string, attr_value?: string): any;
|
|
6
|
+
export declare function number_translated(value: number, precision?: number): string | number;
|
|
7
|
+
export declare function date_translated(value: date | datetime): string | date | datetime;
|
|
8
|
+
export declare function time_translated(value: time | datetime): string | datetime | time;
|
|
9
|
+
export declare function datetime_translated(value: datetime): string | datetime;
|
|
@@ -26,3 +26,40 @@ export function attr_value_translated(hass, entity_id, attr_name, attr_value) {
|
|
|
26
26
|
undefined);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
export function number_translated(value, precision) {
|
|
30
|
+
value = Number(value);
|
|
31
|
+
if (isNaN(value)) {
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
if (precision) {
|
|
35
|
+
return value.toLocaleString(window.haNunjucks.hass.language, {
|
|
36
|
+
minimumFractionDigits: precision,
|
|
37
|
+
maximumFractionDigits: precision,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return window.haNunjucks.numberFormat.format(value);
|
|
41
|
+
}
|
|
42
|
+
export function date_translated(value) {
|
|
43
|
+
try {
|
|
44
|
+
return window.haNunjucks.dateFormat.format(value.jsDate);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export function time_translated(value) {
|
|
51
|
+
try {
|
|
52
|
+
return window.haNunjucks.timeFormat.format(value.jsDate);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function datetime_translated(value) {
|
|
59
|
+
try {
|
|
60
|
+
return window.haNunjucks.datetimeFormat.format(value.jsDate);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
}
|
package/dist/utils/states.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HomeAssistant } from '../models/interfaces/hass';
|
|
2
|
+
export declare function buildStatesObject(): void;
|
|
2
3
|
export declare function states(hass: HomeAssistant, entity_id: string, rounded?: boolean | Record<string, boolean>, with_unit?: boolean): string | undefined;
|
|
3
4
|
export declare function is_state(hass: HomeAssistant, entity_id: string, value: string | string[]): boolean;
|
|
4
5
|
export declare function state_attr(hass: HomeAssistant, entity_id: string, attribute: string): any;
|
|
5
6
|
export declare function is_state_attr(hass: HomeAssistant, entity_id: string, attribute: string, value: string): boolean;
|
|
6
7
|
export declare function has_value(hass: HomeAssistant, entity_id: string): boolean;
|
|
7
|
-
export declare function buildStatesObject(): Record<string, Record<string, import("home-assistant-js-websocket").HassEntity>>;
|
package/dist/utils/states.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
export function buildStatesObject() {
|
|
2
|
+
for (const entityId in window.haNunjucks.hass.states) {
|
|
3
|
+
const [domain, id] = entityId.split('.');
|
|
4
|
+
window.haNunjucks.states[domain] ??= {};
|
|
5
|
+
window.haNunjucks.states[domain][id] =
|
|
6
|
+
window.haNunjucks.hass.states[entityId];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
1
9
|
export function states(hass, entity_id, rounded, with_unit) {
|
|
2
10
|
if (typeof rounded == 'object' && !Array.isArray(rounded)) {
|
|
3
11
|
with_unit = rounded.with_unit ?? with_unit;
|
|
@@ -64,12 +72,3 @@ export function has_value(hass, entity_id) {
|
|
|
64
72
|
return false;
|
|
65
73
|
}
|
|
66
74
|
}
|
|
67
|
-
export function buildStatesObject() {
|
|
68
|
-
for (const entityId in window.haNunjucks.hass.states) {
|
|
69
|
-
const [domain, id] = entityId.split('.');
|
|
70
|
-
window.haNunjucks.states[domain] ??= {};
|
|
71
|
-
window.haNunjucks.states[domain][id] =
|
|
72
|
-
window.haNunjucks.hass.states[entityId];
|
|
73
|
-
}
|
|
74
|
-
return window.haNunjucks.states;
|
|
75
|
-
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import slugifyLib from 'slugify';
|
|
2
|
+
export function slugify(str, separator = '_') {
|
|
3
|
+
return slugifyLib(str, {
|
|
4
|
+
replacement: separator,
|
|
5
|
+
lower: true,
|
|
6
|
+
strict: true,
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
export function ordinal(num) {
|
|
10
|
+
if (isNaN(num)) {
|
|
11
|
+
throw Error('Input must be a number');
|
|
12
|
+
}
|
|
13
|
+
const suffixes = {
|
|
14
|
+
one: 'st',
|
|
15
|
+
two: 'nd',
|
|
16
|
+
few: 'rd',
|
|
17
|
+
other: 'th',
|
|
18
|
+
};
|
|
19
|
+
const suffix = suffixes[window.haNunjucks.ordinalFormat.select(num)] || 'th';
|
|
20
|
+
return `${num}${suffix}`;
|
|
21
|
+
}
|
|
22
|
+
export function base64_encode(value) {
|
|
23
|
+
return btoa(value);
|
|
24
|
+
}
|
|
25
|
+
export function base64_decode(value) {
|
|
26
|
+
return atob(value);
|
|
27
|
+
}
|
package/dist/utils/time.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export declare function as_datetime(value: number | string | datetime | date, fa
|
|
|
6
6
|
export declare function as_timestamp(value: number | string | datetime | date, fallback?: string): string | number;
|
|
7
7
|
export declare function as_local(value: datetime): datetime;
|
|
8
8
|
export declare function strptime(value: string, format: string, fallback?: datetime | string | undefined | Record<string, datetime | string | boolean>, utc?: boolean): string | datetime | Record<string, string | boolean | datetime>;
|
|
9
|
+
export declare function relative_time(input: datetime): string | datetime;
|
|
9
10
|
export declare function time_since(input: datetime, precision?: number): string | datetime;
|
|
10
11
|
export declare function time_until(input: datetime, precision?: number): string | datetime;
|
|
11
12
|
export declare function as_timedelta(value: string): timedelta | null;
|
package/dist/utils/time.js
CHANGED
|
@@ -130,7 +130,7 @@ function timeDiff(input, precision = 1, until = false) {
|
|
|
130
130
|
if (diff <= 0) {
|
|
131
131
|
return input;
|
|
132
132
|
}
|
|
133
|
-
if (precision
|
|
133
|
+
if (precision < 1 || precision > 6) {
|
|
134
134
|
precision = 6;
|
|
135
135
|
}
|
|
136
136
|
const toSeconds = {
|
|
@@ -143,23 +143,29 @@ function timeDiff(input, precision = 1, until = false) {
|
|
|
143
143
|
};
|
|
144
144
|
const units = Object.keys(toSeconds);
|
|
145
145
|
let res = '';
|
|
146
|
-
let
|
|
147
|
-
for (let i = 0; i <
|
|
146
|
+
let p = 0;
|
|
147
|
+
for (let i = 0; i < units.length; i++) {
|
|
148
148
|
let value = diff / toSeconds[units[i]];
|
|
149
|
-
if (i ==
|
|
149
|
+
if (i == p - 1) {
|
|
150
150
|
value = Math.round(value);
|
|
151
151
|
}
|
|
152
152
|
else {
|
|
153
153
|
value = Math.floor(value);
|
|
154
154
|
}
|
|
155
|
-
if (
|
|
156
|
-
|
|
155
|
+
if (value > 0) {
|
|
156
|
+
p += 1;
|
|
157
157
|
res += ` ${value} ${units[i]}${value != 1 ? 's' : ''}`;
|
|
158
158
|
diff -= value * toSeconds[units[i]];
|
|
159
159
|
}
|
|
160
|
+
if (res.length && precision == p) {
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
160
163
|
}
|
|
161
164
|
return res.trim();
|
|
162
165
|
}
|
|
166
|
+
export function relative_time(input) {
|
|
167
|
+
return timeDiff(input);
|
|
168
|
+
}
|
|
163
169
|
export function time_since(input, precision = 1) {
|
|
164
170
|
return timeDiff(input, precision);
|
|
165
171
|
}
|
|
@@ -174,12 +180,10 @@ export function as_timedelta(value) {
|
|
|
174
180
|
/^\d*\.?\d*$/.test(value)) {
|
|
175
181
|
let daysStr, timeStr;
|
|
176
182
|
if (value.includes(' ')) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
[daysStr, timeStr] = value.split(' ');
|
|
182
|
-
}
|
|
183
|
+
[daysStr, timeStr] = value
|
|
184
|
+
.replace(/day(s?)/g, '')
|
|
185
|
+
.replace(/\s+/g, ' ')
|
|
186
|
+
.split(' ');
|
|
183
187
|
}
|
|
184
188
|
else {
|
|
185
189
|
daysStr = 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ha-nunjucks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Wrapper for nunjucks for use with Home Assistant frontend custom components to render templates",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"files": [
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
],
|
|
9
9
|
"type": "module",
|
|
10
10
|
"scripts": {
|
|
11
|
-
"test": "ts-mocha tests/**/*.test.ts",
|
|
11
|
+
"test": "ts-mocha tests/**/*.test.ts --require fixtures.cjs",
|
|
12
12
|
"build": "tsc",
|
|
13
13
|
"prelint": "tsc --noemit",
|
|
14
14
|
"lint": "eslint --config ./.eslintrc.config.cjs"
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"*": "prettier -w"
|
|
18
18
|
},
|
|
19
19
|
"author": "Nerwyn",
|
|
20
|
-
"license": "
|
|
20
|
+
"license": "Apache-2.0",
|
|
21
21
|
"repository": {
|
|
22
22
|
"type": "git",
|
|
23
23
|
"url": "git+https://github.com/Nerwyn/ha-nunjucks.git"
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"home-assistant-js-websocket": "latest",
|
|
31
31
|
"nunjucks": "latest",
|
|
32
|
+
"slugify": "latest",
|
|
32
33
|
"ts-py-datetime": "latest"
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
@@ -39,14 +40,14 @@
|
|
|
39
40
|
"eslint": "latest",
|
|
40
41
|
"eslint-config-prettier": "latest",
|
|
41
42
|
"eslint-plugin-prettier": "latest",
|
|
42
|
-
"jsdom
|
|
43
|
+
"global-jsdom": "latest",
|
|
43
44
|
"lint-staged": "latest",
|
|
44
45
|
"mocha": "latest",
|
|
45
46
|
"prettier": "latest",
|
|
46
47
|
"prettier-plugin-organize-imports": "latest",
|
|
47
48
|
"ts-loader": "latest",
|
|
48
49
|
"ts-mocha": "latest",
|
|
49
|
-
"ts-node": "
|
|
50
|
+
"ts-node": "latest",
|
|
50
51
|
"tsx": "latest",
|
|
51
52
|
"typescript": "latest"
|
|
52
53
|
}
|