@m2c2kit/build-helpers 0.3.27 → 0.3.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +2112 -534
  2. package/package.json +11 -11
package/dist/index.js CHANGED
@@ -3103,7 +3103,7 @@ function findOneChild(test, nodes) {
3103
3103
  * @param recurse Also consider child nodes.
3104
3104
  * @returns The first node that passes `test`.
3105
3105
  */
3106
- function findOne(test, nodes, recurse = true) {
3106
+ function findOne$1(test, nodes, recurse = true) {
3107
3107
  const searchedNodes = Array.isArray(nodes) ? nodes : [nodes];
3108
3108
  for (let i = 0; i < searchedNodes.length; i++) {
3109
3109
  const node = searchedNodes[i];
@@ -3111,7 +3111,9 @@ function findOne(test, nodes, recurse = true) {
3111
3111
  return node;
3112
3112
  }
3113
3113
  if (recurse && hasChildren(node) && node.children.length > 0) {
3114
- return findOne(test, node.children, true);
3114
+ const found = findOne$1(test, node.children, true);
3115
+ if (found)
3116
+ return found;
3115
3117
  }
3116
3118
  }
3117
3119
  return null;
@@ -3138,7 +3140,7 @@ function existsOne(test, nodes) {
3138
3140
  * @param nodes Array of nodes to search.
3139
3141
  * @returns All nodes passing `test`.
3140
3142
  */
3141
- function findAll(test, nodes) {
3143
+ function findAll$1(test, nodes) {
3142
3144
  const result = [];
3143
3145
  const nodeStack = [Array.isArray(nodes) ? nodes : [nodes]];
3144
3146
  const indexStack = [0];
@@ -3271,7 +3273,7 @@ function getElements(options, nodes, recurse, limit = Infinity) {
3271
3273
  function getElementById(id, nodes, recurse = true) {
3272
3274
  if (!Array.isArray(nodes))
3273
3275
  nodes = [nodes];
3274
- return findOne(getAttribCheck("id", id), nodes, recurse);
3276
+ return findOne$1(getAttribCheck("id", id), nodes, recurse);
3275
3277
  }
3276
3278
  /**
3277
3279
  * Returns all nodes with the supplied `tagName`.
@@ -3638,8 +3640,8 @@ var DomUtils = /*#__PURE__*/Object.freeze({
3638
3640
  existsOne: existsOne,
3639
3641
  filter: filter,
3640
3642
  find: find,
3641
- findAll: findAll,
3642
- findOne: findOne,
3643
+ findAll: findAll$1,
3644
+ findOne: findOne$1,
3643
3645
  findOneChild: findOneChild,
3644
3646
  getAttributeValue: getAttributeValue,
3645
3647
  getChildren: getChildren,
@@ -3741,15 +3743,49 @@ var AttributeAction;
3741
3743
  AttributeAction["Start"] = "start";
3742
3744
  })(AttributeAction || (AttributeAction = {}));
3743
3745
 
3744
- const reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/;
3746
+ const reName = /^[^#\\]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\u00B0-\uFFFF-])+/;
3745
3747
  const reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi;
3748
+ var CharCode;
3749
+ (function (CharCode) {
3750
+ CharCode[CharCode["LeftParenthesis"] = 40] = "LeftParenthesis";
3751
+ CharCode[CharCode["RightParenthesis"] = 41] = "RightParenthesis";
3752
+ CharCode[CharCode["LeftSquareBracket"] = 91] = "LeftSquareBracket";
3753
+ CharCode[CharCode["RightSquareBracket"] = 93] = "RightSquareBracket";
3754
+ CharCode[CharCode["Comma"] = 44] = "Comma";
3755
+ CharCode[CharCode["Period"] = 46] = "Period";
3756
+ CharCode[CharCode["Colon"] = 58] = "Colon";
3757
+ CharCode[CharCode["SingleQuote"] = 39] = "SingleQuote";
3758
+ CharCode[CharCode["DoubleQuote"] = 34] = "DoubleQuote";
3759
+ CharCode[CharCode["Plus"] = 43] = "Plus";
3760
+ CharCode[CharCode["Tilde"] = 126] = "Tilde";
3761
+ CharCode[CharCode["QuestionMark"] = 63] = "QuestionMark";
3762
+ CharCode[CharCode["ExclamationMark"] = 33] = "ExclamationMark";
3763
+ CharCode[CharCode["Slash"] = 47] = "Slash";
3764
+ CharCode[CharCode["Equal"] = 61] = "Equal";
3765
+ CharCode[CharCode["Dollar"] = 36] = "Dollar";
3766
+ CharCode[CharCode["Pipe"] = 124] = "Pipe";
3767
+ CharCode[CharCode["Circumflex"] = 94] = "Circumflex";
3768
+ CharCode[CharCode["Asterisk"] = 42] = "Asterisk";
3769
+ CharCode[CharCode["GreaterThan"] = 62] = "GreaterThan";
3770
+ CharCode[CharCode["LessThan"] = 60] = "LessThan";
3771
+ CharCode[CharCode["Hash"] = 35] = "Hash";
3772
+ CharCode[CharCode["LowerI"] = 105] = "LowerI";
3773
+ CharCode[CharCode["LowerS"] = 115] = "LowerS";
3774
+ CharCode[CharCode["BackSlash"] = 92] = "BackSlash";
3775
+ // Whitespace
3776
+ CharCode[CharCode["Space"] = 32] = "Space";
3777
+ CharCode[CharCode["Tab"] = 9] = "Tab";
3778
+ CharCode[CharCode["NewLine"] = 10] = "NewLine";
3779
+ CharCode[CharCode["FormFeed"] = 12] = "FormFeed";
3780
+ CharCode[CharCode["CarriageReturn"] = 13] = "CarriageReturn";
3781
+ })(CharCode || (CharCode = {}));
3746
3782
  const actionTypes = new Map([
3747
- [126 /* Tilde */, AttributeAction.Element],
3748
- [94 /* Circumflex */, AttributeAction.Start],
3749
- [36 /* Dollar */, AttributeAction.End],
3750
- [42 /* Asterisk */, AttributeAction.Any],
3751
- [33 /* ExclamationMark */, AttributeAction.Not],
3752
- [124 /* Pipe */, AttributeAction.Hyphen],
3783
+ [CharCode.Tilde, AttributeAction.Element],
3784
+ [CharCode.Circumflex, AttributeAction.Start],
3785
+ [CharCode.Dollar, AttributeAction.End],
3786
+ [CharCode.Asterisk, AttributeAction.Any],
3787
+ [CharCode.ExclamationMark, AttributeAction.Not],
3788
+ [CharCode.Pipe, AttributeAction.Hyphen],
3753
3789
  ]);
3754
3790
  // Pseudos, whose data property is parsed as well.
3755
3791
  const unpackPseudos = new Set([
@@ -3761,6 +3797,18 @@ const unpackPseudos = new Set([
3761
3797
  "host",
3762
3798
  "host-context",
3763
3799
  ]);
3800
+ /**
3801
+ * Pseudo elements defined in CSS Level 1 and CSS Level 2 can be written with
3802
+ * a single colon; eg. :before will turn into ::before.
3803
+ *
3804
+ * @see {@link https://www.w3.org/TR/2018/WD-selectors-4-20181121/#pseudo-element-syntax}
3805
+ */
3806
+ const pseudosToPseudoElements = new Set([
3807
+ "before",
3808
+ "after",
3809
+ "first-line",
3810
+ "first-letter",
3811
+ ]);
3764
3812
  /**
3765
3813
  * Checks whether a specific selector is a traversal.
3766
3814
  * This is useful eg. in swapping the order of elements that
@@ -3775,43 +3823,44 @@ function isTraversal$1(selector) {
3775
3823
  case SelectorType.Descendant:
3776
3824
  case SelectorType.Parent:
3777
3825
  case SelectorType.Sibling:
3778
- case SelectorType.ColumnCombinator:
3826
+ case SelectorType.ColumnCombinator: {
3779
3827
  return true;
3780
- default:
3828
+ }
3829
+ default: {
3781
3830
  return false;
3831
+ }
3782
3832
  }
3783
3833
  }
3784
3834
  const stripQuotesFromPseudos = new Set(["contains", "icontains"]);
3785
3835
  // Unescape function taken from https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L152
3786
3836
  function funescape(_, escaped, escapedWhitespace) {
3787
- const high = parseInt(escaped, 16) - 0x10000;
3837
+ const high = Number.parseInt(escaped, 16) - 65536;
3788
3838
  // NaN means non-codepoint
3789
3839
  return high !== high || escapedWhitespace
3790
3840
  ? escaped
3791
3841
  : high < 0
3792
3842
  ? // BMP codepoint
3793
- String.fromCharCode(high + 0x10000)
3843
+ String.fromCharCode(high + 65536)
3794
3844
  : // Supplemental Plane codepoint (surrogate pair)
3795
- String.fromCharCode((high >> 10) | 0xd800, (high & 0x3ff) | 0xdc00);
3845
+ String.fromCharCode((high >> 10) | 55296, (high & 1023) | 56320);
3796
3846
  }
3797
- function unescapeCSS(str) {
3798
- return str.replace(reEscape, funescape);
3847
+ function unescapeCSS(cssString) {
3848
+ return cssString.replace(reEscape, funescape);
3799
3849
  }
3800
3850
  function isQuote(c) {
3801
- return c === 39 /* SingleQuote */ || c === 34 /* DoubleQuote */;
3851
+ return c === CharCode.SingleQuote || c === CharCode.DoubleQuote;
3802
3852
  }
3803
3853
  function isWhitespace(c) {
3804
- return (c === 32 /* Space */ ||
3805
- c === 9 /* Tab */ ||
3806
- c === 10 /* NewLine */ ||
3807
- c === 12 /* FormFeed */ ||
3808
- c === 13 /* CarriageReturn */);
3854
+ return (c === CharCode.Space ||
3855
+ c === CharCode.Tab ||
3856
+ c === CharCode.NewLine ||
3857
+ c === CharCode.FormFeed ||
3858
+ c === CharCode.CarriageReturn);
3809
3859
  }
3810
3860
  /**
3811
- * Parses `selector`, optionally with the passed `options`.
3861
+ * Parses `selector`.
3812
3862
  *
3813
3863
  * @param selector Selector to parse.
3814
- * @param options Options for parsing.
3815
3864
  * @returns Returns a two-dimensional array.
3816
3865
  * The first dimension represents selectors separated by commas (eg. `sub1, sub2`),
3817
3866
  * the second contains the relevant tokens for that selector.
@@ -3845,29 +3894,27 @@ function parseSelector(subselects, selector, selectorIndex) {
3845
3894
  function readValueWithParenthesis() {
3846
3895
  selectorIndex += 1;
3847
3896
  const start = selectorIndex;
3848
- let counter = 1;
3849
- for (; counter > 0 && selectorIndex < selector.length; selectorIndex++) {
3850
- if (selector.charCodeAt(selectorIndex) ===
3851
- 40 /* LeftParenthesis */ &&
3852
- !isEscaped(selectorIndex)) {
3853
- counter++;
3854
- }
3855
- else if (selector.charCodeAt(selectorIndex) ===
3856
- 41 /* RightParenthesis */ &&
3857
- !isEscaped(selectorIndex)) {
3858
- counter--;
3897
+ for (let counter = 1; selectorIndex < selector.length; selectorIndex++) {
3898
+ switch (selector.charCodeAt(selectorIndex)) {
3899
+ case CharCode.BackSlash: {
3900
+ // Skip next character
3901
+ selectorIndex += 1;
3902
+ break;
3903
+ }
3904
+ case CharCode.LeftParenthesis: {
3905
+ counter += 1;
3906
+ break;
3907
+ }
3908
+ case CharCode.RightParenthesis: {
3909
+ counter -= 1;
3910
+ if (counter === 0) {
3911
+ return unescapeCSS(selector.slice(start, selectorIndex++));
3912
+ }
3913
+ break;
3914
+ }
3859
3915
  }
3860
3916
  }
3861
- if (counter) {
3862
- throw new Error("Parenthesis not matched");
3863
- }
3864
- return unescapeCSS(selector.slice(start, selectorIndex - 1));
3865
- }
3866
- function isEscaped(pos) {
3867
- let slashCount = 0;
3868
- while (selector.charCodeAt(--pos) === 92 /* BackSlash */)
3869
- slashCount++;
3870
- return (slashCount & 1) === 1;
3917
+ throw new Error("Parenthesis not matched");
3871
3918
  }
3872
3919
  function ensureNotTraversal() {
3873
3920
  if (tokens.length > 0 && isTraversal$1(tokens[tokens.length - 1])) {
@@ -3901,7 +3948,7 @@ function parseSelector(subselects, selector, selectorIndex) {
3901
3948
  * picked up from here.
3902
3949
  */
3903
3950
  function finalizeSubselector() {
3904
- if (tokens.length &&
3951
+ if (tokens.length > 0 &&
3905
3952
  tokens[tokens.length - 1].type === SelectorType.Descendant) {
3906
3953
  tokens.pop();
3907
3954
  }
@@ -3918,11 +3965,11 @@ function parseSelector(subselects, selector, selectorIndex) {
3918
3965
  const firstChar = selector.charCodeAt(selectorIndex);
3919
3966
  switch (firstChar) {
3920
3967
  // Whitespace
3921
- case 32 /* Space */:
3922
- case 9 /* Tab */:
3923
- case 10 /* NewLine */:
3924
- case 12 /* FormFeed */:
3925
- case 13 /* CarriageReturn */: {
3968
+ case CharCode.Space:
3969
+ case CharCode.Tab:
3970
+ case CharCode.NewLine:
3971
+ case CharCode.FormFeed:
3972
+ case CharCode.CarriageReturn: {
3926
3973
  if (tokens.length === 0 ||
3927
3974
  tokens[0].type !== SelectorType.Descendant) {
3928
3975
  ensureNotTraversal();
@@ -3932,41 +3979,41 @@ function parseSelector(subselects, selector, selectorIndex) {
3932
3979
  break;
3933
3980
  }
3934
3981
  // Traversals
3935
- case 62 /* GreaterThan */: {
3982
+ case CharCode.GreaterThan: {
3936
3983
  addTraversal(SelectorType.Child);
3937
3984
  stripWhitespace(1);
3938
3985
  break;
3939
3986
  }
3940
- case 60 /* LessThan */: {
3987
+ case CharCode.LessThan: {
3941
3988
  addTraversal(SelectorType.Parent);
3942
3989
  stripWhitespace(1);
3943
3990
  break;
3944
3991
  }
3945
- case 126 /* Tilde */: {
3992
+ case CharCode.Tilde: {
3946
3993
  addTraversal(SelectorType.Sibling);
3947
3994
  stripWhitespace(1);
3948
3995
  break;
3949
3996
  }
3950
- case 43 /* Plus */: {
3997
+ case CharCode.Plus: {
3951
3998
  addTraversal(SelectorType.Adjacent);
3952
3999
  stripWhitespace(1);
3953
4000
  break;
3954
4001
  }
3955
4002
  // Special attribute selectors: .class, #id
3956
- case 46 /* Period */: {
4003
+ case CharCode.Period: {
3957
4004
  addSpecialAttribute("class", AttributeAction.Element);
3958
4005
  break;
3959
4006
  }
3960
- case 35 /* Hash */: {
4007
+ case CharCode.Hash: {
3961
4008
  addSpecialAttribute("id", AttributeAction.Equals);
3962
4009
  break;
3963
4010
  }
3964
- case 91 /* LeftSquareBracket */: {
4011
+ case CharCode.LeftSquareBracket: {
3965
4012
  stripWhitespace(1);
3966
4013
  // Determine attribute name and namespace
3967
4014
  let name;
3968
4015
  let namespace = null;
3969
- if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */) {
4016
+ if (selector.charCodeAt(selectorIndex) === CharCode.Pipe) {
3970
4017
  // Equivalent to no namespace
3971
4018
  name = getName(1);
3972
4019
  }
@@ -3976,9 +4023,9 @@ function parseSelector(subselects, selector, selectorIndex) {
3976
4023
  }
3977
4024
  else {
3978
4025
  name = getName(0);
3979
- if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */ &&
4026
+ if (selector.charCodeAt(selectorIndex) === CharCode.Pipe &&
3980
4027
  selector.charCodeAt(selectorIndex + 1) !==
3981
- 61 /* Equal */) {
4028
+ CharCode.Equal) {
3982
4029
  namespace = name;
3983
4030
  name = getName(1);
3984
4031
  }
@@ -3990,12 +4037,12 @@ function parseSelector(subselects, selector, selectorIndex) {
3990
4037
  if (possibleAction) {
3991
4038
  action = possibleAction;
3992
4039
  if (selector.charCodeAt(selectorIndex + 1) !==
3993
- 61 /* Equal */) {
4040
+ CharCode.Equal) {
3994
4041
  throw new Error("Expected `=`");
3995
4042
  }
3996
4043
  stripWhitespace(2);
3997
4044
  }
3998
- else if (selector.charCodeAt(selectorIndex) === 61 /* Equal */) {
4045
+ else if (selector.charCodeAt(selectorIndex) === CharCode.Equal) {
3999
4046
  action = AttributeAction.Equals;
4000
4047
  stripWhitespace(1);
4001
4048
  }
@@ -4005,44 +4052,56 @@ function parseSelector(subselects, selector, selectorIndex) {
4005
4052
  if (action !== "exists") {
4006
4053
  if (isQuote(selector.charCodeAt(selectorIndex))) {
4007
4054
  const quote = selector.charCodeAt(selectorIndex);
4008
- let sectionEnd = selectorIndex + 1;
4009
- while (sectionEnd < selector.length &&
4010
- (selector.charCodeAt(sectionEnd) !== quote ||
4011
- isEscaped(sectionEnd))) {
4012
- sectionEnd += 1;
4055
+ selectorIndex += 1;
4056
+ const sectionStart = selectorIndex;
4057
+ while (selectorIndex < selector.length &&
4058
+ selector.charCodeAt(selectorIndex) !== quote) {
4059
+ selectorIndex +=
4060
+ // Skip next character if it is escaped
4061
+ selector.charCodeAt(selectorIndex) ===
4062
+ CharCode.BackSlash
4063
+ ? 2
4064
+ : 1;
4013
4065
  }
4014
- if (selector.charCodeAt(sectionEnd) !== quote) {
4066
+ if (selector.charCodeAt(selectorIndex) !== quote) {
4015
4067
  throw new Error("Attribute value didn't end");
4016
4068
  }
4017
- value = unescapeCSS(selector.slice(selectorIndex + 1, sectionEnd));
4018
- selectorIndex = sectionEnd + 1;
4069
+ value = unescapeCSS(selector.slice(sectionStart, selectorIndex));
4070
+ selectorIndex += 1;
4019
4071
  }
4020
4072
  else {
4021
4073
  const valueStart = selectorIndex;
4022
4074
  while (selectorIndex < selector.length &&
4023
- ((!isWhitespace(selector.charCodeAt(selectorIndex)) &&
4024
- selector.charCodeAt(selectorIndex) !==
4025
- 93 /* RightSquareBracket */) ||
4026
- isEscaped(selectorIndex))) {
4027
- selectorIndex += 1;
4075
+ !isWhitespace(selector.charCodeAt(selectorIndex)) &&
4076
+ selector.charCodeAt(selectorIndex) !==
4077
+ CharCode.RightSquareBracket) {
4078
+ selectorIndex +=
4079
+ // Skip next character if it is escaped
4080
+ selector.charCodeAt(selectorIndex) ===
4081
+ CharCode.BackSlash
4082
+ ? 2
4083
+ : 1;
4028
4084
  }
4029
4085
  value = unescapeCSS(selector.slice(valueStart, selectorIndex));
4030
4086
  }
4031
4087
  stripWhitespace(0);
4032
4088
  // See if we have a force ignore flag
4033
- const forceIgnore = selector.charCodeAt(selectorIndex) | 0x20;
4034
- // If the forceIgnore flag is set (either `i` or `s`), use that value
4035
- if (forceIgnore === 115 /* LowerS */) {
4036
- ignoreCase = false;
4037
- stripWhitespace(1);
4038
- }
4039
- else if (forceIgnore === 105 /* LowerI */) {
4040
- ignoreCase = true;
4041
- stripWhitespace(1);
4089
+ switch (selector.charCodeAt(selectorIndex) | 0x20) {
4090
+ // If the forceIgnore flag is set (either `i` or `s`), use that value
4091
+ case CharCode.LowerI: {
4092
+ ignoreCase = true;
4093
+ stripWhitespace(1);
4094
+ break;
4095
+ }
4096
+ case CharCode.LowerS: {
4097
+ ignoreCase = false;
4098
+ stripWhitespace(1);
4099
+ break;
4100
+ }
4042
4101
  }
4043
4102
  }
4044
4103
  if (selector.charCodeAt(selectorIndex) !==
4045
- 93 /* RightSquareBracket */) {
4104
+ CharCode.RightSquareBracket) {
4046
4105
  throw new Error("Attribute selector didn't terminate");
4047
4106
  }
4048
4107
  selectorIndex += 1;
@@ -4057,22 +4116,30 @@ function parseSelector(subselects, selector, selectorIndex) {
4057
4116
  tokens.push(attributeSelector);
4058
4117
  break;
4059
4118
  }
4060
- case 58 /* Colon */: {
4061
- if (selector.charCodeAt(selectorIndex + 1) === 58 /* Colon */) {
4119
+ case CharCode.Colon: {
4120
+ if (selector.charCodeAt(selectorIndex + 1) === CharCode.Colon) {
4062
4121
  tokens.push({
4063
4122
  type: SelectorType.PseudoElement,
4064
4123
  name: getName(2).toLowerCase(),
4065
4124
  data: selector.charCodeAt(selectorIndex) ===
4066
- 40 /* LeftParenthesis */
4125
+ CharCode.LeftParenthesis
4067
4126
  ? readValueWithParenthesis()
4068
4127
  : null,
4069
4128
  });
4070
- continue;
4129
+ break;
4071
4130
  }
4072
4131
  const name = getName(1).toLowerCase();
4132
+ if (pseudosToPseudoElements.has(name)) {
4133
+ tokens.push({
4134
+ type: SelectorType.PseudoElement,
4135
+ name,
4136
+ data: null,
4137
+ });
4138
+ break;
4139
+ }
4073
4140
  let data = null;
4074
4141
  if (selector.charCodeAt(selectorIndex) ===
4075
- 40 /* LeftParenthesis */) {
4142
+ CharCode.LeftParenthesis) {
4076
4143
  if (unpackPseudos.has(name)) {
4077
4144
  if (isQuote(selector.charCodeAt(selectorIndex + 1))) {
4078
4145
  throw new Error(`Pseudo-selector ${name} cannot be quoted`);
@@ -4080,7 +4147,7 @@ function parseSelector(subselects, selector, selectorIndex) {
4080
4147
  data = [];
4081
4148
  selectorIndex = parseSelector(data, selector, selectorIndex + 1);
4082
4149
  if (selector.charCodeAt(selectorIndex) !==
4083
- 41 /* RightParenthesis */) {
4150
+ CharCode.RightParenthesis) {
4084
4151
  throw new Error(`Missing closing parenthesis in :${name} (${selector})`);
4085
4152
  }
4086
4153
  selectorIndex += 1;
@@ -4100,7 +4167,7 @@ function parseSelector(subselects, selector, selectorIndex) {
4100
4167
  tokens.push({ type: SelectorType.Pseudo, name, data });
4101
4168
  break;
4102
4169
  }
4103
- case 44 /* Comma */: {
4170
+ case CharCode.Comma: {
4104
4171
  finalizeSubselector();
4105
4172
  tokens = [];
4106
4173
  stripWhitespace(1);
@@ -4121,13 +4188,13 @@ function parseSelector(subselects, selector, selectorIndex) {
4121
4188
  }
4122
4189
  let namespace = null;
4123
4190
  let name;
4124
- if (firstChar === 42 /* Asterisk */) {
4191
+ if (firstChar === CharCode.Asterisk) {
4125
4192
  selectorIndex += 1;
4126
4193
  name = "*";
4127
4194
  }
4128
- else if (firstChar === 124 /* Pipe */) {
4195
+ else if (firstChar === CharCode.Pipe) {
4129
4196
  name = "";
4130
- if (selector.charCodeAt(selectorIndex + 1) === 124 /* Pipe */) {
4197
+ if (selector.charCodeAt(selectorIndex + 1) === CharCode.Pipe) {
4131
4198
  addTraversal(SelectorType.ColumnCombinator);
4132
4199
  stripWhitespace(2);
4133
4200
  break;
@@ -4139,11 +4206,11 @@ function parseSelector(subselects, selector, selectorIndex) {
4139
4206
  else {
4140
4207
  break loop;
4141
4208
  }
4142
- if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */ &&
4143
- selector.charCodeAt(selectorIndex + 1) !== 124 /* Pipe */) {
4209
+ if (selector.charCodeAt(selectorIndex) === CharCode.Pipe &&
4210
+ selector.charCodeAt(selectorIndex + 1) !== CharCode.Pipe) {
4144
4211
  namespace = name;
4145
4212
  if (selector.charCodeAt(selectorIndex + 1) ===
4146
- 42 /* Asterisk */) {
4213
+ CharCode.Asterisk) {
4147
4214
  name = "*";
4148
4215
  selectorIndex += 2;
4149
4216
  }
@@ -4161,84 +4228,6 @@ function parseSelector(subselects, selector, selectorIndex) {
4161
4228
  return selectorIndex;
4162
4229
  }
4163
4230
 
4164
- const procedure = new Map([
4165
- [SelectorType.Universal, 50],
4166
- [SelectorType.Tag, 30],
4167
- [SelectorType.Attribute, 1],
4168
- [SelectorType.Pseudo, 0],
4169
- ]);
4170
- function isTraversal(token) {
4171
- return !procedure.has(token.type);
4172
- }
4173
- const attributes = new Map([
4174
- [AttributeAction.Exists, 10],
4175
- [AttributeAction.Equals, 8],
4176
- [AttributeAction.Not, 7],
4177
- [AttributeAction.Start, 6],
4178
- [AttributeAction.End, 6],
4179
- [AttributeAction.Any, 5],
4180
- ]);
4181
- /**
4182
- * Sort the parts of the passed selector,
4183
- * as there is potential for optimization
4184
- * (some types of selectors are faster than others)
4185
- *
4186
- * @param arr Selector to sort
4187
- */
4188
- function sortByProcedure(arr) {
4189
- const procs = arr.map(getProcedure);
4190
- for (let i = 1; i < arr.length; i++) {
4191
- const procNew = procs[i];
4192
- if (procNew < 0)
4193
- continue;
4194
- for (let j = i - 1; j >= 0 && procNew < procs[j]; j--) {
4195
- const token = arr[j + 1];
4196
- arr[j + 1] = arr[j];
4197
- arr[j] = token;
4198
- procs[j + 1] = procs[j];
4199
- procs[j] = procNew;
4200
- }
4201
- }
4202
- }
4203
- function getProcedure(token) {
4204
- var _a, _b;
4205
- let proc = (_a = procedure.get(token.type)) !== null && _a !== void 0 ? _a : -1;
4206
- if (token.type === SelectorType.Attribute) {
4207
- proc = (_b = attributes.get(token.action)) !== null && _b !== void 0 ? _b : 4;
4208
- if (token.action === AttributeAction.Equals && token.name === "id") {
4209
- // Prefer ID selectors (eg. #ID)
4210
- proc = 9;
4211
- }
4212
- if (token.ignoreCase) {
4213
- /*
4214
- * IgnoreCase adds some overhead, prefer "normal" token
4215
- * this is a binary operation, to ensure it's still an int
4216
- */
4217
- proc >>= 1;
4218
- }
4219
- }
4220
- else if (token.type === SelectorType.Pseudo) {
4221
- if (!token.data) {
4222
- proc = 3;
4223
- }
4224
- else if (token.name === "has" || token.name === "contains") {
4225
- proc = 0; // Expensive in any case
4226
- }
4227
- else if (Array.isArray(token.data)) {
4228
- // Eg. :matches, :not
4229
- proc = Math.min(...token.data.map((d) => Math.min(...d.map(getProcedure))));
4230
- // If we have traversals, try to avoid executing this selector
4231
- if (proc < 0) {
4232
- proc = 0;
4233
- }
4234
- }
4235
- else {
4236
- proc = 2;
4237
- }
4238
- }
4239
- return proc;
4240
- }
4241
-
4242
4231
  /**
4243
4232
  * All reserved characters in a regex, used for escaping.
4244
4233
  *
@@ -4357,7 +4346,7 @@ const attributeRules = {
4357
4346
  const { adapter } = options;
4358
4347
  const { name, value } = data;
4359
4348
  if (/\s/.test(value)) {
4360
- return boolbase.falseFunc;
4349
+ return boolbaseExports.falseFunc;
4361
4350
  }
4362
4351
  const regex = new RegExp(`(?:^|\\s)${escapeRegex(value)}(?:$|\\s)`, shouldIgnoreCase(data, options) ? "i" : "");
4363
4352
  return function element(elem) {
@@ -4377,7 +4366,7 @@ const attributeRules = {
4377
4366
  let { value } = data;
4378
4367
  const len = value.length;
4379
4368
  if (len === 0) {
4380
- return boolbase.falseFunc;
4369
+ return boolbaseExports.falseFunc;
4381
4370
  }
4382
4371
  if (shouldIgnoreCase(data, options)) {
4383
4372
  value = value.toLowerCase();
@@ -4389,11 +4378,8 @@ const attributeRules = {
4389
4378
  next(elem));
4390
4379
  };
4391
4380
  }
4392
- return (elem) => {
4393
- var _a;
4394
- return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.startsWith(value)) &&
4395
- next(elem);
4396
- };
4381
+ return (elem) => !!adapter.getAttributeValue(elem, name)?.startsWith(value) &&
4382
+ next(elem);
4397
4383
  },
4398
4384
  end(next, data, options) {
4399
4385
  const { adapter } = options;
@@ -4401,27 +4387,23 @@ const attributeRules = {
4401
4387
  let { value } = data;
4402
4388
  const len = -value.length;
4403
4389
  if (len === 0) {
4404
- return boolbase.falseFunc;
4390
+ return boolbaseExports.falseFunc;
4405
4391
  }
4406
4392
  if (shouldIgnoreCase(data, options)) {
4407
4393
  value = value.toLowerCase();
4408
- return (elem) => {
4409
- var _a;
4410
- return ((_a = adapter
4411
- .getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.substr(len).toLowerCase()) === value && next(elem);
4412
- };
4394
+ return (elem) => adapter
4395
+ .getAttributeValue(elem, name)
4396
+ ?.substr(len)
4397
+ .toLowerCase() === value && next(elem);
4413
4398
  }
4414
- return (elem) => {
4415
- var _a;
4416
- return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.endsWith(value)) &&
4417
- next(elem);
4418
- };
4399
+ return (elem) => !!adapter.getAttributeValue(elem, name)?.endsWith(value) &&
4400
+ next(elem);
4419
4401
  },
4420
4402
  any(next, data, options) {
4421
4403
  const { adapter } = options;
4422
4404
  const { name, value } = data;
4423
4405
  if (value === "") {
4424
- return boolbase.falseFunc;
4406
+ return boolbaseExports.falseFunc;
4425
4407
  }
4426
4408
  if (shouldIgnoreCase(data, options)) {
4427
4409
  const regex = new RegExp(escapeRegex(value), "i");
@@ -4433,11 +4415,8 @@ const attributeRules = {
4433
4415
  next(elem));
4434
4416
  };
4435
4417
  }
4436
- return (elem) => {
4437
- var _a;
4438
- return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.includes(value)) &&
4439
- next(elem);
4440
- };
4418
+ return (elem) => !!adapter.getAttributeValue(elem, name)?.includes(value) &&
4419
+ next(elem);
4441
4420
  },
4442
4421
  not(next, data, options) {
4443
4422
  const { adapter } = options;
@@ -4446,7 +4425,7 @@ const attributeRules = {
4446
4425
  if (value === "") {
4447
4426
  return (elem) => !!adapter.getAttributeValue(elem, name) && next(elem);
4448
4427
  }
4449
- else if (shouldIgnoreCase(data, options)) {
4428
+ if (shouldIgnoreCase(data, options)) {
4450
4429
  value = value.toLowerCase();
4451
4430
  return (elem) => {
4452
4431
  const attr = adapter.getAttributeValue(elem, name);
@@ -4460,6 +4439,169 @@ const attributeRules = {
4460
4439
  },
4461
4440
  };
4462
4441
 
4442
+ /**
4443
+ * Find all elements matching the query. If not in XML mode, the query will ignore
4444
+ * the contents of `<template>` elements.
4445
+ *
4446
+ * @param query - Function that returns true if the element matches the query.
4447
+ * @param elems - Nodes to query. If a node is an element, its children will be queried.
4448
+ * @param options - Options for querying the document.
4449
+ * @returns All matching elements.
4450
+ */
4451
+ function findAll(query, elems, options) {
4452
+ const { adapter, xmlMode = false } = options;
4453
+ const result = [];
4454
+ /** Stack of the arrays we are looking at. */
4455
+ const nodeStack = [elems];
4456
+ /** Stack of the indices within the arrays. */
4457
+ const indexStack = [0];
4458
+ for (;;) {
4459
+ // First, check if the current array has any more elements to look at.
4460
+ if (indexStack[0] >= nodeStack[0].length) {
4461
+ // If we have no more arrays to look at, we are done.
4462
+ if (nodeStack.length === 1) {
4463
+ return result;
4464
+ }
4465
+ nodeStack.shift();
4466
+ indexStack.shift();
4467
+ // Loop back to the start to continue with the next array.
4468
+ continue;
4469
+ }
4470
+ const elem = nodeStack[0][indexStack[0]++];
4471
+ if (!adapter.isTag(elem)) {
4472
+ continue;
4473
+ }
4474
+ if (query(elem)) {
4475
+ result.push(elem);
4476
+ }
4477
+ if (xmlMode || adapter.getName(elem) !== "template") {
4478
+ /*
4479
+ * Add the children to the stack. We are depth-first, so this is
4480
+ * the next array we look at.
4481
+ */
4482
+ const children = adapter.getChildren(elem);
4483
+ if (children.length > 0) {
4484
+ nodeStack.unshift(children);
4485
+ indexStack.unshift(0);
4486
+ }
4487
+ }
4488
+ }
4489
+ }
4490
+ /**
4491
+ * Find the first element matching the query. If not in XML mode, the query will ignore
4492
+ * the contents of `<template>` elements.
4493
+ *
4494
+ * @param query - Function that returns true if the element matches the query.
4495
+ * @param elems - Nodes to query. If a node is an element, its children will be queried.
4496
+ * @param options - Options for querying the document.
4497
+ * @returns The first matching element, or null if there was no match.
4498
+ */
4499
+ function findOne(query, elems, options) {
4500
+ const { adapter, xmlMode = false } = options;
4501
+ /** Stack of the arrays we are looking at. */
4502
+ const nodeStack = [elems];
4503
+ /** Stack of the indices within the arrays. */
4504
+ const indexStack = [0];
4505
+ for (;;) {
4506
+ // First, check if the current array has any more elements to look at.
4507
+ if (indexStack[0] >= nodeStack[0].length) {
4508
+ // If we have no more arrays to look at, we are done.
4509
+ if (nodeStack.length === 1) {
4510
+ return null;
4511
+ }
4512
+ nodeStack.shift();
4513
+ indexStack.shift();
4514
+ // Loop back to the start to continue with the next array.
4515
+ continue;
4516
+ }
4517
+ const elem = nodeStack[0][indexStack[0]++];
4518
+ if (!adapter.isTag(elem)) {
4519
+ continue;
4520
+ }
4521
+ if (query(elem)) {
4522
+ return elem;
4523
+ }
4524
+ if (xmlMode || adapter.getName(elem) !== "template") {
4525
+ /*
4526
+ * Add the children to the stack. We are depth-first, so this is
4527
+ * the next array we look at.
4528
+ */
4529
+ const children = adapter.getChildren(elem);
4530
+ if (children.length > 0) {
4531
+ nodeStack.unshift(children);
4532
+ indexStack.unshift(0);
4533
+ }
4534
+ }
4535
+ }
4536
+ }
4537
+ function getNextSiblings(elem, adapter) {
4538
+ const siblings = adapter.getSiblings(elem);
4539
+ if (siblings.length <= 1) {
4540
+ return [];
4541
+ }
4542
+ const elemIndex = siblings.indexOf(elem);
4543
+ if (elemIndex < 0 || elemIndex === siblings.length - 1) {
4544
+ return [];
4545
+ }
4546
+ return siblings.slice(elemIndex + 1).filter(adapter.isTag);
4547
+ }
4548
+ function getElementParent(node, adapter) {
4549
+ const parent = adapter.getParent(node);
4550
+ return parent != null && adapter.isTag(parent) ? parent : null;
4551
+ }
4552
+
4553
+ /**
4554
+ * Only text controls can be made read-only, since for other controls (such
4555
+ * as checkboxes and buttons) there is no useful distinction between being
4556
+ * read-only and being disabled.
4557
+ *
4558
+ * @see {@link https://html.spec.whatwg.org/multipage/input.html#attr-input-readonly}
4559
+ */
4560
+ const textControl = "input:is([type=text i],[type=search i],[type=url i],[type=tel i],[type=email i],[type=password i],[type=date i],[type=month i],[type=week i],[type=time i],[type=datetime-local i],[type=number i])";
4561
+ /**
4562
+ * Aliases are pseudos that are expressed as selectors.
4563
+ */
4564
+ const aliases = {
4565
+ // Links
4566
+ "any-link": ":is(a, area, link)[href]",
4567
+ link: ":any-link:not(:visited)",
4568
+ // Forms
4569
+ // https://html.spec.whatwg.org/multipage/scripting.html#disabled-elements
4570
+ disabled: `:is(
4571
+ :is(button, input, select, textarea, optgroup, option)[disabled],
4572
+ optgroup[disabled] > option,
4573
+ fieldset[disabled]:not(fieldset[disabled] legend:first-of-type *)
4574
+ )`,
4575
+ enabled: ":not(:disabled)",
4576
+ checked: ":is(:is(input[type=radio], input[type=checkbox])[checked], :selected)",
4577
+ required: ":is(input, select, textarea)[required]",
4578
+ optional: ":is(input, select, textarea):not([required])",
4579
+ "read-only": `[readonly]:is(textarea, ${textControl})`,
4580
+ "read-write": `:not([readonly]):is(textarea, ${textControl})`,
4581
+ // JQuery extensions
4582
+ /**
4583
+ * `:selected` matches option elements that have the `selected` attribute,
4584
+ * or are the first option element in a select element that does not have
4585
+ * the `multiple` attribute and does not have any option elements with the
4586
+ * `selected` attribute.
4587
+ *
4588
+ * @see https://html.spec.whatwg.org/multipage/form-elements.html#concept-option-selectedness
4589
+ */
4590
+ selected: "option:is([selected], select:not([multiple]):not(:has(> option[selected])) > :first-of-type)",
4591
+ checkbox: "[type=checkbox]",
4592
+ file: "[type=file]",
4593
+ password: "[type=password]",
4594
+ radio: "[type=radio]",
4595
+ reset: "[type=reset]",
4596
+ image: "[type=image]",
4597
+ submit: "[type=submit]",
4598
+ parent: ":not(:empty)",
4599
+ header: ":is(h1, h2, h3, h4, h5, h6)",
4600
+ button: ":is(button, input[type=button])",
4601
+ input: ":is(input, textarea, select, button)",
4602
+ text: "input:is(:not([type!='']), [type=text])",
4603
+ };
4604
+
4463
4605
  // Following http://www.w3.org/TR/css3-selectors/#nth-child-pseudo
4464
4606
  // Whitespace as per https://www.w3.org/TR/selectors-3/#lex is " \t\r\n\f"
4465
4607
  const whitespace = new Set([9, 10, 12, 13, 32]);
@@ -4614,38 +4756,73 @@ function nthCheck(formula) {
4614
4756
  return compile(parse(formula));
4615
4757
  }
4616
4758
 
4617
- function getChildFunc(next, adapter) {
4618
- return (elem) => {
4619
- const parent = adapter.getParent(elem);
4620
- return parent != null && adapter.isTag(parent) && next(elem);
4759
+ /**
4760
+ * Some selectors such as `:contains` and (non-relative) `:has` will only be
4761
+ * able to match elements if their parents match the selector (as they contain
4762
+ * a subset of the elements that the parent contains).
4763
+ *
4764
+ * This function wraps the given `matches` function in a function that caches
4765
+ * the results of the parent elements, so that the `matches` function only
4766
+ * needs to be called once for each subtree.
4767
+ */
4768
+ function cacheParentResults(next, { adapter, cacheResults }, matches) {
4769
+ if (cacheResults === false || typeof WeakMap === "undefined") {
4770
+ return (elem) => next(elem) && matches(elem);
4771
+ }
4772
+ // Use a cache to avoid re-checking children of an element.
4773
+ // @ts-expect-error `Node` is not extending object
4774
+ const resultCache = new WeakMap();
4775
+ function addResultToCache(elem) {
4776
+ const result = matches(elem);
4777
+ resultCache.set(elem, result);
4778
+ return result;
4779
+ }
4780
+ return function cachedMatcher(elem) {
4781
+ if (!next(elem)) {
4782
+ return false;
4783
+ }
4784
+ if (resultCache.has(elem)) {
4785
+ return resultCache.get(elem);
4786
+ }
4787
+ // Check all of the element's parents.
4788
+ let node = elem;
4789
+ do {
4790
+ const parent = getElementParent(node, adapter);
4791
+ if (parent === null) {
4792
+ return addResultToCache(elem);
4793
+ }
4794
+ node = parent;
4795
+ } while (!resultCache.has(node));
4796
+ return resultCache.get(node) && addResultToCache(elem);
4621
4797
  };
4622
4798
  }
4799
+
4623
4800
  const filters = {
4624
- contains(next, text, { adapter }) {
4625
- return function contains(elem) {
4626
- return next(elem) && adapter.getText(elem).includes(text);
4627
- };
4801
+ contains(next, text, options) {
4802
+ const { getText } = options.adapter;
4803
+ return cacheParentResults(next, options, (elem) => getText(elem).includes(text));
4628
4804
  },
4629
- icontains(next, text, { adapter }) {
4805
+ icontains(next, text, options) {
4630
4806
  const itext = text.toLowerCase();
4631
- return function icontains(elem) {
4632
- return (next(elem) &&
4633
- adapter.getText(elem).toLowerCase().includes(itext));
4634
- };
4807
+ const { getText } = options.adapter;
4808
+ return cacheParentResults(next, options, (elem) => getText(elem).toLowerCase().includes(itext));
4635
4809
  },
4636
4810
  // Location specific methods
4637
4811
  "nth-child"(next, rule, { adapter, equals }) {
4638
4812
  const func = nthCheck(rule);
4639
- if (func === boolbase.falseFunc)
4640
- return boolbase.falseFunc;
4641
- if (func === boolbase.trueFunc)
4642
- return getChildFunc(next, adapter);
4813
+ if (func === boolbaseExports.falseFunc) {
4814
+ return boolbaseExports.falseFunc;
4815
+ }
4816
+ if (func === boolbaseExports.trueFunc) {
4817
+ return (elem) => getElementParent(elem, adapter) !== null && next(elem);
4818
+ }
4643
4819
  return function nthChild(elem) {
4644
4820
  const siblings = adapter.getSiblings(elem);
4645
4821
  let pos = 0;
4646
4822
  for (let i = 0; i < siblings.length; i++) {
4647
- if (equals(elem, siblings[i]))
4823
+ if (equals(elem, siblings[i])) {
4648
4824
  break;
4825
+ }
4649
4826
  if (adapter.isTag(siblings[i])) {
4650
4827
  pos++;
4651
4828
  }
@@ -4655,16 +4832,19 @@ const filters = {
4655
4832
  },
4656
4833
  "nth-last-child"(next, rule, { adapter, equals }) {
4657
4834
  const func = nthCheck(rule);
4658
- if (func === boolbase.falseFunc)
4659
- return boolbase.falseFunc;
4660
- if (func === boolbase.trueFunc)
4661
- return getChildFunc(next, adapter);
4835
+ if (func === boolbaseExports.falseFunc) {
4836
+ return boolbaseExports.falseFunc;
4837
+ }
4838
+ if (func === boolbaseExports.trueFunc) {
4839
+ return (elem) => getElementParent(elem, adapter) !== null && next(elem);
4840
+ }
4662
4841
  return function nthLastChild(elem) {
4663
4842
  const siblings = adapter.getSiblings(elem);
4664
4843
  let pos = 0;
4665
4844
  for (let i = siblings.length - 1; i >= 0; i--) {
4666
- if (equals(elem, siblings[i]))
4845
+ if (equals(elem, siblings[i])) {
4667
4846
  break;
4847
+ }
4668
4848
  if (adapter.isTag(siblings[i])) {
4669
4849
  pos++;
4670
4850
  }
@@ -4674,17 +4854,20 @@ const filters = {
4674
4854
  },
4675
4855
  "nth-of-type"(next, rule, { adapter, equals }) {
4676
4856
  const func = nthCheck(rule);
4677
- if (func === boolbase.falseFunc)
4678
- return boolbase.falseFunc;
4679
- if (func === boolbase.trueFunc)
4680
- return getChildFunc(next, adapter);
4857
+ if (func === boolbaseExports.falseFunc) {
4858
+ return boolbaseExports.falseFunc;
4859
+ }
4860
+ if (func === boolbaseExports.trueFunc) {
4861
+ return (elem) => getElementParent(elem, adapter) !== null && next(elem);
4862
+ }
4681
4863
  return function nthOfType(elem) {
4682
4864
  const siblings = adapter.getSiblings(elem);
4683
4865
  let pos = 0;
4684
4866
  for (let i = 0; i < siblings.length; i++) {
4685
4867
  const currentSibling = siblings[i];
4686
- if (equals(elem, currentSibling))
4868
+ if (equals(elem, currentSibling)) {
4687
4869
  break;
4870
+ }
4688
4871
  if (adapter.isTag(currentSibling) &&
4689
4872
  adapter.getName(currentSibling) === adapter.getName(elem)) {
4690
4873
  pos++;
@@ -4695,17 +4878,20 @@ const filters = {
4695
4878
  },
4696
4879
  "nth-last-of-type"(next, rule, { adapter, equals }) {
4697
4880
  const func = nthCheck(rule);
4698
- if (func === boolbase.falseFunc)
4699
- return boolbase.falseFunc;
4700
- if (func === boolbase.trueFunc)
4701
- return getChildFunc(next, adapter);
4881
+ if (func === boolbaseExports.falseFunc) {
4882
+ return boolbaseExports.falseFunc;
4883
+ }
4884
+ if (func === boolbaseExports.trueFunc) {
4885
+ return (elem) => getElementParent(elem, adapter) !== null && next(elem);
4886
+ }
4702
4887
  return function nthLastOfType(elem) {
4703
4888
  const siblings = adapter.getSiblings(elem);
4704
4889
  let pos = 0;
4705
4890
  for (let i = siblings.length - 1; i >= 0; i--) {
4706
4891
  const currentSibling = siblings[i];
4707
- if (equals(elem, currentSibling))
4892
+ if (equals(elem, currentSibling)) {
4708
4893
  break;
4894
+ }
4709
4895
  if (adapter.isTag(currentSibling) &&
4710
4896
  adapter.getName(currentSibling) === adapter.getName(elem)) {
4711
4897
  pos++;
@@ -4716,10 +4902,7 @@ const filters = {
4716
4902
  },
4717
4903
  // TODO determine the actual root element
4718
4904
  root(next, _rule, { adapter }) {
4719
- return (elem) => {
4720
- const parent = adapter.getParent(elem);
4721
- return (parent == null || !adapter.isTag(parent)) && next(elem);
4722
- };
4905
+ return (elem) => getElementParent(elem, adapter) === null && next(elem);
4723
4906
  },
4724
4907
  scope(next, rule, options, context) {
4725
4908
  const { equals } = options;
@@ -4747,7 +4930,7 @@ function dynamicStatePseudo(name) {
4747
4930
  return function dynamicPseudo(next, _rule, { adapter }) {
4748
4931
  const func = adapter[name];
4749
4932
  if (typeof func !== "function") {
4750
- return boolbase.falseFunc;
4933
+ return boolbaseExports.falseFunc;
4751
4934
  }
4752
4935
  return function active(elem) {
4753
4936
  return func(elem) && next(elem);
@@ -4755,12 +4938,25 @@ function dynamicStatePseudo(name) {
4755
4938
  };
4756
4939
  }
4757
4940
 
4941
+ /**
4942
+ * CSS limits the characters considered as whitespace to space, tab & line
4943
+ * feed. We add carriage returns as htmlparser2 doesn't normalize them to
4944
+ * line feeds.
4945
+ *
4946
+ * @see {@link https://www.w3.org/TR/css-text-3/#white-space}
4947
+ */
4948
+ const isDocumentWhiteSpace = /^[ \t\r\n]*$/;
4758
4949
  // While filters are precompiled, pseudos get called when they are needed
4759
4950
  const pseudos = {
4760
4951
  empty(elem, { adapter }) {
4761
- return !adapter.getChildren(elem).some((elem) =>
4762
- // FIXME: `getText` call is potentially expensive.
4763
- adapter.isTag(elem) || adapter.getText(elem) !== "");
4952
+ const children = adapter.getChildren(elem);
4953
+ return (
4954
+ // First, make sure the tag does not have any element children.
4955
+ children.every((elem) => !adapter.isTag(elem)) &&
4956
+ // Then, check that the text content is only whitespace.
4957
+ children.every((elem) =>
4958
+ // FIXME: `getText` call is potentially expensive.
4959
+ isDocumentWhiteSpace.test(adapter.getText(elem))));
4764
4960
  },
4765
4961
  "first-child"(elem, { adapter, equals }) {
4766
4962
  if (adapter.prevElementSibling) {
@@ -4774,10 +4970,12 @@ const pseudos = {
4774
4970
  "last-child"(elem, { adapter, equals }) {
4775
4971
  const siblings = adapter.getSiblings(elem);
4776
4972
  for (let i = siblings.length - 1; i >= 0; i--) {
4777
- if (equals(elem, siblings[i]))
4973
+ if (equals(elem, siblings[i])) {
4778
4974
  return true;
4779
- if (adapter.isTag(siblings[i]))
4975
+ }
4976
+ if (adapter.isTag(siblings[i])) {
4780
4977
  break;
4978
+ }
4781
4979
  }
4782
4980
  return false;
4783
4981
  },
@@ -4786,8 +4984,9 @@ const pseudos = {
4786
4984
  const elemName = adapter.getName(elem);
4787
4985
  for (let i = 0; i < siblings.length; i++) {
4788
4986
  const currentSibling = siblings[i];
4789
- if (equals(elem, currentSibling))
4987
+ if (equals(elem, currentSibling)) {
4790
4988
  return true;
4989
+ }
4791
4990
  if (adapter.isTag(currentSibling) &&
4792
4991
  adapter.getName(currentSibling) === elemName) {
4793
4992
  break;
@@ -4800,8 +4999,9 @@ const pseudos = {
4800
4999
  const elemName = adapter.getName(elem);
4801
5000
  for (let i = siblings.length - 1; i >= 0; i--) {
4802
5001
  const currentSibling = siblings[i];
4803
- if (equals(elem, currentSibling))
5002
+ if (equals(elem, currentSibling)) {
4804
5003
  return true;
5004
+ }
4805
5005
  if (adapter.isTag(currentSibling) &&
4806
5006
  adapter.getName(currentSibling) === elemName) {
4807
5007
  break;
@@ -4834,56 +5034,123 @@ function verifyPseudoArgs(func, name, subselect, argIndex) {
4834
5034
  }
4835
5035
  }
4836
5036
 
5037
+ function isTraversal(token) {
5038
+ return token.type === "_flexibleDescendant" || isTraversal$1(token);
5039
+ }
4837
5040
  /**
4838
- * Aliases are pseudos that are expressed as selectors.
5041
+ * Sort the parts of the passed selector, as there is potential for
5042
+ * optimization (some types of selectors are faster than others).
5043
+ *
5044
+ * @param arr Selector to sort
4839
5045
  */
4840
- const aliases = {
4841
- // Links
4842
- "any-link": ":is(a, area, link)[href]",
4843
- link: ":any-link:not(:visited)",
4844
- // Forms
4845
- // https://html.spec.whatwg.org/multipage/scripting.html#disabled-elements
4846
- disabled: `:is(
4847
- :is(button, input, select, textarea, optgroup, option)[disabled],
4848
- optgroup[disabled] > option,
4849
- fieldset[disabled]:not(fieldset[disabled] legend:first-of-type *)
4850
- )`,
4851
- enabled: ":not(:disabled)",
4852
- checked: ":is(:is(input[type=radio], input[type=checkbox])[checked], option:selected)",
4853
- required: ":is(input, select, textarea)[required]",
4854
- optional: ":is(input, select, textarea):not([required])",
4855
- // JQuery extensions
4856
- // https://html.spec.whatwg.org/multipage/form-elements.html#concept-option-selectedness
4857
- selected: "option:is([selected], select:not([multiple]):not(:has(> option[selected])) > :first-of-type)",
4858
- checkbox: "[type=checkbox]",
4859
- file: "[type=file]",
4860
- password: "[type=password]",
4861
- radio: "[type=radio]",
4862
- reset: "[type=reset]",
4863
- image: "[type=image]",
4864
- submit: "[type=submit]",
4865
- parent: ":not(:empty)",
4866
- header: ":is(h1, h2, h3, h4, h5, h6)",
4867
- button: ":is(button, input[type=button])",
4868
- input: ":is(input, textarea, select, button)",
4869
- text: "input:is(:not([type!='']), [type=text])",
4870
- };
4871
-
4872
- /** Used as a placeholder for :has. Will be replaced with the actual element. */
4873
- const PLACEHOLDER_ELEMENT = {};
4874
- function ensureIsTag(next, adapter) {
4875
- if (next === boolbase.falseFunc)
4876
- return boolbase.falseFunc;
4877
- return (elem) => adapter.isTag(elem) && next(elem);
4878
- }
4879
- function getNextSiblings(elem, adapter) {
4880
- const siblings = adapter.getSiblings(elem);
4881
- if (siblings.length <= 1)
4882
- return [];
4883
- const elemIndex = siblings.indexOf(elem);
4884
- if (elemIndex < 0 || elemIndex === siblings.length - 1)
4885
- return [];
4886
- return siblings.slice(elemIndex + 1).filter(adapter.isTag);
5046
+ function sortRules(arr) {
5047
+ const ratings = arr.map(getQuality);
5048
+ for (let i = 1; i < arr.length; i++) {
5049
+ const procNew = ratings[i];
5050
+ if (procNew < 0) {
5051
+ continue;
5052
+ }
5053
+ // Use insertion sort to move the token to the correct position.
5054
+ for (let j = i; j > 0 && procNew < ratings[j - 1]; j--) {
5055
+ const token = arr[j];
5056
+ arr[j] = arr[j - 1];
5057
+ arr[j - 1] = token;
5058
+ ratings[j] = ratings[j - 1];
5059
+ ratings[j - 1] = procNew;
5060
+ }
5061
+ }
5062
+ }
5063
+ function getAttributeQuality(token) {
5064
+ switch (token.action) {
5065
+ case AttributeAction.Exists: {
5066
+ return 10;
5067
+ }
5068
+ case AttributeAction.Equals: {
5069
+ // Prefer ID selectors (eg. #ID)
5070
+ return token.name === "id" ? 9 : 8;
5071
+ }
5072
+ case AttributeAction.Not: {
5073
+ return 7;
5074
+ }
5075
+ case AttributeAction.Start: {
5076
+ return 6;
5077
+ }
5078
+ case AttributeAction.End: {
5079
+ return 6;
5080
+ }
5081
+ case AttributeAction.Any: {
5082
+ return 5;
5083
+ }
5084
+ case AttributeAction.Hyphen: {
5085
+ return 4;
5086
+ }
5087
+ case AttributeAction.Element: {
5088
+ return 3;
5089
+ }
5090
+ }
5091
+ }
5092
+ /**
5093
+ * Determine the quality of the passed token. The higher the number, the
5094
+ * faster the token is to execute.
5095
+ *
5096
+ * @param token Token to get the quality of.
5097
+ * @returns The token's quality.
5098
+ */
5099
+ function getQuality(token) {
5100
+ switch (token.type) {
5101
+ case SelectorType.Universal: {
5102
+ return 50;
5103
+ }
5104
+ case SelectorType.Tag: {
5105
+ return 30;
5106
+ }
5107
+ case SelectorType.Attribute: {
5108
+ return Math.floor(getAttributeQuality(token) /
5109
+ // `ignoreCase` adds some overhead, half the result if applicable.
5110
+ (token.ignoreCase ? 2 : 1));
5111
+ }
5112
+ case SelectorType.Pseudo: {
5113
+ return !token.data
5114
+ ? 3
5115
+ : token.name === "has" ||
5116
+ token.name === "contains" ||
5117
+ token.name === "icontains"
5118
+ ? // Expensive in any case — run as late as possible.
5119
+ 0
5120
+ : Array.isArray(token.data)
5121
+ ? // Eg. `:is`, `:not`
5122
+ Math.max(
5123
+ // If we have traversals, try to avoid executing this selector
5124
+ 0, Math.min(...token.data.map((d) => Math.min(...d.map(getQuality)))))
5125
+ : 2;
5126
+ }
5127
+ default: {
5128
+ return -1;
5129
+ }
5130
+ }
5131
+ }
5132
+ function includesScopePseudo(t) {
5133
+ return (t.type === SelectorType.Pseudo &&
5134
+ (t.name === "scope" ||
5135
+ (Array.isArray(t.data) &&
5136
+ t.data.some((data) => data.some(includesScopePseudo)))));
5137
+ }
5138
+
5139
+ /** Used as a placeholder for :has. Will be replaced with the actual element. */
5140
+ const PLACEHOLDER_ELEMENT = {};
5141
+ /**
5142
+ * Check if the selector has any properties that rely on the current element.
5143
+ * If not, we can cache the result of the selector.
5144
+ *
5145
+ * We can't cache selectors that start with a traversal (e.g. `>`, `+`, `~`),
5146
+ * or include a `:scope`.
5147
+ *
5148
+ * @param selector - The selector to check.
5149
+ * @returns Whether the selector has any properties that rely on the current element.
5150
+ */
5151
+ function hasDependsOnCurrentElement(selector) {
5152
+ return selector.some((sel) => sel.length > 0 &&
5153
+ (isTraversal(sel[0]) || sel.some(includesScopePseudo)));
4887
5154
  }
4888
5155
  function copyOptions(options) {
4889
5156
  // Not copied: context, rootFunc
@@ -4900,10 +5167,10 @@ function copyOptions(options) {
4900
5167
  }
4901
5168
  const is = (next, token, options, context, compileToken) => {
4902
5169
  const func = compileToken(token, copyOptions(options), context);
4903
- return func === boolbase.trueFunc
5170
+ return func === boolbaseExports.trueFunc
4904
5171
  ? next
4905
- : func === boolbase.falseFunc
4906
- ? boolbase.falseFunc
5172
+ : func === boolbaseExports.falseFunc
5173
+ ? boolbaseExports.falseFunc
4907
5174
  : (elem) => func(elem) && next(elem);
4908
5175
  };
4909
5176
  /*
@@ -4920,10 +5187,10 @@ const subselects = {
4920
5187
  where: is,
4921
5188
  not(next, token, options, context, compileToken) {
4922
5189
  const func = compileToken(token, copyOptions(options), context);
4923
- return func === boolbase.falseFunc
5190
+ return func === boolbaseExports.falseFunc
4924
5191
  ? next
4925
- : func === boolbase.trueFunc
4926
- ? boolbase.falseFunc
5192
+ : func === boolbaseExports.trueFunc
5193
+ ? boolbaseExports.falseFunc
4927
5194
  : (elem) => !func(elem) && next(elem);
4928
5195
  },
4929
5196
  has(next, subselect, options, _context, compileToken) {
@@ -4934,35 +5201,54 @@ const subselects = {
4934
5201
  ? // Used as a placeholder. Will be replaced with the actual element.
4935
5202
  [PLACEHOLDER_ELEMENT]
4936
5203
  : undefined;
5204
+ const skipCache = hasDependsOnCurrentElement(subselect);
4937
5205
  const compiled = compileToken(subselect, opts, context);
4938
- if (compiled === boolbase.falseFunc)
4939
- return boolbase.falseFunc;
4940
- const hasElement = ensureIsTag(compiled, adapter);
5206
+ if (compiled === boolbaseExports.falseFunc) {
5207
+ return boolbaseExports.falseFunc;
5208
+ }
4941
5209
  // If `compiled` is `trueFunc`, we can skip this.
4942
- if (context && compiled !== boolbase.trueFunc) {
4943
- /*
4944
- * `shouldTestNextSiblings` will only be true if the query starts with
4945
- * a traversal (sibling or adjacent). That means we will always have a context.
4946
- */
4947
- const { shouldTestNextSiblings = false } = compiled;
4948
- return (elem) => {
4949
- if (!next(elem))
4950
- return false;
4951
- context[0] = elem;
4952
- const childs = adapter.getChildren(elem);
4953
- const nextElements = shouldTestNextSiblings
4954
- ? [...childs, ...getNextSiblings(elem, adapter)]
4955
- : childs;
4956
- return adapter.existsOne(hasElement, nextElements);
4957
- };
5210
+ if (context && compiled !== boolbaseExports.trueFunc) {
5211
+ return skipCache
5212
+ ? (elem) => {
5213
+ if (!next(elem)) {
5214
+ return false;
5215
+ }
5216
+ context[0] = elem;
5217
+ const childs = adapter.getChildren(elem);
5218
+ return (findOne(compiled, compiled.shouldTestNextSiblings
5219
+ ? [
5220
+ ...childs,
5221
+ ...getNextSiblings(elem, adapter),
5222
+ ]
5223
+ : childs, options) !== null);
5224
+ }
5225
+ : cacheParentResults(next, options, (elem) => {
5226
+ context[0] = elem;
5227
+ return (findOne(compiled, adapter.getChildren(elem), options) !== null);
5228
+ });
4958
5229
  }
4959
- return (elem) => next(elem) &&
4960
- adapter.existsOne(hasElement, adapter.getChildren(elem));
5230
+ const hasOne = (elem) => findOne(compiled, adapter.getChildren(elem), options) !== null;
5231
+ return skipCache
5232
+ ? (elem) => next(elem) && hasOne(elem)
5233
+ : cacheParentResults(next, options, hasOne);
4961
5234
  },
4962
5235
  };
4963
5236
 
5237
+ /*
5238
+ * Pseudo selectors
5239
+ *
5240
+ * Pseudo selectors are available in three forms:
5241
+ *
5242
+ * 1. Filters are called when the selector is compiled and return a function
5243
+ * that has to return either false, or the results of `next()`.
5244
+ * 2. Pseudos are called on execution. They have to return a boolean.
5245
+ * 3. Subselects work like filters, but have an embedded selector that will be run separately.
5246
+ *
5247
+ * Filters are great if you want to do some pre-processing, or change the call order
5248
+ * of `next()` and your code.
5249
+ * Pseudos should be used to implement simple checks.
5250
+ */
4964
5251
  function compilePseudoSelector(next, selector, options, context, compileToken) {
4965
- var _a;
4966
5252
  const { name, data } = selector;
4967
5253
  if (Array.isArray(data)) {
4968
5254
  if (!(name in subselects)) {
@@ -4970,7 +5256,7 @@ function compilePseudoSelector(next, selector, options, context, compileToken) {
4970
5256
  }
4971
5257
  return subselects[name](next, data, options, context, compileToken);
4972
5258
  }
4973
- const userPseudo = (_a = options.pseudos) === null || _a === void 0 ? void 0 : _a[name];
5259
+ const userPseudo = options.pseudos?.[name];
4974
5260
  const stringPseudo = typeof userPseudo === "string" ? userPseudo : aliases[name];
4975
5261
  if (typeof stringPseudo === "string") {
4976
5262
  if (data != null) {
@@ -4995,18 +5281,11 @@ function compilePseudoSelector(next, selector, options, context, compileToken) {
4995
5281
  throw new Error(`Unknown pseudo-class :${name}`);
4996
5282
  }
4997
5283
 
4998
- function getElementParent(node, adapter) {
4999
- const parent = adapter.getParent(node);
5000
- if (parent && adapter.isTag(parent)) {
5001
- return parent;
5002
- }
5003
- return null;
5004
- }
5005
5284
  /*
5006
5285
  * All available rules
5007
5286
  */
5008
- function compileGeneralSelector(next, selector, options, context, compileToken) {
5009
- const { adapter, equals } = options;
5287
+ function compileGeneralSelector(next, selector, options, context, compileToken, hasExpensiveSubselector) {
5288
+ const { adapter, equals, cacheResults } = options;
5010
5289
  switch (selector.type) {
5011
5290
  case SelectorType.PseudoElement: {
5012
5291
  throw new Error("Pseudo-elements are not supported by css-select");
@@ -5041,10 +5320,12 @@ function compileGeneralSelector(next, selector, options, context, compileToken)
5041
5320
  }
5042
5321
  // Traversal
5043
5322
  case SelectorType.Descendant: {
5044
- if (options.cacheResults === false ||
5045
- typeof WeakSet === "undefined") {
5323
+ if (!hasExpensiveSubselector ||
5324
+ cacheResults === false ||
5325
+ typeof WeakMap === "undefined") {
5046
5326
  return function descendant(elem) {
5047
5327
  let current = elem;
5328
+ // biome-ignore lint/suspicious/noAssignInExpressions: TODO
5048
5329
  while ((current = getElementParent(current, adapter))) {
5049
5330
  if (next(current)) {
5050
5331
  return true;
@@ -5053,16 +5334,26 @@ function compileGeneralSelector(next, selector, options, context, compileToken)
5053
5334
  return false;
5054
5335
  };
5055
5336
  }
5056
- // @ts-expect-error `ElementNode` is not extending object
5057
- const isFalseCache = new WeakSet();
5337
+ const resultCache = new WeakMap();
5058
5338
  return function cachedDescendant(elem) {
5059
5339
  let current = elem;
5340
+ let result;
5341
+ // biome-ignore lint/suspicious/noAssignInExpressions: TODO
5060
5342
  while ((current = getElementParent(current, adapter))) {
5061
- if (!isFalseCache.has(current)) {
5062
- if (adapter.isTag(current) && next(current)) {
5343
+ const cached = resultCache.get(current);
5344
+ if (cached === undefined) {
5345
+ result ?? (result = { matches: false });
5346
+ result.matches = next(current);
5347
+ resultCache.set(current, result);
5348
+ if (result.matches) {
5063
5349
  return true;
5064
5350
  }
5065
- isFalseCache.add(current);
5351
+ }
5352
+ else {
5353
+ if (result) {
5354
+ result.matches = cached.matches;
5355
+ }
5356
+ return cached.matches;
5066
5357
  }
5067
5358
  }
5068
5359
  return false;
@@ -5073,9 +5364,11 @@ function compileGeneralSelector(next, selector, options, context, compileToken)
5073
5364
  return function flexibleDescendant(elem) {
5074
5365
  let current = elem;
5075
5366
  do {
5076
- if (next(current))
5367
+ if (next(current)) {
5077
5368
  return true;
5078
- } while ((current = getElementParent(current, adapter)));
5369
+ }
5370
+ current = getElementParent(current, adapter);
5371
+ } while (current);
5079
5372
  return false;
5080
5373
  };
5081
5374
  }
@@ -5088,8 +5381,8 @@ function compileGeneralSelector(next, selector, options, context, compileToken)
5088
5381
  }
5089
5382
  case SelectorType.Child: {
5090
5383
  return function child(elem) {
5091
- const parent = adapter.getParent(elem);
5092
- return parent != null && adapter.isTag(parent) && next(parent);
5384
+ const parent = getElementParent(elem, adapter);
5385
+ return parent !== null && next(parent);
5093
5386
  };
5094
5387
  }
5095
5388
  case SelectorType.Sibling: {
@@ -5097,8 +5390,9 @@ function compileGeneralSelector(next, selector, options, context, compileToken)
5097
5390
  const siblings = adapter.getSiblings(elem);
5098
5391
  for (let i = 0; i < siblings.length; i++) {
5099
5392
  const currentSibling = siblings[i];
5100
- if (equals(elem, currentSibling))
5393
+ if (equals(elem, currentSibling)) {
5101
5394
  break;
5395
+ }
5102
5396
  if (adapter.isTag(currentSibling) && next(currentSibling)) {
5103
5397
  return true;
5104
5398
  }
@@ -5118,8 +5412,9 @@ function compileGeneralSelector(next, selector, options, context, compileToken)
5118
5412
  let lastElement;
5119
5413
  for (let i = 0; i < siblings.length; i++) {
5120
5414
  const currentSibling = siblings[i];
5121
- if (equals(elem, currentSibling))
5415
+ if (equals(elem, currentSibling)) {
5122
5416
  break;
5417
+ }
5123
5418
  if (adapter.isTag(currentSibling)) {
5124
5419
  lastElement = currentSibling;
5125
5420
  }
@@ -5136,16 +5431,6 @@ function compileGeneralSelector(next, selector, options, context, compileToken)
5136
5431
  }
5137
5432
  }
5138
5433
 
5139
- function compileUnsafe(selector, options, context) {
5140
- const token = typeof selector === "string" ? parse$1(selector) : selector;
5141
- return compileToken(token, options, context);
5142
- }
5143
- function includesScopePseudo(t) {
5144
- return (t.type === SelectorType.Pseudo &&
5145
- (t.name === "scope" ||
5146
- (Array.isArray(t.data) &&
5147
- t.data.some((data) => data.some(includesScopePseudo)))));
5148
- }
5149
5434
  const DESCENDANT_TOKEN = { type: SelectorType.Descendant };
5150
5435
  const FLEXIBLE_DESCENDANT_TOKEN = {
5151
5436
  type: "_flexibleDescendant",
@@ -5161,10 +5446,8 @@ const SCOPE_TOKEN = {
5161
5446
  */
5162
5447
  function absolutize(token, { adapter }, context) {
5163
5448
  // TODO Use better check if the context is a document
5164
- const hasContext = !!(context === null || context === void 0 ? void 0 : context.every((e) => {
5165
- const parent = adapter.isTag(e) && adapter.getParent(e);
5166
- return e === PLACEHOLDER_ELEMENT || (parent && adapter.isTag(parent));
5167
- }));
5449
+ const hasContext = !!context?.every((e) => e === PLACEHOLDER_ELEMENT ||
5450
+ (adapter.isTag(e) && getElementParent(e, adapter) !== null));
5168
5451
  for (const t of token) {
5169
5452
  if (t.length > 0 &&
5170
5453
  isTraversal(t[0]) &&
@@ -5178,10 +5461,9 @@ function absolutize(token, { adapter }, context) {
5178
5461
  t.unshift(SCOPE_TOKEN);
5179
5462
  }
5180
5463
  }
5181
- function compileToken(token, options, context) {
5182
- var _a;
5183
- token.forEach(sortByProcedure);
5184
- context = (_a = options.context) !== null && _a !== void 0 ? _a : context;
5464
+ function compileToken(token, options, ctx) {
5465
+ token.forEach(sortRules);
5466
+ const { context = ctx, rootFunc = boolbaseExports.trueFunc } = options;
5185
5467
  const isArrayContext = Array.isArray(context);
5186
5468
  const finalContext = context && (Array.isArray(context) ? context : [context]);
5187
5469
  // Check if the selector is relative
@@ -5192,12 +5474,11 @@ function compileToken(token, options, context) {
5192
5474
  throw new Error("Relative selectors are not allowed when the `relativeSelector` option is disabled");
5193
5475
  }
5194
5476
  let shouldTestNextSiblings = false;
5195
- const query = token
5196
- .map((rules) => {
5477
+ let query = boolbaseExports.falseFunc;
5478
+ combineLoop: for (const rules of token) {
5197
5479
  if (rules.length >= 2) {
5198
5480
  const [first, second] = rules;
5199
- if (first.type !== SelectorType.Pseudo ||
5200
- first.name !== "scope") ;
5481
+ if (first.type !== SelectorType.Pseudo || first.name !== "scope") ;
5201
5482
  else if (isArrayContext &&
5202
5483
  second.type === SelectorType.Descendant) {
5203
5484
  rules[1] = FLEXIBLE_DESCENDANT_TOKEN;
@@ -5207,28 +5488,30 @@ function compileToken(token, options, context) {
5207
5488
  shouldTestNextSiblings = true;
5208
5489
  }
5209
5490
  }
5210
- return compileRules(rules, options, finalContext);
5211
- })
5212
- .reduce(reduceRules, boolbase.falseFunc);
5491
+ let next = rootFunc;
5492
+ let hasExpensiveSubselector = false;
5493
+ for (const rule of rules) {
5494
+ next = compileGeneralSelector(next, rule, options, finalContext, compileToken, hasExpensiveSubselector);
5495
+ const quality = getQuality(rule);
5496
+ if (quality === 0) {
5497
+ hasExpensiveSubselector = true;
5498
+ }
5499
+ // If the sub-selector won't match any elements, skip it.
5500
+ if (next === boolbaseExports.falseFunc) {
5501
+ continue combineLoop;
5502
+ }
5503
+ }
5504
+ // If we have a function that always returns true, we can stop here.
5505
+ if (next === rootFunc) {
5506
+ return rootFunc;
5507
+ }
5508
+ query = query === boolbaseExports.falseFunc ? next : or(query, next);
5509
+ }
5213
5510
  query.shouldTestNextSiblings = shouldTestNextSiblings;
5214
5511
  return query;
5215
5512
  }
5216
- function compileRules(rules, options, context) {
5217
- var _a;
5218
- return rules.reduce((previous, rule) => previous === boolbase.falseFunc
5219
- ? boolbase.falseFunc
5220
- : compileGeneralSelector(previous, rule, options, context, compileToken), (_a = options.rootFunc) !== null && _a !== void 0 ? _a : boolbase.trueFunc);
5221
- }
5222
- function reduceRules(a, b) {
5223
- if (b === boolbase.falseFunc || a === boolbase.trueFunc) {
5224
- return a;
5225
- }
5226
- if (a === boolbase.falseFunc || b === boolbase.trueFunc) {
5227
- return b;
5228
- }
5229
- return function combine(elem) {
5230
- return a(elem) || b(elem);
5231
- };
5513
+ function or(a, b) {
5514
+ return (elem) => a(elem) || b(elem);
5232
5515
  }
5233
5516
 
5234
5517
  const defaultEquals = (a, b) => a === b;
@@ -5237,23 +5520,34 @@ const defaultOptions$1 = {
5237
5520
  equals: defaultEquals,
5238
5521
  };
5239
5522
  function convertOptionFormats(options) {
5240
- var _a, _b, _c, _d;
5241
5523
  /*
5242
5524
  * We force one format of options to the other one.
5243
5525
  */
5244
5526
  // @ts-expect-error Default options may have incompatible `Node` / `ElementNode`.
5245
- const opts = options !== null && options !== void 0 ? options : defaultOptions$1;
5527
+ const opts = options ?? defaultOptions$1;
5246
5528
  // @ts-expect-error Same as above.
5247
- (_a = opts.adapter) !== null && _a !== void 0 ? _a : (opts.adapter = DomUtils);
5529
+ opts.adapter ?? (opts.adapter = DomUtils);
5248
5530
  // @ts-expect-error `equals` does not exist on `Options`
5249
- (_b = opts.equals) !== null && _b !== void 0 ? _b : (opts.equals = (_d = (_c = opts.adapter) === null || _c === void 0 ? void 0 : _c.equals) !== null && _d !== void 0 ? _d : defaultEquals);
5531
+ opts.equals ?? (opts.equals = opts.adapter?.equals ?? defaultEquals);
5250
5532
  return opts;
5251
5533
  }
5534
+ /**
5535
+ * Like `compile`, but does not add a check if elements are tags.
5536
+ */
5537
+ function _compileUnsafe(selector, options, context) {
5538
+ return _compileToken(typeof selector === "string" ? parse$1(selector) : selector, options, context);
5539
+ }
5540
+ /**
5541
+ * @deprecated Use `_compileUnsafe` instead.
5542
+ */
5543
+ function _compileToken(selector, options, context) {
5544
+ return compileToken(selector, convertOptionFormats(options), context);
5545
+ }
5252
5546
  function getSelectorFunc(searchFunc) {
5253
5547
  return function select(query, elements, options) {
5254
5548
  const opts = convertOptionFormats(options);
5255
5549
  if (typeof query !== "function") {
5256
- query = compileUnsafe(query, opts, elements);
5550
+ query = _compileUnsafe(query, opts, elements);
5257
5551
  }
5258
5552
  const filteredElements = prepareContext(elements, opts.adapter, query.shouldTestNextSiblings);
5259
5553
  return searchFunc(query, filteredElements, opts);
@@ -5284,111 +5578,102 @@ function appendNextSiblings(elem, adapter) {
5284
5578
  /**
5285
5579
  * @template Node The generic Node type for the DOM adapter being used.
5286
5580
  * @template ElementNode The Node type for elements for the DOM adapter being used.
5287
- * @param elems Elements to query. If it is an element, its children will be queried..
5581
+ * @param elems Elements to query. If it is an element, its children will be queried.
5288
5582
  * @param query can be either a CSS selector string or a compiled query function.
5289
5583
  * @param [options] options for querying the document.
5290
5584
  * @see compile for supported selector queries.
5291
5585
  * @returns All matching elements.
5292
5586
  *
5293
5587
  */
5294
- const selectAll = getSelectorFunc((query, elems, options) => query === boolbase.falseFunc || !elems || elems.length === 0
5588
+ const selectAll = getSelectorFunc((query, elems, options) => query === boolbaseExports.falseFunc || !elems || elems.length === 0
5295
5589
  ? []
5296
- : options.adapter.findAll(query, elems));
5297
-
5298
- const comma = ','.charCodeAt(0);
5299
- const semicolon = ';'.charCodeAt(0);
5300
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
5301
- const intToChar = new Uint8Array(64); // 64 possible chars.
5302
- const charToInt = new Uint8Array(128); // z is 122 in ASCII
5590
+ : findAll(query, elems, options));
5591
+
5592
+ // src/vlq.ts
5593
+ var comma = ",".charCodeAt(0);
5594
+ var semicolon = ";".charCodeAt(0);
5595
+ var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5596
+ var intToChar = new Uint8Array(64);
5597
+ var charToInt = new Uint8Array(128);
5303
5598
  for (let i = 0; i < chars.length; i++) {
5304
- const c = chars.charCodeAt(i);
5305
- intToChar[i] = c;
5306
- charToInt[c] = i;
5599
+ const c = chars.charCodeAt(i);
5600
+ intToChar[i] = c;
5601
+ charToInt[c] = i;
5307
5602
  }
5308
5603
  function encodeInteger(builder, num, relative) {
5309
- let delta = num - relative;
5310
- delta = delta < 0 ? (-delta << 1) | 1 : delta << 1;
5311
- do {
5312
- let clamped = delta & 0b011111;
5313
- delta >>>= 5;
5314
- if (delta > 0)
5315
- clamped |= 0b100000;
5316
- builder.write(intToChar[clamped]);
5317
- } while (delta > 0);
5318
- return num;
5319
- }
5320
-
5321
- const bufLength = 1024 * 16;
5322
- // Provide a fallback for older environments.
5323
- const td = typeof TextDecoder !== 'undefined'
5324
- ? /* #__PURE__ */ new TextDecoder()
5325
- : typeof Buffer !== 'undefined'
5326
- ? {
5327
- decode(buf) {
5328
- const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);
5329
- return out.toString();
5330
- },
5331
- }
5332
- : {
5333
- decode(buf) {
5334
- let out = '';
5335
- for (let i = 0; i < buf.length; i++) {
5336
- out += String.fromCharCode(buf[i]);
5337
- }
5338
- return out;
5339
- },
5340
- };
5341
- class StringWriter {
5342
- constructor() {
5343
- this.pos = 0;
5344
- this.out = '';
5345
- this.buffer = new Uint8Array(bufLength);
5346
- }
5347
- write(v) {
5348
- const { buffer } = this;
5349
- buffer[this.pos++] = v;
5350
- if (this.pos === bufLength) {
5351
- this.out += td.decode(buffer);
5352
- this.pos = 0;
5353
- }
5604
+ let delta = num - relative;
5605
+ delta = delta < 0 ? -delta << 1 | 1 : delta << 1;
5606
+ do {
5607
+ let clamped = delta & 31;
5608
+ delta >>>= 5;
5609
+ if (delta > 0) clamped |= 32;
5610
+ builder.write(intToChar[clamped]);
5611
+ } while (delta > 0);
5612
+ return num;
5613
+ }
5614
+
5615
+ // src/strings.ts
5616
+ var bufLength = 1024 * 16;
5617
+ var td = typeof TextDecoder !== "undefined" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== "undefined" ? {
5618
+ decode(buf) {
5619
+ const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);
5620
+ return out.toString();
5621
+ }
5622
+ } : {
5623
+ decode(buf) {
5624
+ let out = "";
5625
+ for (let i = 0; i < buf.length; i++) {
5626
+ out += String.fromCharCode(buf[i]);
5354
5627
  }
5355
- flush() {
5356
- const { buffer, out, pos } = this;
5357
- return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
5628
+ return out;
5629
+ }
5630
+ };
5631
+ var StringWriter = class {
5632
+ constructor() {
5633
+ this.pos = 0;
5634
+ this.out = "";
5635
+ this.buffer = new Uint8Array(bufLength);
5636
+ }
5637
+ write(v) {
5638
+ const { buffer } = this;
5639
+ buffer[this.pos++] = v;
5640
+ if (this.pos === bufLength) {
5641
+ this.out += td.decode(buffer);
5642
+ this.pos = 0;
5358
5643
  }
5359
- }
5644
+ }
5645
+ flush() {
5646
+ const { buffer, out, pos } = this;
5647
+ return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
5648
+ }
5649
+ };
5360
5650
  function encode(decoded) {
5361
- const writer = new StringWriter();
5362
- let sourcesIndex = 0;
5363
- let sourceLine = 0;
5364
- let sourceColumn = 0;
5365
- let namesIndex = 0;
5366
- for (let i = 0; i < decoded.length; i++) {
5367
- const line = decoded[i];
5368
- if (i > 0)
5369
- writer.write(semicolon);
5370
- if (line.length === 0)
5371
- continue;
5372
- let genColumn = 0;
5373
- for (let j = 0; j < line.length; j++) {
5374
- const segment = line[j];
5375
- if (j > 0)
5376
- writer.write(comma);
5377
- genColumn = encodeInteger(writer, segment[0], genColumn);
5378
- if (segment.length === 1)
5379
- continue;
5380
- sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
5381
- sourceLine = encodeInteger(writer, segment[2], sourceLine);
5382
- sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
5383
- if (segment.length === 4)
5384
- continue;
5385
- namesIndex = encodeInteger(writer, segment[4], namesIndex);
5386
- }
5651
+ const writer = new StringWriter();
5652
+ let sourcesIndex = 0;
5653
+ let sourceLine = 0;
5654
+ let sourceColumn = 0;
5655
+ let namesIndex = 0;
5656
+ for (let i = 0; i < decoded.length; i++) {
5657
+ const line = decoded[i];
5658
+ if (i > 0) writer.write(semicolon);
5659
+ if (line.length === 0) continue;
5660
+ let genColumn = 0;
5661
+ for (let j = 0; j < line.length; j++) {
5662
+ const segment = line[j];
5663
+ if (j > 0) writer.write(comma);
5664
+ genColumn = encodeInteger(writer, segment[0], genColumn);
5665
+ if (segment.length === 1) continue;
5666
+ sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
5667
+ sourceLine = encodeInteger(writer, segment[2], sourceLine);
5668
+ sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
5669
+ if (segment.length === 4) continue;
5670
+ namesIndex = encodeInteger(writer, segment[4], namesIndex);
5387
5671
  }
5388
- return writer.flush();
5672
+ }
5673
+ return writer.flush();
5389
5674
  }
5390
5675
 
5391
- class BitSet {
5676
+ let BitSet$1 = class BitSet {
5392
5677
  constructor(arg) {
5393
5678
  this.bits = arg instanceof BitSet ? arg.bits.slice() : [];
5394
5679
  }
@@ -5400,9 +5685,9 @@ class BitSet {
5400
5685
  has(n) {
5401
5686
  return !!(this.bits[n >> 5] & (1 << (n & 31)));
5402
5687
  }
5403
- }
5688
+ };
5404
5689
 
5405
- class Chunk {
5690
+ let Chunk$1 = class Chunk {
5406
5691
  constructor(start, end, content) {
5407
5692
  this.start = start;
5408
5693
  this.end = end;
@@ -5579,9 +5864,9 @@ class Chunk {
5579
5864
  if (this.outro.length) return true;
5580
5865
  }
5581
5866
  }
5582
- }
5867
+ };
5583
5868
 
5584
- function getBtoa() {
5869
+ function getBtoa$1() {
5585
5870
  if (typeof globalThis !== 'undefined' && typeof globalThis.btoa === 'function') {
5586
5871
  return (str) => globalThis.btoa(unescape(encodeURIComponent(str)));
5587
5872
  } else if (typeof Buffer === 'function') {
@@ -5593,9 +5878,9 @@ function getBtoa() {
5593
5878
  }
5594
5879
  }
5595
5880
 
5596
- const btoa = /*#__PURE__*/ getBtoa();
5881
+ const btoa$1 = /*#__PURE__*/ getBtoa$1();
5597
5882
 
5598
- class SourceMap {
5883
+ let SourceMap$1 = class SourceMap {
5599
5884
  constructor(properties) {
5600
5885
  this.version = 3;
5601
5886
  this.file = properties.file;
@@ -5616,11 +5901,11 @@ class SourceMap {
5616
5901
  }
5617
5902
 
5618
5903
  toUrl() {
5619
- return 'data:application/json;charset=utf-8;base64,' + btoa(this.toString());
5904
+ return 'data:application/json;charset=utf-8;base64,' + btoa$1(this.toString());
5620
5905
  }
5621
- }
5906
+ };
5622
5907
 
5623
- function guessIndent(code) {
5908
+ function guessIndent$1(code) {
5624
5909
  const lines = code.split('\n');
5625
5910
 
5626
5911
  const tabbed = lines.filter((line) => /^\t+/.test(line));
@@ -5646,7 +5931,7 @@ function guessIndent(code) {
5646
5931
  return new Array(min + 1).join(' ');
5647
5932
  }
5648
5933
 
5649
- function getRelativePath(from, to) {
5934
+ function getRelativePath$1(from, to) {
5650
5935
  const fromParts = from.split(/[/\\]/);
5651
5936
  const toParts = to.split(/[/\\]/);
5652
5937
 
@@ -5665,13 +5950,13 @@ function getRelativePath(from, to) {
5665
5950
  return fromParts.concat(toParts).join('/');
5666
5951
  }
5667
5952
 
5668
- const toString = Object.prototype.toString;
5953
+ const toString$1 = Object.prototype.toString;
5669
5954
 
5670
- function isObject(thing) {
5671
- return toString.call(thing) === '[object Object]';
5955
+ function isObject$1(thing) {
5956
+ return toString$1.call(thing) === '[object Object]';
5672
5957
  }
5673
5958
 
5674
- function getLocator(source) {
5959
+ function getLocator$1(source) {
5675
5960
  const originalLines = source.split('\n');
5676
5961
  const lineOffsets = [];
5677
5962
 
@@ -5697,9 +5982,9 @@ function getLocator(source) {
5697
5982
  };
5698
5983
  }
5699
5984
 
5700
- const wordRegex = /\w/;
5985
+ const wordRegex$1 = /\w/;
5701
5986
 
5702
- class Mappings {
5987
+ let Mappings$1 = class Mappings {
5703
5988
  constructor(hires) {
5704
5989
  this.hires = hires;
5705
5990
  this.generatedCodeLine = 0;
@@ -5767,7 +6052,7 @@ class Mappings {
5767
6052
 
5768
6053
  if (this.hires === 'boundary') {
5769
6054
  // in hires "boundary", group segments per word boundary than per char
5770
- if (wordRegex.test(original[originalCharIndex])) {
6055
+ if (wordRegex$1.test(original[originalCharIndex])) {
5771
6056
  // for first char in the boundary found, start the boundary by pushing a segment
5772
6057
  if (!charInHiresBoundary) {
5773
6058
  this.rawSegments.push(segment);
@@ -5809,19 +6094,19 @@ class Mappings {
5809
6094
 
5810
6095
  this.generatedCodeColumn += lines[lines.length - 1].length;
5811
6096
  }
5812
- }
6097
+ };
5813
6098
 
5814
- const n = '\n';
6099
+ const n$1 = '\n';
5815
6100
 
5816
- const warned = {
6101
+ const warned$1 = {
5817
6102
  insertLeft: false,
5818
6103
  insertRight: false,
5819
6104
  storeName: false,
5820
6105
  };
5821
6106
 
5822
- class MagicString {
6107
+ let MagicString$1 = class MagicString {
5823
6108
  constructor(string, options = {}) {
5824
- const chunk = new Chunk(0, string.length, string);
6109
+ const chunk = new Chunk$1(0, string.length, string);
5825
6110
 
5826
6111
  Object.defineProperties(this, {
5827
6112
  original: { writable: true, value: string },
@@ -5834,7 +6119,7 @@ class MagicString {
5834
6119
  byEnd: { writable: true, value: {} },
5835
6120
  filename: { writable: true, value: options.filename },
5836
6121
  indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
5837
- sourcemapLocations: { writable: true, value: new BitSet() },
6122
+ sourcemapLocations: { writable: true, value: new BitSet$1() },
5838
6123
  storedNames: { writable: true, value: {} },
5839
6124
  indentStr: { writable: true, value: undefined },
5840
6125
  ignoreList: { writable: true, value: options.ignoreList },
@@ -5919,7 +6204,7 @@ class MagicString {
5919
6204
  cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
5920
6205
  }
5921
6206
 
5922
- cloned.sourcemapLocations = new BitSet(this.sourcemapLocations);
6207
+ cloned.sourcemapLocations = new BitSet$1(this.sourcemapLocations);
5923
6208
 
5924
6209
  cloned.intro = this.intro;
5925
6210
  cloned.outro = this.outro;
@@ -5932,9 +6217,9 @@ class MagicString {
5932
6217
 
5933
6218
  const sourceIndex = 0;
5934
6219
  const names = Object.keys(this.storedNames);
5935
- const mappings = new Mappings(options.hires);
6220
+ const mappings = new Mappings$1(options.hires);
5936
6221
 
5937
- const locate = getLocator(this.original);
6222
+ const locate = getLocator$1(this.original);
5938
6223
 
5939
6224
  if (this.intro) {
5940
6225
  mappings.advance(this.intro);
@@ -5959,10 +6244,14 @@ class MagicString {
5959
6244
  if (chunk.outro.length) mappings.advance(chunk.outro);
5960
6245
  });
5961
6246
 
6247
+ if (this.outro) {
6248
+ mappings.advance(this.outro);
6249
+ }
6250
+
5962
6251
  return {
5963
6252
  file: options.file ? options.file.split(/[/\\]/).pop() : undefined,
5964
6253
  sources: [
5965
- options.source ? getRelativePath(options.file || '', options.source) : options.file || '',
6254
+ options.source ? getRelativePath$1(options.file || '', options.source) : options.file || '',
5966
6255
  ],
5967
6256
  sourcesContent: options.includeContent ? [this.original] : undefined,
5968
6257
  names,
@@ -5972,12 +6261,12 @@ class MagicString {
5972
6261
  }
5973
6262
 
5974
6263
  generateMap(options) {
5975
- return new SourceMap(this.generateDecodedMap(options));
6264
+ return new SourceMap$1(this.generateDecodedMap(options));
5976
6265
  }
5977
6266
 
5978
6267
  _ensureindentStr() {
5979
6268
  if (this.indentStr === undefined) {
5980
- this.indentStr = guessIndent(this.original);
6269
+ this.indentStr = guessIndent$1(this.original);
5981
6270
  }
5982
6271
  }
5983
6272
 
@@ -5994,7 +6283,7 @@ class MagicString {
5994
6283
  indent(indentStr, options) {
5995
6284
  const pattern = /^[^\r\n]/gm;
5996
6285
 
5997
- if (isObject(indentStr)) {
6286
+ if (isObject$1(indentStr)) {
5998
6287
  options = indentStr;
5999
6288
  indentStr = undefined;
6000
6289
  }
@@ -6086,22 +6375,22 @@ class MagicString {
6086
6375
  }
6087
6376
 
6088
6377
  insertLeft(index, content) {
6089
- if (!warned.insertLeft) {
6378
+ if (!warned$1.insertLeft) {
6090
6379
  console.warn(
6091
6380
  'magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead',
6092
6381
  );
6093
- warned.insertLeft = true;
6382
+ warned$1.insertLeft = true;
6094
6383
  }
6095
6384
 
6096
6385
  return this.appendLeft(index, content);
6097
6386
  }
6098
6387
 
6099
6388
  insertRight(index, content) {
6100
- if (!warned.insertRight) {
6389
+ if (!warned$1.insertRight) {
6101
6390
  console.warn(
6102
6391
  'magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead',
6103
6392
  );
6104
- warned.insertRight = true;
6393
+ warned$1.insertRight = true;
6105
6394
  }
6106
6395
 
6107
6396
  return this.prependRight(index, content);
@@ -6174,11 +6463,11 @@ class MagicString {
6174
6463
  this._split(end);
6175
6464
 
6176
6465
  if (options === true) {
6177
- if (!warned.storeName) {
6466
+ if (!warned$1.storeName) {
6178
6467
  console.warn(
6179
6468
  'The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string',
6180
6469
  );
6181
- warned.storeName = true;
6470
+ warned$1.storeName = true;
6182
6471
  }
6183
6472
 
6184
6473
  options = { storeName: true };
@@ -6211,7 +6500,7 @@ class MagicString {
6211
6500
  first.edit(content, storeName, !overwrite);
6212
6501
  } else {
6213
6502
  // must be inserting at the end
6214
- const newChunk = new Chunk(start, end, '').edit(content, storeName);
6503
+ const newChunk = new Chunk$1(start, end, '').edit(content, storeName);
6215
6504
 
6216
6505
  // TODO last chunk in the array may not be the last chunk, if it's moved...
6217
6506
  last.next = newChunk;
@@ -6330,30 +6619,30 @@ class MagicString {
6330
6619
  }
6331
6620
 
6332
6621
  lastLine() {
6333
- let lineIndex = this.outro.lastIndexOf(n);
6622
+ let lineIndex = this.outro.lastIndexOf(n$1);
6334
6623
  if (lineIndex !== -1) return this.outro.substr(lineIndex + 1);
6335
6624
  let lineStr = this.outro;
6336
6625
  let chunk = this.lastChunk;
6337
6626
  do {
6338
6627
  if (chunk.outro.length > 0) {
6339
- lineIndex = chunk.outro.lastIndexOf(n);
6628
+ lineIndex = chunk.outro.lastIndexOf(n$1);
6340
6629
  if (lineIndex !== -1) return chunk.outro.substr(lineIndex + 1) + lineStr;
6341
6630
  lineStr = chunk.outro + lineStr;
6342
6631
  }
6343
6632
 
6344
6633
  if (chunk.content.length > 0) {
6345
- lineIndex = chunk.content.lastIndexOf(n);
6634
+ lineIndex = chunk.content.lastIndexOf(n$1);
6346
6635
  if (lineIndex !== -1) return chunk.content.substr(lineIndex + 1) + lineStr;
6347
6636
  lineStr = chunk.content + lineStr;
6348
6637
  }
6349
6638
 
6350
6639
  if (chunk.intro.length > 0) {
6351
- lineIndex = chunk.intro.lastIndexOf(n);
6640
+ lineIndex = chunk.intro.lastIndexOf(n$1);
6352
6641
  if (lineIndex !== -1) return chunk.intro.substr(lineIndex + 1) + lineStr;
6353
6642
  lineStr = chunk.intro + lineStr;
6354
6643
  }
6355
6644
  } while ((chunk = chunk.previous));
6356
- lineIndex = this.intro.lastIndexOf(n);
6645
+ lineIndex = this.intro.lastIndexOf(n$1);
6357
6646
  if (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr;
6358
6647
  return this.intro + lineStr;
6359
6648
  }
@@ -6425,19 +6714,25 @@ class MagicString {
6425
6714
  if (this.byStart[index] || this.byEnd[index]) return;
6426
6715
 
6427
6716
  let chunk = this.lastSearchedChunk;
6717
+ let previousChunk = chunk;
6428
6718
  const searchForward = index > chunk.end;
6429
6719
 
6430
6720
  while (chunk) {
6431
6721
  if (chunk.contains(index)) return this._splitChunk(chunk, index);
6432
6722
 
6433
6723
  chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];
6724
+
6725
+ // Prevent infinite loop (e.g. via empty chunks, where start === end)
6726
+ if (chunk === previousChunk) return;
6727
+
6728
+ previousChunk = chunk;
6434
6729
  }
6435
6730
  }
6436
6731
 
6437
6732
  _splitChunk(chunk, index) {
6438
6733
  if (chunk.edited && chunk.content.length) {
6439
6734
  // zero-length edited chunks are a special case (overlapping replacements)
6440
- const loc = getLocator(this.original)(index);
6735
+ const loc = getLocator$1(this.original)(index);
6441
6736
  throw new Error(
6442
6737
  `Cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`,
6443
6738
  );
@@ -6618,7 +6913,12 @@ class MagicString {
6618
6913
  const index = original.indexOf(string);
6619
6914
 
6620
6915
  if (index !== -1) {
6621
- this.overwrite(index, index + string.length, replacement);
6916
+ if (typeof replacement === 'function') {
6917
+ replacement = replacement(string, index, original);
6918
+ }
6919
+ if (string !== replacement) {
6920
+ this.overwrite(index, index + string.length, replacement);
6921
+ }
6622
6922
  }
6623
6923
 
6624
6924
  return this;
@@ -6641,7 +6941,11 @@ class MagicString {
6641
6941
  index = original.indexOf(string, index + stringLength)
6642
6942
  ) {
6643
6943
  const previous = original.slice(index, index + stringLength);
6644
- if (previous !== replacement) this.overwrite(index, index + stringLength, replacement);
6944
+ let _replacement = replacement;
6945
+ if (typeof replacement === 'function') {
6946
+ _replacement = replacement(previous, index, original);
6947
+ }
6948
+ if (previous !== _replacement) this.overwrite(index, index + stringLength, _replacement);
6645
6949
  }
6646
6950
 
6647
6951
  return this;
@@ -6660,7 +6964,7 @@ class MagicString {
6660
6964
 
6661
6965
  return this._replaceRegexp(searchValue, replacement);
6662
6966
  }
6663
- }
6967
+ };
6664
6968
 
6665
6969
  const HASH_CHARACTER_LENGTH = 16;
6666
6970
  function hashM2c2kitAssets(rootDir, cwd = "") {
@@ -6669,7 +6973,7 @@ function hashM2c2kitAssets(rootDir, cwd = "") {
6669
6973
  name: "hash-m2c2kit-assets",
6670
6974
  renderChunk: {
6671
6975
  handler(code) {
6672
- const magicString = new MagicString(code);
6976
+ const magicString = new MagicString$1(code);
6673
6977
  magicString.replace(
6674
6978
  new RegExp("__NO_M2C2KIT_MANIFEST_JSON_URL__", "g"),
6675
6979
  "manifest.json"
@@ -6874,7 +7178,7 @@ function restoreImportMeta(pattern = "import_meta = {};", replacement = "import_
6874
7178
  name: "restore-import-meta",
6875
7179
  renderChunk: {
6876
7180
  handler(code) {
6877
- const magicString = new MagicString(code);
7181
+ const magicString = new MagicString$1(code);
6878
7182
  magicString.replace(new RegExp(pattern, "g"), replacement);
6879
7183
  return {
6880
7184
  code: magicString.toString(),
@@ -22749,7 +23053,7 @@ function addModuleMetadata() {
22749
23053
  transform: {
22750
23054
  async handler(code) {
22751
23055
  const pkg = JSON.parse(await readFile("./package.json", "utf8"));
22752
- const magicString = new MagicString(code);
23056
+ const magicString = new MagicString$1(code);
22753
23057
  magicString.replace(
22754
23058
  new RegExp(
22755
23059
  "moduleMetadata:\\s*Constants.MODULE_METADATA_PLACEHOLDER",
@@ -22766,6 +23070,1280 @@ function addModuleMetadata() {
22766
23070
  };
22767
23071
  }
22768
23072
 
23073
+ class BitSet {
23074
+ constructor(arg) {
23075
+ this.bits = arg instanceof BitSet ? arg.bits.slice() : [];
23076
+ }
23077
+
23078
+ add(n) {
23079
+ this.bits[n >> 5] |= 1 << (n & 31);
23080
+ }
23081
+
23082
+ has(n) {
23083
+ return !!(this.bits[n >> 5] & (1 << (n & 31)));
23084
+ }
23085
+ }
23086
+
23087
+ class Chunk {
23088
+ constructor(start, end, content) {
23089
+ this.start = start;
23090
+ this.end = end;
23091
+ this.original = content;
23092
+
23093
+ this.intro = '';
23094
+ this.outro = '';
23095
+
23096
+ this.content = content;
23097
+ this.storeName = false;
23098
+ this.edited = false;
23099
+
23100
+ {
23101
+ this.previous = null;
23102
+ this.next = null;
23103
+ }
23104
+ }
23105
+
23106
+ appendLeft(content) {
23107
+ this.outro += content;
23108
+ }
23109
+
23110
+ appendRight(content) {
23111
+ this.intro = this.intro + content;
23112
+ }
23113
+
23114
+ clone() {
23115
+ const chunk = new Chunk(this.start, this.end, this.original);
23116
+
23117
+ chunk.intro = this.intro;
23118
+ chunk.outro = this.outro;
23119
+ chunk.content = this.content;
23120
+ chunk.storeName = this.storeName;
23121
+ chunk.edited = this.edited;
23122
+
23123
+ return chunk;
23124
+ }
23125
+
23126
+ contains(index) {
23127
+ return this.start < index && index < this.end;
23128
+ }
23129
+
23130
+ eachNext(fn) {
23131
+ let chunk = this;
23132
+ while (chunk) {
23133
+ fn(chunk);
23134
+ chunk = chunk.next;
23135
+ }
23136
+ }
23137
+
23138
+ eachPrevious(fn) {
23139
+ let chunk = this;
23140
+ while (chunk) {
23141
+ fn(chunk);
23142
+ chunk = chunk.previous;
23143
+ }
23144
+ }
23145
+
23146
+ edit(content, storeName, contentOnly) {
23147
+ this.content = content;
23148
+ if (!contentOnly) {
23149
+ this.intro = '';
23150
+ this.outro = '';
23151
+ }
23152
+ this.storeName = storeName;
23153
+
23154
+ this.edited = true;
23155
+
23156
+ return this;
23157
+ }
23158
+
23159
+ prependLeft(content) {
23160
+ this.outro = content + this.outro;
23161
+ }
23162
+
23163
+ prependRight(content) {
23164
+ this.intro = content + this.intro;
23165
+ }
23166
+
23167
+ reset() {
23168
+ this.intro = '';
23169
+ this.outro = '';
23170
+ if (this.edited) {
23171
+ this.content = this.original;
23172
+ this.storeName = false;
23173
+ this.edited = false;
23174
+ }
23175
+ }
23176
+
23177
+ split(index) {
23178
+ const sliceIndex = index - this.start;
23179
+
23180
+ const originalBefore = this.original.slice(0, sliceIndex);
23181
+ const originalAfter = this.original.slice(sliceIndex);
23182
+
23183
+ this.original = originalBefore;
23184
+
23185
+ const newChunk = new Chunk(index, this.end, originalAfter);
23186
+ newChunk.outro = this.outro;
23187
+ this.outro = '';
23188
+
23189
+ this.end = index;
23190
+
23191
+ if (this.edited) {
23192
+ // after split we should save the edit content record into the correct chunk
23193
+ // to make sure sourcemap correct
23194
+ // For example:
23195
+ // ' test'.trim()
23196
+ // split -> ' ' + 'test'
23197
+ // ✔️ edit -> '' + 'test'
23198
+ // ✖️ edit -> 'test' + ''
23199
+ // TODO is this block necessary?...
23200
+ newChunk.edit('', false);
23201
+ this.content = '';
23202
+ } else {
23203
+ this.content = originalBefore;
23204
+ }
23205
+
23206
+ newChunk.next = this.next;
23207
+ if (newChunk.next) newChunk.next.previous = newChunk;
23208
+ newChunk.previous = this;
23209
+ this.next = newChunk;
23210
+
23211
+ return newChunk;
23212
+ }
23213
+
23214
+ toString() {
23215
+ return this.intro + this.content + this.outro;
23216
+ }
23217
+
23218
+ trimEnd(rx) {
23219
+ this.outro = this.outro.replace(rx, '');
23220
+ if (this.outro.length) return true;
23221
+
23222
+ const trimmed = this.content.replace(rx, '');
23223
+
23224
+ if (trimmed.length) {
23225
+ if (trimmed !== this.content) {
23226
+ this.split(this.start + trimmed.length).edit('', undefined, true);
23227
+ if (this.edited) {
23228
+ // save the change, if it has been edited
23229
+ this.edit(trimmed, this.storeName, true);
23230
+ }
23231
+ }
23232
+ return true;
23233
+ } else {
23234
+ this.edit('', undefined, true);
23235
+
23236
+ this.intro = this.intro.replace(rx, '');
23237
+ if (this.intro.length) return true;
23238
+ }
23239
+ }
23240
+
23241
+ trimStart(rx) {
23242
+ this.intro = this.intro.replace(rx, '');
23243
+ if (this.intro.length) return true;
23244
+
23245
+ const trimmed = this.content.replace(rx, '');
23246
+
23247
+ if (trimmed.length) {
23248
+ if (trimmed !== this.content) {
23249
+ const newChunk = this.split(this.end - trimmed.length);
23250
+ if (this.edited) {
23251
+ // save the change, if it has been edited
23252
+ newChunk.edit(trimmed, this.storeName, true);
23253
+ }
23254
+ this.edit('', undefined, true);
23255
+ }
23256
+ return true;
23257
+ } else {
23258
+ this.edit('', undefined, true);
23259
+
23260
+ this.outro = this.outro.replace(rx, '');
23261
+ if (this.outro.length) return true;
23262
+ }
23263
+ }
23264
+ }
23265
+
23266
+ function getBtoa() {
23267
+ if (typeof globalThis !== 'undefined' && typeof globalThis.btoa === 'function') {
23268
+ return (str) => globalThis.btoa(unescape(encodeURIComponent(str)));
23269
+ } else if (typeof Buffer === 'function') {
23270
+ return (str) => Buffer.from(str, 'utf-8').toString('base64');
23271
+ } else {
23272
+ return () => {
23273
+ throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');
23274
+ };
23275
+ }
23276
+ }
23277
+
23278
+ const btoa = /*#__PURE__*/ getBtoa();
23279
+
23280
+ class SourceMap {
23281
+ constructor(properties) {
23282
+ this.version = 3;
23283
+ this.file = properties.file;
23284
+ this.sources = properties.sources;
23285
+ this.sourcesContent = properties.sourcesContent;
23286
+ this.names = properties.names;
23287
+ this.mappings = encode(properties.mappings);
23288
+ if (typeof properties.x_google_ignoreList !== 'undefined') {
23289
+ this.x_google_ignoreList = properties.x_google_ignoreList;
23290
+ }
23291
+ if (typeof properties.debugId !== 'undefined') {
23292
+ this.debugId = properties.debugId;
23293
+ }
23294
+ }
23295
+
23296
+ toString() {
23297
+ return JSON.stringify(this);
23298
+ }
23299
+
23300
+ toUrl() {
23301
+ return 'data:application/json;charset=utf-8;base64,' + btoa(this.toString());
23302
+ }
23303
+ }
23304
+
23305
+ function guessIndent(code) {
23306
+ const lines = code.split('\n');
23307
+
23308
+ const tabbed = lines.filter((line) => /^\t+/.test(line));
23309
+ const spaced = lines.filter((line) => /^ {2,}/.test(line));
23310
+
23311
+ if (tabbed.length === 0 && spaced.length === 0) {
23312
+ return null;
23313
+ }
23314
+
23315
+ // More lines tabbed than spaced? Assume tabs, and
23316
+ // default to tabs in the case of a tie (or nothing
23317
+ // to go on)
23318
+ if (tabbed.length >= spaced.length) {
23319
+ return '\t';
23320
+ }
23321
+
23322
+ // Otherwise, we need to guess the multiple
23323
+ const min = spaced.reduce((previous, current) => {
23324
+ const numSpaces = /^ +/.exec(current)[0].length;
23325
+ return Math.min(numSpaces, previous);
23326
+ }, Infinity);
23327
+
23328
+ return new Array(min + 1).join(' ');
23329
+ }
23330
+
23331
+ function getRelativePath(from, to) {
23332
+ const fromParts = from.split(/[/\\]/);
23333
+ const toParts = to.split(/[/\\]/);
23334
+
23335
+ fromParts.pop(); // get dirname
23336
+
23337
+ while (fromParts[0] === toParts[0]) {
23338
+ fromParts.shift();
23339
+ toParts.shift();
23340
+ }
23341
+
23342
+ if (fromParts.length) {
23343
+ let i = fromParts.length;
23344
+ while (i--) fromParts[i] = '..';
23345
+ }
23346
+
23347
+ return fromParts.concat(toParts).join('/');
23348
+ }
23349
+
23350
+ const toString = Object.prototype.toString;
23351
+
23352
+ function isObject(thing) {
23353
+ return toString.call(thing) === '[object Object]';
23354
+ }
23355
+
23356
+ function getLocator(source) {
23357
+ const originalLines = source.split('\n');
23358
+ const lineOffsets = [];
23359
+
23360
+ for (let i = 0, pos = 0; i < originalLines.length; i++) {
23361
+ lineOffsets.push(pos);
23362
+ pos += originalLines[i].length + 1;
23363
+ }
23364
+
23365
+ return function locate(index) {
23366
+ let i = 0;
23367
+ let j = lineOffsets.length;
23368
+ while (i < j) {
23369
+ const m = (i + j) >> 1;
23370
+ if (index < lineOffsets[m]) {
23371
+ j = m;
23372
+ } else {
23373
+ i = m + 1;
23374
+ }
23375
+ }
23376
+ const line = i - 1;
23377
+ const column = index - lineOffsets[line];
23378
+ return { line, column };
23379
+ };
23380
+ }
23381
+
23382
+ const wordRegex = /\w/;
23383
+
23384
+ class Mappings {
23385
+ constructor(hires) {
23386
+ this.hires = hires;
23387
+ this.generatedCodeLine = 0;
23388
+ this.generatedCodeColumn = 0;
23389
+ this.raw = [];
23390
+ this.rawSegments = this.raw[this.generatedCodeLine] = [];
23391
+ this.pending = null;
23392
+ }
23393
+
23394
+ addEdit(sourceIndex, content, loc, nameIndex) {
23395
+ if (content.length) {
23396
+ const contentLengthMinusOne = content.length - 1;
23397
+ let contentLineEnd = content.indexOf('\n', 0);
23398
+ let previousContentLineEnd = -1;
23399
+ // Loop through each line in the content and add a segment, but stop if the last line is empty,
23400
+ // else code afterwards would fill one line too many
23401
+ while (contentLineEnd >= 0 && contentLengthMinusOne > contentLineEnd) {
23402
+ const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
23403
+ if (nameIndex >= 0) {
23404
+ segment.push(nameIndex);
23405
+ }
23406
+ this.rawSegments.push(segment);
23407
+
23408
+ this.generatedCodeLine += 1;
23409
+ this.raw[this.generatedCodeLine] = this.rawSegments = [];
23410
+ this.generatedCodeColumn = 0;
23411
+
23412
+ previousContentLineEnd = contentLineEnd;
23413
+ contentLineEnd = content.indexOf('\n', contentLineEnd + 1);
23414
+ }
23415
+
23416
+ const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
23417
+ if (nameIndex >= 0) {
23418
+ segment.push(nameIndex);
23419
+ }
23420
+ this.rawSegments.push(segment);
23421
+
23422
+ this.advance(content.slice(previousContentLineEnd + 1));
23423
+ } else if (this.pending) {
23424
+ this.rawSegments.push(this.pending);
23425
+ this.advance(content);
23426
+ }
23427
+
23428
+ this.pending = null;
23429
+ }
23430
+
23431
+ addUneditedChunk(sourceIndex, chunk, original, loc, sourcemapLocations) {
23432
+ let originalCharIndex = chunk.start;
23433
+ let first = true;
23434
+ // when iterating each char, check if it's in a word boundary
23435
+ let charInHiresBoundary = false;
23436
+
23437
+ while (originalCharIndex < chunk.end) {
23438
+ if (original[originalCharIndex] === '\n') {
23439
+ loc.line += 1;
23440
+ loc.column = 0;
23441
+ this.generatedCodeLine += 1;
23442
+ this.raw[this.generatedCodeLine] = this.rawSegments = [];
23443
+ this.generatedCodeColumn = 0;
23444
+ first = true;
23445
+ charInHiresBoundary = false;
23446
+ } else {
23447
+ if (this.hires || first || sourcemapLocations.has(originalCharIndex)) {
23448
+ const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
23449
+
23450
+ if (this.hires === 'boundary') {
23451
+ // in hires "boundary", group segments per word boundary than per char
23452
+ if (wordRegex.test(original[originalCharIndex])) {
23453
+ // for first char in the boundary found, start the boundary by pushing a segment
23454
+ if (!charInHiresBoundary) {
23455
+ this.rawSegments.push(segment);
23456
+ charInHiresBoundary = true;
23457
+ }
23458
+ } else {
23459
+ // for non-word char, end the boundary by pushing a segment
23460
+ this.rawSegments.push(segment);
23461
+ charInHiresBoundary = false;
23462
+ }
23463
+ } else {
23464
+ this.rawSegments.push(segment);
23465
+ }
23466
+ }
23467
+
23468
+ loc.column += 1;
23469
+ this.generatedCodeColumn += 1;
23470
+ first = false;
23471
+ }
23472
+
23473
+ originalCharIndex += 1;
23474
+ }
23475
+
23476
+ this.pending = null;
23477
+ }
23478
+
23479
+ advance(str) {
23480
+ if (!str) return;
23481
+
23482
+ const lines = str.split('\n');
23483
+
23484
+ if (lines.length > 1) {
23485
+ for (let i = 0; i < lines.length - 1; i++) {
23486
+ this.generatedCodeLine++;
23487
+ this.raw[this.generatedCodeLine] = this.rawSegments = [];
23488
+ }
23489
+ this.generatedCodeColumn = 0;
23490
+ }
23491
+
23492
+ this.generatedCodeColumn += lines[lines.length - 1].length;
23493
+ }
23494
+ }
23495
+
23496
+ const n = '\n';
23497
+
23498
+ const warned = {
23499
+ insertLeft: false,
23500
+ insertRight: false,
23501
+ storeName: false,
23502
+ };
23503
+
23504
+ class MagicString {
23505
+ constructor(string, options = {}) {
23506
+ const chunk = new Chunk(0, string.length, string);
23507
+
23508
+ Object.defineProperties(this, {
23509
+ original: { writable: true, value: string },
23510
+ outro: { writable: true, value: '' },
23511
+ intro: { writable: true, value: '' },
23512
+ firstChunk: { writable: true, value: chunk },
23513
+ lastChunk: { writable: true, value: chunk },
23514
+ lastSearchedChunk: { writable: true, value: chunk },
23515
+ byStart: { writable: true, value: {} },
23516
+ byEnd: { writable: true, value: {} },
23517
+ filename: { writable: true, value: options.filename },
23518
+ indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
23519
+ sourcemapLocations: { writable: true, value: new BitSet() },
23520
+ storedNames: { writable: true, value: {} },
23521
+ indentStr: { writable: true, value: undefined },
23522
+ ignoreList: { writable: true, value: options.ignoreList },
23523
+ offset: { writable: true, value: options.offset || 0 },
23524
+ });
23525
+
23526
+ this.byStart[0] = chunk;
23527
+ this.byEnd[string.length] = chunk;
23528
+ }
23529
+
23530
+ addSourcemapLocation(char) {
23531
+ this.sourcemapLocations.add(char);
23532
+ }
23533
+
23534
+ append(content) {
23535
+ if (typeof content !== 'string') throw new TypeError('outro content must be a string');
23536
+
23537
+ this.outro += content;
23538
+ return this;
23539
+ }
23540
+
23541
+ appendLeft(index, content) {
23542
+ index = index + this.offset;
23543
+
23544
+ if (typeof content !== 'string') throw new TypeError('inserted content must be a string');
23545
+
23546
+ this._split(index);
23547
+
23548
+ const chunk = this.byEnd[index];
23549
+
23550
+ if (chunk) {
23551
+ chunk.appendLeft(content);
23552
+ } else {
23553
+ this.intro += content;
23554
+ }
23555
+ return this;
23556
+ }
23557
+
23558
+ appendRight(index, content) {
23559
+ index = index + this.offset;
23560
+
23561
+ if (typeof content !== 'string') throw new TypeError('inserted content must be a string');
23562
+
23563
+ this._split(index);
23564
+
23565
+ const chunk = this.byStart[index];
23566
+
23567
+ if (chunk) {
23568
+ chunk.appendRight(content);
23569
+ } else {
23570
+ this.outro += content;
23571
+ }
23572
+ return this;
23573
+ }
23574
+
23575
+ clone() {
23576
+ const cloned = new MagicString(this.original, { filename: this.filename, offset: this.offset });
23577
+
23578
+ let originalChunk = this.firstChunk;
23579
+ let clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());
23580
+
23581
+ while (originalChunk) {
23582
+ cloned.byStart[clonedChunk.start] = clonedChunk;
23583
+ cloned.byEnd[clonedChunk.end] = clonedChunk;
23584
+
23585
+ const nextOriginalChunk = originalChunk.next;
23586
+ const nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
23587
+
23588
+ if (nextClonedChunk) {
23589
+ clonedChunk.next = nextClonedChunk;
23590
+ nextClonedChunk.previous = clonedChunk;
23591
+
23592
+ clonedChunk = nextClonedChunk;
23593
+ }
23594
+
23595
+ originalChunk = nextOriginalChunk;
23596
+ }
23597
+
23598
+ cloned.lastChunk = clonedChunk;
23599
+
23600
+ if (this.indentExclusionRanges) {
23601
+ cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
23602
+ }
23603
+
23604
+ cloned.sourcemapLocations = new BitSet(this.sourcemapLocations);
23605
+
23606
+ cloned.intro = this.intro;
23607
+ cloned.outro = this.outro;
23608
+
23609
+ return cloned;
23610
+ }
23611
+
23612
+ generateDecodedMap(options) {
23613
+ options = options || {};
23614
+
23615
+ const sourceIndex = 0;
23616
+ const names = Object.keys(this.storedNames);
23617
+ const mappings = new Mappings(options.hires);
23618
+
23619
+ const locate = getLocator(this.original);
23620
+
23621
+ if (this.intro) {
23622
+ mappings.advance(this.intro);
23623
+ }
23624
+
23625
+ this.firstChunk.eachNext((chunk) => {
23626
+ const loc = locate(chunk.start);
23627
+
23628
+ if (chunk.intro.length) mappings.advance(chunk.intro);
23629
+
23630
+ if (chunk.edited) {
23631
+ mappings.addEdit(
23632
+ sourceIndex,
23633
+ chunk.content,
23634
+ loc,
23635
+ chunk.storeName ? names.indexOf(chunk.original) : -1,
23636
+ );
23637
+ } else {
23638
+ mappings.addUneditedChunk(sourceIndex, chunk, this.original, loc, this.sourcemapLocations);
23639
+ }
23640
+
23641
+ if (chunk.outro.length) mappings.advance(chunk.outro);
23642
+ });
23643
+
23644
+ return {
23645
+ file: options.file ? options.file.split(/[/\\]/).pop() : undefined,
23646
+ sources: [
23647
+ options.source ? getRelativePath(options.file || '', options.source) : options.file || '',
23648
+ ],
23649
+ sourcesContent: options.includeContent ? [this.original] : undefined,
23650
+ names,
23651
+ mappings: mappings.raw,
23652
+ x_google_ignoreList: this.ignoreList ? [sourceIndex] : undefined,
23653
+ };
23654
+ }
23655
+
23656
+ generateMap(options) {
23657
+ return new SourceMap(this.generateDecodedMap(options));
23658
+ }
23659
+
23660
+ _ensureindentStr() {
23661
+ if (this.indentStr === undefined) {
23662
+ this.indentStr = guessIndent(this.original);
23663
+ }
23664
+ }
23665
+
23666
+ _getRawIndentString() {
23667
+ this._ensureindentStr();
23668
+ return this.indentStr;
23669
+ }
23670
+
23671
+ getIndentString() {
23672
+ this._ensureindentStr();
23673
+ return this.indentStr === null ? '\t' : this.indentStr;
23674
+ }
23675
+
23676
+ indent(indentStr, options) {
23677
+ const pattern = /^[^\r\n]/gm;
23678
+
23679
+ if (isObject(indentStr)) {
23680
+ options = indentStr;
23681
+ indentStr = undefined;
23682
+ }
23683
+
23684
+ if (indentStr === undefined) {
23685
+ this._ensureindentStr();
23686
+ indentStr = this.indentStr || '\t';
23687
+ }
23688
+
23689
+ if (indentStr === '') return this; // noop
23690
+
23691
+ options = options || {};
23692
+
23693
+ // Process exclusion ranges
23694
+ const isExcluded = {};
23695
+
23696
+ if (options.exclude) {
23697
+ const exclusions =
23698
+ typeof options.exclude[0] === 'number' ? [options.exclude] : options.exclude;
23699
+ exclusions.forEach((exclusion) => {
23700
+ for (let i = exclusion[0]; i < exclusion[1]; i += 1) {
23701
+ isExcluded[i] = true;
23702
+ }
23703
+ });
23704
+ }
23705
+
23706
+ let shouldIndentNextCharacter = options.indentStart !== false;
23707
+ const replacer = (match) => {
23708
+ if (shouldIndentNextCharacter) return `${indentStr}${match}`;
23709
+ shouldIndentNextCharacter = true;
23710
+ return match;
23711
+ };
23712
+
23713
+ this.intro = this.intro.replace(pattern, replacer);
23714
+
23715
+ let charIndex = 0;
23716
+ let chunk = this.firstChunk;
23717
+
23718
+ while (chunk) {
23719
+ const end = chunk.end;
23720
+
23721
+ if (chunk.edited) {
23722
+ if (!isExcluded[charIndex]) {
23723
+ chunk.content = chunk.content.replace(pattern, replacer);
23724
+
23725
+ if (chunk.content.length) {
23726
+ shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === '\n';
23727
+ }
23728
+ }
23729
+ } else {
23730
+ charIndex = chunk.start;
23731
+
23732
+ while (charIndex < end) {
23733
+ if (!isExcluded[charIndex]) {
23734
+ const char = this.original[charIndex];
23735
+
23736
+ if (char === '\n') {
23737
+ shouldIndentNextCharacter = true;
23738
+ } else if (char !== '\r' && shouldIndentNextCharacter) {
23739
+ shouldIndentNextCharacter = false;
23740
+
23741
+ if (charIndex === chunk.start) {
23742
+ chunk.prependRight(indentStr);
23743
+ } else {
23744
+ this._splitChunk(chunk, charIndex);
23745
+ chunk = chunk.next;
23746
+ chunk.prependRight(indentStr);
23747
+ }
23748
+ }
23749
+ }
23750
+
23751
+ charIndex += 1;
23752
+ }
23753
+ }
23754
+
23755
+ charIndex = chunk.end;
23756
+ chunk = chunk.next;
23757
+ }
23758
+
23759
+ this.outro = this.outro.replace(pattern, replacer);
23760
+
23761
+ return this;
23762
+ }
23763
+
23764
+ insert() {
23765
+ throw new Error(
23766
+ 'magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)',
23767
+ );
23768
+ }
23769
+
23770
+ insertLeft(index, content) {
23771
+ if (!warned.insertLeft) {
23772
+ console.warn(
23773
+ 'magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead',
23774
+ );
23775
+ warned.insertLeft = true;
23776
+ }
23777
+
23778
+ return this.appendLeft(index, content);
23779
+ }
23780
+
23781
+ insertRight(index, content) {
23782
+ if (!warned.insertRight) {
23783
+ console.warn(
23784
+ 'magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead',
23785
+ );
23786
+ warned.insertRight = true;
23787
+ }
23788
+
23789
+ return this.prependRight(index, content);
23790
+ }
23791
+
23792
+ move(start, end, index) {
23793
+ start = start + this.offset;
23794
+ end = end + this.offset;
23795
+ index = index + this.offset;
23796
+
23797
+ if (index >= start && index <= end) throw new Error('Cannot move a selection inside itself');
23798
+
23799
+ this._split(start);
23800
+ this._split(end);
23801
+ this._split(index);
23802
+
23803
+ const first = this.byStart[start];
23804
+ const last = this.byEnd[end];
23805
+
23806
+ const oldLeft = first.previous;
23807
+ const oldRight = last.next;
23808
+
23809
+ const newRight = this.byStart[index];
23810
+ if (!newRight && last === this.lastChunk) return this;
23811
+ const newLeft = newRight ? newRight.previous : this.lastChunk;
23812
+
23813
+ if (oldLeft) oldLeft.next = oldRight;
23814
+ if (oldRight) oldRight.previous = oldLeft;
23815
+
23816
+ if (newLeft) newLeft.next = first;
23817
+ if (newRight) newRight.previous = last;
23818
+
23819
+ if (!first.previous) this.firstChunk = last.next;
23820
+ if (!last.next) {
23821
+ this.lastChunk = first.previous;
23822
+ this.lastChunk.next = null;
23823
+ }
23824
+
23825
+ first.previous = newLeft;
23826
+ last.next = newRight || null;
23827
+
23828
+ if (!newLeft) this.firstChunk = first;
23829
+ if (!newRight) this.lastChunk = last;
23830
+ return this;
23831
+ }
23832
+
23833
+ overwrite(start, end, content, options) {
23834
+ options = options || {};
23835
+ return this.update(start, end, content, { ...options, overwrite: !options.contentOnly });
23836
+ }
23837
+
23838
+ update(start, end, content, options) {
23839
+ start = start + this.offset;
23840
+ end = end + this.offset;
23841
+
23842
+ if (typeof content !== 'string') throw new TypeError('replacement content must be a string');
23843
+
23844
+ if (this.original.length !== 0) {
23845
+ while (start < 0) start += this.original.length;
23846
+ while (end < 0) end += this.original.length;
23847
+ }
23848
+
23849
+ if (end > this.original.length) throw new Error('end is out of bounds');
23850
+ if (start === end)
23851
+ throw new Error(
23852
+ 'Cannot overwrite a zero-length range – use appendLeft or prependRight instead',
23853
+ );
23854
+
23855
+ this._split(start);
23856
+ this._split(end);
23857
+
23858
+ if (options === true) {
23859
+ if (!warned.storeName) {
23860
+ console.warn(
23861
+ 'The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string',
23862
+ );
23863
+ warned.storeName = true;
23864
+ }
23865
+
23866
+ options = { storeName: true };
23867
+ }
23868
+ const storeName = options !== undefined ? options.storeName : false;
23869
+ const overwrite = options !== undefined ? options.overwrite : false;
23870
+
23871
+ if (storeName) {
23872
+ const original = this.original.slice(start, end);
23873
+ Object.defineProperty(this.storedNames, original, {
23874
+ writable: true,
23875
+ value: true,
23876
+ enumerable: true,
23877
+ });
23878
+ }
23879
+
23880
+ const first = this.byStart[start];
23881
+ const last = this.byEnd[end];
23882
+
23883
+ if (first) {
23884
+ let chunk = first;
23885
+ while (chunk !== last) {
23886
+ if (chunk.next !== this.byStart[chunk.end]) {
23887
+ throw new Error('Cannot overwrite across a split point');
23888
+ }
23889
+ chunk = chunk.next;
23890
+ chunk.edit('', false);
23891
+ }
23892
+
23893
+ first.edit(content, storeName, !overwrite);
23894
+ } else {
23895
+ // must be inserting at the end
23896
+ const newChunk = new Chunk(start, end, '').edit(content, storeName);
23897
+
23898
+ // TODO last chunk in the array may not be the last chunk, if it's moved...
23899
+ last.next = newChunk;
23900
+ newChunk.previous = last;
23901
+ }
23902
+ return this;
23903
+ }
23904
+
23905
+ prepend(content) {
23906
+ if (typeof content !== 'string') throw new TypeError('outro content must be a string');
23907
+
23908
+ this.intro = content + this.intro;
23909
+ return this;
23910
+ }
23911
+
23912
+ prependLeft(index, content) {
23913
+ index = index + this.offset;
23914
+
23915
+ if (typeof content !== 'string') throw new TypeError('inserted content must be a string');
23916
+
23917
+ this._split(index);
23918
+
23919
+ const chunk = this.byEnd[index];
23920
+
23921
+ if (chunk) {
23922
+ chunk.prependLeft(content);
23923
+ } else {
23924
+ this.intro = content + this.intro;
23925
+ }
23926
+ return this;
23927
+ }
23928
+
23929
+ prependRight(index, content) {
23930
+ index = index + this.offset;
23931
+
23932
+ if (typeof content !== 'string') throw new TypeError('inserted content must be a string');
23933
+
23934
+ this._split(index);
23935
+
23936
+ const chunk = this.byStart[index];
23937
+
23938
+ if (chunk) {
23939
+ chunk.prependRight(content);
23940
+ } else {
23941
+ this.outro = content + this.outro;
23942
+ }
23943
+ return this;
23944
+ }
23945
+
23946
+ remove(start, end) {
23947
+ start = start + this.offset;
23948
+ end = end + this.offset;
23949
+
23950
+ if (this.original.length !== 0) {
23951
+ while (start < 0) start += this.original.length;
23952
+ while (end < 0) end += this.original.length;
23953
+ }
23954
+
23955
+ if (start === end) return this;
23956
+
23957
+ if (start < 0 || end > this.original.length) throw new Error('Character is out of bounds');
23958
+ if (start > end) throw new Error('end must be greater than start');
23959
+
23960
+ this._split(start);
23961
+ this._split(end);
23962
+
23963
+ let chunk = this.byStart[start];
23964
+
23965
+ while (chunk) {
23966
+ chunk.intro = '';
23967
+ chunk.outro = '';
23968
+ chunk.edit('');
23969
+
23970
+ chunk = end > chunk.end ? this.byStart[chunk.end] : null;
23971
+ }
23972
+ return this;
23973
+ }
23974
+
23975
+ reset(start, end) {
23976
+ start = start + this.offset;
23977
+ end = end + this.offset;
23978
+
23979
+ if (this.original.length !== 0) {
23980
+ while (start < 0) start += this.original.length;
23981
+ while (end < 0) end += this.original.length;
23982
+ }
23983
+
23984
+ if (start === end) return this;
23985
+
23986
+ if (start < 0 || end > this.original.length) throw new Error('Character is out of bounds');
23987
+ if (start > end) throw new Error('end must be greater than start');
23988
+
23989
+ this._split(start);
23990
+ this._split(end);
23991
+
23992
+ let chunk = this.byStart[start];
23993
+
23994
+ while (chunk) {
23995
+ chunk.reset();
23996
+
23997
+ chunk = end > chunk.end ? this.byStart[chunk.end] : null;
23998
+ }
23999
+ return this;
24000
+ }
24001
+
24002
+ lastChar() {
24003
+ if (this.outro.length) return this.outro[this.outro.length - 1];
24004
+ let chunk = this.lastChunk;
24005
+ do {
24006
+ if (chunk.outro.length) return chunk.outro[chunk.outro.length - 1];
24007
+ if (chunk.content.length) return chunk.content[chunk.content.length - 1];
24008
+ if (chunk.intro.length) return chunk.intro[chunk.intro.length - 1];
24009
+ } while ((chunk = chunk.previous));
24010
+ if (this.intro.length) return this.intro[this.intro.length - 1];
24011
+ return '';
24012
+ }
24013
+
24014
+ lastLine() {
24015
+ let lineIndex = this.outro.lastIndexOf(n);
24016
+ if (lineIndex !== -1) return this.outro.substr(lineIndex + 1);
24017
+ let lineStr = this.outro;
24018
+ let chunk = this.lastChunk;
24019
+ do {
24020
+ if (chunk.outro.length > 0) {
24021
+ lineIndex = chunk.outro.lastIndexOf(n);
24022
+ if (lineIndex !== -1) return chunk.outro.substr(lineIndex + 1) + lineStr;
24023
+ lineStr = chunk.outro + lineStr;
24024
+ }
24025
+
24026
+ if (chunk.content.length > 0) {
24027
+ lineIndex = chunk.content.lastIndexOf(n);
24028
+ if (lineIndex !== -1) return chunk.content.substr(lineIndex + 1) + lineStr;
24029
+ lineStr = chunk.content + lineStr;
24030
+ }
24031
+
24032
+ if (chunk.intro.length > 0) {
24033
+ lineIndex = chunk.intro.lastIndexOf(n);
24034
+ if (lineIndex !== -1) return chunk.intro.substr(lineIndex + 1) + lineStr;
24035
+ lineStr = chunk.intro + lineStr;
24036
+ }
24037
+ } while ((chunk = chunk.previous));
24038
+ lineIndex = this.intro.lastIndexOf(n);
24039
+ if (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr;
24040
+ return this.intro + lineStr;
24041
+ }
24042
+
24043
+ slice(start = 0, end = this.original.length - this.offset) {
24044
+ start = start + this.offset;
24045
+ end = end + this.offset;
24046
+
24047
+ if (this.original.length !== 0) {
24048
+ while (start < 0) start += this.original.length;
24049
+ while (end < 0) end += this.original.length;
24050
+ }
24051
+
24052
+ let result = '';
24053
+
24054
+ // find start chunk
24055
+ let chunk = this.firstChunk;
24056
+ while (chunk && (chunk.start > start || chunk.end <= start)) {
24057
+ // found end chunk before start
24058
+ if (chunk.start < end && chunk.end >= end) {
24059
+ return result;
24060
+ }
24061
+
24062
+ chunk = chunk.next;
24063
+ }
24064
+
24065
+ if (chunk && chunk.edited && chunk.start !== start)
24066
+ throw new Error(`Cannot use replaced character ${start} as slice start anchor.`);
24067
+
24068
+ const startChunk = chunk;
24069
+ while (chunk) {
24070
+ if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {
24071
+ result += chunk.intro;
24072
+ }
24073
+
24074
+ const containsEnd = chunk.start < end && chunk.end >= end;
24075
+ if (containsEnd && chunk.edited && chunk.end !== end)
24076
+ throw new Error(`Cannot use replaced character ${end} as slice end anchor.`);
24077
+
24078
+ const sliceStart = startChunk === chunk ? start - chunk.start : 0;
24079
+ const sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
24080
+
24081
+ result += chunk.content.slice(sliceStart, sliceEnd);
24082
+
24083
+ if (chunk.outro && (!containsEnd || chunk.end === end)) {
24084
+ result += chunk.outro;
24085
+ }
24086
+
24087
+ if (containsEnd) {
24088
+ break;
24089
+ }
24090
+
24091
+ chunk = chunk.next;
24092
+ }
24093
+
24094
+ return result;
24095
+ }
24096
+
24097
+ // TODO deprecate this? not really very useful
24098
+ snip(start, end) {
24099
+ const clone = this.clone();
24100
+ clone.remove(0, start);
24101
+ clone.remove(end, clone.original.length);
24102
+
24103
+ return clone;
24104
+ }
24105
+
24106
+ _split(index) {
24107
+ if (this.byStart[index] || this.byEnd[index]) return;
24108
+
24109
+ let chunk = this.lastSearchedChunk;
24110
+ const searchForward = index > chunk.end;
24111
+
24112
+ while (chunk) {
24113
+ if (chunk.contains(index)) return this._splitChunk(chunk, index);
24114
+
24115
+ chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];
24116
+ }
24117
+ }
24118
+
24119
+ _splitChunk(chunk, index) {
24120
+ if (chunk.edited && chunk.content.length) {
24121
+ // zero-length edited chunks are a special case (overlapping replacements)
24122
+ const loc = getLocator(this.original)(index);
24123
+ throw new Error(
24124
+ `Cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`,
24125
+ );
24126
+ }
24127
+
24128
+ const newChunk = chunk.split(index);
24129
+
24130
+ this.byEnd[index] = chunk;
24131
+ this.byStart[index] = newChunk;
24132
+ this.byEnd[newChunk.end] = newChunk;
24133
+
24134
+ if (chunk === this.lastChunk) this.lastChunk = newChunk;
24135
+
24136
+ this.lastSearchedChunk = chunk;
24137
+ return true;
24138
+ }
24139
+
24140
+ toString() {
24141
+ let str = this.intro;
24142
+
24143
+ let chunk = this.firstChunk;
24144
+ while (chunk) {
24145
+ str += chunk.toString();
24146
+ chunk = chunk.next;
24147
+ }
24148
+
24149
+ return str + this.outro;
24150
+ }
24151
+
24152
+ isEmpty() {
24153
+ let chunk = this.firstChunk;
24154
+ do {
24155
+ if (
24156
+ (chunk.intro.length && chunk.intro.trim()) ||
24157
+ (chunk.content.length && chunk.content.trim()) ||
24158
+ (chunk.outro.length && chunk.outro.trim())
24159
+ )
24160
+ return false;
24161
+ } while ((chunk = chunk.next));
24162
+ return true;
24163
+ }
24164
+
24165
+ length() {
24166
+ let chunk = this.firstChunk;
24167
+ let length = 0;
24168
+ do {
24169
+ length += chunk.intro.length + chunk.content.length + chunk.outro.length;
24170
+ } while ((chunk = chunk.next));
24171
+ return length;
24172
+ }
24173
+
24174
+ trimLines() {
24175
+ return this.trim('[\\r\\n]');
24176
+ }
24177
+
24178
+ trim(charType) {
24179
+ return this.trimStart(charType).trimEnd(charType);
24180
+ }
24181
+
24182
+ trimEndAborted(charType) {
24183
+ const rx = new RegExp((charType || '\\s') + '+$');
24184
+
24185
+ this.outro = this.outro.replace(rx, '');
24186
+ if (this.outro.length) return true;
24187
+
24188
+ let chunk = this.lastChunk;
24189
+
24190
+ do {
24191
+ const end = chunk.end;
24192
+ const aborted = chunk.trimEnd(rx);
24193
+
24194
+ // if chunk was trimmed, we have a new lastChunk
24195
+ if (chunk.end !== end) {
24196
+ if (this.lastChunk === chunk) {
24197
+ this.lastChunk = chunk.next;
24198
+ }
24199
+
24200
+ this.byEnd[chunk.end] = chunk;
24201
+ this.byStart[chunk.next.start] = chunk.next;
24202
+ this.byEnd[chunk.next.end] = chunk.next;
24203
+ }
24204
+
24205
+ if (aborted) return true;
24206
+ chunk = chunk.previous;
24207
+ } while (chunk);
24208
+
24209
+ return false;
24210
+ }
24211
+
24212
+ trimEnd(charType) {
24213
+ this.trimEndAborted(charType);
24214
+ return this;
24215
+ }
24216
+ trimStartAborted(charType) {
24217
+ const rx = new RegExp('^' + (charType || '\\s') + '+');
24218
+
24219
+ this.intro = this.intro.replace(rx, '');
24220
+ if (this.intro.length) return true;
24221
+
24222
+ let chunk = this.firstChunk;
24223
+
24224
+ do {
24225
+ const end = chunk.end;
24226
+ const aborted = chunk.trimStart(rx);
24227
+
24228
+ if (chunk.end !== end) {
24229
+ // special case...
24230
+ if (chunk === this.lastChunk) this.lastChunk = chunk.next;
24231
+
24232
+ this.byEnd[chunk.end] = chunk;
24233
+ this.byStart[chunk.next.start] = chunk.next;
24234
+ this.byEnd[chunk.next.end] = chunk.next;
24235
+ }
24236
+
24237
+ if (aborted) return true;
24238
+ chunk = chunk.next;
24239
+ } while (chunk);
24240
+
24241
+ return false;
24242
+ }
24243
+
24244
+ trimStart(charType) {
24245
+ this.trimStartAborted(charType);
24246
+ return this;
24247
+ }
24248
+
24249
+ hasChanged() {
24250
+ return this.original !== this.toString();
24251
+ }
24252
+
24253
+ _replaceRegexp(searchValue, replacement) {
24254
+ function getReplacement(match, str) {
24255
+ if (typeof replacement === 'string') {
24256
+ return replacement.replace(/\$(\$|&|\d+)/g, (_, i) => {
24257
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_a_parameter
24258
+ if (i === '$') return '$';
24259
+ if (i === '&') return match[0];
24260
+ const num = +i;
24261
+ if (num < match.length) return match[+i];
24262
+ return `$${i}`;
24263
+ });
24264
+ } else {
24265
+ return replacement(...match, match.index, str, match.groups);
24266
+ }
24267
+ }
24268
+ function matchAll(re, str) {
24269
+ let match;
24270
+ const matches = [];
24271
+ while ((match = re.exec(str))) {
24272
+ matches.push(match);
24273
+ }
24274
+ return matches;
24275
+ }
24276
+ if (searchValue.global) {
24277
+ const matches = matchAll(searchValue, this.original);
24278
+ matches.forEach((match) => {
24279
+ if (match.index != null) {
24280
+ const replacement = getReplacement(match, this.original);
24281
+ if (replacement !== match[0]) {
24282
+ this.overwrite(match.index, match.index + match[0].length, replacement);
24283
+ }
24284
+ }
24285
+ });
24286
+ } else {
24287
+ const match = this.original.match(searchValue);
24288
+ if (match && match.index != null) {
24289
+ const replacement = getReplacement(match, this.original);
24290
+ if (replacement !== match[0]) {
24291
+ this.overwrite(match.index, match.index + match[0].length, replacement);
24292
+ }
24293
+ }
24294
+ }
24295
+ return this;
24296
+ }
24297
+
24298
+ _replaceString(string, replacement) {
24299
+ const { original } = this;
24300
+ const index = original.indexOf(string);
24301
+
24302
+ if (index !== -1) {
24303
+ this.overwrite(index, index + string.length, replacement);
24304
+ }
24305
+
24306
+ return this;
24307
+ }
24308
+
24309
+ replace(searchValue, replacement) {
24310
+ if (typeof searchValue === 'string') {
24311
+ return this._replaceString(searchValue, replacement);
24312
+ }
24313
+
24314
+ return this._replaceRegexp(searchValue, replacement);
24315
+ }
24316
+
24317
+ _replaceAllString(string, replacement) {
24318
+ const { original } = this;
24319
+ const stringLength = string.length;
24320
+ for (
24321
+ let index = original.indexOf(string);
24322
+ index !== -1;
24323
+ index = original.indexOf(string, index + stringLength)
24324
+ ) {
24325
+ const previous = original.slice(index, index + stringLength);
24326
+ if (previous !== replacement) this.overwrite(index, index + stringLength, replacement);
24327
+ }
24328
+
24329
+ return this;
24330
+ }
24331
+
24332
+ replaceAll(searchValue, replacement) {
24333
+ if (typeof searchValue === 'string') {
24334
+ return this._replaceAllString(searchValue, replacement);
24335
+ }
24336
+
24337
+ if (!searchValue.global) {
24338
+ throw new TypeError(
24339
+ 'MagicString.prototype.replaceAll called with a non-global RegExp argument',
24340
+ );
24341
+ }
24342
+
24343
+ return this._replaceRegexp(searchValue, replacement);
24344
+ }
24345
+ }
24346
+
22769
24347
  var utils = {};
22770
24348
 
22771
24349
  var constants;