123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- 'use strict';
- var FREEZING = require('../internals/freezing');
- var $ = require('../internals/export');
- var makeBuiltIn = require('../internals/make-built-in');
- var uncurryThis = require('../internals/function-uncurry-this');
- var apply = require('../internals/function-apply');
- var anObject = require('../internals/an-object');
- var toObject = require('../internals/to-object');
- var isCallable = require('../internals/is-callable');
- var lengthOfArrayLike = require('../internals/length-of-array-like');
- var defineProperty = require('../internals/object-define-property').f;
- var createArrayFromList = require('../internals/array-slice');
- var WeakMapHelpers = require('../internals/weak-map-helpers');
- var cooked = require('../internals/string-cooked');
- var parse = require('../internals/string-parse');
- var whitespaces = require('../internals/whitespaces');
-
- var DedentMap = new WeakMapHelpers.WeakMap();
- var weakMapGet = WeakMapHelpers.get;
- var weakMapHas = WeakMapHelpers.has;
- var weakMapSet = WeakMapHelpers.set;
-
- var $Array = Array;
- var $TypeError = TypeError;
- // eslint-disable-next-line es/no-object-freeze -- safe
- var freeze = Object.freeze || Object;
- // eslint-disable-next-line es/no-object-isfrozen -- safe
- var isFrozen = Object.isFrozen;
- var min = Math.min;
- var charAt = uncurryThis(''.charAt);
- var stringSlice = uncurryThis(''.slice);
- var split = uncurryThis(''.split);
- var exec = uncurryThis(/./.exec);
-
- var NEW_LINE = /([\n\u2028\u2029]|\r\n?)/g;
- var LEADING_WHITESPACE = RegExp('^[' + whitespaces + ']*');
- var NON_WHITESPACE = RegExp('[^' + whitespaces + ']');
- var INVALID_TAG = 'Invalid tag';
- var INVALID_OPENING_LINE = 'Invalid opening line';
- var INVALID_CLOSING_LINE = 'Invalid closing line';
-
- var dedentTemplateStringsArray = function (template) {
- var rawInput = template.raw;
- // https://github.com/tc39/proposal-string-dedent/issues/75
- if (FREEZING && !isFrozen(rawInput)) throw new $TypeError('Raw template should be frozen');
- if (weakMapHas(DedentMap, rawInput)) return weakMapGet(DedentMap, rawInput);
- var raw = dedentStringsArray(rawInput);
- var cookedArr = cookStrings(raw);
- defineProperty(cookedArr, 'raw', {
- value: freeze(raw)
- });
- freeze(cookedArr);
- weakMapSet(DedentMap, rawInput, cookedArr);
- return cookedArr;
- };
-
- var dedentStringsArray = function (template) {
- var t = toObject(template);
- var length = lengthOfArrayLike(t);
- var blocks = $Array(length);
- var dedented = $Array(length);
- var i = 0;
- var lines, common, quasi, k;
-
- if (!length) throw new $TypeError(INVALID_TAG);
-
- for (; i < length; i++) {
- var element = t[i];
- if (typeof element == 'string') blocks[i] = split(element, NEW_LINE);
- else throw new $TypeError(INVALID_TAG);
- }
-
- for (i = 0; i < length; i++) {
- var lastSplit = i + 1 === length;
- lines = blocks[i];
- if (i === 0) {
- if (lines.length === 1 || lines[0].length > 0) {
- throw new $TypeError(INVALID_OPENING_LINE);
- }
- lines[1] = '';
- }
- if (lastSplit) {
- if (lines.length === 1 || exec(NON_WHITESPACE, lines[lines.length - 1])) {
- throw new $TypeError(INVALID_CLOSING_LINE);
- }
- lines[lines.length - 2] = '';
- lines[lines.length - 1] = '';
- }
- // eslint-disable-next-line sonar/no-redundant-assignments -- false positive, https://github.com/SonarSource/SonarJS/issues/4767
- for (var j = 2; j < lines.length; j += 2) {
- var text = lines[j];
- var lineContainsTemplateExpression = j + 1 === lines.length && !lastSplit;
- var leading = exec(LEADING_WHITESPACE, text)[0];
- if (!lineContainsTemplateExpression && leading.length === text.length) {
- lines[j] = '';
- continue;
- }
- common = commonLeadingIndentation(leading, common);
- }
- }
-
- var count = common ? common.length : 0;
-
- for (i = 0; i < length; i++) {
- lines = blocks[i];
- quasi = lines[0];
- k = 1;
- for (; k < lines.length; k += 2) {
- quasi += lines[k] + stringSlice(lines[k + 1], count);
- }
- dedented[i] = quasi;
- }
-
- return dedented;
- };
-
- var commonLeadingIndentation = function (a, b) {
- if (b === undefined || a === b) return a;
- var i = 0;
- for (var len = min(a.length, b.length); i < len; i++) {
- if (charAt(a, i) !== charAt(b, i)) break;
- }
- return stringSlice(a, 0, i);
- };
-
- var cookStrings = function (raw) {
- var i = 0;
- var length = raw.length;
- var result = $Array(length);
- for (; i < length; i++) {
- result[i] = parse(raw[i]);
- } return result;
- };
-
- var makeDedentTag = function (tag) {
- return makeBuiltIn(function (template /* , ...substitutions */) {
- var args = createArrayFromList(arguments);
- args[0] = dedentTemplateStringsArray(anObject(template));
- return apply(tag, this, args);
- }, '');
- };
-
- var cookedDedentTag = makeDedentTag(cooked);
-
- // `String.dedent` method
- // https://github.com/tc39/proposal-string-dedent
- $({ target: 'String', stat: true, forced: true }, {
- dedent: function dedent(templateOrFn /* , ...substitutions */) {
- anObject(templateOrFn);
- if (isCallable(templateOrFn)) return makeDedentTag(templateOrFn);
- return apply(cookedDedentTag, this, arguments);
- }
- });
|