@doist/react-interpolate 0.2.0 → 0.3.8
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 +49 -48
- package/dist/react-interpolate.cjs +56 -48
- package/dist/react-interpolate.min.cjs +1 -1
- package/dist/react-interpolate.min.mjs +1 -1
- package/dist/react-interpolate.mjs +33 -32
- package/package.json +73 -62
- package/src/constants.js +10 -10
- package/src/index.js +3 -8
- package/src/interpolate.js +13 -20
- package/src/lexer.js +8 -10
- package/src/node.js +11 -11
- package/src/parser.js +7 -8
- package/src/syntax.js +9 -14
- package/.eslintrc.js +0 -36
- package/.github/workflows/nodejs.yml +0 -32
- package/.prettierrc.json +0 -9
- package/CONTRIBUTING.md +0 -7
- package/__test__/Interpolate.test.js +0 -203
- package/__test__/parser.test.js +0 -45
- package/babel.config.js +0 -18
- package/dist/react-interpolate.min.cjs.gz +0 -0
- package/dist/react-interpolate.min.mjs.gz +0 -0
- package/rollup.config.js +0 -17
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
|
2
|
-
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
|
3
|
-
|
|
4
|
-
name: CI
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
push:
|
|
8
|
-
branches: [ master ]
|
|
9
|
-
pull_request:
|
|
10
|
-
branches: [ master ]
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
build:
|
|
14
|
-
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
|
|
17
|
-
strategy:
|
|
18
|
-
matrix:
|
|
19
|
-
node-version: [12.x]
|
|
20
|
-
|
|
21
|
-
steps:
|
|
22
|
-
- uses: actions/checkout@v2
|
|
23
|
-
- name: Use Node.js ${{ matrix.node-version }}
|
|
24
|
-
uses: actions/setup-node@v1
|
|
25
|
-
with:
|
|
26
|
-
node-version: ${{ matrix.node-version }}
|
|
27
|
-
- run: npm ci
|
|
28
|
-
- run: npm run build
|
|
29
|
-
- run: npm test
|
|
30
|
-
env:
|
|
31
|
-
CI: true
|
|
32
|
-
- run: npm run lint
|
package/.prettierrc.json
DELETED
package/CONTRIBUTING.md
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
## Dependencies and target environment
|
|
2
|
-
|
|
3
|
-
One core goal this library is to deliver a lightweight solution. Therefore, it comes to critically when it comes to user of dependencies and also polyfill usage.
|
|
4
|
-
|
|
5
|
-
- `react` should be its only dependencies.
|
|
6
|
-
- No polyfill.
|
|
7
|
-
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
/* eslint-disable react/display-name */
|
|
2
|
-
import React from "react"
|
|
3
|
-
import { render } from "@testing-library/react"
|
|
4
|
-
import Interpolate, { SYNTAX_I18NEXT } from "../src"
|
|
5
|
-
|
|
6
|
-
Interpolate.defaultProps = {
|
|
7
|
-
graceful: false
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const surpressConsole = () => {
|
|
11
|
-
const w = jest.spyOn(console, "warn").mockImplementation()
|
|
12
|
-
const e = jest.spyOn(console, "error").mockImplementation()
|
|
13
|
-
|
|
14
|
-
return () => {
|
|
15
|
-
w.mockRestore()
|
|
16
|
-
e.mockRestore()
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
describe("Interpolate", () => {
|
|
21
|
-
function renderTest({ expected, ...props }) {
|
|
22
|
-
const { container } = render(<Interpolate {...props} />)
|
|
23
|
-
expect(container.innerHTML).toEqual(expected)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
test("when no mapping is provide", () => {
|
|
27
|
-
const restore = surpressConsole() // Interpolate will output warning when no mapping is provided
|
|
28
|
-
|
|
29
|
-
renderTest({
|
|
30
|
-
string: "<h1>hello <b>{name}</b></h1><br/>. welcome to todoist",
|
|
31
|
-
expected: "<h1>hello <b>{name}</b></h1><br>. welcome to todoist"
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
restore()
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
test("tag mapping", () =>
|
|
38
|
-
renderTest({
|
|
39
|
-
string: "<h1>hello <b>steven</b></h1>. welcome to todoist",
|
|
40
|
-
mapping: {
|
|
41
|
-
b: child => <i>{child}</i>,
|
|
42
|
-
h1: child => <h2>{child}</h2>
|
|
43
|
-
},
|
|
44
|
-
expected: "<h2>hello <i>steven</i></h2>. welcome to todoist"
|
|
45
|
-
}))
|
|
46
|
-
|
|
47
|
-
test("tag mapping: should accept element directly", () =>
|
|
48
|
-
renderTest({
|
|
49
|
-
string: "<h1>hello <b>steven</b></h1>. welcome to todoist",
|
|
50
|
-
mapping: {
|
|
51
|
-
b: <i />,
|
|
52
|
-
h1: <h2 />
|
|
53
|
-
},
|
|
54
|
-
expected: "<h2>hello <i>steven</i></h2>. welcome to todoist"
|
|
55
|
-
}))
|
|
56
|
-
|
|
57
|
-
test("placholder mapping", () =>
|
|
58
|
-
renderTest({
|
|
59
|
-
string: "{greeting} <b>{name}</b>. welcome to todoist",
|
|
60
|
-
mapping: {
|
|
61
|
-
greeting: "hi",
|
|
62
|
-
name: () => <i>steven</i>
|
|
63
|
-
},
|
|
64
|
-
expected: "hi <b><i>steven</i></b>. welcome to todoist"
|
|
65
|
-
}))
|
|
66
|
-
|
|
67
|
-
test("void tag mapping", () =>
|
|
68
|
-
renderTest({
|
|
69
|
-
string: "hello <br/>",
|
|
70
|
-
mapping: {
|
|
71
|
-
br: <hr />
|
|
72
|
-
},
|
|
73
|
-
expected: "hello <hr>"
|
|
74
|
-
}))
|
|
75
|
-
|
|
76
|
-
test("combination of mapping", () =>
|
|
77
|
-
renderTest({
|
|
78
|
-
string: "<h1>hello <b>{name}</b></h1>.<br/> welcome to todoist",
|
|
79
|
-
mapping: {
|
|
80
|
-
h1: child => <h2>{child}</h2>,
|
|
81
|
-
b: child => <i>{child}</i>,
|
|
82
|
-
name: "steven",
|
|
83
|
-
br: <hr />
|
|
84
|
-
},
|
|
85
|
-
expected: "<h2>hello <i>steven</i></h2>.<hr> welcome to todoist"
|
|
86
|
-
}))
|
|
87
|
-
|
|
88
|
-
test("combination of mapping with function component", () => {
|
|
89
|
-
// eslint-disable-next-line
|
|
90
|
-
const Subheader = ({ children }) => {
|
|
91
|
-
return <h2 className="subheader">{children}</h2>
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
renderTest({
|
|
95
|
-
string: "<h1>hello <b>{name}</b></h1>.<br/> welcome to todoist",
|
|
96
|
-
mapping: {
|
|
97
|
-
h1: child => <Subheader>{child}</Subheader>,
|
|
98
|
-
b: child => <i>{child}</i>,
|
|
99
|
-
name: "steven",
|
|
100
|
-
br: <hr />
|
|
101
|
-
},
|
|
102
|
-
expected:
|
|
103
|
-
'<h2 class="subheader">hello <i>steven</i></h2>.<hr> welcome to todoist'
|
|
104
|
-
})
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
test("spacing in the void tag and placeholder should be allowed", () =>
|
|
108
|
-
renderTest({
|
|
109
|
-
string: "hello { name }<br /> welcome to todoist",
|
|
110
|
-
mapping: {
|
|
111
|
-
name: "steven",
|
|
112
|
-
br: <hr />
|
|
113
|
-
},
|
|
114
|
-
expected: "hello steven<hr> welcome to todoist"
|
|
115
|
-
}))
|
|
116
|
-
|
|
117
|
-
test("the mapping value should be interpolate corrected with proper html escape", () => {
|
|
118
|
-
renderTest({
|
|
119
|
-
string: "hello { name }<br /> welcome to todoist",
|
|
120
|
-
mapping: {
|
|
121
|
-
name: "<script>window.xss = 1</script>",
|
|
122
|
-
br: "<script>window.xss = 1</script>"
|
|
123
|
-
},
|
|
124
|
-
expected:
|
|
125
|
-
"hello <script>window.xss = 1</script><script>window.xss = 1</script> welcome to todoist"
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
expect(window.css).toBeUndefined()
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
test("when graceful flag is on and string contains syntax error, interpolate should return the original string and should not throw error", () => {
|
|
132
|
-
const restore = surpressConsole()
|
|
133
|
-
|
|
134
|
-
renderTest({
|
|
135
|
-
string: "</h1>",
|
|
136
|
-
expected: "</h1>",
|
|
137
|
-
graceful: true
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
restore()
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
test("using SYNTAX_I18NEXT", () => {
|
|
144
|
-
renderTest({
|
|
145
|
-
syntax: SYNTAX_I18NEXT,
|
|
146
|
-
string: "<0>hello <b>{{name}}</b></0>.<br/> welcome to todoist",
|
|
147
|
-
mapping: {
|
|
148
|
-
0: child => <h2 className="subheader">{child}</h2>,
|
|
149
|
-
b: child => <i>{child}</i>,
|
|
150
|
-
name: "steven",
|
|
151
|
-
br: <hr />
|
|
152
|
-
},
|
|
153
|
-
expected:
|
|
154
|
-
'<h2 class="subheader">hello <i>steven</i></h2>.<hr> welcome to todoist'
|
|
155
|
-
})
|
|
156
|
-
})
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
describe("Interpolate: error cases", () => {
|
|
160
|
-
let restore
|
|
161
|
-
beforeAll(() => {
|
|
162
|
-
restore = surpressConsole()
|
|
163
|
-
})
|
|
164
|
-
afterAll(() => {
|
|
165
|
-
restore()
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
function renderTest({ expectedError, ...props }) {
|
|
169
|
-
return () => {
|
|
170
|
-
expect(() => render(<Interpolate {...props} />)).toThrow(
|
|
171
|
-
expectedError
|
|
172
|
-
)
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
test(
|
|
177
|
-
"non-closing tag",
|
|
178
|
-
renderTest({
|
|
179
|
-
string: "<b>",
|
|
180
|
-
expectedError:
|
|
181
|
-
"Syntax error. Please check if each open tag is closed correctly"
|
|
182
|
-
})
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
test(
|
|
186
|
-
"mapping value for tag should always be a function",
|
|
187
|
-
renderTest({
|
|
188
|
-
string: "<h1>hello</h1>. welcome to todoist",
|
|
189
|
-
mapping: { h1: "hi" },
|
|
190
|
-
expectedError: "Invalid mapping value for"
|
|
191
|
-
})
|
|
192
|
-
)
|
|
193
|
-
|
|
194
|
-
test(
|
|
195
|
-
"when passing element as value but the element contains children, error should be thrown",
|
|
196
|
-
renderTest({
|
|
197
|
-
string: "<h1>hello</h1>. welcome to todoist",
|
|
198
|
-
mapping: { h1: <h1>hi</h1> },
|
|
199
|
-
expectedError:
|
|
200
|
-
"when passing an element as value, the element should not contains children"
|
|
201
|
-
})
|
|
202
|
-
)
|
|
203
|
-
})
|
package/__test__/parser.test.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import parser from "../src/parser"
|
|
2
|
-
|
|
3
|
-
describe("parser", () => {
|
|
4
|
-
const tests = [
|
|
5
|
-
"hello",
|
|
6
|
-
"{steven}",
|
|
7
|
-
"<br />",
|
|
8
|
-
"<div></div>",
|
|
9
|
-
"hello {steven} from taiwan",
|
|
10
|
-
"hello {steven} from taiwan <br/>",
|
|
11
|
-
"<div>hello</div>",
|
|
12
|
-
"<div>hello {steven}</div>",
|
|
13
|
-
"<div>hello <b>{steven}</b></div>",
|
|
14
|
-
"<div>hello <b>mr {steven} from taiwan</b></div>",
|
|
15
|
-
"<div>hello <b>mr {steven} from taiwan</b><br /></div>",
|
|
16
|
-
"<div>hello</div><b>steven</b>"
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
tests.forEach(string => {
|
|
20
|
-
test(string, () => {
|
|
21
|
-
parser(string)
|
|
22
|
-
})
|
|
23
|
-
})
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
describe("parser: error handling", () => {
|
|
27
|
-
const invalids = [
|
|
28
|
-
"<div>hello",
|
|
29
|
-
"hello<div>",
|
|
30
|
-
"<br>",
|
|
31
|
-
"hello {steven}</div>",
|
|
32
|
-
"<div>hello <b>{steven}</div></b>",
|
|
33
|
-
"<div>hello <b>{steven}</b></b></div>"
|
|
34
|
-
]
|
|
35
|
-
|
|
36
|
-
invalids.forEach(string => {
|
|
37
|
-
test(`invalid syntax: ${string}`, () => {
|
|
38
|
-
expect(() => {
|
|
39
|
-
parser(string)
|
|
40
|
-
}).toThrow(
|
|
41
|
-
"Syntax error. Please check if each open tag is closed correctly"
|
|
42
|
-
)
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
})
|
package/babel.config.js
DELETED
|
Binary file
|
|
Binary file
|
package/rollup.config.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import babel from "rollup-plugin-babel"
|
|
2
|
-
import pkg from "./package.json"
|
|
3
|
-
|
|
4
|
-
export default {
|
|
5
|
-
input: "src/index.js",
|
|
6
|
-
output: [
|
|
7
|
-
{
|
|
8
|
-
file: pkg.main,
|
|
9
|
-
format: "cjs"
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
file: pkg.module,
|
|
13
|
-
format: "es"
|
|
14
|
-
}
|
|
15
|
-
],
|
|
16
|
-
plugins: [babel({ runtimeHelpers: true })]
|
|
17
|
-
}
|