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 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 as bar}My colour is {$bar}{/for}
1118
+ {$for:foo}My colour is %s{/for}
1132
1119
  ```
1133
1120
  ```ts
1134
1121
  const template = `
1135
1122
  <ul>
1136
- {$for:foo as bar}<li>{$bar}</li>{/for}
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
- Loops also support object properties using the dot syntax.
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
- If/else statements are supported in templates, which include blocks based on the existence/truthiness of a property.
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
- {$if:is_on_earth}
1172
- Hello, world!
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
- This also works with nested properties and loops.
1151
+ ```ts
1152
+ parse_template(..., {
1153
+ test: 'world'
1154
+ });
1155
+ ```
1179
1156
 
1180
1157
  ```html
1181
- {$for:countries as country}
1182
- {$if:country.is_in_europe}
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "spooder",
3
3
  "type": "module",
4
- "version": "4.3.0",
4
+ "version": "4.3.2",
5
5
  "exports": {
6
6
  ".": {
7
7
  "bun": "./src/api.ts",
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<any> | Record<string, any> | undefined;
112
- type Replacements = Record<string, string | Array<any> | Record<string, any>> | ReplacerFn;
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 [loop_key, loop_var] = buffer.substring(4).split(' as ');
156
- const loop_entries = getValue(loop_key);
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 (Array.isArray(loop_entries)) {
166
- for (const loop_entry of loop_entries)
167
- result += parseBlock(loop_content, { [loop_var]: loop_entry });
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 = loop_close_index + 5; // Move past {/for}
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 = getValue(buffer);
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 (!is_dev_mode) {
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;