fable 3.1.51 → 3.1.52
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 +87 -2
- package/dist/fable.js +7 -5
- package/dist/fable.js.map +1 -1
- package/dist/fable.min.js +1 -1
- package/dist/fable.min.js.map +1 -1
- package/docs/.nojekyll +0 -0
- package/docs/README.md +95 -0
- package/docs/_sidebar.md +42 -0
- package/docs/architecture.md +326 -0
- package/docs/cover.md +11 -0
- package/docs/index.html +51 -0
- package/docs/services/README.md +76 -0
- package/docs/services/anticipate.md +331 -0
- package/docs/services/csv-parser.md +152 -0
- package/docs/services/data-format.md +277 -0
- package/docs/services/data-generation.md +142 -0
- package/docs/services/dates.md +216 -0
- package/docs/services/environment-data.md +44 -0
- package/docs/services/expression-parser-functions/README.md +178 -0
- package/docs/services/expression-parser-functions/abs.md +84 -0
- package/docs/services/expression-parser-functions/aggregationhistogram.md +83 -0
- package/docs/services/expression-parser-functions/aggregationhistogrambyobject.md +64 -0
- package/docs/services/expression-parser-functions/arrayconcat.md +64 -0
- package/docs/services/expression-parser-functions/avg.md +81 -0
- package/docs/services/expression-parser-functions/bucketset.md +69 -0
- package/docs/services/expression-parser-functions/ceil.md +70 -0
- package/docs/services/expression-parser-functions/cleanvaluearray.md +66 -0
- package/docs/services/expression-parser-functions/cleanvalueobject.md +68 -0
- package/docs/services/expression-parser-functions/compare.md +72 -0
- package/docs/services/expression-parser-functions/concat.md +73 -0
- package/docs/services/expression-parser-functions/concatraw.md +73 -0
- package/docs/services/expression-parser-functions/cos.md +75 -0
- package/docs/services/expression-parser-functions/count.md +73 -0
- package/docs/services/expression-parser-functions/countset.md +65 -0
- package/docs/services/expression-parser-functions/countsetelements.md +63 -0
- package/docs/services/expression-parser-functions/createarrayfromabsolutevalues.md +63 -0
- package/docs/services/expression-parser-functions/createvalueobjectbyhashes.md +69 -0
- package/docs/services/expression-parser-functions/cumulativesummation.md +96 -0
- package/docs/services/expression-parser-functions/dateadddays.md +79 -0
- package/docs/services/expression-parser-functions/dateaddhours.md +74 -0
- package/docs/services/expression-parser-functions/dateaddmilliseconds.md +65 -0
- package/docs/services/expression-parser-functions/dateaddminutes.md +72 -0
- package/docs/services/expression-parser-functions/dateaddmonths.md +74 -0
- package/docs/services/expression-parser-functions/dateaddseconds.md +66 -0
- package/docs/services/expression-parser-functions/dateaddweeks.md +73 -0
- package/docs/services/expression-parser-functions/dateaddyears.md +74 -0
- package/docs/services/expression-parser-functions/datedaydifference.md +84 -0
- package/docs/services/expression-parser-functions/datefromparts.md +81 -0
- package/docs/services/expression-parser-functions/datehourdifference.md +64 -0
- package/docs/services/expression-parser-functions/datemathadd.md +72 -0
- package/docs/services/expression-parser-functions/datemilliseconddifference.md +64 -0
- package/docs/services/expression-parser-functions/dateminutedifference.md +64 -0
- package/docs/services/expression-parser-functions/datemonthdifference.md +66 -0
- package/docs/services/expression-parser-functions/dateseconddifference.md +64 -0
- package/docs/services/expression-parser-functions/dateweekdifference.md +65 -0
- package/docs/services/expression-parser-functions/dateyeardifference.md +64 -0
- package/docs/services/expression-parser-functions/distributionhistogram.md +96 -0
- package/docs/services/expression-parser-functions/distributionhistogrambyobject.md +64 -0
- package/docs/services/expression-parser-functions/entryinset.md +72 -0
- package/docs/services/expression-parser-functions/euler.md +77 -0
- package/docs/services/expression-parser-functions/exp.md +74 -0
- package/docs/services/expression-parser-functions/findfirstvaluebyexactmatch.md +67 -0
- package/docs/services/expression-parser-functions/findfirstvaluebystringincludes.md +67 -0
- package/docs/services/expression-parser-functions/flatten.md +76 -0
- package/docs/services/expression-parser-functions/floor.md +70 -0
- package/docs/services/expression-parser-functions/gaussianelimination.md +75 -0
- package/docs/services/expression-parser-functions/generatearrayofobjectsfromsets.md +70 -0
- package/docs/services/expression-parser-functions/getvalue.md +90 -0
- package/docs/services/expression-parser-functions/getvaluearray.md +64 -0
- package/docs/services/expression-parser-functions/getvalueobject.md +67 -0
- package/docs/services/expression-parser-functions/if.md +109 -0
- package/docs/services/expression-parser-functions/iterativeseries.md +107 -0
- package/docs/services/expression-parser-functions/join.md +75 -0
- package/docs/services/expression-parser-functions/joinraw.md +64 -0
- package/docs/services/expression-parser-functions/largestinset.md +63 -0
- package/docs/services/expression-parser-functions/leastsquares.md +66 -0
- package/docs/services/expression-parser-functions/linest.md +58 -0
- package/docs/services/expression-parser-functions/log.md +74 -0
- package/docs/services/expression-parser-functions/match.md +71 -0
- package/docs/services/expression-parser-functions/matrixinverse.md +67 -0
- package/docs/services/expression-parser-functions/matrixmultiply.md +71 -0
- package/docs/services/expression-parser-functions/matrixtranspose.md +72 -0
- package/docs/services/expression-parser-functions/matrixvectormultiply.md +69 -0
- package/docs/services/expression-parser-functions/max.md +73 -0
- package/docs/services/expression-parser-functions/mean.md +63 -0
- package/docs/services/expression-parser-functions/median.md +79 -0
- package/docs/services/expression-parser-functions/min.md +73 -0
- package/docs/services/expression-parser-functions/mode.md +66 -0
- package/docs/services/expression-parser-functions/objectkeystoarray.md +66 -0
- package/docs/services/expression-parser-functions/objectvaluessortbyexternalobjectarray.md +65 -0
- package/docs/services/expression-parser-functions/objectvaluestoarray.md +67 -0
- package/docs/services/expression-parser-functions/percent.md +75 -0
- package/docs/services/expression-parser-functions/pi.md +77 -0
- package/docs/services/expression-parser-functions/polynomialregression.md +69 -0
- package/docs/services/expression-parser-functions/predict.md +71 -0
- package/docs/services/expression-parser-functions/rad.md +85 -0
- package/docs/services/expression-parser-functions/randomfloat.md +63 -0
- package/docs/services/expression-parser-functions/randomfloatbetween.md +72 -0
- package/docs/services/expression-parser-functions/randomfloatupto.md +65 -0
- package/docs/services/expression-parser-functions/randominteger.md +56 -0
- package/docs/services/expression-parser-functions/randomintegerbetween.md +72 -0
- package/docs/services/expression-parser-functions/randomintegerupto.md +64 -0
- package/docs/services/expression-parser-functions/resolvehtmlentities.md +64 -0
- package/docs/services/expression-parser-functions/round.md +111 -0
- package/docs/services/expression-parser-functions/setconcatenate.md +64 -0
- package/docs/services/expression-parser-functions/sin.md +83 -0
- package/docs/services/expression-parser-functions/slice.md +80 -0
- package/docs/services/expression-parser-functions/smallestinset.md +63 -0
- package/docs/services/expression-parser-functions/sorthistogram.md +70 -0
- package/docs/services/expression-parser-functions/sorthistogrambykeys.md +69 -0
- package/docs/services/expression-parser-functions/sortset.md +75 -0
- package/docs/services/expression-parser-functions/sqrt.md +85 -0
- package/docs/services/expression-parser-functions/stdev.md +81 -0
- package/docs/services/expression-parser-functions/stdeva.md +58 -0
- package/docs/services/expression-parser-functions/stdevp.md +83 -0
- package/docs/services/expression-parser-functions/stringcountsegments.md +66 -0
- package/docs/services/expression-parser-functions/stringgetsegments.md +74 -0
- package/docs/services/expression-parser-functions/subtractingsummation.md +66 -0
- package/docs/services/expression-parser-functions/sum.md +78 -0
- package/docs/services/expression-parser-functions/tan.md +78 -0
- package/docs/services/expression-parser-functions/tofixed.md +75 -0
- package/docs/services/expression-parser-functions/var.md +67 -0
- package/docs/services/expression-parser-functions/vara.md +58 -0
- package/docs/services/expression-parser-functions/varp.md +66 -0
- package/docs/services/expression-parser-functions/when.md +98 -0
- package/docs/services/expression-parser.md +314 -0
- package/docs/services/file-persistence.md +279 -0
- package/docs/services/logging.md +237 -0
- package/docs/services/logic.md +166 -0
- package/docs/services/manifest.md +256 -0
- package/docs/services/math.md +279 -0
- package/docs/services/meta-template.md +268 -0
- package/docs/services/object-cache.md +171 -0
- package/docs/services/operation.md +207 -0
- package/docs/services/progress-time.md +167 -0
- package/docs/services/progress-tracker-set.md +222 -0
- package/docs/services/rest-client.md +296 -0
- package/docs/services/settings-manager.md +265 -0
- package/docs/services/template.md +233 -0
- package/docs/services/utility.md +304 -0
- package/docs/services/uuid.md +162 -0
- package/package.json +1 -1
- package/source/services/Fable-Service-DataFormat.js +1 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ValueMarshal.js +6 -4
- package/test/ExpressionParser_tests.js +3 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# Settings Manager Service
|
|
2
|
+
|
|
3
|
+
The Settings Manager provides centralized configuration management for Fable applications, with support for environment-aware settings and default value merging.
|
|
4
|
+
|
|
5
|
+
## Access
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
// Pre-initialized, available directly
|
|
9
|
+
fable.SettingsManager
|
|
10
|
+
fable.settings // Shorthand for SettingsManager.settings
|
|
11
|
+
fable.settingsManager // Alias
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Basic Usage
|
|
15
|
+
|
|
16
|
+
### Reading Settings
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
// Access settings directly
|
|
20
|
+
const productName = fable.settings.Product;
|
|
21
|
+
const version = fable.settings.ProductVersion;
|
|
22
|
+
|
|
23
|
+
// Access nested settings
|
|
24
|
+
const dbHost = fable.settings.Database.Host;
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Providing Configuration
|
|
28
|
+
|
|
29
|
+
Pass settings when creating a Fable instance:
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
const fable = new Fable({
|
|
33
|
+
Product: 'MyApplication',
|
|
34
|
+
ProductVersion: '1.0.0',
|
|
35
|
+
|
|
36
|
+
Database: {
|
|
37
|
+
Host: 'localhost',
|
|
38
|
+
Port: 5432,
|
|
39
|
+
Name: 'myapp'
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
API: {
|
|
43
|
+
BaseURL: 'https://api.example.com',
|
|
44
|
+
Timeout: 30000
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Default Settings
|
|
50
|
+
|
|
51
|
+
Fable provides sensible defaults that your configuration extends:
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
{
|
|
55
|
+
Product: 'Fable',
|
|
56
|
+
ProductVersion: '0.0.0',
|
|
57
|
+
|
|
58
|
+
UUID: {
|
|
59
|
+
DataCenter: 0,
|
|
60
|
+
Worker: 0
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
LogStreams: [
|
|
64
|
+
{ level: 'info' }
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Your settings are merged with these defaults using [precedent](https://github.com/stevenvelozo/precedent).
|
|
70
|
+
|
|
71
|
+
## Environment-Aware Configuration
|
|
72
|
+
|
|
73
|
+
### Using Environment Variables
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
const fable = new Fable({
|
|
77
|
+
Product: 'MyApp',
|
|
78
|
+
|
|
79
|
+
Database: {
|
|
80
|
+
Host: process.env.DB_HOST || 'localhost',
|
|
81
|
+
Port: parseInt(process.env.DB_PORT) || 5432,
|
|
82
|
+
Password: process.env.DB_PASSWORD
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Environment-Specific Config Files
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
const environment = process.env.NODE_ENV || 'development';
|
|
91
|
+
const config = require(`./config/${environment}.json`);
|
|
92
|
+
|
|
93
|
+
const fable = new Fable(config);
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Precedent Integration
|
|
97
|
+
|
|
98
|
+
The Settings Manager uses precedent for deep configuration merging:
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
// Base configuration
|
|
102
|
+
const baseConfig = {
|
|
103
|
+
API: {
|
|
104
|
+
Timeout: 5000,
|
|
105
|
+
RetryCount: 3
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// Environment override
|
|
110
|
+
const envConfig = {
|
|
111
|
+
API: {
|
|
112
|
+
Timeout: 30000 // Override just the timeout
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Result: { API: { Timeout: 30000, RetryCount: 3 } }
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Configuration Patterns
|
|
120
|
+
|
|
121
|
+
### Layered Configuration
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
const defaults = require('./config/default.json');
|
|
125
|
+
const environment = require(`./config/${process.env.NODE_ENV}.json`);
|
|
126
|
+
const local = require('./config/local.json'); // gitignored
|
|
127
|
+
|
|
128
|
+
const fable = new Fable({
|
|
129
|
+
...defaults,
|
|
130
|
+
...environment,
|
|
131
|
+
...local
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Feature Flags
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
const fable = new Fable({
|
|
139
|
+
Features: {
|
|
140
|
+
NewDashboard: process.env.FEATURE_NEW_DASHBOARD === 'true',
|
|
141
|
+
BetaAPI: false
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Usage
|
|
146
|
+
if (fable.settings.Features.NewDashboard) {
|
|
147
|
+
// New dashboard code
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Service Configuration
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
const fable = new Fable({
|
|
155
|
+
Services: {
|
|
156
|
+
Email: {
|
|
157
|
+
Provider: 'sendgrid',
|
|
158
|
+
APIKey: process.env.SENDGRID_API_KEY
|
|
159
|
+
},
|
|
160
|
+
Storage: {
|
|
161
|
+
Provider: 's3',
|
|
162
|
+
Bucket: 'my-app-storage'
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Accessing Settings in Services
|
|
169
|
+
|
|
170
|
+
All Fable services can access settings:
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
class MyService extends libFableServiceBase {
|
|
174
|
+
constructor(pFable, pOptions, pServiceHash) {
|
|
175
|
+
super(pFable, pOptions, pServiceHash);
|
|
176
|
+
|
|
177
|
+
// Access global settings
|
|
178
|
+
this.apiUrl = this.fable.settings.API.BaseURL;
|
|
179
|
+
|
|
180
|
+
// Access service-specific options
|
|
181
|
+
this.localOption = this.options.myOption;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Common Configuration Options
|
|
187
|
+
|
|
188
|
+
### Product Information
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
{
|
|
192
|
+
Product: 'MyApp',
|
|
193
|
+
ProductVersion: '1.0.0'
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### UUID Configuration
|
|
198
|
+
|
|
199
|
+
```javascript
|
|
200
|
+
{
|
|
201
|
+
UUID: {
|
|
202
|
+
DataCenter: 1, // 0-31
|
|
203
|
+
Worker: 5 // 0-31
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Logging Configuration
|
|
209
|
+
|
|
210
|
+
```javascript
|
|
211
|
+
{
|
|
212
|
+
LogStreams: [
|
|
213
|
+
{ level: 'info' },
|
|
214
|
+
{ level: 'error', path: '/var/log/app/error.log' }
|
|
215
|
+
]
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### REST Client Configuration
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
{
|
|
223
|
+
RestClientURLPrefix: 'https://api.example.com/v1'
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Best Practices
|
|
228
|
+
|
|
229
|
+
1. **Don't hardcode secrets**: Use environment variables
|
|
230
|
+
2. **Use typed configuration**: Define interfaces for your config shape
|
|
231
|
+
3. **Provide sensible defaults**: Make configuration optional where possible
|
|
232
|
+
4. **Document your settings**: List all configuration options
|
|
233
|
+
5. **Validate on startup**: Check for required settings early
|
|
234
|
+
|
|
235
|
+
```javascript
|
|
236
|
+
// Validation example
|
|
237
|
+
const fable = new Fable(config);
|
|
238
|
+
|
|
239
|
+
if (!fable.settings.Database?.Host) {
|
|
240
|
+
throw new Error('Database.Host is required');
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Reading External Config Files
|
|
245
|
+
|
|
246
|
+
```javascript
|
|
247
|
+
const fs = require('fs');
|
|
248
|
+
const path = require('path');
|
|
249
|
+
|
|
250
|
+
const configPath = path.join(__dirname, 'config.json');
|
|
251
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
252
|
+
|
|
253
|
+
const fable = new Fable(config);
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Runtime Configuration Updates
|
|
257
|
+
|
|
258
|
+
While generally not recommended, settings can be modified at runtime:
|
|
259
|
+
|
|
260
|
+
```javascript
|
|
261
|
+
// Not recommended, but possible
|
|
262
|
+
fable.settings.MyFeature.Enabled = true;
|
|
263
|
+
|
|
264
|
+
// Better: Use a service for dynamic configuration
|
|
265
|
+
```
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Template Service
|
|
2
|
+
|
|
3
|
+
The Template service provides underscore/lodash-style template compilation and rendering. It compiles string templates into reusable functions.
|
|
4
|
+
|
|
5
|
+
## Access
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
// On-demand service - instantiate when needed
|
|
9
|
+
const template = fable.instantiateServiceProvider('Template');
|
|
10
|
+
|
|
11
|
+
// Or use the Utility service shorthand
|
|
12
|
+
const renderFn = fable.Utility.template('Hello, <%= name %>!');
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Template Syntax
|
|
16
|
+
|
|
17
|
+
### Interpolation (`<%= %>`)
|
|
18
|
+
|
|
19
|
+
Output a value:
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
const template = fable.instantiateServiceProvider('Template');
|
|
23
|
+
const render = template.buildTemplateFunction('Hello, <%= name %>!');
|
|
24
|
+
|
|
25
|
+
render({ name: 'World' }); // Returns 'Hello, World!'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Evaluation (`<% %>`)
|
|
29
|
+
|
|
30
|
+
Execute JavaScript code:
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
const render = template.buildTemplateFunction(`
|
|
34
|
+
<% for (var i = 0; i < items.length; i++) { %>
|
|
35
|
+
Item: <%= items[i] %>
|
|
36
|
+
<% } %>
|
|
37
|
+
`);
|
|
38
|
+
|
|
39
|
+
render({ items: ['Apple', 'Banana', 'Cherry'] });
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Basic Usage
|
|
43
|
+
|
|
44
|
+
### Create and Use Template
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
const template = fable.instantiateServiceProvider('Template');
|
|
48
|
+
|
|
49
|
+
// Build the template function
|
|
50
|
+
const greetingTemplate = template.buildTemplateFunction('Hello, <%= name %>!');
|
|
51
|
+
|
|
52
|
+
// Use it multiple times
|
|
53
|
+
greetingTemplate({ name: 'Alice' }); // 'Hello, Alice!'
|
|
54
|
+
greetingTemplate({ name: 'Bob' }); // 'Hello, Bob!'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Immediate Rendering
|
|
58
|
+
|
|
59
|
+
Pass data as the second argument to render immediately:
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
const result = template.buildTemplateFunction('Sum: <%= a + b %>', { a: 5, b: 3 });
|
|
63
|
+
// Returns 'Sum: 8'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Using the Utility Shorthand
|
|
67
|
+
|
|
68
|
+
The Utility service provides a convenient wrapper:
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
// Create a template function
|
|
72
|
+
const greet = fable.Utility.template('Hello, <%= name %>!');
|
|
73
|
+
greet({ name: 'World' });
|
|
74
|
+
|
|
75
|
+
// Or render immediately
|
|
76
|
+
fable.Utility.template('Hello, <%= name %>!', { name: 'World' });
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Hashed Templates
|
|
80
|
+
|
|
81
|
+
Register templates for reuse by name:
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
// Register a template
|
|
85
|
+
fable.Utility.buildHashedTemplate('user-card', `
|
|
86
|
+
<div class="card">
|
|
87
|
+
<h2><%= user.name %></h2>
|
|
88
|
+
<p><%= user.email %></p>
|
|
89
|
+
</div>
|
|
90
|
+
`);
|
|
91
|
+
|
|
92
|
+
// Use the registered template
|
|
93
|
+
fable.Utility.templates['user-card']({ user: { name: 'John', email: 'john@example.com' } });
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Examples
|
|
97
|
+
|
|
98
|
+
### HTML Generation
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
const cardTemplate = template.buildTemplateFunction(`
|
|
102
|
+
<div class="card">
|
|
103
|
+
<h2><%= title %></h2>
|
|
104
|
+
<p><%= description %></p>
|
|
105
|
+
<% if (showButton) { %>
|
|
106
|
+
<button><%= buttonText %></button>
|
|
107
|
+
<% } %>
|
|
108
|
+
</div>
|
|
109
|
+
`);
|
|
110
|
+
|
|
111
|
+
cardTemplate({
|
|
112
|
+
title: 'Welcome',
|
|
113
|
+
description: 'This is a card component',
|
|
114
|
+
showButton: true,
|
|
115
|
+
buttonText: 'Click Me'
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Lists and Loops
|
|
120
|
+
|
|
121
|
+
```javascript
|
|
122
|
+
const listTemplate = template.buildTemplateFunction(`
|
|
123
|
+
<ul>
|
|
124
|
+
<% for (var i = 0; i < items.length; i++) { %>
|
|
125
|
+
<li><%= items[i].name %>: $<%= items[i].price %></li>
|
|
126
|
+
<% } %>
|
|
127
|
+
</ul>
|
|
128
|
+
`);
|
|
129
|
+
|
|
130
|
+
listTemplate({
|
|
131
|
+
items: [
|
|
132
|
+
{ name: 'Apple', price: 1.50 },
|
|
133
|
+
{ name: 'Banana', price: 0.75 }
|
|
134
|
+
]
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Conditional Content
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
const statusTemplate = template.buildTemplateFunction(`
|
|
142
|
+
<% if (status === 'active') { %>
|
|
143
|
+
<span class="badge-green">Active</span>
|
|
144
|
+
<% } else if (status === 'pending') { %>
|
|
145
|
+
<span class="badge-yellow">Pending</span>
|
|
146
|
+
<% } else { %>
|
|
147
|
+
<span class="badge-red">Inactive</span>
|
|
148
|
+
<% } %>
|
|
149
|
+
`);
|
|
150
|
+
|
|
151
|
+
statusTemplate({ status: 'active' });
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Nested Data
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
const profileTemplate = template.buildTemplateFunction(`
|
|
158
|
+
<div class="profile">
|
|
159
|
+
<h1><%= user.name %></h1>
|
|
160
|
+
<p>Email: <%= user.contact.email %></p>
|
|
161
|
+
<p>Phone: <%= user.contact.phone %></p>
|
|
162
|
+
<h3>Addresses:</h3>
|
|
163
|
+
<% for (var i = 0; i < user.addresses.length; i++) { %>
|
|
164
|
+
<p><%= user.addresses[i].street %>, <%= user.addresses[i].city %></p>
|
|
165
|
+
<% } %>
|
|
166
|
+
</div>
|
|
167
|
+
`);
|
|
168
|
+
|
|
169
|
+
profileTemplate({
|
|
170
|
+
user: {
|
|
171
|
+
name: 'John Doe',
|
|
172
|
+
contact: {
|
|
173
|
+
email: 'john@example.com',
|
|
174
|
+
phone: '555-1234'
|
|
175
|
+
},
|
|
176
|
+
addresses: [
|
|
177
|
+
{ street: '123 Main St', city: 'Anytown' },
|
|
178
|
+
{ street: '456 Oak Ave', city: 'Other City' }
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Print Function
|
|
185
|
+
|
|
186
|
+
Use `print()` for inline output:
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
const template = template.buildTemplateFunction(`
|
|
190
|
+
<% print('Hello'); print(' '); print('World'); %>
|
|
191
|
+
`);
|
|
192
|
+
|
|
193
|
+
template({}); // Returns 'Hello World'
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Template Source Access
|
|
197
|
+
|
|
198
|
+
After building a template, you can access the generated source:
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
const tpl = fable.instantiateServiceProvider('Template');
|
|
202
|
+
tpl.buildTemplateFunction('Hello, <%= name %>!');
|
|
203
|
+
|
|
204
|
+
// Access the generated function source
|
|
205
|
+
console.log(tpl.TemplateSource);
|
|
206
|
+
console.log(tpl.TemplateSourceCompiled);
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Escape Handling
|
|
210
|
+
|
|
211
|
+
The template engine handles these escape sequences:
|
|
212
|
+
|
|
213
|
+
- `\\` - Backslash
|
|
214
|
+
- `'` - Single quote
|
|
215
|
+
- `\r` - Carriage return
|
|
216
|
+
- `\n` - Newline
|
|
217
|
+
- `\t` - Tab
|
|
218
|
+
- `\u2028` - Line separator
|
|
219
|
+
- `\u2029` - Paragraph separator
|
|
220
|
+
|
|
221
|
+
## Notes
|
|
222
|
+
|
|
223
|
+
- This implementation is compatible with underscore/lodash template syntax
|
|
224
|
+
- Does NOT implement underscore's escape expressions (`<%- %>`)
|
|
225
|
+
- Does NOT implement automatic browser variable assignment
|
|
226
|
+
- Templates are compiled to JavaScript functions for performance
|
|
227
|
+
- URL-encoded content in templates is automatically decoded
|
|
228
|
+
|
|
229
|
+
## Performance Tips
|
|
230
|
+
|
|
231
|
+
1. **Compile once, use many times**: Store template functions and reuse them
|
|
232
|
+
2. **Use hashed templates**: For frequently used templates, register them with `buildHashedTemplate`
|
|
233
|
+
3. **Avoid complex logic**: Keep template logic simple; move complex operations to the data preparation phase
|