spyne 0.20.7 → 0.20.9

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Spyne 0.20.7
2
+ * Spyne 0.20.9
3
3
  * https://spynejs.org
4
4
  *
5
5
  * @license
@@ -15,7 +15,7 @@
15
15
  */
16
16
 
17
17
  /*!
18
- * spynejs 0.20.7
18
+ * spynejs 0.20.9
19
19
  * https://spynejs.org
20
20
  * (c) 2017-present Frank Batista
21
21
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spyne",
3
- "version": "0.20.7",
3
+ "version": "0.20.9",
4
4
  "description": "Reactive Real-DOM Framework for Advanced Javascript applications",
5
5
  "sideEffects": true,
6
6
  "main": "./lib/spyne.esm.js",
@@ -44,8 +44,8 @@
44
44
  "JavaScript Framework",
45
45
  "Single-Page-Application Framework"
46
46
  ],
47
- "author": "Frank Batista",
48
- "license": "LGPL",
47
+ "license": "LGPL-3.0",
48
+ "author": "Frank Batista <frank@spynejs.com> (Relevant Context, Inc.)",
49
49
  "devDependencies": {
50
50
  "@rollup/plugin-commonjs": "^28.0.2",
51
51
  "@rollup/plugin-json": "^6.1.0",
@@ -5,7 +5,7 @@ import { SpyneAppProperties } from './utils/spyne-app-properties.js'
5
5
  import { sanitizeHTMLConfigure } from './utils/sanitize-html.js'
6
6
 
7
7
  const _channels = new ChannelsMap()
8
- const version = '0.20.7'
8
+ const version = '0.20.9'
9
9
 
10
10
  class SpyneApplication {
11
11
  /**
@@ -42,7 +42,7 @@ class SpyneApplication {
42
42
  init(config = {}, testMode = false) {
43
43
  // this.channels = new ChannelsMap();
44
44
  /*!
45
- * Spyne 0.20.7
45
+ * Spyne 0.20.9
46
46
  * https://spynejs.org
47
47
  *
48
48
  * @license
@@ -311,6 +311,7 @@ export class DomElementTemplate {
311
311
  }
312
312
 
313
313
  const parseString = (item, str, index, origIndex) => {
314
+ item = item.replace(/\$/g, '$$$$') // $ → $$
314
315
  return str.replace(DomElementTemplate.swapParamsForTagsRE(), item)
315
316
  }
316
317
 
@@ -15,6 +15,6 @@ describe('package.json export import statement', () => {
15
15
 
16
16
  (isPublic ? describe : describe.skip)('license should be LGPL', () => {
17
17
  it('should have LGPL as license', () => {
18
- expect(pkg.license).to.equal('LGPL');
18
+ expect(pkg.license).to.equal('LGPL-3.0');
19
19
  });
20
20
  });
@@ -3,6 +3,78 @@ import { ScriptTemplate, StringTemplate, starWarsData } from '../mocks/template-
3
3
  import { DomElement } from '../../spyne/views/dom-element'
4
4
 
5
5
  chai.use(require('chai-dom'))
6
+ describe('DomElementTemplate should safely render special strings', () => {
7
+
8
+
9
+
10
+ const testCases = [
11
+ {
12
+ ref: 'dollarDigit',
13
+ label: 'should properly add $ sign before a number',
14
+ val: 'Currently raising $1.5M'
15
+ },
16
+ {
17
+ ref: 'dollarAmp',
18
+ label: 'should preserve $& which refers to full match in replace',
19
+ val: 'Matched value was: $&'
20
+ },
21
+ {
22
+ ref: 'dollarBacktick',
23
+ label: 'should preserve $` which refers to text before match in replace',
24
+ val: 'Before the match: $`'
25
+ },
26
+ {
27
+ ref: 'dollarSingleQuote',
28
+ label: 'should preserve $\' which refers to text after match in replace',
29
+ val: "After the match: $\'"
30
+ },
31
+ {
32
+ ref: 'backslashPath',
33
+ label: 'should preserve file path backslashes',
34
+ val: 'User path: C:\\Users\\Frank\\Documents'
35
+ },
36
+ {
37
+ ref: 'curlyBraces',
38
+ label: 'should preserve double curly brace templates in string',
39
+ val: 'This is not a template: {{user.name}}'
40
+ },
41
+ {
42
+ ref: 'scriptTag',
43
+ label: 'should render inline script tags safely (if allowed)',
44
+ val: 'Click here: <script>alert("XSS")</script>'
45
+ },
46
+ {
47
+ ref: 'richContentWithDot',
48
+ label: 'should allow rich content with template syntax inside',
49
+ val: 'Hello <b>{{.}}</b>, welcome back.'
50
+ },
51
+ {
52
+ ref: 'unicodeCurrency',
53
+ label: 'should preserve Unicode and currency characters',
54
+ val: 'Price is €100 or ¥12000'
55
+ }
56
+ ];
57
+
58
+ testCases.forEach(({ label, val, ref }) => {
59
+ it(`${ref}: ${label}`, () => {
60
+ const data = { val, arr: [val] };
61
+
62
+ const template = '<h1>I am {{val}}'
63
+ const domElTmpl = new DomElementTemplate(template, data, { testMode: true });
64
+ const render = domElTmpl.renderDocFrag();
65
+
66
+ const templateArr = '<h1>{{#arr}}{{.*}}{{/arr}}</h1>'
67
+ const domElTmpArr = new DomElementTemplate(templateArr, data, { testMode: true });
68
+ const renderArr = domElTmpArr.renderDocFrag();
69
+
70
+ //console.log("RENDER: ", render.firstElementChild.innerText," RENDERARR: ", renderArr.firstElementChild.innerText);
71
+
72
+ expect(render.firstElementChild.innerHTML).to.include(val.replace(/\n/g, ''));
73
+ expect(renderArr.firstElementChild.innerHTML).to.include(val.replace(/\n/g, ''));
74
+ });
75
+ });
76
+
77
+ });
6
78
 
7
79
  describe('DomElTemplate', () => {
8
80
  it('template renderer exists', () => {