ha-nunjucks 1.5.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 CHANGED
@@ -168,15 +168,17 @@ Functions used to determine an entity's state or an attribute.
168
168
  | device_attr | function, filter | device_or_entity_id, attr_name | Returns the value of attr_name for the given device or entity ID. |
169
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. |
170
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. |
171
172
 
172
173
  ### [Floors](https://www.home-assistant.io/docs/configuration/templating/#floors)
173
174
 
174
- | Name | Type | Arguments | Description |
175
- | ----------- | ---------------- | ---------------- | ----------------------------------------------------------------------------------------- |
176
- | floors | function | | Returns the full list of floor IDs that include an area. |
177
- | floor_id | function, filter | lookup_value | Returns the floor ID for a given device ID, entity ID, area ID, or area name. |
178
- | floor_name | function, filter | lookup_value | Returns the floor name for a given device ID, entity ID, area ID, area name, or floor ID. |
179
- | floor_areas | function, filter | floor_name_or_id | Returns the list of area IDs tied to a given floor ID or name. |
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. |
180
182
 
181
183
  ### [Areas](https://www.home-assistant.io/docs/configuration/templating/#areas)
182
184
 
@@ -198,14 +200,15 @@ Functions used to determine an entity's state or an attribute.
198
200
 
199
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.
200
202
 
201
- | Name | Type | Arguments | Description |
202
- | -------------- | ---------------- | ----------------------- | ------------------------------------------------------------------------------------------ |
203
- | 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. |
204
- | label_id | function, filter | lookup_value | Returns the label ID for a given label name. |
205
- | label_name | function, filter | lookup_value | Returns the label name for a given label ID. |
206
- | label_areas | function, filter | label_name_or_id | Returns the list of area IDs tied to a given label ID or name. |
207
- | label_devices | function, filter | label_name_or_id | Returns the list of device IDs tied to a given label ID or name. |
208
- | label_entities | function, filter | label_name_or_id | Returns the list of entity IDs tied to a given label ID or name. |
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. |
209
212
 
210
213
  ### [Immediate If](https://www.home-assistant.io/docs/configuration/templating/#immediate-if-iif)
211
214
 
@@ -223,21 +226,22 @@ A shorthand for an if else statement.
223
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`.
224
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.
225
228
 
226
- | Name | Type | Arguments | Description |
227
- | ---------------- | ---------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
228
- | now | function | | Returns a datetime object that represents the current time in your time zone. |
229
- | utcnow | function | | Returns a datetime object of the current time in the UTC timezone. |
230
- | 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). |
231
- | 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. |
232
- | 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. |
233
- | as_local | function, filter | value | Converts a datetime object to local time. |
234
- | 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. |
235
- | 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 past it returns the input. If the input datetime is not a datetime object it returns nothing. |
236
- | 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 future it returns the input. If the input datetime is not a datetime object it returns nothing. |
237
- | 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`). |
238
- | 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. |
239
- | 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. |
240
- | 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. |
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. |
241
245
 
242
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.
243
247
 
@@ -260,6 +264,12 @@ In addition to these functions, you have access to [a datetime library](https://
260
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.** |
261
265
  | from_json | filter | value | Parse a string as JSON. |
262
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
+
263
273
  ### [Distance](https://www.home-assistant.io/docs/configuration/templating/#distance)
264
274
 
265
275
  | Name | Type | Arguments | Description |
@@ -319,10 +329,11 @@ In addition to these functions, you have access to [a datetime library](https://
319
329
 
320
330
  ### [Type Conversions](https://www.home-assistant.io/docs/configuration/templating/#type-conversions)
321
331
 
322
- | Name | Type | Arguments | Description |
323
- | ---- | -------- | --------- | ------------------------------------------------------ |
324
- | set | function | args | Convert a list/array to a set. Removes duplicates. |
325
- | list | function | args | Convert a set to an array. Does not remove duplicates. |
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. |
326
337
 
327
338
  ### [Iterating Multiple Objects](https://www.home-assistant.io/docs/configuration/templating/#iterating-multiple-objects)
328
339
 
@@ -330,6 +341,16 @@ In addition to these functions, you have access to [a datetime library](https://
330
341
  | ---- | -------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------- |
331
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. |
332
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
+
333
354
  ### [Regular Expressions](https://www.home-assistant.io/docs/configuration/templating/#regular-expressions)
334
355
 
335
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.
@@ -347,10 +368,9 @@ In addition to these functions, you have access to [a datetime library](https://
347
368
 
348
369
  Functions that are not from the Home Assistant templating documentation.
349
370
 
350
- | Name | Type | Arguments | Description |
351
- | ----------- | ---------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
352
- | 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). |
353
- | 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). |
354
374
 
355
375
  [last-commit-shield]: https://img.shields.io/github/last-commit/Nerwyn/ha-nunjucks?style=for-the-badge
356
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
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 { as_datetime, as_local, as_timestamp, time_since, time_until, timestamp_custom, timestamp_local, timestamp_utc, today_at, } from './utils/time';
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,11 +67,14 @@ 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,
@@ -80,6 +86,8 @@ const FILTERS = {
80
86
  // To/From JSON
81
87
  to_json,
82
88
  from_json,
89
+ // Is Defined
90
+ is_defined,
83
91
  // Distance
84
92
  closest,
85
93
  // Contains
@@ -111,10 +119,16 @@ const FILTERS = {
111
119
  multiply,
112
120
  add,
113
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,
114
130
  // Regular Expressions
115
131
  regex_replace,
116
132
  regex_findall,
117
133
  regex_findall_index,
118
- // Miscellaneous
119
- str,
120
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
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 { as_datetime, as_local, as_timedelta, as_timestamp, now, strptime, time_since, time_until, today_at, utcnow, } from './utils/time';
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,6 +96,7 @@ 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,
@@ -121,11 +126,13 @@ const GLOBALS = {
121
126
  // Type Conversions
122
127
  set,
123
128
  list,
129
+ str,
124
130
  // Iterating Multiple Objects
125
131
  zip,
132
+ // String fitlers
133
+ slugify,
126
134
  // Miscellaneous
127
135
  match_media,
128
- str,
129
136
  };
130
137
  const CONST_GLOBALS = {
131
138
  e,
package/dist/index.js CHANGED
@@ -25,6 +25,8 @@ if (!window.haNunjucks) {
25
25
  window.haNunjucks.dateFormat = new Intl.DateTimeFormat(ha.hass.language, { dateStyle: 'full' });
26
26
  window.haNunjucks.timeFormat = new Intl.DateTimeFormat(ha.hass.language, { timeStyle: 'long' });
27
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' });
28
30
  // Label registry and states object
29
31
  window.haNunjucks.hass = ha.hass;
30
32
  fetchLabelRegistry();
@@ -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 deviceId of deviceIds) {
62
- for (const entityId in hass.entities) {
63
- if (hass.entities[entityId].device_id == deviceId) {
64
- entityIds.push(entityId);
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
  }
@@ -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;
@@ -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
+ }
@@ -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[];
@@ -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
+ }
@@ -1,2 +1,3 @@
1
1
  export declare function to_json(obj: object, ensure_ascii?: boolean | Record<string, boolean>, pretty_print?: boolean, sort_keys?: boolean): string;
2
2
  export declare function from_json(value: string): any;
3
+ export declare function is_defined(value: any): any;
@@ -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
+ }
@@ -3,6 +3,7 @@ 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[];
@@ -32,6 +32,9 @@ export function label_id(lookup_value) {
32
32
  export function label_name(lookup_value) {
33
33
  return window.haNunjucks.labelRegistry[lookup_value]?.name;
34
34
  }
35
+ export function label_description(lookup_value) {
36
+ return window.haNunjucks.labelRegistry[lookup_value]?.description;
37
+ }
35
38
  export function label_areas(hass, label_name_or_id) {
36
39
  try {
37
40
  const areaIds = [];
@@ -3,7 +3,7 @@ import { HomeAssistant } from '../models/interfaces/hass';
3
3
  export declare function state_translated(hass: HomeAssistant, entity_id: string, state?: string): string;
4
4
  export declare function attr_name_translated(hass: HomeAssistant, entity_id: string, attr_name: string): string;
5
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): string | number;
6
+ export declare function number_translated(value: number, precision?: number): string | number;
7
7
  export declare function date_translated(value: date | datetime): string | date | datetime;
8
8
  export declare function time_translated(value: time | datetime): string | datetime | time;
9
9
  export declare function datetime_translated(value: datetime): string | datetime;
@@ -26,10 +26,17 @@ 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) {
29
+ export function number_translated(value, precision) {
30
+ value = Number(value);
30
31
  if (isNaN(value)) {
31
32
  return value;
32
33
  }
34
+ if (precision) {
35
+ return value.toLocaleString(window.haNunjucks.hass.language, {
36
+ minimumFractionDigits: precision,
37
+ maximumFractionDigits: precision,
38
+ });
39
+ }
33
40
  return window.haNunjucks.numberFormat.format(value);
34
41
  }
35
42
  export function date_translated(value) {
@@ -0,0 +1,4 @@
1
+ export declare function slugify(str: string, separator?: string): string;
2
+ export declare function ordinal(num: number): string;
3
+ export declare function base64_encode(value: string): string;
4
+ export declare function base64_decode(value: string): string;
@@ -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
+ }
@@ -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;
@@ -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 == 0 || precision > 6) {
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 startRes = false;
147
- for (let i = 0; i < precision; 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 == precision - 1) {
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 (startRes || value > 0) {
156
- startRes = true;
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
- if (value.includes('days')) {
178
- [daysStr, timeStr] = value.split(' days ');
179
- }
180
- else {
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.5.0",
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": [
@@ -17,7 +17,7 @@
17
17
  "*": "prettier -w"
18
18
  },
19
19
  "author": "Nerwyn",
20
- "license": "ISC",
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-global": "latest",
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": "^10.9.2",
50
+ "ts-node": "latest",
50
51
  "tsx": "latest",
51
52
  "typescript": "latest"
52
53
  }