Node-Red configuration
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

esnext.string.dedent.js 5.0KB

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