UNPKG

2.14 kBJavaScriptView Raw
1'use strict'
2
3const vm = require('vm')
4
5const htmlRegexp = /[&<>"']/g
6const htmlSymbols = {
7 '&': '&amp;',
8 '<': '&lt;',
9 '>': '&gt;',
10 '"': '&quot;',
11 '\'': '&#039;'
12}
13
14/**
15 * @description Escape HTML characters with their respective entities
16 *
17 * @method escapeHTML
18 *
19 * @param {String} unescaped Unsafe HTML
20 *
21 * @return {String} escaped Save HTML
22 */
23function escapeHTML (unescaped) {
24 return unescaped.replace(htmlRegexp, (match) => htmlSymbols[match])
25}
26
27/**
28 * @description Replace Expressions
29 *
30 * @method placeholders
31 *
32 * @param {String} input Input
33 * @param {Object} ctx Context
34 * @param {Array} settings Settings
35 * @param {Array} opts Options
36 *
37 * @return {String} input Replaced Input
38 */
39function placeholders (input, ctx, settings, opts) {
40 // Since we are matching multiple sets of delimiters, we need to run a loop
41 // here to match each one.
42 for (let i = 0; i < settings.length; i++) {
43 const matches = input.match(settings[i].regexp)
44
45 if (!matches) continue
46
47 const delimiters = settings[i].text
48
49 for (let j = 0; j < matches.length; j++) {
50 const match = matches[j]
51
52 const expression = match.substring(delimiters[0].length, match.length - delimiters[1].length).trim()
53
54 // If expression has non-word characters then use VM
55 let value
56
57 if (/\W+/.test(expression)) {
58 try {
59 value = vm.runInContext(expression, ctx)
60 } catch (error) {
61 if (opts.strictMode) {
62 throw new SyntaxError(error)
63 }
64 }
65 } else if (Object.prototype.hasOwnProperty.call(ctx, expression)) {
66 value = ctx[expression]
67 }
68
69 // Escape html if necessary
70 if (settings[i].escape && typeof value === 'string') {
71 value = escapeHTML(value)
72 }
73
74 // Stringify if value object
75 if (typeof value === 'object') {
76 value = JSON.stringify(value)
77 }
78
79 // Replace placeholder on evaluated value
80 input = input.replace(match, value)
81 }
82 }
83
84 return input
85}
86
87/**
88 * @module placeholders
89 *
90 * @requires vm
91 *
92 * @type {Function}
93 */
94module.exports = placeholders