1 | 'use strict'
|
2 |
|
3 | const vm = require('vm')
|
4 |
|
5 | const htmlRegexp = /[&<>"']/g
|
6 | const htmlSymbols = {
|
7 | '&': '&',
|
8 | '<': '<',
|
9 | '>': '>',
|
10 | '"': '"',
|
11 | '\'': '''
|
12 | }
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | function escapeHTML (unescaped) {
|
24 | return unescaped.replace(htmlRegexp, (match) => htmlSymbols[match])
|
25 | }
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | function placeholders (input, ctx, settings) {
|
39 |
|
40 |
|
41 | for (let i = 0; i < settings.length; i++) {
|
42 | const matches = input.match(settings[i].regexp)
|
43 |
|
44 | if (!matches) continue
|
45 |
|
46 | const delimiters = settings[i].text
|
47 |
|
48 | for (let j = 0; j < matches.length; j++) {
|
49 | const match = matches[j]
|
50 |
|
51 | const expression = match.substring(delimiters[0].length, match.length - delimiters[1].length).trim()
|
52 |
|
53 |
|
54 | let value
|
55 |
|
56 | if (/\W+/.test(expression)) {
|
57 | value = vm.runInContext(expression, ctx)
|
58 | } else if (Object.prototype.hasOwnProperty.call(ctx, expression)) {
|
59 | value = ctx[expression]
|
60 | }
|
61 |
|
62 |
|
63 | if (settings[i].escape && typeof value === 'string') {
|
64 | value = escapeHTML(value)
|
65 | }
|
66 |
|
67 |
|
68 | if (typeof value === 'object') {
|
69 | value = JSON.stringify(value)
|
70 | }
|
71 |
|
72 |
|
73 | input = input.replace(match, value)
|
74 | }
|
75 | }
|
76 |
|
77 | return input
|
78 | }
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 | module.exports = placeholders
|