1 |
|
2 | const has = require('has')
|
3 | const xtend = require('xtend')
|
4 |
|
5 |
|
6 | module.exports = encode
|
7 |
|
8 | encode.escape = escape
|
9 |
|
10 |
|
11 | const defaultEscapes = {
|
12 | '#': '\\#',
|
13 | '$': '\\$',
|
14 | '%': '\\%',
|
15 | '&': '\\&',
|
16 | '\\': '\\textbackslash{}',
|
17 | '^': '\\textasciicircum{}',
|
18 | '_': '\\_',
|
19 | '{': '\\{',
|
20 | '}': '\\}',
|
21 | '~': '\\textasciitilde{}',
|
22 | }
|
23 |
|
24 |
|
25 | function encode (value, opts = {}) {
|
26 | const escapes = xtend(defaultEscapes, opts)
|
27 | const set = toExpression(Object.keys(escapes))
|
28 |
|
29 | value = value.replace(set, function (char, pos, val) {
|
30 | return one(char, val.charAt(pos + 1), escapes)
|
31 | })
|
32 |
|
33 | return value
|
34 | }
|
35 |
|
36 |
|
37 | function one (char, next, escapes) {
|
38 | if (has(escapes, char)) {
|
39 | return escapes[char]
|
40 | }
|
41 |
|
42 | return char
|
43 | }
|
44 |
|
45 |
|
46 | function toExpression (characters) {
|
47 | const pattern = characters.map(escapeRegExp).join('|')
|
48 |
|
49 | return new RegExp(`[${pattern}]`, 'g')
|
50 | }
|
51 |
|
52 | function escapeRegExp (str) {
|
53 | return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&')
|
54 | }
|