'use strict'; var FREEZING = require('../internals/freezing'); var $ = require('../internals/export'); var shared = require('../internals/shared'); var getBuiltIn = require('../internals/get-built-in'); 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-simple'); var cooked = require('../internals/string-cooked'); var parse = require('../internals/string-parse'); var whitespaces = require('../internals/whitespaces'); var WeakMap = getBuiltIn('WeakMap'); var globalDedentRegistry = shared('GlobalDedentRegistry', new WeakMap()); /* eslint-disable no-self-assign -- prototype methods protection */ globalDedentRegistry.has = globalDedentRegistry.has; globalDedentRegistry.get = globalDedentRegistry.get; globalDedentRegistry.set = globalDedentRegistry.set; /* eslint-enable no-self-assign -- prototype methods protection */ 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 $TypeError('Raw template should be frozen'); if (globalDedentRegistry.has(rawInput)) return globalDedentRegistry.get(rawInput); var raw = dedentStringsArray(rawInput); var cookedArr = cookStrings(raw); defineProperty(cookedArr, 'raw', { value: freeze(raw) }); freeze(cookedArr); globalDedentRegistry.set(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 $TypeError(INVALID_TAG); for (; i < length; i++) { var element = t[i]; if (typeof element == 'string') blocks[i] = split(element, NEW_LINE); else throw $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 $TypeError(INVALID_OPENING_LINE); } lines[1] = ''; } if (lastSplit) { if (lines.length === 1 || exec(NON_WHITESPACE, lines[lines.length - 1])) { throw $TypeError(INVALID_CLOSING_LINE); } lines[lines.length - 2] = ''; lines[lines.length - 1] = ''; } 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); } });