spooder 4.3.0 → 4.3.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.
- package/README.md +18 -46
- package/package.json +1 -1
- package/src/api.ts +12 -62
- package/src/cli.ts +6 -3
package/README.md
CHANGED
|
@@ -225,6 +225,10 @@ server.webhook(process.env.WEBHOOK_SECRET, '/webhook', payload => {
|
|
|
225
225
|
});
|
|
226
226
|
```
|
|
227
227
|
|
|
228
|
+
### Skip Updates
|
|
229
|
+
|
|
230
|
+
In addition to being skipped in [dev mode](#cli-dev-mode), updates can also be skipped in production mode by passing the `--no-update` flag.
|
|
231
|
+
|
|
228
232
|
<a id="cli-canary"></a>
|
|
229
233
|
## CLI > Canary
|
|
230
234
|
|
|
@@ -1066,24 +1070,6 @@ const html = parse_template(template, replacements);
|
|
|
1066
1070
|
</html>
|
|
1067
1071
|
```
|
|
1068
1072
|
|
|
1069
|
-
Object properties are supported by using the dot syntax.
|
|
1070
|
-
|
|
1071
|
-
```ts
|
|
1072
|
-
const template = `<span>{$foo.bar}</span>`;
|
|
1073
|
-
|
|
1074
|
-
const replacements = {
|
|
1075
|
-
foo: {
|
|
1076
|
-
bar: 'Hello, world!';
|
|
1077
|
-
}
|
|
1078
|
-
};
|
|
1079
|
-
|
|
1080
|
-
const html = parse_template(template, replacements);
|
|
1081
|
-
```
|
|
1082
|
-
|
|
1083
|
-
```html
|
|
1084
|
-
<span>Hello, world!</span>
|
|
1085
|
-
```
|
|
1086
|
-
|
|
1087
1073
|
By default, placeholders that do not appear in the replacement object will be left as-is. Set `drop_missing` to `true` to remove them.
|
|
1088
1074
|
|
|
1089
1075
|
```ts
|
|
@@ -1125,15 +1111,16 @@ parse_template('Hello {$world}', replacer);
|
|
|
1125
1111
|
</body>
|
|
1126
1112
|
</html>
|
|
1127
1113
|
```
|
|
1114
|
+
|
|
1128
1115
|
`parse_template` supports looping arrays with the following syntax.
|
|
1129
1116
|
|
|
1130
1117
|
```html
|
|
1131
|
-
{$for:foo
|
|
1118
|
+
{$for:foo}My colour is %s{/for}
|
|
1132
1119
|
```
|
|
1133
1120
|
```ts
|
|
1134
1121
|
const template = `
|
|
1135
1122
|
<ul>
|
|
1136
|
-
{$for:foo
|
|
1123
|
+
{$for:foo}<li>%s</li>{/for}
|
|
1137
1124
|
</ul>
|
|
1138
1125
|
`;
|
|
1139
1126
|
|
|
@@ -1152,39 +1139,24 @@ const html = parse_template(template, replacements);
|
|
|
1152
1139
|
</ul>
|
|
1153
1140
|
```
|
|
1154
1141
|
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
```html
|
|
1158
|
-
{$for:foo as bar}My colour is {$bar.baz}{/for}
|
|
1159
|
-
```
|
|
1160
|
-
```ts
|
|
1161
|
-
const template = `
|
|
1162
|
-
<ul>
|
|
1163
|
-
{$for:foo as bar}<li>My colour is {$bar.baz}</li>{/for}
|
|
1164
|
-
</ul>
|
|
1165
|
-
`;
|
|
1166
|
-
```
|
|
1142
|
+
All placeholders inside a `{$for:}` loop are substituted, but only if the loop variable exists.
|
|
1167
1143
|
|
|
1168
|
-
|
|
1144
|
+
In the following example, `missing` does not exist, so `test` is not substituted inside the loop, but `test` is still substituted outside the loop.
|
|
1169
1145
|
|
|
1170
1146
|
```html
|
|
1171
|
-
{$
|
|
1172
|
-
|
|
1173
|
-
{else}
|
|
1174
|
-
Hello, Mars!
|
|
1175
|
-
{/if}
|
|
1147
|
+
<div>Hello {$test}!</div>
|
|
1148
|
+
{$for:missing}<div>Loop {$test}</div>{/for}
|
|
1176
1149
|
```
|
|
1177
1150
|
|
|
1178
|
-
|
|
1151
|
+
```ts
|
|
1152
|
+
parse_template(..., {
|
|
1153
|
+
test: 'world'
|
|
1154
|
+
});
|
|
1155
|
+
```
|
|
1179
1156
|
|
|
1180
1157
|
```html
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
Europe: {$country.name}
|
|
1184
|
-
{else}
|
|
1185
|
-
Not Europe: {$country.name}
|
|
1186
|
-
{/if}
|
|
1187
|
-
{/for}
|
|
1158
|
+
<div>Hello world!</div>
|
|
1159
|
+
{$for}Loop <div>{$test}</div>{/for}
|
|
1188
1160
|
```
|
|
1189
1161
|
|
|
1190
1162
|
<a id="api-content-generate-hash-subs"></a>
|
package/package.json
CHANGED
package/src/api.ts
CHANGED
|
@@ -108,8 +108,8 @@ export async function safe(target_fn: Callable) {
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
type ReplacerFn = (key: string) => string | Array<
|
|
112
|
-
type Replacements = Record<string, string | Array<
|
|
111
|
+
type ReplacerFn = (key: string) => string | Array<string> | undefined;
|
|
112
|
+
type Replacements = Record<string, string | Array<string>> | ReplacerFn;
|
|
113
113
|
|
|
114
114
|
export function parse_template(template: string, replacements: Replacements, drop_missing = false): string {
|
|
115
115
|
let result = '';
|
|
@@ -118,28 +118,6 @@ export function parse_template(template: string, replacements: Replacements, dro
|
|
|
118
118
|
|
|
119
119
|
const is_replacer_fn = typeof replacements === 'function';
|
|
120
120
|
|
|
121
|
-
function getValue(key: string): any {
|
|
122
|
-
const var_parts = key.split('.');
|
|
123
|
-
let value: any = is_replacer_fn ? replacements(var_parts[0]) : replacements[var_parts[0]];
|
|
124
|
-
|
|
125
|
-
for (let j = 1; j < var_parts.length; j++) {
|
|
126
|
-
if (value && typeof value === 'object') {
|
|
127
|
-
value = value[var_parts[j]];
|
|
128
|
-
} else {
|
|
129
|
-
value = undefined;
|
|
130
|
-
break;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return value;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function parseBlock(content: string, local_replacements: Replacements): string {
|
|
137
|
-
return parse_template(content, {
|
|
138
|
-
...replacements,
|
|
139
|
-
...local_replacements
|
|
140
|
-
}, drop_missing);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
121
|
const template_length = template.length;
|
|
144
122
|
for (let i = 0; i < template_length; i++) {
|
|
145
123
|
const char = template[i];
|
|
@@ -152,8 +130,9 @@ export function parse_template(template: string, replacements: Replacements, dro
|
|
|
152
130
|
buffer_active = false;
|
|
153
131
|
|
|
154
132
|
if (buffer.startsWith('for:')) {
|
|
155
|
-
const
|
|
156
|
-
|
|
133
|
+
const loop_key = buffer.substring(4);
|
|
134
|
+
|
|
135
|
+
const loop_entries = is_replacer_fn ? replacements(loop_key) : replacements[loop_key];
|
|
157
136
|
const loop_content_start_index = i + 1;
|
|
158
137
|
const loop_close_index = template.indexOf('{/for}', loop_content_start_index);
|
|
159
138
|
|
|
@@ -162,48 +141,19 @@ export function parse_template(template: string, replacements: Replacements, dro
|
|
|
162
141
|
result += '{$' + buffer + '}';
|
|
163
142
|
} else {
|
|
164
143
|
const loop_content = template.substring(loop_content_start_index, loop_close_index);
|
|
165
|
-
if (
|
|
166
|
-
for (const loop_entry of loop_entries)
|
|
167
|
-
|
|
144
|
+
if (loop_entries !== undefined) {
|
|
145
|
+
for (const loop_entry of loop_entries) {
|
|
146
|
+
const inner_content = loop_content.replaceAll('%s', loop_entry);
|
|
147
|
+
result += parse_template(inner_content, replacements, drop_missing);
|
|
148
|
+
}
|
|
168
149
|
} else {
|
|
169
150
|
if (!drop_missing)
|
|
170
151
|
result += '{$' + buffer + '}' + loop_content + '{/for}';
|
|
171
152
|
}
|
|
172
|
-
i
|
|
173
|
-
}
|
|
174
|
-
} else if (buffer.startsWith('if:')) {
|
|
175
|
-
const condition_key = buffer.substring(3);
|
|
176
|
-
const condition_value = getValue(condition_key);
|
|
177
|
-
const if_content_start_index = i + 1;
|
|
178
|
-
const if_close_index = template.indexOf('{/if}', if_content_start_index);
|
|
179
|
-
|
|
180
|
-
if (if_close_index === -1) {
|
|
181
|
-
if (!drop_missing)
|
|
182
|
-
result += '{$' + buffer + '}';
|
|
183
|
-
} else {
|
|
184
|
-
const if_content = template.substring(if_content_start_index, if_close_index);
|
|
185
|
-
const else_index = if_content.indexOf('{else}');
|
|
186
|
-
|
|
187
|
-
if (else_index === -1) {
|
|
188
|
-
// No else block
|
|
189
|
-
if (condition_value) {
|
|
190
|
-
result += parseBlock(if_content, {});
|
|
191
|
-
}
|
|
192
|
-
} else {
|
|
193
|
-
// Has else block
|
|
194
|
-
const true_content = if_content.substring(0, else_index);
|
|
195
|
-
const false_content = if_content.substring(else_index + 6); // +6 to move past {else}
|
|
196
|
-
|
|
197
|
-
if (condition_value)
|
|
198
|
-
result += parseBlock(true_content, {});
|
|
199
|
-
else
|
|
200
|
-
result += parseBlock(false_content, {});
|
|
201
|
-
}
|
|
202
|
-
i = if_close_index + 4; // Move past {/if}
|
|
153
|
+
i += loop_content.length + 6;
|
|
203
154
|
}
|
|
204
155
|
} else {
|
|
205
|
-
const replacement =
|
|
206
|
-
|
|
156
|
+
const replacement = is_replacer_fn ? replacements(buffer) : replacements[buffer];
|
|
207
157
|
if (replacement !== undefined)
|
|
208
158
|
result += replacement;
|
|
209
159
|
else if (!drop_missing)
|
package/src/cli.ts
CHANGED
|
@@ -8,13 +8,18 @@ async function start_server() {
|
|
|
8
8
|
|
|
9
9
|
const argv = process.argv.slice(2);
|
|
10
10
|
const is_dev_mode = argv.includes('--dev');
|
|
11
|
+
const skip_updates = argv.includes('--no-update');
|
|
11
12
|
|
|
12
13
|
if (is_dev_mode)
|
|
13
14
|
log('[{dev}] spooder has been started in {dev mode}');
|
|
14
15
|
|
|
15
16
|
const config = await get_config();
|
|
16
17
|
|
|
17
|
-
if (
|
|
18
|
+
if (is_dev_mode) {
|
|
19
|
+
log('[{update}] skipping update commands in {dev mode}');
|
|
20
|
+
} else if (skip_updates) {
|
|
21
|
+
log('[{update}] skipping update commands due to {--no-update} flag');
|
|
22
|
+
} else {
|
|
18
23
|
const update_commands = config.update;
|
|
19
24
|
const n_update_commands = update_commands.length;
|
|
20
25
|
|
|
@@ -42,8 +47,6 @@ async function start_server() {
|
|
|
42
47
|
}
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
|
-
} else {
|
|
46
|
-
log('[{dev}] skipping update commands in {dev mode}');
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
const crash_console_history = config.canary.crash_console_history;
|