saasufy-components 7.9.1 → 7.10.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/input-provider.js CHANGED
@@ -75,7 +75,7 @@ class InputProvider extends HTMLElement {
75
75
  delete this.forceTriggerChange;
76
76
  }
77
77
  if (newValue && this.hasAttribute('computable-value')) {
78
- newValue = renderTemplate(newValue);
78
+ newValue = renderTemplate(newValue, null, null, true);
79
79
  }
80
80
  this.updateInputClassList(newValue);
81
81
  let oldValue;
package/model-input.js CHANGED
@@ -71,7 +71,7 @@ class ModelInput extends SocketConsumer {
71
71
  set value(newValue) {
72
72
  if (this.inputElement) {
73
73
  if (newValue && this.hasAttribute('computable-value')) {
74
- newValue = renderTemplate(newValue);
74
+ newValue = renderTemplate(newValue, null, null, true);
75
75
  }
76
76
  let oldValue;
77
77
  if (this.inputElement.type === 'checkbox') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "saasufy-components",
3
- "version": "7.9.1",
3
+ "version": "7.10.0",
4
4
  "description": "Components for Saasufy.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -20,7 +20,7 @@
20
20
  "ag-collection": "^5.3.1",
21
21
  "ag-model": "^3.1.0",
22
22
  "capitalisk-auth-client": "^1.5.1",
23
- "socketcluster-client": "^19.2.1",
23
+ "socketcluster-client": "^19.2.3",
24
24
  "uuid": "^8.3.2"
25
25
  },
26
26
  "bugs": {
package/utils.js CHANGED
@@ -5,10 +5,9 @@ import { sha256 } from './sha256.js';
5
5
 
6
6
  const DEFAULT_DEBOUNCE_DELAY = 300;
7
7
  const DEFAULT_RELOAD_DELAY = 0;
8
-
9
- export function toSafeHTML(text) {
10
- if (typeof text === 'string') {
11
- return text.replace(/&(?!(amp|lt|gt|quot|#039|#123|#125);)/g, '&')
8
+ export function toSafeHTML(value) {
9
+ if (typeof value === 'string') {
10
+ return value.replace(/&(?!(amp|lt|gt|quot|#039|#123|#125);)/g, '&')
12
11
  .replace(/<(?!br ?\/?>)/g, '&lt;')
13
12
  .replace(/(?<!br ?\/?)>/g, '&gt;')
14
13
  .replace(/"/g, '&quot;')
@@ -16,14 +15,14 @@ export function toSafeHTML(text) {
16
15
  .replace(/\{/g, '&#123;')
17
16
  .replace(/\}/g, '&#125;')
18
17
  .replace(/\n/g, '<br>');
19
- } else if (text != null && typeof text.toString !== 'function') {
18
+ } else if (value != null && typeof value.toString !== 'function') {
20
19
  return '[invalid]';
21
20
  }
22
- return text;
21
+ return value;
23
22
  }
24
23
 
25
- export function toExpression(html) {
26
- return html.replace(/&amp;/g, '&')
24
+ export function toExpression(value) {
25
+ return value.replace(/&amp;/g, '&')
27
26
  .replace(/&lt;/g, '<')
28
27
  .replace(/&gt;/g, '>');
29
28
  }
@@ -216,9 +215,6 @@ let templateFormatters = {
216
215
  safeString: toSafeHTML
217
216
  };
218
217
 
219
- let templateTripleTagsRegExp = /{{{.*?}}}/gs;
220
- let templateTagsRegExp = /{{.*?}}/gs;
221
-
222
218
  function execExpression(expression, options) {
223
219
  let keys = Object.keys(options);
224
220
  let args = [
@@ -300,29 +296,53 @@ function replaceExpressions(string, replaceFn) {
300
296
  return charList.join('');
301
297
  }
302
298
 
303
- export function renderTemplate(templateString, data, socket) {
299
+ let templateMultiStartBracesRegExp = /{{{*/g
300
+ let templateMultiEndBracesRegExp = /}}}*/g
301
+
302
+ export function renderTemplate(templateString, data, socket, autoExecFunction) {
304
303
  let options = getRenderOptions(data, socket);
305
304
  return replaceExpressions(templateString, (expression) => {
306
305
  let expString;
307
306
  if (expression.startsWith('{{{') && expression.endsWith('}}}')) {
308
307
  expString = expression.slice(3, -3);
309
308
  try {
310
- return execExpression(
309
+ let result = execExpression(
311
310
  toExpression(expString),
312
311
  options
313
312
  );
313
+ if (typeof result === 'function') {
314
+ if (!autoExecFunction) {
315
+ return expression;
316
+ }
317
+ result = result();
318
+ }
319
+ return result;
314
320
  } catch (error) {
315
321
  return expression;
316
322
  }
317
323
  }
318
324
  expString = expression.slice(2, -2);
319
325
  try {
320
- return toSafeHTML(
321
- execExpression(
322
- toExpression(expString),
323
- options
324
- )
326
+ let result = execExpression(
327
+ toExpression(expString),
328
+ options
325
329
  );
330
+ if (typeof result === 'function') {
331
+ if (!autoExecFunction) {
332
+ return expression;
333
+ }
334
+ result = result();
335
+ }
336
+ if (typeof result === 'string') {
337
+ // Double braces cannot contain sub-expressions as it
338
+ // would present an XSS vulnerability.
339
+ // Replace them with square braces so that any code inside
340
+ // will not be executed if output is re-processed later.
341
+ result = result
342
+ .replace(templateMultiStartBracesRegExp, '[[')
343
+ .replace(templateMultiEndBracesRegExp, ']]');
344
+ }
345
+ return toSafeHTML(result);
326
346
  } catch (error) {
327
347
  return expression;
328
348
  }
@@ -340,7 +360,7 @@ export function updateConsumerElements(consumers, value, template, sourceElement
340
360
  .filter(([ selector, attributeName ]) => selector);
341
361
 
342
362
  if (template) {
343
- value = renderTemplate(template, { value });
363
+ value = renderTemplate(template, { value }, null, true);
344
364
  }
345
365
 
346
366
  if (outputType === 'boolean') {