[79a0317] | 1 | 'use strict';
|
---|
| 2 | var FREEZING = require('../internals/freezing');
|
---|
| 3 | var $ = require('../internals/export');
|
---|
| 4 | var makeBuiltIn = require('../internals/make-built-in');
|
---|
| 5 | var uncurryThis = require('../internals/function-uncurry-this');
|
---|
| 6 | var apply = require('../internals/function-apply');
|
---|
| 7 | var anObject = require('../internals/an-object');
|
---|
| 8 | var toObject = require('../internals/to-object');
|
---|
| 9 | var isCallable = require('../internals/is-callable');
|
---|
| 10 | var lengthOfArrayLike = require('../internals/length-of-array-like');
|
---|
| 11 | var defineProperty = require('../internals/object-define-property').f;
|
---|
| 12 | var createArrayFromList = require('../internals/array-slice');
|
---|
| 13 | var WeakMapHelpers = require('../internals/weak-map-helpers');
|
---|
| 14 | var cooked = require('../internals/string-cooked');
|
---|
| 15 | var parse = require('../internals/string-parse');
|
---|
| 16 | var whitespaces = require('../internals/whitespaces');
|
---|
| 17 |
|
---|
| 18 | var DedentMap = new WeakMapHelpers.WeakMap();
|
---|
| 19 | var weakMapGet = WeakMapHelpers.get;
|
---|
| 20 | var weakMapHas = WeakMapHelpers.has;
|
---|
| 21 | var weakMapSet = WeakMapHelpers.set;
|
---|
| 22 |
|
---|
| 23 | var $Array = Array;
|
---|
| 24 | var $TypeError = TypeError;
|
---|
| 25 | // eslint-disable-next-line es/no-object-freeze -- safe
|
---|
| 26 | var freeze = Object.freeze || Object;
|
---|
| 27 | // eslint-disable-next-line es/no-object-isfrozen -- safe
|
---|
| 28 | var isFrozen = Object.isFrozen;
|
---|
| 29 | var min = Math.min;
|
---|
| 30 | var charAt = uncurryThis(''.charAt);
|
---|
| 31 | var stringSlice = uncurryThis(''.slice);
|
---|
| 32 | var split = uncurryThis(''.split);
|
---|
| 33 | var exec = uncurryThis(/./.exec);
|
---|
| 34 |
|
---|
| 35 | var NEW_LINE = /([\n\u2028\u2029]|\r\n?)/g;
|
---|
| 36 | var LEADING_WHITESPACE = RegExp('^[' + whitespaces + ']*');
|
---|
| 37 | var NON_WHITESPACE = RegExp('[^' + whitespaces + ']');
|
---|
| 38 | var INVALID_TAG = 'Invalid tag';
|
---|
| 39 | var INVALID_OPENING_LINE = 'Invalid opening line';
|
---|
| 40 | var INVALID_CLOSING_LINE = 'Invalid closing line';
|
---|
| 41 |
|
---|
| 42 | var dedentTemplateStringsArray = function (template) {
|
---|
| 43 | var rawInput = template.raw;
|
---|
| 44 | // https://github.com/tc39/proposal-string-dedent/issues/75
|
---|
| 45 | if (FREEZING && !isFrozen(rawInput)) throw new $TypeError('Raw template should be frozen');
|
---|
| 46 | if (weakMapHas(DedentMap, rawInput)) return weakMapGet(DedentMap, rawInput);
|
---|
| 47 | var raw = dedentStringsArray(rawInput);
|
---|
| 48 | var cookedArr = cookStrings(raw);
|
---|
| 49 | defineProperty(cookedArr, 'raw', {
|
---|
| 50 | value: freeze(raw)
|
---|
| 51 | });
|
---|
| 52 | freeze(cookedArr);
|
---|
| 53 | weakMapSet(DedentMap, rawInput, cookedArr);
|
---|
| 54 | return cookedArr;
|
---|
| 55 | };
|
---|
| 56 |
|
---|
| 57 | var dedentStringsArray = function (template) {
|
---|
| 58 | var t = toObject(template);
|
---|
| 59 | var length = lengthOfArrayLike(t);
|
---|
| 60 | var blocks = $Array(length);
|
---|
| 61 | var dedented = $Array(length);
|
---|
| 62 | var i = 0;
|
---|
| 63 | var lines, common, quasi, k;
|
---|
| 64 |
|
---|
| 65 | if (!length) throw new $TypeError(INVALID_TAG);
|
---|
| 66 |
|
---|
| 67 | for (; i < length; i++) {
|
---|
| 68 | var element = t[i];
|
---|
| 69 | if (typeof element == 'string') blocks[i] = split(element, NEW_LINE);
|
---|
| 70 | else throw new $TypeError(INVALID_TAG);
|
---|
| 71 | }
|
---|
| 72 |
|
---|
| 73 | for (i = 0; i < length; i++) {
|
---|
| 74 | var lastSplit = i + 1 === length;
|
---|
| 75 | lines = blocks[i];
|
---|
| 76 | if (i === 0) {
|
---|
| 77 | if (lines.length === 1 || lines[0].length > 0) {
|
---|
| 78 | throw new $TypeError(INVALID_OPENING_LINE);
|
---|
| 79 | }
|
---|
| 80 | lines[1] = '';
|
---|
| 81 | }
|
---|
| 82 | if (lastSplit) {
|
---|
| 83 | if (lines.length === 1 || exec(NON_WHITESPACE, lines[lines.length - 1])) {
|
---|
| 84 | throw new $TypeError(INVALID_CLOSING_LINE);
|
---|
| 85 | }
|
---|
| 86 | lines[lines.length - 2] = '';
|
---|
| 87 | lines[lines.length - 1] = '';
|
---|
| 88 | }
|
---|
| 89 | // eslint-disable-next-line sonarjs/no-redundant-assignments -- false positive, https://github.com/SonarSource/SonarJS/issues/4767
|
---|
| 90 | for (var j = 2; j < lines.length; j += 2) {
|
---|
| 91 | var text = lines[j];
|
---|
| 92 | var lineContainsTemplateExpression = j + 1 === lines.length && !lastSplit;
|
---|
| 93 | var leading = exec(LEADING_WHITESPACE, text)[0];
|
---|
| 94 | if (!lineContainsTemplateExpression && leading.length === text.length) {
|
---|
| 95 | lines[j] = '';
|
---|
| 96 | continue;
|
---|
| 97 | }
|
---|
| 98 | common = commonLeadingIndentation(leading, common);
|
---|
| 99 | }
|
---|
| 100 | }
|
---|
| 101 |
|
---|
| 102 | var count = common ? common.length : 0;
|
---|
| 103 |
|
---|
| 104 | for (i = 0; i < length; i++) {
|
---|
| 105 | lines = blocks[i];
|
---|
| 106 | quasi = lines[0];
|
---|
| 107 | k = 1;
|
---|
| 108 | for (; k < lines.length; k += 2) {
|
---|
| 109 | quasi += lines[k] + stringSlice(lines[k + 1], count);
|
---|
| 110 | }
|
---|
| 111 | dedented[i] = quasi;
|
---|
| 112 | }
|
---|
| 113 |
|
---|
| 114 | return dedented;
|
---|
| 115 | };
|
---|
| 116 |
|
---|
| 117 | var commonLeadingIndentation = function (a, b) {
|
---|
| 118 | if (b === undefined || a === b) return a;
|
---|
| 119 | var i = 0;
|
---|
| 120 | for (var len = min(a.length, b.length); i < len; i++) {
|
---|
| 121 | if (charAt(a, i) !== charAt(b, i)) break;
|
---|
| 122 | }
|
---|
| 123 | return stringSlice(a, 0, i);
|
---|
| 124 | };
|
---|
| 125 |
|
---|
| 126 | var cookStrings = function (raw) {
|
---|
| 127 | var i = 0;
|
---|
| 128 | var length = raw.length;
|
---|
| 129 | var result = $Array(length);
|
---|
| 130 | for (; i < length; i++) {
|
---|
| 131 | result[i] = parse(raw[i]);
|
---|
| 132 | } return result;
|
---|
| 133 | };
|
---|
| 134 |
|
---|
| 135 | var makeDedentTag = function (tag) {
|
---|
| 136 | return makeBuiltIn(function (template /* , ...substitutions */) {
|
---|
| 137 | var args = createArrayFromList(arguments);
|
---|
| 138 | args[0] = dedentTemplateStringsArray(anObject(template));
|
---|
| 139 | return apply(tag, this, args);
|
---|
| 140 | }, '');
|
---|
| 141 | };
|
---|
| 142 |
|
---|
| 143 | var cookedDedentTag = makeDedentTag(cooked);
|
---|
| 144 |
|
---|
| 145 | // `String.dedent` method
|
---|
| 146 | // https://github.com/tc39/proposal-string-dedent
|
---|
| 147 | $({ target: 'String', stat: true, forced: true }, {
|
---|
| 148 | dedent: function dedent(templateOrFn /* , ...substitutions */) {
|
---|
| 149 | anObject(templateOrFn);
|
---|
| 150 | if (isCallable(templateOrFn)) return makeDedentTag(templateOrFn);
|
---|
| 151 | return apply(cookedDedentTag, this, arguments);
|
---|
| 152 | }
|
---|
| 153 | });
|
---|