miki-template 2.0.0 → 2.2.2

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.
Files changed (87) hide show
  1. package/.github/workflows/ci.yml +14 -10
  2. package/.github/workflows/docs.yml +105 -0
  3. package/.github/workflows/npm-publish-github-packages.yml +36 -0
  4. package/README.md +142 -26
  5. package/assets/logo.png +0 -0
  6. package/benchmarks/ejs-results.json +17 -0
  7. package/benchmarks/ejs.js +36 -0
  8. package/benchmarks/handlebars-results.json +17 -0
  9. package/benchmarks/handlebars.js +48 -0
  10. package/benchmarks/miki-results.json +17 -0
  11. package/benchmarks/miki.js +36 -0
  12. package/benchmarks/pug-results.json +17 -0
  13. package/benchmarks/pug.js +36 -0
  14. package/benchmarks/run.js +69 -37
  15. package/benchmarks/stress.mjs +1 -1
  16. package/docs/api/async-render.md +85 -0
  17. package/docs/api/cache.md +87 -0
  18. package/docs/api/compile.md +128 -0
  19. package/docs/api/context-processors.md +77 -0
  20. package/docs/api/filters.md +217 -0
  21. package/docs/api/finder.md +94 -0
  22. package/docs/api/helpers.md +53 -0
  23. package/docs/api/i18n.md +157 -0
  24. package/docs/api/index.md +54 -0
  25. package/docs/api/libraries.md +207 -0
  26. package/docs/api/render-partial.md +81 -0
  27. package/docs/api/render.md +92 -0
  28. package/docs/api/security.md +145 -0
  29. package/docs/api/setup-express.md +76 -0
  30. package/docs/api/tags.md +134 -0
  31. package/docs/assets/banner.png +0 -0
  32. package/docs/assets/logo.png +0 -0
  33. package/docs/guide/advanced-usage.md +397 -0
  34. package/docs/guide/async-rendering.md +308 -0
  35. package/docs/guide/context-processors.md +257 -0
  36. package/docs/guide/custom-filters.md +311 -0
  37. package/docs/guide/custom-tags.md +271 -0
  38. package/docs/guide/filters.md +642 -0
  39. package/docs/guide/getting-started.md +102 -0
  40. package/docs/guide/installation.md +95 -0
  41. package/docs/guide/partial-templates.md +367 -0
  42. package/docs/guide/quick-start.md +222 -0
  43. package/docs/guide/security.md +345 -0
  44. package/docs/guide/tags.md +783 -0
  45. package/docs/guide/template-discovery.md +170 -0
  46. package/docs/guide/template-inheritance.md +273 -0
  47. package/docs/guide/what-is-miki-template.md +28 -0
  48. package/docs/guide/why-miki-template.md +75 -0
  49. package/docs/index.md +104 -0
  50. package/docs/integrations/elysia.md +78 -0
  51. package/docs/integrations/express.md +219 -0
  52. package/docs/integrations/fastify.md +77 -0
  53. package/docs/integrations/hono.md +78 -0
  54. package/docs/integrations/index.md +68 -0
  55. package/docs/integrations/koa.md +88 -0
  56. package/docs/integrations/nestjs.md +78 -0
  57. package/docs/integrations/tsed.md +81 -0
  58. package/docs/javascripts/extra.js +174 -0
  59. package/docs/performance.md +37 -0
  60. package/docs/stylesheets/extra.css +819 -0
  61. package/live-test/integrations/elysia-example.js +16 -0
  62. package/live-test/integrations/express-example.js +24 -0
  63. package/live-test/integrations/fastify-example.js +20 -0
  64. package/live-test/integrations/hono-example.js +16 -0
  65. package/live-test/integrations/koa-example.js +30 -0
  66. package/live-test/integrations/nestjs-example.js +25 -0
  67. package/live-test/integrations/smoke-test.js +166 -0
  68. package/live-test/integrations/tsed-example.js +23 -0
  69. package/live-test/package-lock.json +235 -0
  70. package/live-test/package.json +4 -0
  71. package/live-test/views/home.html +17 -0
  72. package/mkdocs.yml +217 -0
  73. package/overrides/main.html +26 -0
  74. package/overrides/partials/footer.html +9 -0
  75. package/package.json +16 -6
  76. package/requirements-docs.txt +1 -0
  77. package/tests/integration/partial-render.test.cjs +13 -0
  78. package/docs/README.md +0 -18
  79. package/docs/advanced_usage.md +0 -71
  80. package/docs/api.md +0 -122
  81. package/docs/filters.md +0 -708
  82. package/docs/installation.md +0 -106
  83. package/docs/overview.md +0 -79
  84. package/docs/partialdef.md +0 -70
  85. package/docs/security.md +0 -27
  86. package/docs/tags.md +0 -673
  87. package/docs/usage.md +0 -646
@@ -0,0 +1,217 @@
1
+ # Filters API
2
+
3
+ ## registerFilter
4
+
5
+ Register a custom filter callable from templates as `{{ value|filter_name:arg }}`.
6
+
7
+ === "CommonJS"
8
+
9
+ ```javascript
10
+ const { registerFilter } = require('miki-template');
11
+
12
+ registerFilter('reverse', (val) => {
13
+ return String(val).split('').reverse().join('');
14
+ });
15
+ ```
16
+
17
+ === "ES Modules"
18
+
19
+ ```javascript
20
+ import { registerFilter } from 'miki-template';
21
+
22
+ registerFilter('reverse', (val) => {
23
+ return String(val).split('').reverse().join('');
24
+ });
25
+ ```
26
+
27
+ ### Filter Signature
28
+
29
+ Filters receive `(value, argument, context)` and must return a string (or `SafeString`):
30
+
31
+ ```javascript
32
+ registerFilter('greet', (val, greeting, context) => {
33
+ return `${greeting}, ${val}!`;
34
+ });
35
+ ```
36
+
37
+ ### Async Filters
38
+
39
+ Filters that return a Promise are awaited automatically when using `asyncRender()`:
40
+
41
+ === "CommonJS"
42
+
43
+ ```javascript
44
+ const { registerFilter, asyncRender } = require('miki-template');
45
+
46
+ registerFilter('fetch_data', async (url) => {
47
+ const res = await fetch(url);
48
+ return res.text();
49
+ });
50
+
51
+ const html = await asyncRender('{{ endpoint|fetch_data }}', {
52
+ endpoint: 'https://api.example.com/data'
53
+ });
54
+ ```
55
+
56
+ === "ES Modules"
57
+
58
+ ```javascript
59
+ import { registerFilter, asyncRender } from 'miki-template';
60
+
61
+ registerFilter('fetch_data', async (url) => {
62
+ const res = await fetch(url);
63
+ return res.text();
64
+ });
65
+
66
+ const html = await asyncRender('{{ endpoint|fetch_data }}', {
67
+ endpoint: 'https://api.example.com/data'
68
+ });
69
+ ```
70
+
71
+ ## getFilter
72
+
73
+ Retrieve a registered filter by name.
74
+
75
+ === "CommonJS"
76
+
77
+ ```javascript
78
+ const { getFilter } = require('miki-template);
79
+
80
+ const reverseFilter = getFilter('reverse');
81
+ console.log(reverseFilter('hello')); // 'olleh'
82
+ ```
83
+
84
+ === "ES Modules"
85
+
86
+ ```javascript
87
+ import { getFilter } from 'miki-template';
88
+
89
+ const reverseFilter = getFilter('reverse');
90
+ ```
91
+
92
+ ## Built-in Filters
93
+
94
+ ### Text Filters
95
+
96
+ | Filter | Description |
97
+ |--------|-------------|
98
+ | `upper` | Uppercase |
99
+ | `lower` | Lowercase |
100
+ | `title` | Title case |
101
+ | `capfirst` | Capitalize first character |
102
+ | `truncatewords:N` | Truncate to N words |
103
+ | `truncatechars:N` | Truncate to N characters (ellipsis) |
104
+ | `truncatechars_html:N` | Truncate to N chars, preserving HTML |
105
+ | `wordcount` | Count words |
106
+ | `striptags` | Remove HTML tags |
107
+ | `slugify` | Convert to URL-friendly slug |
108
+ | `linebreaks` | Convert newlines to `<br>` and `<p>` |
109
+ | `linebreaksbr` | Convert newlines to `<br>` |
110
+ | `length_is:N` | Return length if equals N, else empty |
111
+
112
+ ### HTML Filters
113
+
114
+ | Filter | Description |
115
+ |--------|-------------|
116
+ | `safe` | Mark as safe (no escaping) |
117
+ | `escape` | Force HTML escaping |
118
+
119
+ ### List Filters
120
+
121
+ | Filter | Description |
122
+ |--------|-------------|
123
+ | `length` | Number of items |
124
+ | `join:sep` | Join items with separator |
125
+ | `slice:"start:end"` | Slice a list/string |
126
+ | `dictsort:"key"` | Sort by key (ascending) |
127
+ | `dictsortreversed:"key"` | Sort by key (descending) |
128
+ | `sort` | Sort items |
129
+ | `unique` | Remove duplicates |
130
+ | `random` | Random item |
131
+ | `reverse` | Reverse order |
132
+ | `split:sep` | Split string into list |
133
+ | `replace:"old,new"` | Replace occurrences |
134
+
135
+ ### Default Filters
136
+
137
+ | Filter | Description |
138
+ |--------|-------------|
139
+ | `default:"fallback"` | Show fallback if value is falsy |
140
+ | `default_if_none:"fallback"` | Show fallback if value is `null`/`undefined` |
141
+ | `firstof:v1 v2 v3` | First non-empty value |
142
+
143
+ ### Date/Time Filters
144
+
145
+ | Filter | Description |
146
+ |--------|-------------|
147
+ | `date:"Y-m-d"` | Django-style date format |
148
+ | `time:"H:i"` | Django-style time format |
149
+ | `date_format:"yyyy-MM-dd"` | Intl-style date format |
150
+ | `strftime:"PPPP"` | Intl-style time format |
151
+ | `timesince` | Time since date ("2 hours ago") |
152
+ | `timeuntil` | Time until date |
153
+ | `ago` | Short time-ago ("2m", "3h") |
154
+ | `until` | Short time-until |
155
+ | `time_diff:other_date` | Difference between two dates |
156
+
157
+ ### Numeric Filters
158
+
159
+ | Filter | Description |
160
+ |--------|-------------|
161
+ | `add:N` | Add N |
162
+ | `sub:N` | Subtract N |
163
+ | `mult:N` | Multiply by N |
164
+ | `divisibleby:N` | Check divisibility |
165
+ | `mod:N` | Modulo |
166
+ | `floatformat:N` | Format float with N decimals |
167
+ | `square` | Square a number |
168
+ | `sqrt` | Square root |
169
+ | `abs` | Absolute value |
170
+ | `round:N` | Round to N decimals |
171
+ | `floor` | Floor |
172
+ | `ceil` | Ceiling |
173
+ | `min:N` | Minimum of value and N |
174
+ | `max:N` | Maximum of value and N |
175
+ | `sum` | Sum of list |
176
+ | `average` | Average of list |
177
+
178
+ ### Currency and Data Formatting
179
+
180
+ | Filter | Description |
181
+ |--------|-------------|
182
+ | `currency:"$"` | Format as currency |
183
+ | `phone_number` | Format phone number |
184
+ | `email` | Format as email link |
185
+ | `url` | Format as URL link |
186
+ | `mask:"*"` | Mask sensitive data |
187
+ | `whatsapp_link:"msg"` | Generate WhatsApp link |
188
+ | `credit_card` | Format credit card number |
189
+ | `ssn` | Format SSN |
190
+ | `ip_address` | Format IP address |
191
+ | `uuid` | Format UUID |
192
+ | `filesizeformat` | Human-readable file size |
193
+ | `yesno:"yes,no,maybe"` | Yes/no based on boolean |
194
+ | `pluralize:"s"` | Add plural suffix if needed |
195
+ | `urlencode` | URL-encode |
196
+ | `escapeuri` | Escape URI component |
197
+ | `stringformat:"%s"` | String format |
198
+ | `cut:"text"` | Remove occurrences |
199
+ | `addslashes` | Add slashes |
200
+ | `removetags:"p,div"` | Remove specified tags |
201
+ | `trans:"key"` | Translate key |
202
+ | `regroup:"attr"` | Regroup list by attribute |
203
+ | `json` | Serialize to JSON |
204
+ | `urlize` | Auto-link URLs in text |
205
+
206
+ ### Encoding Filters
207
+
208
+ | Filter | Description |
209
+ |--------|-------------|
210
+ | `base64_encode` | Base64 encode |
211
+ | `base64_decode` | Base64 decode |
212
+
213
+ ## Next Steps
214
+
215
+ - [Filters Guide](../guide/filters)
216
+ - [Custom Filters](../guide/custom-filters)
217
+ - [API Reference](../)
@@ -0,0 +1,94 @@
1
+ # Finder API
2
+
3
+ ## findTemplateInViews
4
+
5
+ Find a template file by name in the provided views directories.
6
+
7
+ === "CommonJS"
8
+
9
+ ```javascript
10
+ const { findTemplateInViews } = require('miki-template');
11
+
12
+ const found = findTemplateInViews('home', ['./views', './app/templates']);
13
+ console.log(found);
14
+ // Output: /absolute/path/to/home.html
15
+ ```
16
+
17
+ === "ES Modules"
18
+
19
+ ```javascript
20
+ import { findTemplateInViews } from 'miki-template';
21
+
22
+ const found = findTemplateInViews('home', ['./views', './app/templates']);
23
+ console.log(found);
24
+ ```
25
+
26
+ ### Parameters
27
+
28
+ | Parameter | Type | Description |
29
+ |-----------|------|-------------|
30
+ | `templateName` | `string` | Template name to search for (with or without extension) |
31
+ | `viewsDirs` | `string[]` | Array of views directories to search |
32
+
33
+ ### Returns
34
+
35
+ `string | null` — Absolute path to the template file, or `null` if not found.
36
+
37
+ ### Behavior
38
+
39
+ - Searches recursively through subdirectories for bare template names (no `/` in name).
40
+ - Tries `.html` and `.miki` extensions when no extension is provided.
41
+ - Also searches app-style `templates/` directories nested inside the views root.
42
+ - Returns the **first match found**.
43
+
44
+ ## setAppTemplateDirNames
45
+
46
+ Configure which directory names are treated as app-style template directories.
47
+
48
+ === "CommonJS"
49
+
50
+ ```javascript
51
+ const { setAppTemplateDirNames } = require('miki-template');
52
+
53
+ setAppTemplateDirNames(['templates', 'views', 'pages']);
54
+ ```
55
+
56
+ === "ES Modules"
57
+
58
+ ```javascript
59
+ import { setAppTemplateDirNames } from 'miki-template';
60
+
61
+ setAppTemplateDirNames(['templates', 'views', 'pages']);
62
+ ```
63
+
64
+ ### Parameters
65
+
66
+ | Parameter | Type | Description |
67
+ |-----------|------|-------------|
68
+ | `names` | `string \| string[]` | Directory name(s) to recognize |
69
+
70
+ ## getAppTemplateDirNames
71
+
72
+ Get the current app template directory names.
73
+
74
+ === "CommonJS"
75
+
76
+ ```javascript
77
+ const { getAppTemplateDirNames } = require('miki-template');
78
+
79
+ console.log(getAppTemplateDirNames());
80
+ // ['templates']
81
+ ```
82
+
83
+ === "ES Modules"
84
+
85
+ ```javascript
86
+ import { getAppTemplateDirNames } from 'miki-template';
87
+
88
+ console.log(getAppTemplateDirNames());
89
+ ```
90
+
91
+ ## Next Steps
92
+
93
+ - [Guide: Smart Template Discovery](../guide/template-discovery)
94
+ - [API Reference](../)
@@ -0,0 +1,53 @@
1
+ # Helpers API
2
+
3
+ ## registerHelper
4
+
5
+ Register a helper function that can be called from templates.
6
+
7
+ === "CommonJS"
8
+
9
+ ```javascript
10
+ const { registerHelper } = require('miki-template');
11
+
12
+ registerHelper('bold', (inner, context) => `<b>${inner}</b>`);
13
+ ```
14
+
15
+ === "ES Modules"
16
+
17
+ ```javascript
18
+ import { registerHelper } from 'miki-template';
19
+
20
+ registerHelper('bold', (inner, context) => `<b>${inner}</b>`);
21
+ ```
22
+
23
+ ### Helper Signature
24
+
25
+ Helpers receive `(content, context)` where `content` is the rendered inner content of the tag:
26
+
27
+ ```javascript
28
+ registerHelper('panel', (content, context) => {
29
+ return `<div class="panel">${content}</div>`;
30
+ });
31
+ ```
32
+
33
+ Usage in templates:
34
+
35
+ ```html
36
+ {% panel %}
37
+ <h2>{{ title }}</h2>
38
+ <p>{{ description }}</p>
39
+ {% endpanel %}
40
+ ```
41
+
42
+ ## Built-in Helpers
43
+
44
+ miki-template includes built-in helpers for common formatting tasks:
45
+
46
+ - `bold` — Wrap content in `<b>` tags
47
+ - `italic` — Wrap content in `<i>` tags
48
+ - `underline` — Wrap content in `<u>` tags
49
+
50
+ ## Next Steps
51
+
52
+ - [Custom Tags](../guide/custom-tags)
53
+ - [API Reference](../)
@@ -0,0 +1,157 @@
1
+ # i18n API
2
+
3
+ ## registerTranslation
4
+
5
+ Register translations for a language. Keys match the `{% trans "text" %}` source string.
6
+
7
+ === "CommonJS"
8
+
9
+ ```javascript
10
+ const { registerTranslation } = require('miki-template');
11
+
12
+ registerTranslation('en', {
13
+ hello: 'Hello',
14
+ goodbye: 'Goodbye'
15
+ });
16
+ ```
17
+
18
+ === "ES Modules"
19
+
20
+ ```javascript
21
+ import { registerTranslation } from 'miki-template';
22
+
23
+ registerTranslation('en', {
24
+ hello: 'Hello',
25
+ goodbye: 'Goodbye'
26
+ });
27
+ ```
28
+
29
+ You can also register nested keys for `blocktrans` with variables:
30
+
31
+ === "CommonJS"
32
+
33
+ ```javascript
34
+ const { registerTranslation, setLanguage } = require('miki-template');
35
+
36
+ setLanguage('en');
37
+ registerTranslation('en', {
38
+ 'Welcome, {name}!': 'Welcome, {name}!',
39
+ 'Goodbye, {name}!': 'Goodbye, {name}!'
40
+ });
41
+ ```
42
+
43
+ === "ES Modules"
44
+
45
+ ```javascript
46
+ import { registerTranslation, setLanguage } from 'miki-template';
47
+
48
+ setLanguage('en');
49
+ registerTranslation('en', {
50
+ 'Welcome, {name}!': 'Welcome, {name}!',
51
+ 'Goodbye, {name}!': 'Goodbye, {name}!'
52
+ });
53
+ ```
54
+
55
+ ## unregisterTranslation
56
+
57
+ === "CommonJS"
58
+
59
+ ```javascript
60
+ const { unregisterTranslation } = require('miki-template');
61
+
62
+ // Unregister a specific key
63
+ unregisterTranslation('en', 'hello');
64
+
65
+ // Unregister entire language
66
+ unregisterTranslation('en');
67
+
68
+ // Unregister all translations
69
+ unregisterTranslation();
70
+ ```
71
+
72
+ === "ES Modules"
73
+
74
+ ```javascript
75
+ import { unregisterTranslation } from 'miki-template';
76
+
77
+ unregisterTranslation('en', 'hello');
78
+ ```
79
+
80
+ ## setLanguage / getLanguage
81
+
82
+ Set or get the active language.
83
+
84
+ === "CommonJS"
85
+
86
+ ```javascript
87
+ const { setLanguage, getLanguage } = require('miki-template');
88
+
89
+ setLanguage('fr');
90
+ console.log(getLanguage()); // 'fr'
91
+ ```
92
+
93
+ === "ES Modules"
94
+
95
+ ```javascript
96
+ import { setLanguage, getLanguage } from 'miki-template';
97
+
98
+ setLanguage('fr');
99
+ console.log(getLanguage()); // 'fr'
100
+ ```
101
+
102
+ ## setFallbackLanguage / getFallbackLanguage
103
+
104
+ Set or get the fallback language (used when a key is missing from the active language).
105
+
106
+ === "CommonJS"
107
+
108
+ ```javascript
109
+ const { setFallbackLanguage, getFallbackLanguage } = require('miki-template');
110
+
111
+ setFallbackLanguage('en');
112
+ console.log(getFallbackLanguage()); // 'en'
113
+ ```
114
+
115
+ === "ES Modules"
116
+
117
+ ```javascript
118
+ import { setFallbackLanguage, getFallbackLanguage } from 'miki-template';
119
+
120
+ setFallbackLanguage('en');
121
+ ```
122
+
123
+ ## getAvailableLanguages
124
+
125
+ List all registered languages.
126
+
127
+ === "CommonJS"
128
+
129
+ ```javascript
130
+ const { getAvailableLanguages } = require('miki-template');
131
+
132
+ console.log(getAvailableLanguages());
133
+ // ['en', 'fr', 'es']
134
+ ```
135
+
136
+ === "ES Modules"
137
+
138
+ ```javascript
139
+ import { getAvailableLanguages } from 'miki-template';
140
+
141
+ console.log(getAvailableLanguages());
142
+ ```
143
+
144
+ ## Template Tags
145
+
146
+ The `{% trans %}` and `{% blocktrans %}` tags are provided by the auto-activated `i18n` library:
147
+
148
+ ```html
149
+ {% trans "Hello" %}
150
+ {% blocktrans %}Welcome, {{ name }}!{% endblocktrans %}
151
+ {% language "fr" %}...{% endlanguage %}
152
+ ```
153
+
154
+ ## Next Steps
155
+
156
+ - [Advanced Usage: i18n](../guide/advanced-usage#i18n--internationalization)
157
+ - [API Reference](../)
@@ -0,0 +1,54 @@
1
+ # API Reference
2
+
3
+ ## Core Functions
4
+
5
+ - [render()](./render) — Render a template string or file partial
6
+ - [compile()](./compile) — Compile a template into a reusable object with `render()`, `asyncRender()`, `renderBlock()`, `renderPartial()`
7
+ - [asyncRender()](./async-render) — Asynchronous rendering (supports async filters/tags)
8
+ - [renderPartialFromFile()](./render-partial) — Render a named partial from a file
9
+ - [renderPartialFromSource()](./render-partial) — Render a named partial from source
10
+ - [setupExpress()](./setup-express) — One-line Express integration
11
+
12
+ ## Tag and Filter Registration
13
+
14
+ - [registerFilter()](./filters) — Register a custom filter
15
+ - [getFilter()](./filters) — Retrieve a registered filter
16
+ - [registerTag()](./tags) — Register a custom tag
17
+ - [registerHelper()](./helpers) — Register a custom helper
18
+
19
+ ## Utilities
20
+
21
+ - [findTemplateInViews()](./finder) — Locate a template in views directories
22
+ - [setAppTemplateDirNames()](./finder) — Configure app-style template directory names
23
+ - [clearCache()](./cache) — Clear the compiled template cache
24
+ - [registerContextProcessor()](./context-processors) — Register a global context processor
25
+ - [clearContextProcessors()](./context-processors) — Clear all context processors
26
+
27
+ ## Security
28
+
29
+ - [markSafe()](./security) — Mark a string as safe (bypass escaping)
30
+ - [isSafe()](./security) — Check if a value is marked safe
31
+ - [escapeHtml()](./security) — Escape HTML special characters
32
+ - [SafeString](./security) — SafeString class
33
+
34
+ ## Express Engine Functions
35
+
36
+ - `__express(filePath, options, callback)` — Express-compatible sync view engine
37
+ - `__expressAsync(filePath, options)` — Express 5 async view engine (returns Promise)
38
+ - `express(options)` — Returns a view engine function for `app.engine()`
39
+ - `expressPartialRenderer()` — Express middleware adding `res.renderPartial()`
40
+ - `stripExpressContext(options)` — Remove Express framework keys from context
41
+
42
+ ## i18n
43
+
44
+ - [registerTranslation()](./i18n) — Register translations for a language
45
+ - [unregisterTranslation()](./i18n) — Unregister translations
46
+ - [setLanguage()](./i18n) / [getLanguage()](./i18n) — Set/get active language
47
+ - [setFallbackLanguage()](./i18n) / [getFallbackLanguage()](./i18n) — Set/get fallback language
48
+ - [getAvailableLanguages()](./i18n) — List registered languages
49
+
50
+ ## Libraries
51
+
52
+ - [registerLibrary()](./libraries) — Register a named library (filters, tags, helpers)
53
+ - [activateLibrary()](./libraries) / [registerLibraryFromPath()](./libraries) — Activate or load from file
54
+ - [unregisterLibrary()](./libraries) / [hasLibrary()](./libraries) / [getLibraryNames()](./libraries) — Library management