@sv443-network/userutils 9.4.3 → 10.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # @sv443-network/userutils
2
2
 
3
+ ## 10.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 905881a: **Moved a majority of the general-purpose code to the `@sv443-network/coreutils` package.**
8
+ The features are still accessible in this library in the same way, but some of them needed to be modified so they were more generic and consistent with the new package's codebase.
9
+ Refer to [the CoreUtils documentation](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md) for more information.
10
+
11
+ ### Breaking Changes
12
+
13
+ - **Renamed `index.<ext>` files in `dist/` to `UserUtils.<ext>`**
14
+ If you're specifying the URL to the bundle, make sure to replace the `index` in the file name with `UserUtils`.
15
+ - Turned `index.global.js` into an actual full-fledged UMD bundle at `UserUtils.umd.js` (where previously it would only declare a global variable).
16
+ - **Reworked `DataStore` class**
17
+ - The constructor now needs an `engine` property that is an instance of a [`DataStoreEngine`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-datastoreengine)
18
+ - Encoding using `deflate-raw` will now be enabled by default.
19
+ If you're not using the `encodeData` and `decodeData` props, set `compressionFormat: null` to explicitly disable compression.
20
+ - The properties `encodeData` and `decodeData` are now a tuple of a string format identifier (like `gzip`, `deflate-raw`, `base64`, etc.) and the respective function that used to be the only value of those properties.
21
+ - Added [`DataStoreEngine` class](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-datastoreengine) with three implementations available out-of-the-box; [`FileStorageEngine`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-filestorageengine), [`BrowserStorageEngine`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-browserstorageengine) and [`GMStorageEngine`](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#class-gmstorageengine), for Node/Deno and two kinds of browser environments, respectively.
22
+ Userscripts need to use either the `GMStorageEngine` or `BrowserStorageEngine` depending on whether they want to use GreaseMonkey storage (only accessible to the userscript) or standard browser storage (accessible by the website's scripts).
23
+ Userscripts migrating from UserUtils v9 DataStores should use the `GMStorageEngine` to preserve all stored data.
24
+ - Added shorthand property `compressionFormat` as an alternative to the properties `encodeData` and `decodeData`.
25
+ - (The global key `__ds_fmt_ver` will now contain a global version number for DataStore-internal format integrity, stored via the given engine.)
26
+ - **Renamed functions**
27
+ - Renamed `ab2str()` to `abtoa()` and `str2ab()` to `atoab()` to match `btoa()` and `atob()`
28
+ - Renamed `purifyObj()` to `pureObj()`
29
+
30
+ - 422da75: Increased library target to ES2018. Any build systems or environments that do not support ES2018 or newer might not be able to just include the pre-built library bundles as they are and could need a transpilation step to downlevel the code to an older ECMAScript version.
31
+
32
+ ### Minor Changes
33
+
34
+ - 49e359f: Added `GMStorageEngine`, a [`DataStore`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#datastore) engine for GreaseMonkey environments that stores data in [GM storage.](https://wiki.greasespot.net/GM.setValue)
35
+
36
+ ## 9.4.4
37
+
38
+ ### Patch Changes
39
+
40
+ - e8846b5: Fixed infinite recursion in `translate()` when using `setFallbackLanguage()`
41
+ - 59011c1: Removed package.json engines field
42
+
3
43
  ## 9.4.3
4
44
 
5
45
  ### Patch Changes
package/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Sven Fehler (Sv443)
3
+ Copyright (c) 2023 Sv443 Network and Sven Fehler (Sv443)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -4,17 +4,15 @@
4
4
  ## UserUtils
5
5
  General purpose DOM/GreaseMonkey library that allows you to register listeners for when CSS selectors exist, intercept events, create persistent & synchronous data stores, modify the DOM more easily and much more.
6
6
  Contains builtin TypeScript declarations. Supports ESM and CJS imports via a bundler and global declaration via `@require` or `<script>`
7
- The library works in any DOM environment with or without the [GreaseMonkey API](https://wiki.greasespot.net/Greasemonkey_Manual:API), but some features will be unavailable or limited.
7
+ The library works in any DOM environment with or without the [GreaseMonkey API](https://wiki.greasespot.net/Greasemonkey_Manual:API), but some features will be unavailable or require special setup.
8
8
 
9
9
  You may want to check out my [template for userscripts in TypeScript](https://github.com/Sv443/Userscript.ts) that you can use to get started quickly. It also includes this library by default.
10
10
  If you like using this library, please consider [supporting the development ❤️](https://github.com/sponsors/Sv443)
11
11
 
12
12
  <br>
13
13
 
14
- [![Tree shaking support badge](https://badgen.net/bundlephobia/tree-shaking/@sv443-network/userutils)](https://bundlephobia.com/package/@sv443-network/userutils)
15
14
  [![Code coverage percentage badge](https://img.shields.io/coverallsCoverage/github/Sv443-Network/UserUtils?branch=main)](https://coveralls.io/github/Sv443-Network/UserUtils)
16
- [![Minified bundle size badge](https://badgen.net/bundlephobia/min/@sv443-network/userutils)](https://bundlephobia.com/package/@sv443-network/userutils)
17
- [![Minified and gzipped bundle size badge](https://badgen.net/bundlephobia/minzip/@sv443-network/userutils)](https://bundlephobia.com/package/@sv443-network/userutils)
15
+ [![Bundle size badge](https://deno.bundlejs.com/badge?q=@sv443-network/userutils@latest)](https://bundlejs.com/?q=%40sv443-network%2Fuserutils%40latest)
18
16
 
19
17
  [![Discord server badge](https://badgen.net/discord/online-members/aBH4uRG?icon=discord)](https://dc.sv443.net/)
20
18
  [![Github stargazers badge](https://badgen.net/github/stars/Sv443-Network/UserUtils?icon=github)](https://github.com/Sv443-Network/UserUtils/stargazers)
@@ -23,13 +21,20 @@ If you like using this library, please consider [supporting the development ❤
23
21
  <br>
24
22
  <sub>
25
23
 
26
- View the documentation of previous releases:
24
+ View the documentation of previous major versions:
25
+
26
+ <a title="View docs for patch version 9.4.4" href="https://github.com/Sv443-Network/UserUtils/blob/v9.4.4/docs.md" rel="noopener noreferrer">**v9.4.4**</a> &bull; <a title="View docs for minor version 8.4.0" href="https://github.com/Sv443-Network/UserUtils/blob/v8.4.0/README.md" rel="noopener noreferrer">**v8.4.0**</a> &bull; <a href="https://github.com/Sv443-Network/UserUtils/blob/v7.3.0/README.md" title="View docs for minor version 7.3.0" rel="noopener noreferrer">**v7.3.0**</a> &bull; <a href="https://github.com/Sv443-Network/UserUtils/blob/v6.3.0/README.md" title="View docs for minor version 6.3.0" rel="noopener noreferrer">**v6.3.0**</a> &bull; <a href="https://github.com/Sv443-Network/UserUtils/blob/v5.0.1/README.md" title="View docs for patch version 5.0.1" rel="noopener noreferrer">**v5.0.1**</a> &bull; <a href="https://github.com/Sv443-Network/UserUtils/blob/v4.2.1/README.md" title="View docs for patch version 4.2.1" rel="noopener noreferrer">**v4.2.1**</a> &bull; <a href="https://github.com/Sv443-Network/UserUtils/blob/v3.0.0/README.md" title="View docs for major version 3.0.0" rel="noopener noreferrer">**v3.0.0**</a> &bull; <a href="https://github.com/Sv443-Network/UserUtils/blob/v2.0.1/README.md" title="View docs for patch version 2.0.1" rel="noopener noreferrer">**v2.0.1**</a> &bull; <a href="https://github.com/Sv443-Network/UserUtils/blob/v1.2.0/README.md" title="View docs for minor version 1.2.0" rel="noopener noreferrer">**v1.2.0**</a> &bull; <a href="https://github.com/Sv443-Network/UserUtils/blob/v0.5.3/README.md" title="View docs for patch version 0.5.3" rel="noopener noreferrer">**v0.5.3**</a>
27
27
 
28
- <a href="https://github.com/Sv443-Network/UserUtils/blob/v8.0.0/README.md" title="View docs for major version 8.0.0" rel="noopener noreferrer">**v8**</a> <sup>(<a title="View docs for minor version 8.4.0" href="https://github.com/Sv443-Network/UserUtils/blob/v8.4.0/README.md" rel="noopener noreferrer">8.4.0</a>)</sup> • <a href="https://github.com/Sv443-Network/UserUtils/blob/v7.0.0/README.md" title="View docs for major version 7.0.0" rel="noopener noreferrer">**v7**</a> <sup>(<a href="https://github.com/Sv443-Network/UserUtils/blob/v7.3.0/README.md" title="View docs for minor version 7.3.0" rel="noopener noreferrer">7.3.0</a>)</sup> • <a href="https://github.com/Sv443-Network/UserUtils/blob/v6.0.0/README.md" title="View docs for major version 6.0.0" rel="noopener noreferrer">**v6**</a> <sup>(<a href="https://github.com/Sv443-Network/UserUtils/blob/v6.3.0/README.md" title="View docs for minor version 6.3.0" rel="noopener noreferrer">6.3.0</a>)</sup> • <a href="https://github.com/Sv443-Network/UserUtils/blob/v5.0.0/README.md" title="View docs for major version 5.0.0" rel="noopener noreferrer">**v5**</a> <sup>(<a href="https://github.com/Sv443-Network/UserUtils/blob/v5.0.1/README.md" title="View docs for patch version 5.0.1" rel="noopener noreferrer">5.0.1</a>)</sup> • <a href="https://github.com/Sv443-Network/UserUtils/blob/v4.0.0/README.md" title="View docs for major version 4.0.0" rel="noopener noreferrer">**v4**</a> <sup>(<a href="https://github.com/Sv443-Network/UserUtils/blob/v4.2.1/README.md" title="View docs for patch version 4.2.1" rel="noopener noreferrer">4.2.1</a>)</sup> • <a href="https://github.com/Sv443-Network/UserUtils/blob/v3.0.0/README.md" title="View docs for major version 3.0.0" rel="noopener noreferrer">**v3**</a> • <a href="https://github.com/Sv443-Network/UserUtils/blob/v2.0.0/README.md" title="View docs for major version 2.0.0" rel="noopener noreferrer">**v2**</a> <sup>(<a href="https://github.com/Sv443-Network/UserUtils/blob/v2.0.1/README.md" title="View docs for patch version 2.0.1" rel="noopener noreferrer">2.0.1</a>)</sup> • <a href="https://github.com/Sv443-Network/UserUtils/blob/v1.0.0/README.md" title="View docs for major version 1.0.0" rel="noopener noreferrer">**v1**</a> <sup>(<a href="https://github.com/Sv443-Network/UserUtils/blob/v1.2.0/README.md" title="View docs for minor version 1.2.0" rel="noopener noreferrer">1.2.0</a>)</sup> • <a href="https://github.com/Sv443-Network/UserUtils/blob/v0.5.3/README.md" title="View docs for patch version 0.5.3" rel="noopener noreferrer">**v0.5.3**</a>
29
- <!-- <a href="https://github.com/Sv443-Network/UserUtils/blob/vX.0.0/docs.md" rel="noopener noreferrer">X.0.0</a>, -->
30
28
  </sub>
31
29
 
30
+ <br>
31
+
32
32
  </div>
33
+
34
+ > [!NOTE]
35
+ > In version 10.0.0, many of the platform-agnostic features were moved to [the CoreUtils library.](https://github.com/Sv443-Network/CoreUtils)
36
+ > <sub>Everything is re-exported by UserUtils for backwards compatibility, but you may want to consider using CoreUtils directly if you don't need any of the DOM- or GreaseMonkey-specific features or want control over the installed version of CoreUtils.</sub>
37
+
33
38
  <br>
34
39
 
35
40
  <!-- #region Table of Contents -->
@@ -37,87 +42,159 @@ View the documentation of previous releases:
37
42
  - [**Installation**](#installation)
38
43
  - [**License**](#license)
39
44
  - [**Preamble** (info about the documentation)](./docs.md#preamble)
40
- - [**Features**](./docs.md#features)
45
+ - [**UserUtils Features**](./docs.md#features)
41
46
  - [**DOM:**](./docs.md#dom)
42
- - [`SelectorObserver`](./docs.md#selectorobserver) - class that manages listeners that are called when selectors are found in the DOM
43
- - [`getUnsafeWindow()`](./docs.md#getunsafewindow) - get the unsafeWindow object or fall back to the regular window object
44
- - [`isDomLoaded()`](./docs.md#isdomloaded) - check if the DOM has finished loading and can be queried and modified
45
- - [`onDomLoad()`](./docs.md#ondomload) - run a function or pause async execution until the DOM has finished loading (or immediately if DOM is already loaded)
46
- - [`addParent()`](./docs.md#addparent) - add a parent element around another element
47
- - [`addGlobalStyle()`](./docs.md#addglobalstyle) - add a global style to the page
48
- - [`preloadImages()`](./docs.md#preloadimages) - preload images into the browser cache for faster loading later on
49
- - [`openInNewTab()`](./docs.md#openinnewtab) - open a link in a new tab
50
- - [`interceptEvent()`](./docs.md#interceptevent) - conditionally intercepts events registered by `addEventListener()` on any given EventTarget object
51
- - [`interceptWindowEvent()`](./docs.md#interceptwindowevent) - conditionally intercepts events registered by `addEventListener()` on the window object
52
- - [`isScrollable()`](./docs.md#isscrollable) - check if an element has a horizontal or vertical scroll bar
53
- - [`observeElementProp()`](./docs.md#observeelementprop) - observe changes to an element's property that can't be observed with MutationObserver
54
- - [`getSiblingsFrame()`](./docs.md#getsiblingsframe) - returns a frame of an element's siblings, with a given alignment and size
55
- - [`setInnerHtmlUnsafe()`](./docs.md#setinnerhtmlunsafe) - set the innerHTML of an element using a [Trusted Types policy](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API) without sanitizing or escaping it
56
- - [`probeElementStyle()`](./docs.md#probeelementstyle) - probe the computed style of a temporary element (get default font size, resolve CSS variables, etc.)
57
- - [**Math:**](./docs.md#math)
58
- - [`clamp()`](./docs.md#clamp) - constrain a number between a min and max value
59
- - [`mapRange()`](./docs.md#maprange) - map a number from one range to the same spot in another range
60
- - [`randRange()`](./docs.md#randrange) - generate a random number between a min and max boundary
61
- - [`digitCount()`](./docs.md#digitcount) - calculate the amount of digits in a number
62
- - [`roundFixed()`](./docs.md#roundfixed) - round a floating-point number at the given amount of decimals, or to the given power of 10
63
- - [`bitSetHas()`](./docs.md#bitsethas) - check if a bit is set in a [bitset](https://www.geeksforgeeks.org/cpp-bitset-and-its-application/)
47
+ - 🟧 [`Dialog`](./docs.md#class-dialog) - class for creating custom modal dialogs with a promise-based API and a generic, default style
48
+ - 🟧 [`SelectorObserver`](./docs.md#class-selectorobserver) - class that manages listeners that are called when selectors are found in the DOM
49
+ - 🟣 [`getUnsafeWindow()`](./docs.md#function-getunsafewindow) - get the unsafeWindow object or fall back to the regular window object
50
+ - 🟣 [`isDomLoaded()`](./docs.md#function-isdomloaded) - check if the DOM has finished loading and can be queried and modified
51
+ - 🟣 [`onDomLoad()`](./docs.md#function-ondomload) - run a function or pause async execution until the DOM has finished loading (or immediately if DOM is already loaded)
52
+ - 🟣 [`addParent()`](./docs.md#function-addparent) - add a parent element around another element
53
+ - 🟣 [`addGlobalStyle()`](./docs.md#function-addglobalstyle) - add a global style to the page
54
+ - 🟣 [`preloadImages()`](./docs.md#function-preloadimages) - preload images into the browser cache for faster loading later on
55
+ - 🟣 [`openInNewTab()`](./docs.md#function-openinnewtab) - open a link in a new tab
56
+ - 🟣 [`interceptEvent()`](./docs.md#function-interceptevent) - conditionally intercepts events registered by `addEventListener()` on any given EventTarget object
57
+ - 🟣 [`interceptWindowEvent()`](./docs.md#function-interceptwindowevent) - conditionally intercepts events registered by `addEventListener()` on the window object
58
+ - 🟣 [`isScrollable()`](./docs.md#function-isscrollable) - check if an element has a horizontal or vertical scroll bar
59
+ - 🟣 [`observeElementProp()`](./docs.md#function-observeelementprop) - observe changes to an element's property that can't be observed with MutationObserver
60
+ - 🟣 [`getSiblingsFrame()`](./docs.md#function-getsiblingsframe) - returns a frame of an element's siblings, with a given alignment and size
61
+ - 🟣 [`setInnerHtmlUnsafe()`](./docs.md#function-setinnerhtmlunsafe) - set the innerHTML of an element using a [Trusted Types policy](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API) without sanitizing or escaping it
62
+ - 🟣 [`probeElementStyle()`](./docs.md#function-probeelementstyle) - probe the computed style of a temporary element (get default font size, resolve CSS variables, etc.)
64
63
  - [**Misc:**](./docs.md#misc)
65
- - [`DataStore`](./docs.md#datastore) - class that manages a hybrid sync & async persistent JSON database, including data migration
66
- - [`DataStoreSerializer`](./docs.md#datastoreserializer) - class for importing & exporting data of multiple DataStore instances, including compression, checksumming and running migrations
67
- - [`Dialog`](./docs.md#dialog) - class for creating custom modal dialogs with a promise-based API and a generic, default style
68
- - [`Mixins`](./docs.md#mixins) - class for creating mixin functions that allow multiple sources to modify a target value in a highly flexible way
69
- - [`NanoEmitter`](./docs.md#nanoemitter) - tiny event emitter class with a focus on performance and simplicity (based on [nanoevents](https://npmjs.com/package/nanoevents))
70
- - [`Debouncer`](./docs.md#debouncer) - class for debouncing function calls with a given timeout
71
- - [`debounce()`](./docs.md#debounce) - function wrapper for the Debouncer class for easier usage
72
- - [`autoPlural()`](./docs.md#autoplural) - automatically pluralize a string
73
- - [`pauseFor()`](./docs.md#pausefor) - pause the execution of a function for a given amount of time
74
- - [`fetchAdvanced()`](./docs.md#fetchadvanced) - wrapper around the fetch API with a timeout option
75
- - [`insertValues()`](./docs.md#insertvalues) - insert values into a string at specified placeholders
76
- - [`compress()`](./docs.md#compress) - compress a string with Gzip or Deflate
77
- - [`decompress()`](./docs.md#decompress) - decompress a previously compressed string
78
- - [`computeHash()`](./docs.md#computehash) - compute the hash / checksum of a string or ArrayBuffer
79
- - [`randomId()`](./docs.md#randomid) - generate a random ID of a given length and radix
80
- - [`consumeGen()`](./docs.md#consumegen) - consumes a ValueGen and returns the value
81
- - [`consumeStringGen()`](./docs.md#consumestringgen) - consumes a StringGen and returns the string
82
- - [`getListLength()`](./docs.md#getlistlength) - get the length of any object with a numeric `length`, `count` or `size` property
83
- - [`purifyObj()`](./docs.md#purifyobj) - removes the prototype chain (all default properties like `toString`, `__proto__`, etc.) from an object
84
- - [**Arrays:**](./docs.md#arrays)
85
- - [`randomItem()`](./docs.md#randomitem) - returns a random item from an array
86
- - [`randomItemIndex()`](./docs.md#randomitemindex) - returns a tuple of a random item and its index from an array
87
- - [`takeRandomItem()`](./docs.md#takerandomitem) - returns a random item from an array and mutates it to remove the item
88
- - [`randomizeArray()`](./docs.md#randomizearray) - returns a copy of the array with its items in a random order
64
+ - 🟧 [`GMStorageEngine`](./docs.md#class-gmstorageengine) - storage engine class for [`DataStore`s](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#datastore) using the GreaseMonkey API
65
+ - 🟧 [`Mixins`](./docs.md#class-mixins) - class for creating mixin functions that allow multiple sources to modify a target value in a highly flexible way
89
66
  - [**Translation:**](./docs.md#translation)
90
- - [`tr.for()`](./docs.md#trfor) - translates a key for the specified language
91
- - [`tr.use()`](./docs.md#truse) - creates a translation function for the specified language
92
- - [`tr.hasKey()`](./docs.md#trhaskey) - checks if a key exists in the given language
93
- - [`tr.addTranslations()`](./docs.md#traddtranslations) - add a flat or recursive translation object for a language
94
- - [`tr.getTranslations()`](./docs.md#trgettranslations) - returns the translation object for a language
95
- - [`tr.deleteTranslations()`](./docs.md#trdeletetranslations) - delete the translation object for a language
96
- - [`tr.setFallbackLanguage()`](./docs.md#trsetfallbacklanguage) - set the fallback language used when a key is not found in the given language
97
- - [`tr.getFallbackLanguage()`](./docs.md#trgetfallbacklanguage) - returns the fallback language
98
- - [`tr.addTransform()`](./docs.md#traddtransform) - adds a transform function to the translation system for custom argument insertion and much more
99
- - [`tr.deleteTransform()`](./docs.md#trdeletetransform) - removes a transform function
100
- - [`tr.transforms`](./docs.md#trtransforms) - predefined transform functions for quickly adding custom argument insertion
101
- - [`TrKeys`](./docs.md#trkeys) - generic type that extracts all keys from a flat or recursive translation object into a union
102
- - [**Colors:**](./docs.md#colors)
103
- - [`hexToRgb()`](./docs.md#hextorgb) - convert a hex color string to an RGB or RGBA value tuple
104
- - [`rgbToHex()`](./docs.md#rgbtohex) - convert RGB or RGBA values to a hex color string
105
- - [`lightenColor()`](./docs.md#lightencolor) - lighten a CSS color string (hex, rgb or rgba) by a given percentage
106
- - [`darkenColor()`](./docs.md#darkencolor) - darken a CSS color string (hex, rgb or rgba) by a given percentage
107
- - [**Utility types for TypeScript:**](./docs.md#utility-types)
108
- - [`Stringifiable`](./docs.md#stringifiable) - any value that is a string or can be converted to one (implicitly or explicitly)
109
- - [`NonEmptyArray`](./docs.md#nonemptyarray) - any array that should have at least one item
110
- - [`NonEmptyString`](./docs.md#nonemptystring) - any string that should have at least one character
111
- - [`LooseUnion`](./docs.md#looseunion) - a union that gives autocomplete in the IDE but also allows any other value of the same type
112
- - [`Prettify`](./docs.md#prettify) - expands a complex type into a more readable format while keeping functionality the same
113
- - [`ValueGen`](./docs.md#valuegen) - a "generator" value that allows for super flexible value typing and declaration
114
- - [`StringGen`](./docs.md#stringgen) - a "generator" string that allows for super flexible string typing and declaration, including enhanced support for unions
115
- - [`ListWithLength`](./docs.md#listwithlength) - represents an array or object with a numeric `length`, `count` or `size` property
116
- - [**Custom Error classes**](./docs.md#error-classes)
117
- - [`UUError`](./docs.md#uuerror) - base class for all custom UserUtils errors - has a custom `date` prop set to the time of creation
118
- - [`ChecksumMismatchError`](./docs.md#checksummismatcherror) - thrown when a string of data doesn't match its checksum
119
- - [`MigrationError`](./docs.md#migrationerror) - thrown when a data migration fails
120
- - [`PlatformError`](./docs.md#platformerror) - thrown when a function is called in an unsupported environment
67
+ - 🟣 [`tr.for()`](./docs.md#function-trfor) - translates a key for the specified language
68
+ - 🟣 [`tr.use()`](./docs.md#function-truse) - creates a translation function for the specified language
69
+ - 🟣 [`tr.hasKey()`](./docs.md#function-trhaskey) - checks if a key exists in the given language
70
+ - 🟣 [`tr.addTranslations()`](./docs.md#function-traddtranslations) - add a flat or recursive translation object for a language
71
+ - 🟣 [`tr.getTranslations()`](./docs.md#function-trgettranslations) - returns the translation object for a language
72
+ - 🟣 [`tr.deleteTranslations()`](./docs.md#function-trdeletetranslations) - delete the translation object for a language
73
+ - 🟣 [`tr.setFallbackLanguage()`](./docs.md#function-trsetfallbacklanguage) - set the fallback language used when a key is not found in the given language
74
+ - 🟣 [`tr.getFallbackLanguage()`](./docs.md#function-trgetfallbacklanguage) - returns the fallback language
75
+ - 🟣 [`tr.addTransform()`](./docs.md#function-traddtransform) - adds a transform function to the translation system for custom argument insertion and much more
76
+ - 🟣 [`tr.deleteTransform()`](./docs.md#function-trdeletetransform) - removes a transform function
77
+ - 🟩 [`tr.transforms`](./docs.md#const-trtransforms) - predefined transform functions for quickly adding custom argument insertion
78
+ - 🔷 [`TrKeys`](./docs.md#type-trkeys) - generic type that extracts all keys from a flat or recursive translation object into a union
79
+ - [**Errors**](./docs.md#error-classes)
80
+ - 🟧 [`PlatformError`](./docs.md#class-platformerror) - thrown when the current platform doesn't support a certain feature, like calling a DOM function in a non-DOM environment
81
+ - [**CoreUtils Features** (re-exported for backwards compatibility)](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#table-of-contents)
82
+ - [**Array:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#array)
83
+ - 🟣 [`function randomItem()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-randomitem) - Returns a random item from the given array
84
+ - 🟣 [`function randomItemIndex()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-randomitemindex) - Returns a random array item and index as a tuple
85
+ - 🟣 [`function randomizeArray()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-randomizearray) - Returns a new array with the items in random order
86
+ - 🟣 [`function takeRandomItem()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-takerandomitem) - Returns a random array item and mutates the array to remove it
87
+ - 🟣 [`function takeRandomItemIndex()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-randomitemindex) - Returns a random array item and index as a tuple and mutates the array to remove it
88
+ - 🔷 [`type NonEmptyArray`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-nonemptyarray) - Non-empty array type
89
+ - [**Colors:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#colors)
90
+ - 🟣 [`function darkenColor()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-darkencolor) - Darkens the given color by the given percentage
91
+ - 🟣 [`function hexToRgb()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-hextorgb) - Converts a hex color string to an RGB object
92
+ - 🟣 [`function lightenColor()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-lightencolor) - Lightens the given color by the given percentage
93
+ - 🟣 [`function rgbToHex()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-rgbtohex) - Converts an RGB object to a hex color string
94
+ - [**Crypto:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#crypto)
95
+ - 🟣 [`function abtoa()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-abtoa) - Converts an ArrayBuffer to a string
96
+ - 🟣 [`function atoab()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-atoab) - Converts a string to an ArrayBuffer
97
+ - 🟣 [`function compress()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-compress) - Compresses the given string using the given algorithm and encoding
98
+ - 🟣 [`function decompress()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-decompress) - Decompresses the given string using the given algorithm and encoding
99
+ - 🟣 [`function computeHash()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-computehash) - Computes a string's hash using the given algorithm
100
+ - 🟣 [`function randomId()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-randomid) - Generates a random ID of the given length
101
+ - [**DataStore:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#datastore) - Cross-platform, general-purpose, sync/async hybrid, JSON-serializable database infrastructure:
102
+ - 🟧 [`class DataStore`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-datastore) - The main class for the data store
103
+ - 🔷 [`type DataStoreOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-datastoreoptions) - Options for the data store
104
+ - 🔷 [`type DataMigrationsDict`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-datamigrationsdict) - Dictionary of data migration functions
105
+ - 🔷 [`type DataStoreData`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-datastoredata) - The type of the serializable data
106
+ - 🟧 [`class DataStoreSerializer`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-datastoreserializer) - Serializes and deserializes data for multiple DataStore instances
107
+ - 🔷 [`type DataStoreSerializerOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-datastoreserializeroptions) - Options for the DataStoreSerializer
108
+ - 🔷 [`type LoadStoresDataResult`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-loadstoresdataresult) - Result of calling [`loadStoresData()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#datastoreserializer-loadstoresdata)
109
+ - 🔷 [`type SerializedDataStore`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-serializeddatastore) - Meta object and serialized data of a DataStore instance
110
+ - 🔷 [`type StoreFilter`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-storefilter) - Filter for selecting data stores
111
+ - 🟧 [`class DataStoreEngine`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-datastoreengine) - Base class for DataStore storage engines, which handle the data storage
112
+ - 🔷 [`type DataStoreEngineDSOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-datastoreenginedsoptions) - Reduced version of [`DataStoreOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-datastoreoptions)
113
+ - [Storage Engines:](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#storage-engines)
114
+ - 🟧 [`class BrowserStorageEngine`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-browserstorageengine) - Storage engine for browser environments (localStorage, sessionStorage)
115
+ - 🔷 [`type BrowserStorageEngineOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#browserstorageengineoptions) - Options for the browser storage engine
116
+ - 🟧 [`class FileStorageEngine`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-FileStorageEngine) - File-based storage engine for Node.js and Deno
117
+ - 🔷 [`type FileStorageEngineOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#FileStorageEngineoptions) - Options for the file storage engine
118
+ - [**Debouncer:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#debouncer)
119
+ - 🟣 [`function debounce()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-debounce) - Function wrapper for the [`Debouncer` class](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-debouncer)
120
+ - 🟧 [`class Debouncer`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-debouncer) - Class that manages listeners whose calls are rate-limited
121
+ - 🔷 [`type DebouncerType`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-debouncertype) - The triggering type for the debouncer
122
+ - 🔷 [`type DebouncedFunction`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-debouncedfunction) - Function type that is returned by the [`debounce()` function](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-debounce)
123
+ - 🔷 [`type DebouncerEventMap`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-debouncereventmap) - Event map type for the [`Debouncer` class](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-debouncer)
124
+ - [**Errors:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#errors)
125
+ - 🟧 [`class DatedError`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-datederror) - Base error class with a `date` property
126
+ - 🟧 [`class ChecksumMismatchError`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-checksummismatcherror) - Error thrown when two checksums don't match
127
+ - 🟧 [`class CustomError`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-customerror) - Custom error with a configurable name for one-off situations
128
+ - 🟧 [`class MigrationError`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-migrationerror) - Error thrown in a failed data migration
129
+ - 🟧 [`class ValidationError`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-validationerror) - Error while validating data
130
+ - [**Math:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#math)
131
+ - 🟣 [`function bitSetHas()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-bitsethas) - Checks if a bit is set in a bitset
132
+ - 🟣 [`function clamp()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-clamp) - Clamps a number between a given range
133
+ - 🟣 [`function digitCount()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-digitcount) - Returns the number of digits in a number
134
+ - 🟣 [`function formatNumber()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-formatnumber) - Formats a number to a string using the given locale and format identifier
135
+ - 🔷 [`type NumberFormat`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-numberformat) - Number format identifier
136
+ - 🟣 [`function mapRange()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-maprange) - Maps a number from one range to another
137
+ - 🟣 [`function overflowVal()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-overflowVal) - Makes sure a number is in a range by over- & underflowing it
138
+ - 🟣 [`function randRange()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-randrange) - Returns a random number in the given range
139
+ - 🟣 [`function roundFixed()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-roundfixed) - Rounds the given number to the given number of decimal places
140
+ - 🟣 [`function valsWithin()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-valswithin) - Checks if the given numbers are within a certain range of each other
141
+ - [**Misc:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#misc)
142
+ - 🟣 [`function consumeGen()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-consumegen) - Consumes a [`ValueGen` object](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-valuegen)
143
+ - 🔷 [`type ValueGen`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-valuegen) - A value that can be either type T, or a sync or async function that returns T
144
+ - 🟣 [`function consumeStringGen()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-consumestringgen) - Consumes a [`StringGen` object](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-stringgen)
145
+ - 🔷 [`type StringGen`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-stringgen) - A value that can be either of type string, or a sync or async function that returns a string
146
+ - 🟣 [`function fetchAdvanced()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-fetchadvanced) - Wrapper around [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) with options like a timeout
147
+ - 🔷 [`type FetchAdvancedOpts`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-fetchadvancedopts) - Options for the [`fetchAdvanced()` function](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-fetchadvanced)
148
+ - 🟣 [`function getListLength()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-getlistlength) - Returns the length of a [`ListLike` object](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-listlike)
149
+ - 🟣 [`function pauseFor()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-pausefor) - Pauses async execution for the given amount of time
150
+ - 🟣 [`function pureObj()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-pureobj) - Applies an object's props to a null object (object without prototype chain) or just returns a new null object
151
+ - 🟣 [`function setImmediateInterval()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-setimmediateinterval) - Like `setInterval()`, but instantly calls the callback and supports passing an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
152
+ - 🟣 [`function setImmediateTimeoutLoop()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-setimmediatetimeoutloop) - Like a recursive `setTimeout()` loop, but instantly calls the callback and supports passing an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
153
+ - 🟣 [`function scheduleExit()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-scheduleexit) - Schedules a process exit after the next event loop tick, to allow operations like IO writes to finish.
154
+ - 🟣 [`function getCallStack()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-getcallstack) - Returns the current call stack, starting at the caller of this function.
155
+ - [**NanoEmitter:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#nanoemitter)
156
+ - 🟧 [`class NanoEmitter`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-nanoemitter) - Simple, lightweight event emitter class that can be used in both FP and OOP, inspired by [`EventEmitter` from `node:events`](https://nodejs.org/api/events.html#class-eventemitter), based on [`nanoevents`](https://npmjs.com/package/nanoevents)
157
+ - 🔷 [`type NanoEmitterOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-nanoemitteroptions) - Options for the [`NanoEmitter` class](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-nanoemitter)
158
+ - [**Text:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#text)
159
+ - 🟣 [`function autoPlural()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-autoplural) - Turns the given term into its plural form, depending on the given number or list length
160
+ - 🟣 [`function capitalize()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-capitalize) - Capitalizes the first letter of the given string
161
+ - 🟣 [`function createProgressBar()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-createprogressbar) - Creates a progress bar string with the given percentage and length
162
+ - 🟩 [`const defaultPbChars`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#const-defaultpbchars) - Default characters for the progress bar
163
+ - 🔷 [`type ProgressBarChars`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-progressbarchars) - Type for the progress bar characters object
164
+ - 🟣 [`function joinArrayReadable()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-joinarrayreadable) - Joins the given array into a string, using the given separators and last separator
165
+ - 🟣 [`function secsToTimeStr()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-secstotimestr) - Turns the given number of seconds into a string in the format `(hh:)mm:ss` with intelligent zero-padding
166
+ - 🟣 [`function truncStr()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-truncstr) - Truncates the given string to the given length
167
+ <!-- - *[**TieredCache:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#tieredcache)
168
+ - 🟧 *[`class TieredCache`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-tieredcache) - A multi-tier cache that uses multiple storage engines with different expiration times
169
+ - 🔷 *[`type TieredCacheOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-tieredcacheoptions) - Options for the [`TieredCache` class](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-tieredcache)
170
+ - 🔷 *[`type TieredCachePropagateTierOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-tieredcachestaleoptions) - Entry propagation options for each tier
171
+ - 🔷 *[`type TieredCacheStaleOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-tieredcachepropagatetieroptions) - Entry staleness options for each tier
172
+ - 🔷 *[`type TieredCacheTierOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-tieredcachetieroptions) - Options for each tier of a [`TieredCache` instance](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-tieredcache)
173
+ - *[**Translate:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#translate)
174
+ - 🟧 *[`class Translate`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-translate) - JSON-based translation system supporting transformation hooks, value injection, nested objects, etc.
175
+ - 🔷 *[`type TransformFn`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-transformfn) - The type of the transformation hook functions
176
+ - 🔷 *[`type TransformFnProps`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-transformfnprops) - The properties passed to the transformation functions
177
+ - 🔷 *[`type TranslateOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-translateoptions) - The options for the [`Translate` class](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-translate)
178
+ - 🔷 *[`type TrKeys`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-trkeys) - Generic type that gives you a union of keys from the passed [`TrObject` object](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-trobject)
179
+ - 🔷 *[`type TrObject`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-trobject) - The translation object for a specific language -->
180
+ - [**Misc. Types:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#types)
181
+ - 🔷 [`type LooseUnion`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-looseunion) - A union type that allows for autocomplete suggestions as well as substitutions of the same type
182
+ - 🔷 [`type ListLike`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-listlike) - Any value with a quantifiable `length`, `count` or `size` property
183
+ - 🔷 [`type Newable`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-newable) - Any class reference that can be instantiated with `new`
184
+ - 🔷 [`type NonEmptyArray`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-nonemptyarray) - Non-empty array type
185
+ - 🔷 [`type NonEmptyString`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-nonemptystring) - String type with at least one character
186
+ - 🔷 [`type NumberFormat`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-numberformat) - Number format identifier
187
+ - 🔷 [`type Prettify`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-prettify) - Makes the structure of a type more readable by fully expanding it (recursively)
188
+ - 🔷 [`type SerializableVal`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-serializableval) - Any value that can be serialized to JSON
189
+ - 🔷 [`type StringGen`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-stringgen) - A value that can be either of type string, or a sync or async function that returns a string
190
+ - 🔷 [`type ValueGen`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-valuegen) - A value that can be either the generic type T, or a sync or async function that returns T
191
+ - 🔷 [`type Stringifiable`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-stringifiable) - Any value that can be implicitly converted to a string
192
+
193
+ > [!NOTE]
194
+ > 🟣 = function
195
+ > 🟧 = class
196
+ > 🔷 = type
197
+ > 🟩 = const
121
198
 
122
199
  <br><br>
123
200
 
@@ -199,7 +276,8 @@ Shameless plug: I made a [template for userscripts in TypeScript](https://github
199
276
 
200
277
  <br>
201
278
 
202
- - If you're using a linter like ESLint, it might complain about the global variable `UserUtils` not being defined. To fix this, add the following to your ESLint configuration file:
279
+ - If you're using a linter like ESLint, it might complain about the global variable `UserUtils` not being defined. To fix this, add the following to your ESLint configuration file:
280
+
203
281
  ```json
204
282
  "globals": {
205
283
  "UserUtils": "readonly"