[79a0317] | 1 | 'use strict';
|
---|
| 2 | // adapted from https://github.com/jridgewell/string-dedent
|
---|
| 3 | var getBuiltIn = require('../internals/get-built-in');
|
---|
| 4 | var uncurryThis = require('../internals/function-uncurry-this');
|
---|
| 5 |
|
---|
| 6 | var fromCharCode = String.fromCharCode;
|
---|
| 7 | var fromCodePoint = getBuiltIn('String', 'fromCodePoint');
|
---|
| 8 | var charAt = uncurryThis(''.charAt);
|
---|
| 9 | var charCodeAt = uncurryThis(''.charCodeAt);
|
---|
| 10 | var stringIndexOf = uncurryThis(''.indexOf);
|
---|
| 11 | var stringSlice = uncurryThis(''.slice);
|
---|
| 12 |
|
---|
| 13 | var ZERO_CODE = 48;
|
---|
| 14 | var NINE_CODE = 57;
|
---|
| 15 | var LOWER_A_CODE = 97;
|
---|
| 16 | var LOWER_F_CODE = 102;
|
---|
| 17 | var UPPER_A_CODE = 65;
|
---|
| 18 | var UPPER_F_CODE = 70;
|
---|
| 19 |
|
---|
| 20 | var isDigit = function (str, index) {
|
---|
| 21 | var c = charCodeAt(str, index);
|
---|
| 22 | return c >= ZERO_CODE && c <= NINE_CODE;
|
---|
| 23 | };
|
---|
| 24 |
|
---|
| 25 | var parseHex = function (str, index, end) {
|
---|
| 26 | if (end >= str.length) return -1;
|
---|
| 27 | var n = 0;
|
---|
| 28 | for (; index < end; index++) {
|
---|
| 29 | var c = hexToInt(charCodeAt(str, index));
|
---|
| 30 | if (c === -1) return -1;
|
---|
| 31 | n = n * 16 + c;
|
---|
| 32 | }
|
---|
| 33 | return n;
|
---|
| 34 | };
|
---|
| 35 |
|
---|
| 36 | var hexToInt = function (c) {
|
---|
| 37 | if (c >= ZERO_CODE && c <= NINE_CODE) return c - ZERO_CODE;
|
---|
| 38 | if (c >= LOWER_A_CODE && c <= LOWER_F_CODE) return c - LOWER_A_CODE + 10;
|
---|
| 39 | if (c >= UPPER_A_CODE && c <= UPPER_F_CODE) return c - UPPER_A_CODE + 10;
|
---|
| 40 | return -1;
|
---|
| 41 | };
|
---|
| 42 |
|
---|
| 43 | module.exports = function (raw) {
|
---|
| 44 | var out = '';
|
---|
| 45 | var start = 0;
|
---|
| 46 | // We need to find every backslash escape sequence, and cook the escape into a real char.
|
---|
| 47 | var i = 0;
|
---|
| 48 | var n;
|
---|
| 49 | while ((i = stringIndexOf(raw, '\\', i)) > -1) {
|
---|
| 50 | out += stringSlice(raw, start, i);
|
---|
| 51 | // If the backslash is the last char of the string, then it was an invalid sequence.
|
---|
| 52 | // This can't actually happen in a tagged template literal, but could happen if you manually
|
---|
| 53 | // invoked the tag with an array.
|
---|
| 54 | if (++i === raw.length) return;
|
---|
| 55 | var next = charAt(raw, i++);
|
---|
| 56 | switch (next) {
|
---|
| 57 | // Escaped control codes need to be individually processed.
|
---|
| 58 | case 'b':
|
---|
| 59 | out += '\b';
|
---|
| 60 | break;
|
---|
| 61 | case 't':
|
---|
| 62 | out += '\t';
|
---|
| 63 | break;
|
---|
| 64 | case 'n':
|
---|
| 65 | out += '\n';
|
---|
| 66 | break;
|
---|
| 67 | case 'v':
|
---|
| 68 | out += '\v';
|
---|
| 69 | break;
|
---|
| 70 | case 'f':
|
---|
| 71 | out += '\f';
|
---|
| 72 | break;
|
---|
| 73 | case 'r':
|
---|
| 74 | out += '\r';
|
---|
| 75 | break;
|
---|
| 76 | // Escaped line terminators just skip the char.
|
---|
| 77 | case '\r':
|
---|
| 78 | // Treat `\r\n` as a single terminator.
|
---|
| 79 | if (i < raw.length && charAt(raw, i) === '\n') ++i;
|
---|
| 80 | // break omitted
|
---|
| 81 | case '\n':
|
---|
| 82 | case '\u2028':
|
---|
| 83 | case '\u2029':
|
---|
| 84 | break;
|
---|
| 85 | // `\0` is a null control char, but `\0` followed by another digit is an illegal octal escape.
|
---|
| 86 | case '0':
|
---|
| 87 | if (isDigit(raw, i)) return;
|
---|
| 88 | out += '\0';
|
---|
| 89 | break;
|
---|
| 90 | // Hex escapes must contain 2 hex chars.
|
---|
| 91 | case 'x':
|
---|
| 92 | n = parseHex(raw, i, i + 2);
|
---|
| 93 | if (n === -1) return;
|
---|
| 94 | i += 2;
|
---|
| 95 | out += fromCharCode(n);
|
---|
| 96 | break;
|
---|
| 97 | // Unicode escapes contain either 4 chars, or an unlimited number between `{` and `}`.
|
---|
| 98 | // The hex value must not overflow 0x10FFFF.
|
---|
| 99 | case 'u':
|
---|
| 100 | if (i < raw.length && charAt(raw, i) === '{') {
|
---|
| 101 | var end = stringIndexOf(raw, '}', ++i);
|
---|
| 102 | if (end === -1) return;
|
---|
| 103 | n = parseHex(raw, i, end);
|
---|
| 104 | i = end + 1;
|
---|
| 105 | } else {
|
---|
| 106 | n = parseHex(raw, i, i + 4);
|
---|
| 107 | i += 4;
|
---|
| 108 | }
|
---|
| 109 | if (n === -1 || n > 0x10FFFF) return;
|
---|
| 110 | out += fromCodePoint(n);
|
---|
| 111 | break;
|
---|
| 112 | default:
|
---|
| 113 | if (isDigit(next, 0)) return;
|
---|
| 114 | out += next;
|
---|
| 115 | }
|
---|
| 116 | start = i;
|
---|
| 117 | }
|
---|
| 118 | return out + stringSlice(raw, start);
|
---|
| 119 | };
|
---|