@jobber/components 6.100.0 → 6.101.0

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.
@@ -8,7 +8,7 @@ var Content = require('./Content-cjs.js');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
9
  var _commonjsHelpers = require('./_commonjsHelpers-cjs.js');
10
10
 
11
- function ok$1() {}
11
+ function ok$2() {}
12
12
 
13
13
  function unreachable() {}
14
14
 
@@ -33,7 +33,7 @@ function unreachable() {}
33
33
  * Comma-separated tokens.
34
34
  */
35
35
  function stringify$1(values, options) {
36
- const settings = options || {};
36
+ const settings = {};
37
37
 
38
38
  // Ensure the last empty entry is seen.
39
39
  const input = values[values.length - 1] === '' ? [...values, ''] : values;
@@ -71,7 +71,7 @@ const emptyOptions$2 = {};
71
71
  * Whether `name` can be an identifier.
72
72
  */
73
73
  function name(name, options) {
74
- const settings = options || emptyOptions$2;
74
+ const settings = emptyOptions$2;
75
75
  const re = settings.jsx ? nameReJsx : nameRe;
76
76
  return re.test(name)
77
77
  }
@@ -98,16 +98,16 @@ const re = /[ \t\n\f\r]/g;
98
98
  function whitespace(thing) {
99
99
  return typeof thing === 'object'
100
100
  ? thing.type === 'text'
101
- ? empty$1(thing.value)
101
+ ? empty$2(thing.value)
102
102
  : false
103
- : empty$1(thing)
103
+ : empty$2(thing)
104
104
  }
105
105
 
106
106
  /**
107
107
  * @param {string} value
108
108
  * @returns {boolean}
109
109
  */
110
- function empty$1(value) {
110
+ function empty$2(value) {
111
111
  return value.replace(re, '') === ''
112
112
  }
113
113
 
@@ -170,7 +170,7 @@ function merge(definitions, space) {
170
170
  * @param {string} value
171
171
  * @returns {string}
172
172
  */
173
- function normalize$2(value) {
173
+ function normalize$1(value) {
174
174
  return value.toLowerCase()
175
175
  }
176
176
 
@@ -315,8 +315,8 @@ function create(definition) {
315
315
 
316
316
  property[prop] = info;
317
317
 
318
- normal[normalize$2(prop)] = prop;
319
- normal[normalize$2(info.attribute)] = prop;
318
+ normal[normalize$1(prop)] = prop;
319
+ normal[normalize$1(info.attribute)] = prop;
320
320
  }
321
321
  }
322
322
 
@@ -1314,7 +1314,7 @@ const cap$1 = /[A-Z]/g;
1314
1314
  * @returns {Info}
1315
1315
  */
1316
1316
  function find(schema, value) {
1317
- const normal = normalize$2(value);
1317
+ const normal = normalize$1(value);
1318
1318
  let prop = value;
1319
1319
  let Type = Info;
1320
1320
 
@@ -1758,7 +1758,7 @@ var styleToObject = _default.default || _default;
1758
1758
  * @returns
1759
1759
  * Point.
1760
1760
  */
1761
- const pointEnd = point$5('end');
1761
+ const pointEnd = point$3('end');
1762
1762
 
1763
1763
  /**
1764
1764
  * Get the starting point of `node`.
@@ -1768,7 +1768,7 @@ const pointEnd = point$5('end');
1768
1768
  * @returns
1769
1769
  * Point.
1770
1770
  */
1771
- const pointStart = point$5('start');
1771
+ const pointStart = point$3('start');
1772
1772
 
1773
1773
  /**
1774
1774
  * Get the positional info of `node`.
@@ -1778,7 +1778,7 @@ const pointStart = point$5('start');
1778
1778
  * @returns
1779
1779
  * Getter.
1780
1780
  */
1781
- function point$5(type) {
1781
+ function point$3(type) {
1782
1782
  return point
1783
1783
 
1784
1784
  /**
@@ -1816,7 +1816,7 @@ function point$5(type) {
1816
1816
  * @returns {Position | undefined}
1817
1817
  * Position.
1818
1818
  */
1819
- function position$4(node) {
1819
+ function position$2(node) {
1820
1820
  const start = pointStart(node);
1821
1821
  const end = pointEnd(node);
1822
1822
 
@@ -1861,7 +1861,7 @@ function position$4(node) {
1861
1861
  * An empty string (`''`) is returned if the given value is neither `node`,
1862
1862
  * `position`, nor `point`.
1863
1863
  */
1864
- function stringifyPosition$3(value) {
1864
+ function stringifyPosition$1(value) {
1865
1865
  // Nothing.
1866
1866
  if (!value || typeof value !== 'object') {
1867
1867
  return ''
@@ -1869,17 +1869,17 @@ function stringifyPosition$3(value) {
1869
1869
 
1870
1870
  // Node.
1871
1871
  if ('position' in value || 'type' in value) {
1872
- return position$3(value.position)
1872
+ return position$1(value.position)
1873
1873
  }
1874
1874
 
1875
1875
  // Position.
1876
1876
  if ('start' in value || 'end' in value) {
1877
- return position$3(value)
1877
+ return position$1(value)
1878
1878
  }
1879
1879
 
1880
1880
  // Point.
1881
1881
  if ('line' in value || 'column' in value) {
1882
- return point$4(value)
1882
+ return point$2(value)
1883
1883
  }
1884
1884
 
1885
1885
  // ?
@@ -1890,23 +1890,23 @@ function stringifyPosition$3(value) {
1890
1890
  * @param {Point | PointLike | null | undefined} point
1891
1891
  * @returns {string}
1892
1892
  */
1893
- function point$4(point) {
1894
- return index$3(point && point.line) + ':' + index$3(point && point.column)
1893
+ function point$2(point) {
1894
+ return index$1(point && point.line) + ':' + index$1(point && point.column)
1895
1895
  }
1896
1896
 
1897
1897
  /**
1898
1898
  * @param {Position | PositionLike | null | undefined} pos
1899
1899
  * @returns {string}
1900
1900
  */
1901
- function position$3(pos) {
1902
- return point$4(pos && pos.start) + '-' + point$4(pos && pos.end)
1901
+ function position$1(pos) {
1902
+ return point$2(pos && pos.start) + '-' + point$2(pos && pos.end)
1903
1903
  }
1904
1904
 
1905
1905
  /**
1906
1906
  * @param {number | null | undefined} value
1907
1907
  * @returns {number}
1908
1908
  */
1909
- function index$3(value) {
1909
+ function index$1(value) {
1910
1910
  return value && typeof value === 'number' ? value : 1
1911
1911
  }
1912
1912
 
@@ -1920,7 +1920,7 @@ function index$3(value) {
1920
1920
  /**
1921
1921
  * Message.
1922
1922
  */
1923
- let VFileMessage$2 = class VFileMessage extends Error {
1923
+ let VFileMessage$1 = class VFileMessage extends Error {
1924
1924
  /**
1925
1925
  * Create a message for `reason`.
1926
1926
  *
@@ -2114,7 +2114,7 @@ let VFileMessage$2 = class VFileMessage extends Error {
2114
2114
  * On normal errors, this would be something like `ParseError`, buit in
2115
2115
  * `VFile` messages we use this space to show where an error happened.
2116
2116
  */
2117
- this.name = stringifyPosition$3(options.place) || '1:1';
2117
+ this.name = stringifyPosition$1(options.place) || '1:1';
2118
2118
 
2119
2119
  /**
2120
2120
  * Place of message.
@@ -2197,19 +2197,19 @@ let VFileMessage$2 = class VFileMessage extends Error {
2197
2197
  }
2198
2198
  };
2199
2199
 
2200
- VFileMessage$2.prototype.file = '';
2201
- VFileMessage$2.prototype.name = '';
2202
- VFileMessage$2.prototype.reason = '';
2203
- VFileMessage$2.prototype.message = '';
2204
- VFileMessage$2.prototype.stack = '';
2205
- VFileMessage$2.prototype.column = undefined;
2206
- VFileMessage$2.prototype.line = undefined;
2207
- VFileMessage$2.prototype.ancestors = undefined;
2208
- VFileMessage$2.prototype.cause = undefined;
2209
- VFileMessage$2.prototype.fatal = undefined;
2210
- VFileMessage$2.prototype.place = undefined;
2211
- VFileMessage$2.prototype.ruleId = undefined;
2212
- VFileMessage$2.prototype.source = undefined;
2200
+ VFileMessage$1.prototype.file = '';
2201
+ VFileMessage$1.prototype.name = '';
2202
+ VFileMessage$1.prototype.reason = '';
2203
+ VFileMessage$1.prototype.message = '';
2204
+ VFileMessage$1.prototype.stack = '';
2205
+ VFileMessage$1.prototype.column = undefined;
2206
+ VFileMessage$1.prototype.line = undefined;
2207
+ VFileMessage$1.prototype.ancestors = undefined;
2208
+ VFileMessage$1.prototype.cause = undefined;
2209
+ VFileMessage$1.prototype.fatal = undefined;
2210
+ VFileMessage$1.prototype.place = undefined;
2211
+ VFileMessage$1.prototype.ruleId = undefined;
2212
+ VFileMessage$1.prototype.source = undefined;
2213
2213
 
2214
2214
  /**
2215
2215
  * @import {Identifier, Literal, MemberExpression} from 'estree'
@@ -2418,7 +2418,7 @@ function mdxExpression(state, node) {
2418
2418
  if (node.data && node.data.estree && state.evaluater) {
2419
2419
  const program = node.data.estree;
2420
2420
  const expression = program.body[0];
2421
- ok$1(expression.type === 'ExpressionStatement');
2421
+ ok$2(expression.type === 'ExpressionStatement');
2422
2422
 
2423
2423
  // Assume result is a child.
2424
2424
  return /** @type {Child | undefined} */ (
@@ -2685,11 +2685,11 @@ function createJsxElementProps(state, node) {
2685
2685
  if (attribute.data && attribute.data.estree && state.evaluater) {
2686
2686
  const program = attribute.data.estree;
2687
2687
  const expression = program.body[0];
2688
- ok$1(expression.type === 'ExpressionStatement');
2688
+ ok$2(expression.type === 'ExpressionStatement');
2689
2689
  const objectExpression = expression.expression;
2690
- ok$1(objectExpression.type === 'ObjectExpression');
2690
+ ok$2(objectExpression.type === 'ObjectExpression');
2691
2691
  const property = objectExpression.properties[0];
2692
- ok$1(property.type === 'SpreadElement');
2692
+ ok$2(property.type === 'SpreadElement');
2693
2693
 
2694
2694
  Object.assign(
2695
2695
  props,
@@ -2712,7 +2712,7 @@ function createJsxElementProps(state, node) {
2712
2712
  ) {
2713
2713
  const program = attribute.value.data.estree;
2714
2714
  const expression = program.body[0];
2715
- ok$1(expression.type === 'ExpressionStatement');
2715
+ ok$2(expression.type === 'ExpressionStatement');
2716
2716
  value = state.evaluater.evaluateExpression(expression.expression);
2717
2717
  } else {
2718
2718
  crashEstree(state, node.position);
@@ -2847,7 +2847,7 @@ function parseStyle(state, value) {
2847
2847
  } catch (error) {
2848
2848
  if (!state.ignoreInvalidStyle) {
2849
2849
  const cause = /** @type {Error} */ (error);
2850
- const message = new VFileMessage$2('Cannot parse `style` attribute', {
2850
+ const message = new VFileMessage$1('Cannot parse `style` attribute', {
2851
2851
  ancestors: state.ancestors,
2852
2852
  cause,
2853
2853
  ruleId: 'style',
@@ -2954,7 +2954,7 @@ function findComponentFromName(state, name$1, allowExpression) {
2954
2954
  * @returns {never}
2955
2955
  */
2956
2956
  function crashEstree(state, place) {
2957
- const message = new VFileMessage$2(
2957
+ const message = new VFileMessage$1(
2958
2958
  'Cannot handle MDX estrees without `createEvaluater`',
2959
2959
  {
2960
2960
  ancestors: state.ancestors,
@@ -3089,7 +3089,7 @@ const emptyOptions$1 = {};
3089
3089
  * Serialized `value`.
3090
3090
  */
3091
3091
  function toString$1(value, options) {
3092
- const settings = options || emptyOptions$1;
3092
+ const settings = emptyOptions$1;
3093
3093
  const includeImageAlt =
3094
3094
  typeof settings.includeImageAlt === 'boolean'
3095
3095
  ? settings.includeImageAlt
@@ -5582,7 +5582,7 @@ function normalizeIdentifier(value) {
5582
5582
  * @returns {boolean}
5583
5583
  * Whether it matches.
5584
5584
  */
5585
- const asciiAlpha = regexCheck(/[A-Za-z]/);
5585
+ const asciiAlpha = regexCheck$1(/[A-Za-z]/);
5586
5586
 
5587
5587
  /**
5588
5588
  * Check whether the character code represents an ASCII alphanumeric (`a`
@@ -5596,7 +5596,7 @@ const asciiAlpha = regexCheck(/[A-Za-z]/);
5596
5596
  * @returns {boolean}
5597
5597
  * Whether it matches.
5598
5598
  */
5599
- const asciiAlphanumeric = regexCheck(/[\dA-Za-z]/);
5599
+ const asciiAlphanumeric$1 = regexCheck$1(/[\dA-Za-z]/);
5600
5600
 
5601
5601
  /**
5602
5602
  * Check whether the character code represents an ASCII atext.
@@ -5619,7 +5619,7 @@ const asciiAlphanumeric = regexCheck(/[\dA-Za-z]/);
5619
5619
  * @returns {boolean}
5620
5620
  * Whether it matches.
5621
5621
  */
5622
- const asciiAtext = regexCheck(/[#-'*+\--9=?A-Z^-~]/);
5622
+ const asciiAtext = regexCheck$1(/[#-'*+\--9=?A-Z^-~]/);
5623
5623
 
5624
5624
  /**
5625
5625
  * Check whether a character code is an ASCII control character.
@@ -5651,7 +5651,7 @@ function asciiControl(code) {
5651
5651
  * @returns {boolean}
5652
5652
  * Whether it matches.
5653
5653
  */
5654
- const asciiDigit = regexCheck(/\d/);
5654
+ const asciiDigit = regexCheck$1(/\d/);
5655
5655
 
5656
5656
  /**
5657
5657
  * Check whether the character code represents an ASCII hex digit (`a` through
@@ -5671,7 +5671,7 @@ const asciiDigit = regexCheck(/\d/);
5671
5671
  * @returns {boolean}
5672
5672
  * Whether it matches.
5673
5673
  */
5674
- const asciiHexDigit = regexCheck(/[\dA-Fa-f]/);
5674
+ const asciiHexDigit = regexCheck$1(/[\dA-Fa-f]/);
5675
5675
 
5676
5676
  /**
5677
5677
  * Check whether the character code represents ASCII punctuation.
@@ -5686,7 +5686,7 @@ const asciiHexDigit = regexCheck(/[\dA-Fa-f]/);
5686
5686
  * @returns {boolean}
5687
5687
  * Whether it matches.
5688
5688
  */
5689
- const asciiPunctuation = regexCheck(/[!-/:-@[-`{-~]/);
5689
+ const asciiPunctuation = regexCheck$1(/[!-/:-@[-`{-~]/);
5690
5690
 
5691
5691
  /**
5692
5692
  * Check whether a character code is a markdown line ending.
@@ -5760,7 +5760,7 @@ function markdownSpace(code) {
5760
5760
  * @returns
5761
5761
  * Whether it matches.
5762
5762
  */
5763
- const unicodePunctuation = regexCheck(/\p{P}|\p{S}/u);
5763
+ const unicodePunctuation = regexCheck$1(/\p{P}|\p{S}/u);
5764
5764
 
5765
5765
  /**
5766
5766
  * Check whether the character code represents Unicode whitespace.
@@ -5782,7 +5782,7 @@ const unicodePunctuation = regexCheck(/\p{P}|\p{S}/u);
5782
5782
  * @returns
5783
5783
  * Whether it matches.
5784
5784
  */
5785
- const unicodeWhitespace = regexCheck(/\s/);
5785
+ const unicodeWhitespace = regexCheck$1(/\s/);
5786
5786
 
5787
5787
  /**
5788
5788
  * Create a code check from a regex.
@@ -5792,7 +5792,7 @@ const unicodeWhitespace = regexCheck(/\s/);
5792
5792
  * @returns {(code: Code) => boolean}
5793
5793
  * Check.
5794
5794
  */
5795
- function regexCheck(regex) {
5795
+ function regexCheck$1(regex) {
5796
5796
  return check;
5797
5797
 
5798
5798
  /**
@@ -5808,69 +5808,6 @@ function regexCheck(regex) {
5808
5808
  }
5809
5809
  }
5810
5810
 
5811
- /**
5812
- * Normalize a URL.
5813
- *
5814
- * Encode unsafe characters with percent-encoding, skipping already encoded
5815
- * sequences.
5816
- *
5817
- * @param {string} value
5818
- * URI to normalize.
5819
- * @returns {string}
5820
- * Normalized URI.
5821
- */
5822
- function normalizeUri(value) {
5823
- /** @type {Array<string>} */
5824
- const result = [];
5825
- let index = -1;
5826
- let start = 0;
5827
- let skip = 0;
5828
- while (++index < value.length) {
5829
- const code = value.charCodeAt(index);
5830
- /** @type {string} */
5831
- let replace = '';
5832
-
5833
- // A correct percent encoded value.
5834
- if (code === 37 && asciiAlphanumeric(value.charCodeAt(index + 1)) && asciiAlphanumeric(value.charCodeAt(index + 2))) {
5835
- skip = 2;
5836
- }
5837
- // ASCII.
5838
- else if (code < 128) {
5839
- if (!/[!#$&-;=?-Z_a-z~]/.test(String.fromCharCode(code))) {
5840
- replace = String.fromCharCode(code);
5841
- }
5842
- }
5843
- // Astral.
5844
- else if (code > 55_295 && code < 57_344) {
5845
- const next = value.charCodeAt(index + 1);
5846
-
5847
- // A correct surrogate pair.
5848
- if (code < 56_320 && next > 56_319 && next < 57_344) {
5849
- replace = String.fromCharCode(code, next);
5850
- skip = 1;
5851
- }
5852
- // Lone surrogate.
5853
- else {
5854
- replace = "\uFFFD";
5855
- }
5856
- }
5857
- // Unicode.
5858
- else {
5859
- replace = String.fromCharCode(code);
5860
- }
5861
- if (replace) {
5862
- result.push(value.slice(start, index), encodeURIComponent(replace));
5863
- start = index + skip + 1;
5864
- replace = '';
5865
- }
5866
- if (skip) {
5867
- index += skip;
5868
- skip = 0;
5869
- }
5870
- }
5871
- return result.join('') + value.slice(start);
5872
- }
5873
-
5874
5811
  /**
5875
5812
  * @import {Effects, State, TokenType} from 'micromark-util-types'
5876
5813
  */
@@ -6749,7 +6686,7 @@ function tokenizeAutolink(effects, ok, nok) {
6749
6686
  */
6750
6687
  function schemeOrEmailAtext(code) {
6751
6688
  // ASCII alphanumeric and `+`, `-`, and `.`.
6752
- if (code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code)) {
6689
+ if (code === 43 || code === 45 || code === 46 || asciiAlphanumeric$1(code)) {
6753
6690
  // Count the previous alphabetical from `open` too.
6754
6691
  size = 1;
6755
6692
  return schemeInsideOrEmailAtext(code);
@@ -6777,7 +6714,7 @@ function tokenizeAutolink(effects, ok, nok) {
6777
6714
  }
6778
6715
 
6779
6716
  // ASCII alphanumeric and `+`, `-`, and `.`.
6780
- if ((code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code)) && size++ < 32) {
6717
+ if ((code === 43 || code === 45 || code === 46 || asciiAlphanumeric$1(code)) && size++ < 32) {
6781
6718
  effects.consume(code);
6782
6719
  return schemeInsideOrEmailAtext;
6783
6720
  }
@@ -6846,7 +6783,7 @@ function tokenizeAutolink(effects, ok, nok) {
6846
6783
  * @type {State}
6847
6784
  */
6848
6785
  function emailAtSignOrDot(code) {
6849
- return asciiAlphanumeric(code) ? emailLabel(code) : nok(code);
6786
+ return asciiAlphanumeric$1(code) ? emailLabel(code) : nok(code);
6850
6787
  }
6851
6788
 
6852
6789
  /**
@@ -6891,7 +6828,7 @@ function tokenizeAutolink(effects, ok, nok) {
6891
6828
  */
6892
6829
  function emailValue(code) {
6893
6830
  // ASCII alphanumeric or `-`.
6894
- if ((code === 45 || asciiAlphanumeric(code)) && size++ < 63) {
6831
+ if ((code === 45 || asciiAlphanumeric$1(code)) && size++ < 63) {
6895
6832
  const next = code === 45 ? emailValue : emailLabel;
6896
6833
  effects.consume(code);
6897
6834
  return next;
@@ -7242,7 +7179,7 @@ function tokenizeCharacterReference(effects, ok, nok) {
7242
7179
  }
7243
7180
  effects.enter("characterReferenceValue");
7244
7181
  max = 31;
7245
- test = asciiAlphanumeric;
7182
+ test = asciiAlphanumeric$1;
7246
7183
  return value(code);
7247
7184
  }
7248
7185
 
@@ -7294,7 +7231,7 @@ function tokenizeCharacterReference(effects, ok, nok) {
7294
7231
  function value(code) {
7295
7232
  if (code === 59 && size) {
7296
7233
  const token = effects.exit("characterReferenceValue");
7297
- if (test === asciiAlphanumeric && !decodeNamedCharacterReference(self.sliceSerialize(token))) {
7234
+ if (test === asciiAlphanumeric$1 && !decodeNamedCharacterReference(self.sliceSerialize(token))) {
7298
7235
  return nok(code);
7299
7236
  }
7300
7237
 
@@ -10243,7 +10180,7 @@ function tokenizeHtmlFlow(effects, ok, nok) {
10243
10180
  }
10244
10181
 
10245
10182
  // ASCII alphanumerical and `-`.
10246
- if (code === 45 || asciiAlphanumeric(code)) {
10183
+ if (code === 45 || asciiAlphanumeric$1(code)) {
10247
10184
  effects.consume(code);
10248
10185
  buffer += String.fromCharCode(code);
10249
10186
  return tagName;
@@ -10346,7 +10283,7 @@ function tokenizeHtmlFlow(effects, ok, nok) {
10346
10283
  */
10347
10284
  function completeAttributeName(code) {
10348
10285
  // ASCII alphanumerical and `-`, `.`, `:`, and `_`.
10349
- if (code === 45 || code === 46 || code === 58 || code === 95 || asciiAlphanumeric(code)) {
10286
+ if (code === 45 || code === 46 || code === 58 || code === 95 || asciiAlphanumeric$1(code)) {
10350
10287
  effects.consume(code);
10351
10288
  return completeAttributeName;
10352
10289
  }
@@ -11199,7 +11136,7 @@ function tokenizeHtmlText(effects, ok, nok) {
11199
11136
  */
11200
11137
  function tagClose(code) {
11201
11138
  // ASCII alphanumerical and `-`.
11202
- if (code === 45 || asciiAlphanumeric(code)) {
11139
+ if (code === 45 || asciiAlphanumeric$1(code)) {
11203
11140
  effects.consume(code);
11204
11141
  return tagClose;
11205
11142
  }
@@ -11240,7 +11177,7 @@ function tokenizeHtmlText(effects, ok, nok) {
11240
11177
  */
11241
11178
  function tagOpen(code) {
11242
11179
  // ASCII alphanumerical and `-`.
11243
- if (code === 45 || asciiAlphanumeric(code)) {
11180
+ if (code === 45 || asciiAlphanumeric$1(code)) {
11244
11181
  effects.consume(code);
11245
11182
  return tagOpen;
11246
11183
  }
@@ -11294,7 +11231,7 @@ function tokenizeHtmlText(effects, ok, nok) {
11294
11231
  */
11295
11232
  function tagOpenAttributeName(code) {
11296
11233
  // ASCII alphabetical and `-`, `.`, `:`, and `_`.
11297
- if (code === 45 || code === 46 || code === 58 || code === 95 || asciiAlphanumeric(code)) {
11234
+ if (code === 45 || code === 46 || code === 58 || code === 95 || asciiAlphanumeric$1(code)) {
11298
11235
  effects.consume(code);
11299
11236
  return tagOpenAttributeName;
11300
11237
  }
@@ -13943,7 +13880,7 @@ function decode($0, $1, $2) {
13943
13880
  * An empty string (`''`) is returned if the given value is neither `node`,
13944
13881
  * `position`, nor `point`.
13945
13882
  */
13946
- function stringifyPosition$2(value) {
13883
+ function stringifyPosition(value) {
13947
13884
  // Nothing.
13948
13885
  if (!value || typeof value !== 'object') {
13949
13886
  return ''
@@ -13951,17 +13888,17 @@ function stringifyPosition$2(value) {
13951
13888
 
13952
13889
  // Node.
13953
13890
  if ('position' in value || 'type' in value) {
13954
- return position$2(value.position)
13891
+ return position(value.position)
13955
13892
  }
13956
13893
 
13957
13894
  // Position.
13958
13895
  if ('start' in value || 'end' in value) {
13959
- return position$2(value)
13896
+ return position(value)
13960
13897
  }
13961
13898
 
13962
13899
  // Point.
13963
13900
  if ('line' in value || 'column' in value) {
13964
- return point$3(value)
13901
+ return point$1(value)
13965
13902
  }
13966
13903
 
13967
13904
  // ?
@@ -13972,23 +13909,23 @@ function stringifyPosition$2(value) {
13972
13909
  * @param {Point | PointLike | null | undefined} point
13973
13910
  * @returns {string}
13974
13911
  */
13975
- function point$3(point) {
13976
- return index$2(point && point.line) + ':' + index$2(point && point.column)
13912
+ function point$1(point) {
13913
+ return index(point && point.line) + ':' + index(point && point.column)
13977
13914
  }
13978
13915
 
13979
13916
  /**
13980
13917
  * @param {Position | PositionLike | null | undefined} pos
13981
13918
  * @returns {string}
13982
13919
  */
13983
- function position$2(pos) {
13984
- return point$3(pos && pos.start) + '-' + point$3(pos && pos.end)
13920
+ function position(pos) {
13921
+ return point$1(pos && pos.start) + '-' + point$1(pos && pos.end)
13985
13922
  }
13986
13923
 
13987
13924
  /**
13988
13925
  * @param {number | null | undefined} value
13989
13926
  * @returns {number}
13990
13927
  */
13991
- function index$2(value) {
13928
+ function index(value) {
13992
13929
  return value && typeof value === 'number' ? value : 1
13993
13930
  }
13994
13931
 
@@ -14236,12 +14173,12 @@ function compiler(options) {
14236
14173
 
14237
14174
  // Figure out `root` position.
14238
14175
  tree.position = {
14239
- start: point$2(events.length > 0 ? events[0][1].start : {
14176
+ start: point(events.length > 0 ? events[0][1].start : {
14240
14177
  line: 1,
14241
14178
  column: 1,
14242
14179
  offset: 0
14243
14180
  }),
14244
- end: point$2(events.length > 0 ? events[events.length - 2][1].end : {
14181
+ end: point(events.length > 0 ? events[events.length - 2][1].end : {
14245
14182
  line: 1,
14246
14183
  column: 1,
14247
14184
  offset: 0
@@ -14411,7 +14348,7 @@ function compiler(options) {
14411
14348
  this.stack.push(node);
14412
14349
  this.tokenStack.push([token, errorHandler || undefined]);
14413
14350
  node.position = {
14414
- start: point$2(token.start),
14351
+ start: point(token.start),
14415
14352
  // @ts-expect-error: `end` will be patched later.
14416
14353
  end: undefined
14417
14354
  };
@@ -14446,7 +14383,7 @@ function compiler(options) {
14446
14383
  const node = this.stack.pop();
14447
14384
  const open = this.tokenStack.pop();
14448
14385
  if (!open) {
14449
- throw new Error('Cannot close `' + token.type + '` (' + stringifyPosition$2({
14386
+ throw new Error('Cannot close `' + token.type + '` (' + stringifyPosition({
14450
14387
  start: token.start,
14451
14388
  end: token.end
14452
14389
  }) + '): it’s not open');
@@ -14458,7 +14395,7 @@ function compiler(options) {
14458
14395
  handler.call(this, token, open[0]);
14459
14396
  }
14460
14397
  }
14461
- node.position.end = point$2(token.end);
14398
+ node.position.end = point(token.end);
14462
14399
  }
14463
14400
 
14464
14401
  /**
@@ -14626,7 +14563,7 @@ function compiler(options) {
14626
14563
  // Add a new text node.
14627
14564
  tail = text();
14628
14565
  tail.position = {
14629
- start: point$2(token.start),
14566
+ start: point(token.start),
14630
14567
  // @ts-expect-error: we’ll add `end` later.
14631
14568
  end: undefined
14632
14569
  };
@@ -14643,7 +14580,7 @@ function compiler(options) {
14643
14580
  function onexitdata(token) {
14644
14581
  const tail = this.stack.pop();
14645
14582
  tail.value += this.sliceSerialize(token);
14646
- tail.position.end = point$2(token.end);
14583
+ tail.position.end = point(token.end);
14647
14584
  }
14648
14585
 
14649
14586
  /**
@@ -14656,7 +14593,7 @@ function compiler(options) {
14656
14593
  // If we’re at a hard break, include the line ending in there.
14657
14594
  if (this.data.atHardBreak) {
14658
14595
  const tail = context.children[context.children.length - 1];
14659
- tail.position.end = point$2(token.end);
14596
+ tail.position.end = point(token.end);
14660
14597
  this.data.atHardBreak = undefined;
14661
14598
  return;
14662
14599
  }
@@ -14892,7 +14829,7 @@ function compiler(options) {
14892
14829
  */
14893
14830
  function onexitcharacterreference(token) {
14894
14831
  const tail = this.stack.pop();
14895
- tail.position.end = point$2(token.end);
14832
+ tail.position.end = point(token.end);
14896
14833
  }
14897
14834
 
14898
14835
  /**
@@ -15076,7 +15013,7 @@ function compiler(options) {
15076
15013
  * @returns {Point}
15077
15014
  * unist point.
15078
15015
  */
15079
- function point$2(d) {
15016
+ function point(d) {
15080
15017
  return {
15081
15018
  line: d.line,
15082
15019
  column: d.column,
@@ -15146,15 +15083,15 @@ function extension(combined, extension) {
15146
15083
  /** @type {OnEnterError} */
15147
15084
  function defaultOnError(left, right) {
15148
15085
  if (left) {
15149
- throw new Error('Cannot close `' + left.type + '` (' + stringifyPosition$2({
15086
+ throw new Error('Cannot close `' + left.type + '` (' + stringifyPosition({
15150
15087
  start: left.start,
15151
15088
  end: left.end
15152
- }) + '): a different token (`' + right.type + '`, ' + stringifyPosition$2({
15089
+ }) + '): a different token (`' + right.type + '`, ' + stringifyPosition({
15153
15090
  start: right.start,
15154
15091
  end: right.end
15155
15092
  }) + ') is open');
15156
15093
  } else {
15157
- throw new Error('Cannot close document, a token (`' + right.type + '`, ' + stringifyPosition$2({
15094
+ throw new Error('Cannot close document, a token (`' + right.type + '`, ' + stringifyPosition({
15158
15095
  start: right.start,
15159
15096
  end: right.end
15160
15097
  }) + ') is still open');
@@ -15361,6 +15298,114 @@ function emphasis(state, node) {
15361
15298
  return state.applyData(node, result)
15362
15299
  }
15363
15300
 
15301
+ /**
15302
+ * @typedef {import('micromark-util-types').Code} Code
15303
+ */
15304
+
15305
+
15306
+ /**
15307
+ * Check whether the character code represents an ASCII alphanumeric (`a`
15308
+ * through `z`, case insensitive, or `0` through `9`).
15309
+ *
15310
+ * An **ASCII alphanumeric** is an ASCII digit (see `asciiDigit`) or ASCII alpha
15311
+ * (see `asciiAlpha`).
15312
+ *
15313
+ * @param code
15314
+ * Code.
15315
+ * @returns {boolean}
15316
+ * Whether it matches.
15317
+ */
15318
+ const asciiAlphanumeric = regexCheck(/[\dA-Za-z]/);
15319
+
15320
+ /**
15321
+ * Create a code check from a regex.
15322
+ *
15323
+ * @param {RegExp} regex
15324
+ * @returns {(code: Code) => boolean}
15325
+ */
15326
+ function regexCheck(regex) {
15327
+ return check;
15328
+
15329
+ /**
15330
+ * Check whether a code matches the bound regex.
15331
+ *
15332
+ * @param {Code} code
15333
+ * Character code.
15334
+ * @returns {boolean}
15335
+ * Whether the character code matches the bound regex.
15336
+ */
15337
+ function check(code) {
15338
+ return code !== null && code > -1 && regex.test(String.fromCharCode(code));
15339
+ }
15340
+ }
15341
+
15342
+ /**
15343
+ * Normalize a URL.
15344
+ *
15345
+ * Encode unsafe characters with percent-encoding, skipping already encoded
15346
+ * sequences.
15347
+ *
15348
+ * @param {string} value
15349
+ * URI to normalize.
15350
+ * @returns {string}
15351
+ * Normalized URI.
15352
+ */
15353
+ function normalizeUri(value) {
15354
+ /** @type {Array<string>} */
15355
+ const result = [];
15356
+ let index = -1;
15357
+ let start = 0;
15358
+ let skip = 0;
15359
+ while (++index < value.length) {
15360
+ const code = value.charCodeAt(index);
15361
+ /** @type {string} */
15362
+ let replace = '';
15363
+
15364
+ // A correct percent encoded value.
15365
+ if (
15366
+ code === 37 &&
15367
+ asciiAlphanumeric(value.charCodeAt(index + 1)) &&
15368
+ asciiAlphanumeric(value.charCodeAt(index + 2))
15369
+ ) {
15370
+ skip = 2;
15371
+ }
15372
+ // ASCII.
15373
+ else if (code < 128) {
15374
+ if (!/[!#$&-;=?-Z_a-z~]/.test(String.fromCharCode(code))) {
15375
+ replace = String.fromCharCode(code);
15376
+ }
15377
+ }
15378
+ // Astral.
15379
+ else if (code > 55_295 && code < 57_344) {
15380
+ const next = value.charCodeAt(index + 1);
15381
+
15382
+ // A correct surrogate pair.
15383
+ if (code < 56_320 && next > 56_319 && next < 57_344) {
15384
+ replace = String.fromCharCode(code, next);
15385
+ skip = 1;
15386
+ }
15387
+ // Lone surrogate.
15388
+ else {
15389
+ replace = '\uFFFD';
15390
+ }
15391
+ }
15392
+ // Unicode.
15393
+ else {
15394
+ replace = String.fromCharCode(code);
15395
+ }
15396
+ if (replace) {
15397
+ result.push(value.slice(start, index), encodeURIComponent(replace));
15398
+ start = index + skip + 1;
15399
+ replace = '';
15400
+ }
15401
+ if (skip) {
15402
+ index += skip;
15403
+ skip = 0;
15404
+ }
15405
+ }
15406
+ return result.join('') + value.slice(start)
15407
+ }
15408
+
15364
15409
  /**
15365
15410
  * @typedef {import('hast').Element} Element
15366
15411
  * @typedef {import('mdast').FootnoteReference} FootnoteReference
@@ -16799,7 +16844,7 @@ function footer(state) {
16799
16844
  * @returns {Check}
16800
16845
  * An assertion.
16801
16846
  */
16802
- const convert =
16847
+ const convert$1 =
16803
16848
  // Note: overloads in JSDoc can’t yet use different `@template`s.
16804
16849
  /**
16805
16850
  * @type {(
@@ -16817,19 +16862,19 @@ const convert =
16817
16862
  */
16818
16863
  function (test) {
16819
16864
  if (test === null || test === undefined) {
16820
- return ok
16865
+ return ok$1
16821
16866
  }
16822
16867
 
16823
16868
  if (typeof test === 'function') {
16824
- return castFactory(test)
16869
+ return castFactory$1(test)
16825
16870
  }
16826
16871
 
16827
16872
  if (typeof test === 'object') {
16828
- return Array.isArray(test) ? anyFactory(test) : propsFactory(test)
16873
+ return Array.isArray(test) ? anyFactory$1(test) : propsFactory$1(test)
16829
16874
  }
16830
16875
 
16831
16876
  if (typeof test === 'string') {
16832
- return typeFactory(test)
16877
+ return typeFactory$1(test)
16833
16878
  }
16834
16879
 
16835
16880
  throw new Error('Expected function, string, or object as test')
@@ -16840,16 +16885,16 @@ const convert =
16840
16885
  * @param {Array<Props | TestFunction | string>} tests
16841
16886
  * @returns {Check}
16842
16887
  */
16843
- function anyFactory(tests) {
16888
+ function anyFactory$1(tests) {
16844
16889
  /** @type {Array<Check>} */
16845
16890
  const checks = [];
16846
16891
  let index = -1;
16847
16892
 
16848
16893
  while (++index < tests.length) {
16849
- checks[index] = convert(tests[index]);
16894
+ checks[index] = convert$1(tests[index]);
16850
16895
  }
16851
16896
 
16852
- return castFactory(any)
16897
+ return castFactory$1(any)
16853
16898
 
16854
16899
  /**
16855
16900
  * @this {unknown}
@@ -16872,10 +16917,10 @@ function anyFactory(tests) {
16872
16917
  * @param {Props} check
16873
16918
  * @returns {Check}
16874
16919
  */
16875
- function propsFactory(check) {
16920
+ function propsFactory$1(check) {
16876
16921
  const checkAsRecord = /** @type {Record<string, unknown>} */ (check);
16877
16922
 
16878
- return castFactory(all)
16923
+ return castFactory$1(all)
16879
16924
 
16880
16925
  /**
16881
16926
  * @param {Node} node
@@ -16903,8 +16948,8 @@ function propsFactory(check) {
16903
16948
  * @param {string} check
16904
16949
  * @returns {Check}
16905
16950
  */
16906
- function typeFactory(check) {
16907
- return castFactory(type)
16951
+ function typeFactory$1(check) {
16952
+ return castFactory$1(type)
16908
16953
 
16909
16954
  /**
16910
16955
  * @param {Node} node
@@ -16920,7 +16965,7 @@ function typeFactory(check) {
16920
16965
  * @param {TestFunction} testFunction
16921
16966
  * @returns {Check}
16922
16967
  */
16923
- function castFactory(testFunction) {
16968
+ function castFactory$1(testFunction) {
16924
16969
  return check
16925
16970
 
16926
16971
  /**
@@ -16929,7 +16974,7 @@ function castFactory(testFunction) {
16929
16974
  */
16930
16975
  function check(value, index, parent) {
16931
16976
  return Boolean(
16932
- looksLikeANode(value) &&
16977
+ looksLikeANode$1(value) &&
16933
16978
  testFunction.call(
16934
16979
  this,
16935
16980
  value,
@@ -16940,7 +16985,7 @@ function castFactory(testFunction) {
16940
16985
  }
16941
16986
  }
16942
16987
 
16943
- function ok() {
16988
+ function ok$1() {
16944
16989
  return true
16945
16990
  }
16946
16991
 
@@ -16948,7 +16993,7 @@ function ok() {
16948
16993
  * @param {unknown} value
16949
16994
  * @returns {value is Node}
16950
16995
  */
16951
- function looksLikeANode(value) {
16996
+ function looksLikeANode$1(value) {
16952
16997
  return value !== null && typeof value === 'object' && 'type' in value
16953
16998
  }
16954
16999
 
@@ -16956,7 +17001,7 @@ function looksLikeANode(value) {
16956
17001
  * @param {string} d
16957
17002
  * @returns {string}
16958
17003
  */
16959
- function color(d) {
17004
+ function color$1(d) {
16960
17005
  return d
16961
17006
  }
16962
17007
 
@@ -16967,22 +17012,22 @@ function color(d) {
16967
17012
 
16968
17013
 
16969
17014
  /** @type {Readonly<ActionTuple>} */
16970
- const empty = [];
17015
+ const empty$1 = [];
16971
17016
 
16972
17017
  /**
16973
17018
  * Continue traversing as normal.
16974
17019
  */
16975
- const CONTINUE = true;
17020
+ const CONTINUE$1 = true;
16976
17021
 
16977
17022
  /**
16978
17023
  * Stop traversing immediately.
16979
17024
  */
16980
- const EXIT = false;
17025
+ const EXIT$1 = false;
16981
17026
 
16982
17027
  /**
16983
17028
  * Do not traverse this node’s children.
16984
17029
  */
16985
- const SKIP = 'skip';
17030
+ const SKIP$1 = 'skip';
16986
17031
 
16987
17032
  /**
16988
17033
  * Visit nodes, with ancestral information.
@@ -17031,7 +17076,7 @@ const SKIP = 'skip';
17031
17076
  * @template {Test} Check
17032
17077
  * `unist-util-is`-compatible test.
17033
17078
  */
17034
- function visitParents(tree, test, visitor, reverse) {
17079
+ function visitParents$1(tree, test, visitor, reverse) {
17035
17080
  /** @type {Test} */
17036
17081
  let check;
17037
17082
 
@@ -17044,7 +17089,7 @@ function visitParents(tree, test, visitor, reverse) {
17044
17089
  check = test;
17045
17090
  }
17046
17091
 
17047
- const is = convert(check);
17092
+ const is = convert$1(check);
17048
17093
  const step = reverse ? -1 : 1;
17049
17094
 
17050
17095
  factory(tree, undefined, [])();
@@ -17071,7 +17116,7 @@ function visitParents(tree, test, visitor, reverse) {
17071
17116
 
17072
17117
  Object.defineProperty(visit, 'name', {
17073
17118
  value:
17074
- 'node (' + color(node.type + (name ? '<' + name + '>' : '')) + ')'
17119
+ 'node (' + color$1(node.type + (name ? '<' + name + '>' : '')) + ')'
17075
17120
  });
17076
17121
  }
17077
17122
 
@@ -17079,7 +17124,7 @@ function visitParents(tree, test, visitor, reverse) {
17079
17124
 
17080
17125
  function visit() {
17081
17126
  /** @type {Readonly<ActionTuple>} */
17082
- let result = empty;
17127
+ let result = empty$1;
17083
17128
  /** @type {Readonly<ActionTuple>} */
17084
17129
  let subresult;
17085
17130
  /** @type {number} */
@@ -17089,9 +17134,9 @@ function visitParents(tree, test, visitor, reverse) {
17089
17134
 
17090
17135
  if (!test || is(node, index, parents[parents.length - 1] || undefined)) {
17091
17136
  // @ts-expect-error: `visitor` is now a visitor.
17092
- result = toResult(visitor(node, parents));
17137
+ result = toResult$1(visitor(node, parents));
17093
17138
 
17094
- if (result[0] === EXIT) {
17139
+ if (result[0] === EXIT$1) {
17095
17140
  return result
17096
17141
  }
17097
17142
  }
@@ -17099,7 +17144,7 @@ function visitParents(tree, test, visitor, reverse) {
17099
17144
  if ('children' in node && node.children) {
17100
17145
  const nodeAsParent = /** @type {UnistParent} */ (node);
17101
17146
 
17102
- if (nodeAsParent.children && result[0] !== SKIP) {
17147
+ if (nodeAsParent.children && result[0] !== SKIP$1) {
17103
17148
  offset = (reverse ? nodeAsParent.children.length : -1) + step;
17104
17149
  grandparents = parents.concat(nodeAsParent);
17105
17150
 
@@ -17108,7 +17153,7 @@ function visitParents(tree, test, visitor, reverse) {
17108
17153
 
17109
17154
  subresult = factory(child, offset, grandparents)();
17110
17155
 
17111
- if (subresult[0] === EXIT) {
17156
+ if (subresult[0] === EXIT$1) {
17112
17157
  return subresult
17113
17158
  }
17114
17159
 
@@ -17131,16 +17176,16 @@ function visitParents(tree, test, visitor, reverse) {
17131
17176
  * @returns {Readonly<ActionTuple>}
17132
17177
  * Clean result.
17133
17178
  */
17134
- function toResult(value) {
17179
+ function toResult$1(value) {
17135
17180
  if (Array.isArray(value)) {
17136
17181
  return value
17137
17182
  }
17138
17183
 
17139
17184
  if (typeof value === 'number') {
17140
- return [CONTINUE, value]
17185
+ return [CONTINUE$1, value]
17141
17186
  }
17142
17187
 
17143
- return value === null || value === undefined ? empty : [value]
17188
+ return value === null || value === undefined ? empty$1 : [value]
17144
17189
  }
17145
17190
 
17146
17191
  /**
@@ -17197,7 +17242,7 @@ function toResult(value) {
17197
17242
  * @template {Test} Check
17198
17243
  * `unist-util-is`-compatible test.
17199
17244
  */
17200
- function visit(tree, testOrVisitor, visitorOrReverse, maybeReverse) {
17245
+ function visit$1(tree, testOrVisitor, visitorOrReverse, maybeReverse) {
17201
17246
  /** @type {boolean | null | undefined} */
17202
17247
  let reverse;
17203
17248
  /** @type {Test} */
@@ -17220,7 +17265,7 @@ function visit(tree, testOrVisitor, visitorOrReverse, maybeReverse) {
17220
17265
  reverse = maybeReverse;
17221
17266
  }
17222
17267
 
17223
- visitParents(tree, test, overload, reverse);
17268
+ visitParents$1(tree, test, overload, reverse);
17224
17269
 
17225
17270
  /**
17226
17271
  * @param {UnistNode} node
@@ -17296,7 +17341,7 @@ function createState(tree, options) {
17296
17341
  wrap: wrap$1
17297
17342
  };
17298
17343
 
17299
- visit(tree, function (node) {
17344
+ visit$1(tree, function (node) {
17300
17345
  if (node.type === 'definition' || node.type === 'footnoteDefinition') {
17301
17346
  const map = node.type === 'definition' ? definitionById : footnoteById;
17302
17347
  const id = String(node.identifier).toUpperCase();
@@ -17407,7 +17452,7 @@ function createState(tree, options) {
17407
17452
  * Nothing.
17408
17453
  */
17409
17454
  function patch(from, to) {
17410
- if (from.position) to.position = position$4(from);
17455
+ if (from.position) to.position = position$2(from);
17411
17456
  }
17412
17457
 
17413
17458
  /**
@@ -18144,99 +18189,14 @@ function wrap(middleware, callback) {
18144
18189
  }
18145
18190
 
18146
18191
  /**
18147
- * @typedef {import('unist').Node} Node
18148
- * @typedef {import('unist').Point} Point
18149
- * @typedef {import('unist').Position} Position
18150
- */
18151
-
18152
- /**
18153
- * @typedef NodeLike
18154
- * @property {string} type
18155
- * @property {PositionLike | null | undefined} [position]
18156
- *
18157
- * @typedef PointLike
18158
- * @property {number | null | undefined} [line]
18159
- * @property {number | null | undefined} [column]
18160
- * @property {number | null | undefined} [offset]
18161
- *
18162
- * @typedef PositionLike
18163
- * @property {PointLike | null | undefined} [start]
18164
- * @property {PointLike | null | undefined} [end]
18165
- */
18166
-
18167
- /**
18168
- * Serialize the positional info of a point, position (start and end points),
18169
- * or node.
18170
- *
18171
- * @param {Node | NodeLike | Point | PointLike | Position | PositionLike | null | undefined} [value]
18172
- * Node, position, or point.
18173
- * @returns {string}
18174
- * Pretty printed positional info of a node (`string`).
18175
- *
18176
- * In the format of a range `ls:cs-le:ce` (when given `node` or `position`)
18177
- * or a point `l:c` (when given `point`), where `l` stands for line, `c` for
18178
- * column, `s` for `start`, and `e` for end.
18179
- * An empty string (`''`) is returned if the given value is neither `node`,
18180
- * `position`, nor `point`.
18181
- */
18182
- function stringifyPosition$1(value) {
18183
- // Nothing.
18184
- if (!value || typeof value !== 'object') {
18185
- return ''
18186
- }
18187
-
18188
- // Node.
18189
- if ('position' in value || 'type' in value) {
18190
- return position$1(value.position)
18191
- }
18192
-
18193
- // Position.
18194
- if ('start' in value || 'end' in value) {
18195
- return position$1(value)
18196
- }
18197
-
18198
- // Point.
18199
- if ('line' in value || 'column' in value) {
18200
- return point$1(value)
18201
- }
18202
-
18203
- // ?
18204
- return ''
18205
- }
18206
-
18207
- /**
18208
- * @param {Point | PointLike | null | undefined} point
18209
- * @returns {string}
18210
- */
18211
- function point$1(point) {
18212
- return index$1(point && point.line) + ':' + index$1(point && point.column)
18213
- }
18214
-
18215
- /**
18216
- * @param {Position | PositionLike | null | undefined} pos
18217
- * @returns {string}
18218
- */
18219
- function position$1(pos) {
18220
- return point$1(pos && pos.start) + '-' + point$1(pos && pos.end)
18221
- }
18222
-
18223
- /**
18224
- * @param {number | null | undefined} value
18225
- * @returns {number}
18226
- */
18227
- function index$1(value) {
18228
- return value && typeof value === 'number' ? value : 1
18229
- }
18230
-
18231
- /**
18232
- * @import {Node, Point, Position} from 'unist'
18192
+ * @import {Node, Point, Position} from 'unist'
18233
18193
  */
18234
18194
 
18235
18195
 
18236
18196
  /**
18237
18197
  * Message.
18238
18198
  */
18239
- let VFileMessage$1 = class VFileMessage extends Error {
18199
+ class VFileMessage extends Error {
18240
18200
  /**
18241
18201
  * Create a message for `reason`.
18242
18202
  *
@@ -18429,7 +18389,7 @@ let VFileMessage$1 = class VFileMessage extends Error {
18429
18389
  * On normal errors, this would be something like `ParseError`, buit in
18430
18390
  * `VFile` messages we use this space to show where an error happened.
18431
18391
  */
18432
- this.name = stringifyPosition$1(options.place) || '1:1';
18392
+ this.name = stringifyPosition(options.place) || '1:1';
18433
18393
 
18434
18394
  /**
18435
18395
  * Place of message.
@@ -18509,21 +18469,21 @@ let VFileMessage$1 = class VFileMessage extends Error {
18509
18469
  */
18510
18470
  this.url = undefined;
18511
18471
  }
18512
- };
18472
+ }
18513
18473
 
18514
- VFileMessage$1.prototype.file = '';
18515
- VFileMessage$1.prototype.name = '';
18516
- VFileMessage$1.prototype.reason = '';
18517
- VFileMessage$1.prototype.message = '';
18518
- VFileMessage$1.prototype.stack = '';
18519
- VFileMessage$1.prototype.column = undefined;
18520
- VFileMessage$1.prototype.line = undefined;
18521
- VFileMessage$1.prototype.ancestors = undefined;
18522
- VFileMessage$1.prototype.cause = undefined;
18523
- VFileMessage$1.prototype.fatal = undefined;
18524
- VFileMessage$1.prototype.place = undefined;
18525
- VFileMessage$1.prototype.ruleId = undefined;
18526
- VFileMessage$1.prototype.source = undefined;
18474
+ VFileMessage.prototype.file = '';
18475
+ VFileMessage.prototype.name = '';
18476
+ VFileMessage.prototype.reason = '';
18477
+ VFileMessage.prototype.message = '';
18478
+ VFileMessage.prototype.stack = '';
18479
+ VFileMessage.prototype.column = undefined;
18480
+ VFileMessage.prototype.line = undefined;
18481
+ VFileMessage.prototype.ancestors = undefined;
18482
+ VFileMessage.prototype.cause = undefined;
18483
+ VFileMessage.prototype.fatal = undefined;
18484
+ VFileMessage.prototype.place = undefined;
18485
+ VFileMessage.prototype.ruleId = undefined;
18486
+ VFileMessage.prototype.source = undefined;
18527
18487
 
18528
18488
  // A derivative work based on:
18529
18489
  // <https://github.com/browserify/path-browserify>.
@@ -18576,7 +18536,7 @@ VFileMessage$1.prototype.source = undefined;
18576
18536
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18577
18537
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
18578
18538
 
18579
- const minpath$1 = {basename: basename$1, dirname: dirname$1, extname: extname$1, join: join$1, sep: '/'};
18539
+ const minpath = {basename, dirname, extname, join, sep: '/'};
18580
18540
 
18581
18541
  /* eslint-disable max-depth, complexity */
18582
18542
 
@@ -18590,12 +18550,12 @@ const minpath$1 = {basename: basename$1, dirname: dirname$1, extname: extname$1,
18590
18550
  * @returns {string}
18591
18551
  * Stem or basename.
18592
18552
  */
18593
- function basename$1(path, extname) {
18553
+ function basename(path, extname) {
18594
18554
  if (extname !== undefined && typeof extname !== 'string') {
18595
18555
  throw new TypeError('"ext" argument must be a string')
18596
18556
  }
18597
18557
 
18598
- assertPath$3(path);
18558
+ assertPath$1(path);
18599
18559
  let start = 0;
18600
18560
  let end = -1;
18601
18561
  let index = path.length;
@@ -18684,8 +18644,8 @@ function basename$1(path, extname) {
18684
18644
  * @returns {string}
18685
18645
  * File path.
18686
18646
  */
18687
- function dirname$1(path) {
18688
- assertPath$3(path);
18647
+ function dirname(path) {
18648
+ assertPath$1(path);
18689
18649
 
18690
18650
  if (path.length === 0) {
18691
18651
  return '.'
@@ -18726,8 +18686,8 @@ function dirname$1(path) {
18726
18686
  * @returns {string}
18727
18687
  * Extname.
18728
18688
  */
18729
- function extname$1(path) {
18730
- assertPath$3(path);
18689
+ function extname(path) {
18690
+ assertPath$1(path);
18731
18691
 
18732
18692
  let index = path.length;
18733
18693
 
@@ -18797,13 +18757,13 @@ function extname$1(path) {
18797
18757
  * @returns {string}
18798
18758
  * File path.
18799
18759
  */
18800
- function join$1(...segments) {
18760
+ function join(...segments) {
18801
18761
  let index = -1;
18802
18762
  /** @type {string | undefined} */
18803
18763
  let joined;
18804
18764
 
18805
18765
  while (++index < segments.length) {
18806
- assertPath$3(segments[index]);
18766
+ assertPath$1(segments[index]);
18807
18767
 
18808
18768
  if (segments[index]) {
18809
18769
  joined =
@@ -18811,7 +18771,7 @@ function join$1(...segments) {
18811
18771
  }
18812
18772
  }
18813
18773
 
18814
- return joined === undefined ? '.' : normalize$1(joined)
18774
+ return joined === undefined ? '.' : normalize(joined)
18815
18775
  }
18816
18776
 
18817
18777
  /**
@@ -18824,13 +18784,13 @@ function join$1(...segments) {
18824
18784
  */
18825
18785
  // Note: `normalize` is not exposed as `path.normalize`, so some code is
18826
18786
  // manually removed from it.
18827
- function normalize$1(path) {
18828
- assertPath$3(path);
18787
+ function normalize(path) {
18788
+ assertPath$1(path);
18829
18789
 
18830
18790
  const absolute = path.codePointAt(0) === 47; /* `/` */
18831
18791
 
18832
18792
  // Normalize the path according to POSIX rules.
18833
- let value = normalizeString$1(path, !absolute);
18793
+ let value = normalizeString(path, !absolute);
18834
18794
 
18835
18795
  if (value.length === 0 && !absolute) {
18836
18796
  value = '.';
@@ -18853,7 +18813,7 @@ function normalize$1(path) {
18853
18813
  * @returns {string}
18854
18814
  * File path.
18855
18815
  */
18856
- function normalizeString$1(path, allowAboveRoot) {
18816
+ function normalizeString(path, allowAboveRoot) {
18857
18817
  let result = '';
18858
18818
  let lastSegmentLength = 0;
18859
18819
  let lastSlash = -1;
@@ -18940,7 +18900,7 @@ function normalizeString$1(path, allowAboveRoot) {
18940
18900
  * @returns {asserts path is string}
18941
18901
  * Nothing.
18942
18902
  */
18943
- function assertPath$3(path) {
18903
+ function assertPath$1(path) {
18944
18904
  if (typeof path !== 'string') {
18945
18905
  throw new TypeError(
18946
18906
  'Path must be a string. Received ' + JSON.stringify(path)
@@ -18953,9 +18913,9 @@ function assertPath$3(path) {
18953
18913
  // Somewhat based on:
18954
18914
  // <https://github.com/defunctzombie/node-process/blob/master/browser.js>.
18955
18915
  // But I don’t think one tiny line of code can be copyrighted. 😅
18956
- const minproc$1 = {cwd: cwd$1};
18916
+ const minproc = {cwd};
18957
18917
 
18958
- function cwd$1() {
18918
+ function cwd() {
18959
18919
  return '/'
18960
18920
  }
18961
18921
 
@@ -18978,7 +18938,7 @@ function cwd$1() {
18978
18938
  * Whether it’s a URL.
18979
18939
  */
18980
18940
  // From: <https://github.com/nodejs/node/blob/6a3403c/lib/internal/url.js#L720>
18981
- function isUrl$1(fileUrlOrPath) {
18941
+ function isUrl(fileUrlOrPath) {
18982
18942
  return Boolean(
18983
18943
  fileUrlOrPath !== null &&
18984
18944
  typeof fileUrlOrPath === 'object' &&
@@ -18999,10 +18959,10 @@ function isUrl$1(fileUrlOrPath) {
18999
18959
  * @returns {string}
19000
18960
  * File URL.
19001
18961
  */
19002
- function urlToPath$1(path) {
18962
+ function urlToPath(path) {
19003
18963
  if (typeof path === 'string') {
19004
18964
  path = new URL(path);
19005
- } else if (!isUrl$1(path)) {
18965
+ } else if (!isUrl(path)) {
19006
18966
  /** @type {NodeJS.ErrnoException} */
19007
18967
  const error = new TypeError(
19008
18968
  'The "path" argument must be of type string or an instance of URL. Received `' +
@@ -19020,7 +18980,7 @@ function urlToPath$1(path) {
19020
18980
  throw error
19021
18981
  }
19022
18982
 
19023
- return getPathFromURLPosix$1(path)
18983
+ return getPathFromURLPosix(path)
19024
18984
  }
19025
18985
 
19026
18986
  /**
@@ -19031,7 +18991,7 @@ function urlToPath$1(path) {
19031
18991
  * @returns {string}
19032
18992
  * File path.
19033
18993
  */
19034
- function getPathFromURLPosix$1(url) {
18994
+ function getPathFromURLPosix(url) {
19035
18995
  if (url.hostname !== '') {
19036
18996
  /** @type {NodeJS.ErrnoException} */
19037
18997
  const error = new TypeError(
@@ -19076,7 +19036,7 @@ function getPathFromURLPosix$1(url) {
19076
19036
  * `{stem: 'a', path: '~/b.js'}` would throw, as a path is needed before a
19077
19037
  * stem can be set.
19078
19038
  */
19079
- const order$1 = /** @type {const} */ ([
19039
+ const order = /** @type {const} */ ([
19080
19040
  'history',
19081
19041
  'path',
19082
19042
  'basename',
@@ -19085,7 +19045,7 @@ const order$1 = /** @type {const} */ ([
19085
19045
  'dirname'
19086
19046
  ]);
19087
19047
 
19088
- let VFile$1 = class VFile {
19048
+ class VFile {
19089
19049
  /**
19090
19050
  * Create a new virtual file.
19091
19051
  *
@@ -19114,9 +19074,9 @@ let VFile$1 = class VFile {
19114
19074
 
19115
19075
  if (!value) {
19116
19076
  options = {};
19117
- } else if (isUrl$1(value)) {
19077
+ } else if (isUrl(value)) {
19118
19078
  options = {path: value};
19119
- } else if (typeof value === 'string' || isUint8Array$2(value)) {
19079
+ } else if (typeof value === 'string' || isUint8Array$1(value)) {
19120
19080
  options = {value};
19121
19081
  } else {
19122
19082
  options = value;
@@ -19131,7 +19091,7 @@ let VFile$1 = class VFile {
19131
19091
  */
19132
19092
  // Prevent calling `cwd` (which could be expensive) if it’s not needed;
19133
19093
  // the empty string will be overridden in the next block.
19134
- this.cwd = 'cwd' in options ? '' : minproc$1.cwd();
19094
+ this.cwd = 'cwd' in options ? '' : minproc.cwd();
19135
19095
 
19136
19096
  /**
19137
19097
  * Place to store custom info (default: `{}`).
@@ -19201,8 +19161,8 @@ let VFile$1 = class VFile {
19201
19161
  // Set path related properties in the correct order.
19202
19162
  let index = -1;
19203
19163
 
19204
- while (++index < order$1.length) {
19205
- const field = order$1[index];
19164
+ while (++index < order.length) {
19165
+ const field = order[index];
19206
19166
 
19207
19167
  // Note: we specifically use `in` instead of `hasOwnProperty` to accept
19208
19168
  // `vfile`s too.
@@ -19222,7 +19182,7 @@ let VFile$1 = class VFile {
19222
19182
  // Set non-path related properties.
19223
19183
  for (field in options) {
19224
19184
  // @ts-expect-error: fine to set other things.
19225
- if (!order$1.includes(field)) {
19185
+ if (!order.includes(field)) {
19226
19186
  // @ts-expect-error: fine to set other things.
19227
19187
  this[field] = options[field];
19228
19188
  }
@@ -19237,7 +19197,7 @@ let VFile$1 = class VFile {
19237
19197
  */
19238
19198
  get basename() {
19239
19199
  return typeof this.path === 'string'
19240
- ? minpath$1.basename(this.path)
19200
+ ? minpath.basename(this.path)
19241
19201
  : undefined
19242
19202
  }
19243
19203
 
@@ -19254,9 +19214,9 @@ let VFile$1 = class VFile {
19254
19214
  * Nothing.
19255
19215
  */
19256
19216
  set basename(basename) {
19257
- assertNonEmpty$1(basename, 'basename');
19258
- assertPart$1(basename, 'basename');
19259
- this.path = minpath$1.join(this.dirname || '', basename);
19217
+ assertNonEmpty(basename, 'basename');
19218
+ assertPart(basename, 'basename');
19219
+ this.path = minpath.join(this.dirname || '', basename);
19260
19220
  }
19261
19221
 
19262
19222
  /**
@@ -19267,7 +19227,7 @@ let VFile$1 = class VFile {
19267
19227
  */
19268
19228
  get dirname() {
19269
19229
  return typeof this.path === 'string'
19270
- ? minpath$1.dirname(this.path)
19230
+ ? minpath.dirname(this.path)
19271
19231
  : undefined
19272
19232
  }
19273
19233
 
@@ -19282,8 +19242,8 @@ let VFile$1 = class VFile {
19282
19242
  * Nothing.
19283
19243
  */
19284
19244
  set dirname(dirname) {
19285
- assertPath$2(this.basename, 'dirname');
19286
- this.path = minpath$1.join(dirname || '', this.basename);
19245
+ assertPath(this.basename, 'dirname');
19246
+ this.path = minpath.join(dirname || '', this.basename);
19287
19247
  }
19288
19248
 
19289
19249
  /**
@@ -19294,7 +19254,7 @@ let VFile$1 = class VFile {
19294
19254
  */
19295
19255
  get extname() {
19296
19256
  return typeof this.path === 'string'
19297
- ? minpath$1.extname(this.path)
19257
+ ? minpath.extname(this.path)
19298
19258
  : undefined
19299
19259
  }
19300
19260
 
@@ -19311,8 +19271,8 @@ let VFile$1 = class VFile {
19311
19271
  * Nothing.
19312
19272
  */
19313
19273
  set extname(extname) {
19314
- assertPart$1(extname, 'extname');
19315
- assertPath$2(this.dirname, 'extname');
19274
+ assertPart(extname, 'extname');
19275
+ assertPath(this.dirname, 'extname');
19316
19276
 
19317
19277
  if (extname) {
19318
19278
  if (extname.codePointAt(0) !== 46 /* `.` */) {
@@ -19324,7 +19284,7 @@ let VFile$1 = class VFile {
19324
19284
  }
19325
19285
  }
19326
19286
 
19327
- this.path = minpath$1.join(this.dirname, this.stem + (extname || ''));
19287
+ this.path = minpath.join(this.dirname, this.stem + (extname || ''));
19328
19288
  }
19329
19289
 
19330
19290
  /**
@@ -19350,11 +19310,11 @@ let VFile$1 = class VFile {
19350
19310
  * Nothing.
19351
19311
  */
19352
19312
  set path(path) {
19353
- if (isUrl$1(path)) {
19354
- path = urlToPath$1(path);
19313
+ if (isUrl(path)) {
19314
+ path = urlToPath(path);
19355
19315
  }
19356
19316
 
19357
- assertNonEmpty$1(path, 'path');
19317
+ assertNonEmpty(path, 'path');
19358
19318
 
19359
19319
  if (this.path !== path) {
19360
19320
  this.history.push(path);
@@ -19369,7 +19329,7 @@ let VFile$1 = class VFile {
19369
19329
  */
19370
19330
  get stem() {
19371
19331
  return typeof this.path === 'string'
19372
- ? minpath$1.basename(this.path, this.extname)
19332
+ ? minpath.basename(this.path, this.extname)
19373
19333
  : undefined
19374
19334
  }
19375
19335
 
@@ -19386,9 +19346,9 @@ let VFile$1 = class VFile {
19386
19346
  * Nothing.
19387
19347
  */
19388
19348
  set stem(stem) {
19389
- assertNonEmpty$1(stem, 'stem');
19390
- assertPart$1(stem, 'stem');
19391
- this.path = minpath$1.join(this.dirname || '', stem + (this.extname || ''));
19349
+ assertNonEmpty(stem, 'stem');
19350
+ assertPart(stem, 'stem');
19351
+ this.path = minpath.join(this.dirname || '', stem + (this.extname || ''));
19392
19352
  }
19393
19353
 
19394
19354
  // Normal prototypal methods.
@@ -19587,7 +19547,7 @@ let VFile$1 = class VFile {
19587
19547
  * Message.
19588
19548
  */
19589
19549
  message(causeOrReason, optionsOrParentOrPlace, origin) {
19590
- const message = new VFileMessage$1(
19550
+ const message = new VFileMessage(
19591
19551
  // @ts-expect-error: the overloads are fine.
19592
19552
  causeOrReason,
19593
19553
  optionsOrParentOrPlace,
@@ -19631,7 +19591,7 @@ let VFile$1 = class VFile {
19631
19591
  const decoder = new TextDecoder(encoding || undefined);
19632
19592
  return decoder.decode(this.value)
19633
19593
  }
19634
- };
19594
+ }
19635
19595
 
19636
19596
  /**
19637
19597
  * Assert that `part` is not a path (as in, does not contain `path.sep`).
@@ -19643,10 +19603,10 @@ let VFile$1 = class VFile {
19643
19603
  * @returns {undefined}
19644
19604
  * Nothing.
19645
19605
  */
19646
- function assertPart$1(part, name) {
19647
- if (part && part.includes(minpath$1.sep)) {
19606
+ function assertPart(part, name) {
19607
+ if (part && part.includes(minpath.sep)) {
19648
19608
  throw new Error(
19649
- '`' + name + '` cannot be a path: did not expect `' + minpath$1.sep + '`'
19609
+ '`' + name + '` cannot be a path: did not expect `' + minpath.sep + '`'
19650
19610
  )
19651
19611
  }
19652
19612
  }
@@ -19661,7 +19621,7 @@ function assertPart$1(part, name) {
19661
19621
  * @returns {asserts part is string}
19662
19622
  * Nothing.
19663
19623
  */
19664
- function assertNonEmpty$1(part, name) {
19624
+ function assertNonEmpty(part, name) {
19665
19625
  if (!part) {
19666
19626
  throw new Error('`' + name + '` cannot be empty')
19667
19627
  }
@@ -19677,7 +19637,7 @@ function assertNonEmpty$1(part, name) {
19677
19637
  * @returns {asserts path is string}
19678
19638
  * Nothing.
19679
19639
  */
19680
- function assertPath$2(path, name) {
19640
+ function assertPath(path, name) {
19681
19641
  if (!path) {
19682
19642
  throw new Error('Setting `' + name + '` requires `path` to be set too')
19683
19643
  }
@@ -19691,7 +19651,7 @@ function assertPath$2(path, name) {
19691
19651
  * @returns {value is Uint8Array}
19692
19652
  * Whether `value` is an `Uint8Array`.
19693
19653
  */
19694
- function isUint8Array$2(value) {
19654
+ function isUint8Array$1(value) {
19695
19655
  return Boolean(
19696
19656
  value &&
19697
19657
  typeof value === 'object' &&
@@ -20674,7 +20634,7 @@ function assertDone(name, asyncName, complete) {
20674
20634
  * @returns {VFile}
20675
20635
  */
20676
20636
  function vfile(value) {
20677
- return looksLikeAVFile(value) ? value : new VFile$1(value)
20637
+ return looksLikeAVFile(value) ? value : new VFile(value)
20678
20638
  }
20679
20639
 
20680
20640
  /**
@@ -20695,7 +20655,7 @@ function looksLikeAVFile(value) {
20695
20655
  * @returns {value is Value}
20696
20656
  */
20697
20657
  function looksLikeAValue(value) {
20698
- return typeof value === 'string' || isUint8Array$1(value)
20658
+ return typeof value === 'string' || isUint8Array(value)
20699
20659
  }
20700
20660
 
20701
20661
  /**
@@ -20706,7 +20666,7 @@ function looksLikeAValue(value) {
20706
20666
  * @returns {value is Uint8Array}
20707
20667
  * Whether `value` is an `Uint8Array`.
20708
20668
  */
20709
- function isUint8Array$1(value) {
20669
+ function isUint8Array(value) {
20710
20670
  return Boolean(
20711
20671
  value &&
20712
20672
  typeof value === 'object' &&
@@ -20717,1559 +20677,460 @@ function isUint8Array$1(value) {
20717
20677
 
20718
20678
  /**
20719
20679
  * @typedef {import('unist').Node} Node
20720
- * @typedef {import('unist').Point} Point
20721
- * @typedef {import('unist').Position} Position
20680
+ * @typedef {import('unist').Parent} Parent
20722
20681
  */
20723
20682
 
20724
- /**
20725
- * @typedef NodeLike
20726
- * @property {string} type
20727
- * @property {PositionLike | null | undefined} [position]
20728
- *
20729
- * @typedef PointLike
20730
- * @property {number | null | undefined} [line]
20731
- * @property {number | null | undefined} [column]
20732
- * @property {number | null | undefined} [offset]
20733
- *
20734
- * @typedef PositionLike
20735
- * @property {PointLike | null | undefined} [start]
20736
- * @property {PointLike | null | undefined} [end]
20737
- */
20738
20683
 
20739
20684
  /**
20740
- * Serialize the positional info of a point, position (start and end points),
20741
- * or node.
20685
+ * Generate an assertion from a test.
20742
20686
  *
20743
- * @param {Node | NodeLike | Point | PointLike | Position | PositionLike | null | undefined} [value]
20744
- * Node, position, or point.
20745
- * @returns {string}
20746
- * Pretty printed positional info of a node (`string`).
20687
+ * Useful if you’re going to test many nodes, for example when creating a
20688
+ * utility where something else passes a compatible test.
20747
20689
  *
20748
- * In the format of a range `ls:cs-le:ce` (when given `node` or `position`)
20749
- * or a point `l:c` (when given `point`), where `l` stands for line, `c` for
20750
- * column, `s` for `start`, and `e` for end.
20751
- * An empty string (`''`) is returned if the given value is neither `node`,
20752
- * `position`, nor `point`.
20690
+ * The created function is a bit faster because it expects valid input only:
20691
+ * a `node`, `index`, and `parent`.
20692
+ *
20693
+ * @param {Test} test
20694
+ * * when nullish, checks if `node` is a `Node`.
20695
+ * * when `string`, works like passing `(node) => node.type === test`.
20696
+ * * when `function` checks if function passed the node is true.
20697
+ * * when `object`, checks that all keys in test are in node, and that they have (strictly) equal values.
20698
+ * * when `array`, checks if any one of the subtests pass.
20699
+ * @returns {Check}
20700
+ * An assertion.
20753
20701
  */
20754
- function stringifyPosition(value) {
20755
- // Nothing.
20756
- if (!value || typeof value !== 'object') {
20757
- return ''
20758
- }
20702
+ const convert =
20703
+ // Note: overloads in JSDoc can’t yet use different `@template`s.
20704
+ /**
20705
+ * @type {(
20706
+ * (<Condition extends string>(test: Condition) => (node: unknown, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node & {type: Condition}) &
20707
+ * (<Condition extends Props>(test: Condition) => (node: unknown, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node & Condition) &
20708
+ * (<Condition extends TestFunction>(test: Condition) => (node: unknown, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node & Predicate<Condition, Node>) &
20709
+ * ((test?: null | undefined) => (node?: unknown, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node) &
20710
+ * ((test?: Test) => Check)
20711
+ * )}
20712
+ */
20713
+ (
20714
+ /**
20715
+ * @param {Test} [test]
20716
+ * @returns {Check}
20717
+ */
20718
+ function (test) {
20719
+ if (test === null || test === undefined) {
20720
+ return ok
20721
+ }
20759
20722
 
20760
- // Node.
20761
- if ('position' in value || 'type' in value) {
20762
- return position(value.position)
20763
- }
20723
+ if (typeof test === 'function') {
20724
+ return castFactory(test)
20725
+ }
20764
20726
 
20765
- // Position.
20766
- if ('start' in value || 'end' in value) {
20767
- return position(value)
20768
- }
20727
+ if (typeof test === 'object') {
20728
+ return Array.isArray(test) ? anyFactory(test) : propsFactory(test)
20729
+ }
20769
20730
 
20770
- // Point.
20771
- if ('line' in value || 'column' in value) {
20772
- return point(value)
20773
- }
20731
+ if (typeof test === 'string') {
20732
+ return typeFactory(test)
20733
+ }
20774
20734
 
20775
- // ?
20776
- return ''
20777
- }
20735
+ throw new Error('Expected function, string, or object as test')
20736
+ }
20737
+ );
20778
20738
 
20779
20739
  /**
20780
- * @param {Point | PointLike | null | undefined} point
20781
- * @returns {string}
20740
+ * @param {Array<Props | TestFunction | string>} tests
20741
+ * @returns {Check}
20782
20742
  */
20783
- function point(point) {
20784
- return index(point && point.line) + ':' + index(point && point.column)
20785
- }
20743
+ function anyFactory(tests) {
20744
+ /** @type {Array<Check>} */
20745
+ const checks = [];
20746
+ let index = -1;
20786
20747
 
20787
- /**
20788
- * @param {Position | PositionLike | null | undefined} pos
20789
- * @returns {string}
20790
- */
20791
- function position(pos) {
20792
- return point(pos && pos.start) + '-' + point(pos && pos.end)
20748
+ while (++index < tests.length) {
20749
+ checks[index] = convert(tests[index]);
20750
+ }
20751
+
20752
+ return castFactory(any)
20753
+
20754
+ /**
20755
+ * @this {unknown}
20756
+ * @type {TestFunction}
20757
+ */
20758
+ function any(...parameters) {
20759
+ let index = -1;
20760
+
20761
+ while (++index < checks.length) {
20762
+ if (checks[index].apply(this, parameters)) return true
20763
+ }
20764
+
20765
+ return false
20766
+ }
20793
20767
  }
20794
20768
 
20795
20769
  /**
20796
- * @param {number | null | undefined} value
20797
- * @returns {number}
20770
+ * Turn an object into a test for a node with a certain fields.
20771
+ *
20772
+ * @param {Props} check
20773
+ * @returns {Check}
20798
20774
  */
20799
- function index(value) {
20800
- return value && typeof value === 'number' ? value : 1
20775
+ function propsFactory(check) {
20776
+ const checkAsRecord = /** @type {Record<string, unknown>} */ (check);
20777
+
20778
+ return castFactory(all)
20779
+
20780
+ /**
20781
+ * @param {Node} node
20782
+ * @returns {boolean}
20783
+ */
20784
+ function all(node) {
20785
+ const nodeAsRecord = /** @type {Record<string, unknown>} */ (
20786
+ /** @type {unknown} */ (node)
20787
+ );
20788
+
20789
+ /** @type {string} */
20790
+ let key;
20791
+
20792
+ for (key in check) {
20793
+ if (nodeAsRecord[key] !== checkAsRecord[key]) return false
20794
+ }
20795
+
20796
+ return true
20797
+ }
20801
20798
  }
20802
20799
 
20803
20800
  /**
20804
- * @import {Node, Point, Position} from 'unist'
20801
+ * Turn a string into a test for a node with a certain type.
20802
+ *
20803
+ * @param {string} check
20804
+ * @returns {Check}
20805
20805
  */
20806
+ function typeFactory(check) {
20807
+ return castFactory(type)
20806
20808
 
20809
+ /**
20810
+ * @param {Node} node
20811
+ */
20812
+ function type(node) {
20813
+ return node && node.type === check
20814
+ }
20815
+ }
20807
20816
 
20808
20817
  /**
20809
- * Message.
20818
+ * Turn a custom test into a test for a node that passes that test.
20819
+ *
20820
+ * @param {TestFunction} testFunction
20821
+ * @returns {Check}
20810
20822
  */
20811
- class VFileMessage extends Error {
20823
+ function castFactory(testFunction) {
20824
+ return check
20825
+
20812
20826
  /**
20813
- * Create a message for `reason`.
20814
- *
20815
- * > 🪦 **Note**: also has obsolete signatures.
20816
- *
20817
- * @overload
20818
- * @param {string} reason
20819
- * @param {Options | null | undefined} [options]
20820
- * @returns
20821
- *
20822
- * @overload
20823
- * @param {string} reason
20824
- * @param {Node | NodeLike | null | undefined} parent
20825
- * @param {string | null | undefined} [origin]
20826
- * @returns
20827
- *
20828
- * @overload
20829
- * @param {string} reason
20830
- * @param {Point | Position | null | undefined} place
20831
- * @param {string | null | undefined} [origin]
20832
- * @returns
20833
- *
20834
- * @overload
20835
- * @param {string} reason
20836
- * @param {string | null | undefined} [origin]
20837
- * @returns
20838
- *
20839
- * @overload
20840
- * @param {Error | VFileMessage} cause
20841
- * @param {Node | NodeLike | null | undefined} parent
20842
- * @param {string | null | undefined} [origin]
20843
- * @returns
20844
- *
20845
- * @overload
20846
- * @param {Error | VFileMessage} cause
20847
- * @param {Point | Position | null | undefined} place
20848
- * @param {string | null | undefined} [origin]
20849
- * @returns
20850
- *
20851
- * @overload
20852
- * @param {Error | VFileMessage} cause
20853
- * @param {string | null | undefined} [origin]
20854
- * @returns
20855
- *
20856
- * @param {Error | VFileMessage | string} causeOrReason
20857
- * Reason for message, should use markdown.
20858
- * @param {Node | NodeLike | Options | Point | Position | string | null | undefined} [optionsOrParentOrPlace]
20859
- * Configuration (optional).
20860
- * @param {string | null | undefined} [origin]
20861
- * Place in code where the message originates (example:
20862
- * `'my-package:my-rule'` or `'my-rule'`).
20863
- * @returns
20864
- * Instance of `VFileMessage`.
20827
+ * @this {unknown}
20828
+ * @type {Check}
20865
20829
  */
20866
- // eslint-disable-next-line complexity
20867
- constructor(causeOrReason, optionsOrParentOrPlace, origin) {
20868
- super();
20869
-
20870
- if (typeof optionsOrParentOrPlace === 'string') {
20871
- origin = optionsOrParentOrPlace;
20872
- optionsOrParentOrPlace = undefined;
20873
- }
20830
+ function check(value, index, parent) {
20831
+ return Boolean(
20832
+ looksLikeANode(value) &&
20833
+ testFunction.call(
20834
+ this,
20835
+ value,
20836
+ typeof index === 'number' ? index : undefined,
20837
+ parent || undefined
20838
+ )
20839
+ )
20840
+ }
20841
+ }
20874
20842
 
20875
- /** @type {string} */
20876
- let reason = '';
20877
- /** @type {Options} */
20878
- let options = {};
20879
- let legacyCause = false;
20843
+ function ok() {
20844
+ return true
20845
+ }
20880
20846
 
20881
- if (optionsOrParentOrPlace) {
20882
- // Point.
20883
- if (
20884
- 'line' in optionsOrParentOrPlace &&
20885
- 'column' in optionsOrParentOrPlace
20886
- ) {
20887
- options = {place: optionsOrParentOrPlace};
20888
- }
20889
- // Position.
20890
- else if (
20891
- 'start' in optionsOrParentOrPlace &&
20892
- 'end' in optionsOrParentOrPlace
20893
- ) {
20894
- options = {place: optionsOrParentOrPlace};
20895
- }
20896
- // Node.
20897
- else if ('type' in optionsOrParentOrPlace) {
20898
- options = {
20899
- ancestors: [optionsOrParentOrPlace],
20900
- place: optionsOrParentOrPlace.position
20901
- };
20902
- }
20903
- // Options.
20904
- else {
20905
- options = {...optionsOrParentOrPlace};
20906
- }
20907
- }
20847
+ /**
20848
+ * @param {unknown} value
20849
+ * @returns {value is Node}
20850
+ */
20851
+ function looksLikeANode(value) {
20852
+ return value !== null && typeof value === 'object' && 'type' in value
20853
+ }
20908
20854
 
20909
- if (typeof causeOrReason === 'string') {
20910
- reason = causeOrReason;
20911
- }
20912
- // Error.
20913
- else if (!options.cause && causeOrReason) {
20914
- legacyCause = true;
20915
- reason = causeOrReason.message;
20916
- options.cause = causeOrReason;
20917
- }
20855
+ /**
20856
+ * @param {string} d
20857
+ * @returns {string}
20858
+ */
20859
+ function color(d) {
20860
+ return d
20861
+ }
20918
20862
 
20919
- if (!options.ruleId && !options.source && typeof origin === 'string') {
20920
- const index = origin.indexOf(':');
20863
+ /**
20864
+ * @typedef {import('unist').Node} UnistNode
20865
+ * @typedef {import('unist').Parent} UnistParent
20866
+ */
20921
20867
 
20922
- if (index === -1) {
20923
- options.ruleId = origin;
20924
- } else {
20925
- options.source = origin.slice(0, index);
20926
- options.ruleId = origin.slice(index + 1);
20927
- }
20928
- }
20929
20868
 
20930
- if (!options.place && options.ancestors && options.ancestors) {
20931
- const parent = options.ancestors[options.ancestors.length - 1];
20869
+ /** @type {Readonly<ActionTuple>} */
20870
+ const empty = [];
20932
20871
 
20933
- if (parent) {
20934
- options.place = parent.position;
20935
- }
20936
- }
20872
+ /**
20873
+ * Continue traversing as normal.
20874
+ */
20875
+ const CONTINUE = true;
20937
20876
 
20938
- const start =
20939
- options.place && 'start' in options.place
20940
- ? options.place.start
20941
- : options.place;
20877
+ /**
20878
+ * Stop traversing immediately.
20879
+ */
20880
+ const EXIT = false;
20942
20881
 
20943
- /**
20944
- * Stack of ancestor nodes surrounding the message.
20945
- *
20946
- * @type {Array<Node> | undefined}
20947
- */
20948
- this.ancestors = options.ancestors || undefined;
20949
-
20950
- /**
20951
- * Original error cause of the message.
20952
- *
20953
- * @type {Error | undefined}
20954
- */
20955
- this.cause = options.cause || undefined;
20956
-
20957
- /**
20958
- * Starting column of message.
20959
- *
20960
- * @type {number | undefined}
20961
- */
20962
- this.column = start ? start.column : undefined;
20963
-
20964
- /**
20965
- * State of problem.
20966
- *
20967
- * * `true` — error, file not usable
20968
- * * `false` — warning, change may be needed
20969
- * * `undefined` — change likely not needed
20970
- *
20971
- * @type {boolean | null | undefined}
20972
- */
20973
- this.fatal = undefined;
20974
-
20975
- /**
20976
- * Path of a file (used throughout the `VFile` ecosystem).
20977
- *
20978
- * @type {string | undefined}
20979
- */
20980
- this.file = '';
20981
-
20982
- // Field from `Error`.
20983
- /**
20984
- * Reason for message.
20985
- *
20986
- * @type {string}
20987
- */
20988
- this.message = reason;
20989
-
20990
- /**
20991
- * Starting line of error.
20992
- *
20993
- * @type {number | undefined}
20994
- */
20995
- this.line = start ? start.line : undefined;
20996
-
20997
- // Field from `Error`.
20998
- /**
20999
- * Serialized positional info of message.
21000
- *
21001
- * On normal errors, this would be something like `ParseError`, buit in
21002
- * `VFile` messages we use this space to show where an error happened.
21003
- */
21004
- this.name = stringifyPosition(options.place) || '1:1';
21005
-
21006
- /**
21007
- * Place of message.
21008
- *
21009
- * @type {Point | Position | undefined}
21010
- */
21011
- this.place = options.place || undefined;
21012
-
21013
- /**
21014
- * Reason for message, should use markdown.
21015
- *
21016
- * @type {string}
21017
- */
21018
- this.reason = this.message;
21019
-
21020
- /**
21021
- * Category of message (example: `'my-rule'`).
21022
- *
21023
- * @type {string | undefined}
21024
- */
21025
- this.ruleId = options.ruleId || undefined;
21026
-
21027
- /**
21028
- * Namespace of message (example: `'my-package'`).
21029
- *
21030
- * @type {string | undefined}
21031
- */
21032
- this.source = options.source || undefined;
21033
-
21034
- // Field from `Error`.
21035
- /**
21036
- * Stack of message.
21037
- *
21038
- * This is used by normal errors to show where something happened in
21039
- * programming code, irrelevant for `VFile` messages,
21040
- *
21041
- * @type {string}
21042
- */
21043
- this.stack =
21044
- legacyCause && options.cause && typeof options.cause.stack === 'string'
21045
- ? options.cause.stack
21046
- : '';
21047
-
21048
- // The following fields are “well known”.
21049
- // Not standard.
21050
- // Feel free to add other non-standard fields to your messages.
21051
-
21052
- /**
21053
- * Specify the source value that’s being reported, which is deemed
21054
- * incorrect.
21055
- *
21056
- * @type {string | undefined}
21057
- */
21058
- this.actual = undefined;
21059
-
21060
- /**
21061
- * Suggest acceptable values that can be used instead of `actual`.
21062
- *
21063
- * @type {Array<string> | undefined}
21064
- */
21065
- this.expected = undefined;
21066
-
21067
- /**
21068
- * Long form description of the message (you should use markdown).
21069
- *
21070
- * @type {string | undefined}
21071
- */
21072
- this.note = undefined;
21073
-
21074
- /**
21075
- * Link to docs for the message.
21076
- *
21077
- * > 👉 **Note**: this must be an absolute URL that can be passed as `x`
21078
- * > to `new URL(x)`.
21079
- *
21080
- * @type {string | undefined}
21081
- */
21082
- this.url = undefined;
21083
- }
21084
- }
21085
-
21086
- VFileMessage.prototype.file = '';
21087
- VFileMessage.prototype.name = '';
21088
- VFileMessage.prototype.reason = '';
21089
- VFileMessage.prototype.message = '';
21090
- VFileMessage.prototype.stack = '';
21091
- VFileMessage.prototype.column = undefined;
21092
- VFileMessage.prototype.line = undefined;
21093
- VFileMessage.prototype.ancestors = undefined;
21094
- VFileMessage.prototype.cause = undefined;
21095
- VFileMessage.prototype.fatal = undefined;
21096
- VFileMessage.prototype.place = undefined;
21097
- VFileMessage.prototype.ruleId = undefined;
21098
- VFileMessage.prototype.source = undefined;
21099
-
21100
- // A derivative work based on:
21101
- // <https://github.com/browserify/path-browserify>.
21102
- // Which is licensed:
21103
- //
21104
- // MIT License
21105
- //
21106
- // Copyright (c) 2013 James Halliday
21107
- //
21108
- // Permission is hereby granted, free of charge, to any person obtaining a copy of
21109
- // this software and associated documentation files (the "Software"), to deal in
21110
- // the Software without restriction, including without limitation the rights to
21111
- // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
21112
- // the Software, and to permit persons to whom the Software is furnished to do so,
21113
- // subject to the following conditions:
21114
- //
21115
- // The above copyright notice and this permission notice shall be included in all
21116
- // copies or substantial portions of the Software.
21117
- //
21118
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21119
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
21120
- // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21121
- // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21122
- // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21123
- // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21124
- // A derivative work based on:
21125
- //
21126
- // Parts of that are extracted from Node’s internal `path` module:
21127
- // <https://github.com/nodejs/node/blob/master/lib/path.js>.
21128
- // Which is licensed:
21129
- //
21130
- // Copyright Joyent, Inc. and other Node contributors.
21131
- //
21132
- // Permission is hereby granted, free of charge, to any person obtaining a
21133
- // copy of this software and associated documentation files (the
21134
- // "Software"), to deal in the Software without restriction, including
21135
- // without limitation the rights to use, copy, modify, merge, publish,
21136
- // distribute, sublicense, and/or sell copies of the Software, and to permit
21137
- // persons to whom the Software is furnished to do so, subject to the
21138
- // following conditions:
21139
- //
21140
- // The above copyright notice and this permission notice shall be included
21141
- // in all copies or substantial portions of the Software.
21142
- //
21143
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21144
- // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21145
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
21146
- // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21147
- // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21148
- // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21149
- // USE OR OTHER DEALINGS IN THE SOFTWARE.
21150
-
21151
- const minpath = {basename, dirname, extname, join, sep: '/'};
21152
-
21153
- /* eslint-disable max-depth, complexity */
20882
+ /**
20883
+ * Do not traverse this node’s children.
20884
+ */
20885
+ const SKIP = 'skip';
21154
20886
 
21155
20887
  /**
21156
- * Get the basename from a path.
20888
+ * Visit nodes, with ancestral information.
21157
20889
  *
21158
- * @param {string} path
21159
- * File path.
21160
- * @param {string | null | undefined} [extname]
21161
- * Extension to strip.
21162
- * @returns {string}
21163
- * Stem or basename.
20890
+ * This algorithm performs *depth-first* *tree traversal* in *preorder*
20891
+ * (**NLR**) or if `reverse` is given, in *reverse preorder* (**NRL**).
20892
+ *
20893
+ * You can choose for which nodes `visitor` is called by passing a `test`.
20894
+ * For complex tests, you should test yourself in `visitor`, as it will be
20895
+ * faster and will have improved type information.
20896
+ *
20897
+ * Walking the tree is an intensive task.
20898
+ * Make use of the return values of the visitor when possible.
20899
+ * Instead of walking a tree multiple times, walk it once, use `unist-util-is`
20900
+ * to check if a node matches, and then perform different operations.
20901
+ *
20902
+ * You can change the tree.
20903
+ * See `Visitor` for more info.
20904
+ *
20905
+ * @overload
20906
+ * @param {Tree} tree
20907
+ * @param {Check} check
20908
+ * @param {BuildVisitor<Tree, Check>} visitor
20909
+ * @param {boolean | null | undefined} [reverse]
20910
+ * @returns {undefined}
20911
+ *
20912
+ * @overload
20913
+ * @param {Tree} tree
20914
+ * @param {BuildVisitor<Tree>} visitor
20915
+ * @param {boolean | null | undefined} [reverse]
20916
+ * @returns {undefined}
20917
+ *
20918
+ * @param {UnistNode} tree
20919
+ * Tree to traverse.
20920
+ * @param {Visitor | Test} test
20921
+ * `unist-util-is`-compatible test
20922
+ * @param {Visitor | boolean | null | undefined} [visitor]
20923
+ * Handle each node.
20924
+ * @param {boolean | null | undefined} [reverse]
20925
+ * Traverse in reverse preorder (NRL) instead of the default preorder (NLR).
20926
+ * @returns {undefined}
20927
+ * Nothing.
20928
+ *
20929
+ * @template {UnistNode} Tree
20930
+ * Node type.
20931
+ * @template {Test} Check
20932
+ * `unist-util-is`-compatible test.
21164
20933
  */
21165
- function basename(path, extname) {
21166
- if (extname !== undefined && typeof extname !== 'string') {
21167
- throw new TypeError('"ext" argument must be a string')
21168
- }
21169
-
21170
- assertPath$1(path);
21171
- let start = 0;
21172
- let end = -1;
21173
- let index = path.length;
21174
- /** @type {boolean | undefined} */
21175
- let seenNonSlash;
21176
-
21177
- if (
21178
- extname === undefined ||
21179
- extname.length === 0 ||
21180
- extname.length > path.length
21181
- ) {
21182
- while (index--) {
21183
- if (path.codePointAt(index) === 47 /* `/` */) {
21184
- // If we reached a path separator that was not part of a set of path
21185
- // separators at the end of the string, stop now.
21186
- if (seenNonSlash) {
21187
- start = index + 1;
21188
- break
21189
- }
21190
- } else if (end < 0) {
21191
- // We saw the first non-path separator, mark this as the end of our
21192
- // path component.
21193
- seenNonSlash = true;
21194
- end = index + 1;
21195
- }
21196
- }
21197
-
21198
- return end < 0 ? '' : path.slice(start, end)
21199
- }
21200
-
21201
- if (extname === path) {
21202
- return ''
21203
- }
21204
-
21205
- let firstNonSlashEnd = -1;
21206
- let extnameIndex = extname.length - 1;
21207
-
21208
- while (index--) {
21209
- if (path.codePointAt(index) === 47 /* `/` */) {
21210
- // If we reached a path separator that was not part of a set of path
21211
- // separators at the end of the string, stop now.
21212
- if (seenNonSlash) {
21213
- start = index + 1;
21214
- break
21215
- }
21216
- } else {
21217
- if (firstNonSlashEnd < 0) {
21218
- // We saw the first non-path separator, remember this index in case
21219
- // we need it if the extension ends up not matching.
21220
- seenNonSlash = true;
21221
- firstNonSlashEnd = index + 1;
21222
- }
21223
-
21224
- if (extnameIndex > -1) {
21225
- // Try to match the explicit extension.
21226
- if (path.codePointAt(index) === extname.codePointAt(extnameIndex--)) {
21227
- if (extnameIndex < 0) {
21228
- // We matched the extension, so mark this as the end of our path
21229
- // component
21230
- end = index;
21231
- }
21232
- } else {
21233
- // Extension does not match, so our result is the entire path
21234
- // component
21235
- extnameIndex = -1;
21236
- end = firstNonSlashEnd;
21237
- }
21238
- }
21239
- }
21240
- }
21241
-
21242
- if (start === end) {
21243
- end = firstNonSlashEnd;
21244
- } else if (end < 0) {
21245
- end = path.length;
21246
- }
21247
-
21248
- return path.slice(start, end)
21249
- }
21250
-
21251
- /**
21252
- * Get the dirname from a path.
21253
- *
21254
- * @param {string} path
21255
- * File path.
21256
- * @returns {string}
21257
- * File path.
21258
- */
21259
- function dirname(path) {
21260
- assertPath$1(path);
21261
-
21262
- if (path.length === 0) {
21263
- return '.'
21264
- }
21265
-
21266
- let end = -1;
21267
- let index = path.length;
21268
- /** @type {boolean | undefined} */
21269
- let unmatchedSlash;
21270
-
21271
- // Prefix `--` is important to not run on `0`.
21272
- while (--index) {
21273
- if (path.codePointAt(index) === 47 /* `/` */) {
21274
- if (unmatchedSlash) {
21275
- end = index;
21276
- break
21277
- }
21278
- } else if (!unmatchedSlash) {
21279
- // We saw the first non-path separator
21280
- unmatchedSlash = true;
21281
- }
21282
- }
21283
-
21284
- return end < 0
21285
- ? path.codePointAt(0) === 47 /* `/` */
21286
- ? '/'
21287
- : '.'
21288
- : end === 1 && path.codePointAt(0) === 47 /* `/` */
21289
- ? '//'
21290
- : path.slice(0, end)
21291
- }
21292
-
21293
- /**
21294
- * Get an extname from a path.
21295
- *
21296
- * @param {string} path
21297
- * File path.
21298
- * @returns {string}
21299
- * Extname.
21300
- */
21301
- function extname(path) {
21302
- assertPath$1(path);
21303
-
21304
- let index = path.length;
21305
-
21306
- let end = -1;
21307
- let startPart = 0;
21308
- let startDot = -1;
21309
- // Track the state of characters (if any) we see before our first dot and
21310
- // after any path separator we find.
21311
- let preDotState = 0;
21312
- /** @type {boolean | undefined} */
21313
- let unmatchedSlash;
21314
-
21315
- while (index--) {
21316
- const code = path.codePointAt(index);
21317
-
21318
- if (code === 47 /* `/` */) {
21319
- // If we reached a path separator that was not part of a set of path
21320
- // separators at the end of the string, stop now.
21321
- if (unmatchedSlash) {
21322
- startPart = index + 1;
21323
- break
21324
- }
21325
-
21326
- continue
21327
- }
21328
-
21329
- if (end < 0) {
21330
- // We saw the first non-path separator, mark this as the end of our
21331
- // extension.
21332
- unmatchedSlash = true;
21333
- end = index + 1;
21334
- }
21335
-
21336
- if (code === 46 /* `.` */) {
21337
- // If this is our first dot, mark it as the start of our extension.
21338
- if (startDot < 0) {
21339
- startDot = index;
21340
- } else if (preDotState !== 1) {
21341
- preDotState = 1;
21342
- }
21343
- } else if (startDot > -1) {
21344
- // We saw a non-dot and non-path separator before our dot, so we should
21345
- // have a good chance at having a non-empty extension.
21346
- preDotState = -1;
21347
- }
21348
- }
21349
-
21350
- if (
21351
- startDot < 0 ||
21352
- end < 0 ||
21353
- // We saw a non-dot character immediately before the dot.
21354
- preDotState === 0 ||
21355
- // The (right-most) trimmed path component is exactly `..`.
21356
- (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)
21357
- ) {
21358
- return ''
21359
- }
21360
-
21361
- return path.slice(startDot, end)
21362
- }
21363
-
21364
- /**
21365
- * Join segments from a path.
21366
- *
21367
- * @param {Array<string>} segments
21368
- * Path segments.
21369
- * @returns {string}
21370
- * File path.
21371
- */
21372
- function join(...segments) {
21373
- let index = -1;
21374
- /** @type {string | undefined} */
21375
- let joined;
21376
-
21377
- while (++index < segments.length) {
21378
- assertPath$1(segments[index]);
21379
-
21380
- if (segments[index]) {
21381
- joined =
21382
- joined === undefined ? segments[index] : joined + '/' + segments[index];
21383
- }
21384
- }
21385
-
21386
- return joined === undefined ? '.' : normalize(joined)
21387
- }
21388
-
21389
- /**
21390
- * Normalize a basic file path.
21391
- *
21392
- * @param {string} path
21393
- * File path.
21394
- * @returns {string}
21395
- * File path.
21396
- */
21397
- // Note: `normalize` is not exposed as `path.normalize`, so some code is
21398
- // manually removed from it.
21399
- function normalize(path) {
21400
- assertPath$1(path);
21401
-
21402
- const absolute = path.codePointAt(0) === 47; /* `/` */
21403
-
21404
- // Normalize the path according to POSIX rules.
21405
- let value = normalizeString(path, !absolute);
21406
-
21407
- if (value.length === 0 && !absolute) {
21408
- value = '.';
21409
- }
21410
-
21411
- if (value.length > 0 && path.codePointAt(path.length - 1) === 47 /* / */) {
21412
- value += '/';
21413
- }
21414
-
21415
- return absolute ? '/' + value : value
21416
- }
21417
-
21418
- /**
21419
- * Resolve `.` and `..` elements in a path with directory names.
21420
- *
21421
- * @param {string} path
21422
- * File path.
21423
- * @param {boolean} allowAboveRoot
21424
- * Whether `..` can move above root.
21425
- * @returns {string}
21426
- * File path.
21427
- */
21428
- function normalizeString(path, allowAboveRoot) {
21429
- let result = '';
21430
- let lastSegmentLength = 0;
21431
- let lastSlash = -1;
21432
- let dots = 0;
21433
- let index = -1;
21434
- /** @type {number | undefined} */
21435
- let code;
21436
- /** @type {number} */
21437
- let lastSlashIndex;
21438
-
21439
- while (++index <= path.length) {
21440
- if (index < path.length) {
21441
- code = path.codePointAt(index);
21442
- } else if (code === 47 /* `/` */) {
21443
- break
21444
- } else {
21445
- code = 47; /* `/` */
21446
- }
21447
-
21448
- if (code === 47 /* `/` */) {
21449
- if (lastSlash === index - 1 || dots === 1) ; else if (lastSlash !== index - 1 && dots === 2) {
21450
- if (
21451
- result.length < 2 ||
21452
- lastSegmentLength !== 2 ||
21453
- result.codePointAt(result.length - 1) !== 46 /* `.` */ ||
21454
- result.codePointAt(result.length - 2) !== 46 /* `.` */
21455
- ) {
21456
- if (result.length > 2) {
21457
- lastSlashIndex = result.lastIndexOf('/');
21458
-
21459
- if (lastSlashIndex !== result.length - 1) {
21460
- if (lastSlashIndex < 0) {
21461
- result = '';
21462
- lastSegmentLength = 0;
21463
- } else {
21464
- result = result.slice(0, lastSlashIndex);
21465
- lastSegmentLength = result.length - 1 - result.lastIndexOf('/');
21466
- }
21467
-
21468
- lastSlash = index;
21469
- dots = 0;
21470
- continue
21471
- }
21472
- } else if (result.length > 0) {
21473
- result = '';
21474
- lastSegmentLength = 0;
21475
- lastSlash = index;
21476
- dots = 0;
21477
- continue
21478
- }
21479
- }
21480
-
21481
- if (allowAboveRoot) {
21482
- result = result.length > 0 ? result + '/..' : '..';
21483
- lastSegmentLength = 2;
21484
- }
21485
- } else {
21486
- if (result.length > 0) {
21487
- result += '/' + path.slice(lastSlash + 1, index);
21488
- } else {
21489
- result = path.slice(lastSlash + 1, index);
21490
- }
21491
-
21492
- lastSegmentLength = index - lastSlash - 1;
21493
- }
21494
-
21495
- lastSlash = index;
21496
- dots = 0;
21497
- } else if (code === 46 /* `.` */ && dots > -1) {
21498
- dots++;
21499
- } else {
21500
- dots = -1;
21501
- }
21502
- }
21503
-
21504
- return result
21505
- }
21506
-
21507
- /**
21508
- * Make sure `path` is a string.
21509
- *
21510
- * @param {string} path
21511
- * File path.
21512
- * @returns {asserts path is string}
21513
- * Nothing.
21514
- */
21515
- function assertPath$1(path) {
21516
- if (typeof path !== 'string') {
21517
- throw new TypeError(
21518
- 'Path must be a string. Received ' + JSON.stringify(path)
21519
- )
21520
- }
21521
- }
21522
-
21523
- /* eslint-enable max-depth, complexity */
21524
-
21525
- // Somewhat based on:
21526
- // <https://github.com/defunctzombie/node-process/blob/master/browser.js>.
21527
- // But I don’t think one tiny line of code can be copyrighted. 😅
21528
- const minproc = {cwd};
21529
-
21530
- function cwd() {
21531
- return '/'
21532
- }
21533
-
21534
- /**
21535
- * Checks if a value has the shape of a WHATWG URL object.
21536
- *
21537
- * Using a symbol or instanceof would not be able to recognize URL objects
21538
- * coming from other implementations (e.g. in Electron), so instead we are
21539
- * checking some well known properties for a lack of a better test.
21540
- *
21541
- * We use `href` and `protocol` as they are the only properties that are
21542
- * easy to retrieve and calculate due to the lazy nature of the getters.
21543
- *
21544
- * We check for auth attribute to distinguish legacy url instance with
21545
- * WHATWG URL instance.
21546
- *
21547
- * @param {unknown} fileUrlOrPath
21548
- * File path or URL.
21549
- * @returns {fileUrlOrPath is URL}
21550
- * Whether it’s a URL.
21551
- */
21552
- // From: <https://github.com/nodejs/node/blob/6a3403c/lib/internal/url.js#L720>
21553
- function isUrl(fileUrlOrPath) {
21554
- return Boolean(
21555
- fileUrlOrPath !== null &&
21556
- typeof fileUrlOrPath === 'object' &&
21557
- 'href' in fileUrlOrPath &&
21558
- fileUrlOrPath.href &&
21559
- 'protocol' in fileUrlOrPath &&
21560
- fileUrlOrPath.protocol &&
21561
- // @ts-expect-error: indexing is fine.
21562
- fileUrlOrPath.auth === undefined
21563
- )
21564
- }
21565
-
21566
- // See: <https://github.com/nodejs/node/blob/6a3403c/lib/internal/url.js>
21567
-
21568
- /**
21569
- * @param {URL | string} path
21570
- * File URL.
21571
- * @returns {string}
21572
- * File URL.
21573
- */
21574
- function urlToPath(path) {
21575
- if (typeof path === 'string') {
21576
- path = new URL(path);
21577
- } else if (!isUrl(path)) {
21578
- /** @type {NodeJS.ErrnoException} */
21579
- const error = new TypeError(
21580
- 'The "path" argument must be of type string or an instance of URL. Received `' +
21581
- path +
21582
- '`'
21583
- );
21584
- error.code = 'ERR_INVALID_ARG_TYPE';
21585
- throw error
21586
- }
21587
-
21588
- if (path.protocol !== 'file:') {
21589
- /** @type {NodeJS.ErrnoException} */
21590
- const error = new TypeError('The URL must be of scheme file');
21591
- error.code = 'ERR_INVALID_URL_SCHEME';
21592
- throw error
21593
- }
21594
-
21595
- return getPathFromURLPosix(path)
21596
- }
21597
-
21598
- /**
21599
- * Get a path from a POSIX URL.
21600
- *
21601
- * @param {URL} url
21602
- * URL.
21603
- * @returns {string}
21604
- * File path.
21605
- */
21606
- function getPathFromURLPosix(url) {
21607
- if (url.hostname !== '') {
21608
- /** @type {NodeJS.ErrnoException} */
21609
- const error = new TypeError(
21610
- 'File URL host must be "localhost" or empty on darwin'
21611
- );
21612
- error.code = 'ERR_INVALID_FILE_URL_HOST';
21613
- throw error
21614
- }
21615
-
21616
- const pathname = url.pathname;
21617
- let index = -1;
21618
-
21619
- while (++index < pathname.length) {
21620
- if (
21621
- pathname.codePointAt(index) === 37 /* `%` */ &&
21622
- pathname.codePointAt(index + 1) === 50 /* `2` */
21623
- ) {
21624
- const third = pathname.codePointAt(index + 2);
21625
- if (third === 70 /* `F` */ || third === 102 /* `f` */) {
21626
- /** @type {NodeJS.ErrnoException} */
21627
- const error = new TypeError(
21628
- 'File URL path must not include encoded / characters'
21629
- );
21630
- error.code = 'ERR_INVALID_FILE_URL_PATH';
21631
- throw error
21632
- }
21633
- }
21634
- }
21635
-
21636
- return decodeURIComponent(pathname)
21637
- }
21638
-
21639
- /**
21640
- * @import {Node, Point, Position} from 'unist'
21641
- * @import {Options as MessageOptions} from 'vfile-message'
21642
- * @import {Compatible, Data, Map, Options, Value} from 'vfile'
21643
- */
21644
-
21645
-
21646
- /**
21647
- * Order of setting (least specific to most), we need this because otherwise
21648
- * `{stem: 'a', path: '~/b.js'}` would throw, as a path is needed before a
21649
- * stem can be set.
21650
- */
21651
- const order = /** @type {const} */ ([
21652
- 'history',
21653
- 'path',
21654
- 'basename',
21655
- 'stem',
21656
- 'extname',
21657
- 'dirname'
21658
- ]);
21659
-
21660
- class VFile {
21661
- /**
21662
- * Create a new virtual file.
21663
- *
21664
- * `options` is treated as:
21665
- *
21666
- * * `string` or `Uint8Array` — `{value: options}`
21667
- * * `URL` — `{path: options}`
21668
- * * `VFile` — shallow copies its data over to the new file
21669
- * * `object` — all fields are shallow copied over to the new file
21670
- *
21671
- * Path related fields are set in the following order (least specific to
21672
- * most specific): `history`, `path`, `basename`, `stem`, `extname`,
21673
- * `dirname`.
21674
- *
21675
- * You cannot set `dirname` or `extname` without setting either `history`,
21676
- * `path`, `basename`, or `stem` too.
21677
- *
21678
- * @param {Compatible | null | undefined} [value]
21679
- * File value.
21680
- * @returns
21681
- * New instance.
21682
- */
21683
- constructor(value) {
21684
- /** @type {Options | VFile} */
21685
- let options;
21686
-
21687
- if (!value) {
21688
- options = {};
21689
- } else if (isUrl(value)) {
21690
- options = {path: value};
21691
- } else if (typeof value === 'string' || isUint8Array(value)) {
21692
- options = {value};
21693
- } else {
21694
- options = value;
21695
- }
21696
-
21697
- /* eslint-disable no-unused-expressions */
21698
-
21699
- /**
21700
- * Base of `path` (default: `process.cwd()` or `'/'` in browsers).
21701
- *
21702
- * @type {string}
21703
- */
21704
- // Prevent calling `cwd` (which could be expensive) if it’s not needed;
21705
- // the empty string will be overridden in the next block.
21706
- this.cwd = 'cwd' in options ? '' : minproc.cwd();
21707
-
21708
- /**
21709
- * Place to store custom info (default: `{}`).
21710
- *
21711
- * It’s OK to store custom data directly on the file but moving it to
21712
- * `data` is recommended.
21713
- *
21714
- * @type {Data}
21715
- */
21716
- this.data = {};
21717
-
21718
- /**
21719
- * List of file paths the file moved between.
21720
- *
21721
- * The first is the original path and the last is the current path.
21722
- *
21723
- * @type {Array<string>}
21724
- */
21725
- this.history = [];
21726
-
21727
- /**
21728
- * List of messages associated with the file.
21729
- *
21730
- * @type {Array<VFileMessage>}
21731
- */
21732
- this.messages = [];
21733
-
21734
- /**
21735
- * Raw value.
21736
- *
21737
- * @type {Value}
21738
- */
21739
- this.value;
21740
-
21741
- // The below are non-standard, they are “well-known”.
21742
- // As in, used in several tools.
21743
- /**
21744
- * Source map.
21745
- *
21746
- * This type is equivalent to the `RawSourceMap` type from the `source-map`
21747
- * module.
21748
- *
21749
- * @type {Map | null | undefined}
21750
- */
21751
- this.map;
21752
-
21753
- /**
21754
- * Custom, non-string, compiled, representation.
21755
- *
21756
- * This is used by unified to store non-string results.
21757
- * One example is when turning markdown into React nodes.
21758
- *
21759
- * @type {unknown}
21760
- */
21761
- this.result;
21762
-
21763
- /**
21764
- * Whether a file was saved to disk.
21765
- *
21766
- * This is used by vfile reporters.
21767
- *
21768
- * @type {boolean}
21769
- */
21770
- this.stored;
21771
- /* eslint-enable no-unused-expressions */
21772
-
21773
- // Set path related properties in the correct order.
21774
- let index = -1;
21775
-
21776
- while (++index < order.length) {
21777
- const field = order[index];
21778
-
21779
- // Note: we specifically use `in` instead of `hasOwnProperty` to accept
21780
- // `vfile`s too.
21781
- if (
21782
- field in options &&
21783
- options[field] !== undefined &&
21784
- options[field] !== null
21785
- ) {
21786
- // @ts-expect-error: TS doesn’t understand basic reality.
21787
- this[field] = field === 'history' ? [...options[field]] : options[field];
21788
- }
21789
- }
21790
-
21791
- /** @type {string} */
21792
- let field;
21793
-
21794
- // Set non-path related properties.
21795
- for (field in options) {
21796
- // @ts-expect-error: fine to set other things.
21797
- if (!order.includes(field)) {
21798
- // @ts-expect-error: fine to set other things.
21799
- this[field] = options[field];
21800
- }
21801
- }
21802
- }
21803
-
21804
- /**
21805
- * Get the basename (including extname) (example: `'index.min.js'`).
21806
- *
21807
- * @returns {string | undefined}
21808
- * Basename.
21809
- */
21810
- get basename() {
21811
- return typeof this.path === 'string'
21812
- ? minpath.basename(this.path)
21813
- : undefined
21814
- }
21815
-
21816
- /**
21817
- * Set basename (including extname) (`'index.min.js'`).
21818
- *
21819
- * Cannot contain path separators (`'/'` on unix, macOS, and browsers, `'\'`
21820
- * on windows).
21821
- * Cannot be nullified (use `file.path = file.dirname` instead).
21822
- *
21823
- * @param {string} basename
21824
- * Basename.
21825
- * @returns {undefined}
21826
- * Nothing.
21827
- */
21828
- set basename(basename) {
21829
- assertNonEmpty(basename, 'basename');
21830
- assertPart(basename, 'basename');
21831
- this.path = minpath.join(this.dirname || '', basename);
21832
- }
21833
-
21834
- /**
21835
- * Get the parent path (example: `'~'`).
21836
- *
21837
- * @returns {string | undefined}
21838
- * Dirname.
21839
- */
21840
- get dirname() {
21841
- return typeof this.path === 'string'
21842
- ? minpath.dirname(this.path)
21843
- : undefined
21844
- }
21845
-
21846
- /**
21847
- * Set the parent path (example: `'~'`).
21848
- *
21849
- * Cannot be set if there’s no `path` yet.
21850
- *
21851
- * @param {string | undefined} dirname
21852
- * Dirname.
21853
- * @returns {undefined}
21854
- * Nothing.
21855
- */
21856
- set dirname(dirname) {
21857
- assertPath(this.basename, 'dirname');
21858
- this.path = minpath.join(dirname || '', this.basename);
21859
- }
21860
-
21861
- /**
21862
- * Get the extname (including dot) (example: `'.js'`).
21863
- *
21864
- * @returns {string | undefined}
21865
- * Extname.
21866
- */
21867
- get extname() {
21868
- return typeof this.path === 'string'
21869
- ? minpath.extname(this.path)
21870
- : undefined
21871
- }
21872
-
21873
- /**
21874
- * Set the extname (including dot) (example: `'.js'`).
21875
- *
21876
- * Cannot contain path separators (`'/'` on unix, macOS, and browsers, `'\'`
21877
- * on windows).
21878
- * Cannot be set if there’s no `path` yet.
21879
- *
21880
- * @param {string | undefined} extname
21881
- * Extname.
21882
- * @returns {undefined}
21883
- * Nothing.
21884
- */
21885
- set extname(extname) {
21886
- assertPart(extname, 'extname');
21887
- assertPath(this.dirname, 'extname');
21888
-
21889
- if (extname) {
21890
- if (extname.codePointAt(0) !== 46 /* `.` */) {
21891
- throw new Error('`extname` must start with `.`')
21892
- }
21893
-
21894
- if (extname.includes('.', 1)) {
21895
- throw new Error('`extname` cannot contain multiple dots')
21896
- }
21897
- }
21898
-
21899
- this.path = minpath.join(this.dirname, this.stem + (extname || ''));
21900
- }
21901
-
21902
- /**
21903
- * Get the full path (example: `'~/index.min.js'`).
21904
- *
21905
- * @returns {string}
21906
- * Path.
21907
- */
21908
- get path() {
21909
- return this.history[this.history.length - 1]
21910
- }
21911
-
21912
- /**
21913
- * Set the full path (example: `'~/index.min.js'`).
21914
- *
21915
- * Cannot be nullified.
21916
- * You can set a file URL (a `URL` object with a `file:` protocol) which will
21917
- * be turned into a path with `url.fileURLToPath`.
21918
- *
21919
- * @param {URL | string} path
21920
- * Path.
21921
- * @returns {undefined}
21922
- * Nothing.
21923
- */
21924
- set path(path) {
21925
- if (isUrl(path)) {
21926
- path = urlToPath(path);
21927
- }
21928
-
21929
- assertNonEmpty(path, 'path');
21930
-
21931
- if (this.path !== path) {
21932
- this.history.push(path);
21933
- }
21934
- }
21935
-
21936
- /**
21937
- * Get the stem (basename w/o extname) (example: `'index.min'`).
21938
- *
21939
- * @returns {string | undefined}
21940
- * Stem.
21941
- */
21942
- get stem() {
21943
- return typeof this.path === 'string'
21944
- ? minpath.basename(this.path, this.extname)
21945
- : undefined
21946
- }
21947
-
21948
- /**
21949
- * Set the stem (basename w/o extname) (example: `'index.min'`).
21950
- *
21951
- * Cannot contain path separators (`'/'` on unix, macOS, and browsers, `'\'`
21952
- * on windows).
21953
- * Cannot be nullified (use `file.path = file.dirname` instead).
21954
- *
21955
- * @param {string} stem
21956
- * Stem.
21957
- * @returns {undefined}
21958
- * Nothing.
21959
- */
21960
- set stem(stem) {
21961
- assertNonEmpty(stem, 'stem');
21962
- assertPart(stem, 'stem');
21963
- this.path = minpath.join(this.dirname || '', stem + (this.extname || ''));
21964
- }
21965
-
21966
- // Normal prototypal methods.
21967
- /**
21968
- * Create a fatal message for `reason` associated with the file.
21969
- *
21970
- * The `fatal` field of the message is set to `true` (error; file not usable)
21971
- * and the `file` field is set to the current file path.
21972
- * The message is added to the `messages` field on `file`.
21973
- *
21974
- * > 🪦 **Note**: also has obsolete signatures.
21975
- *
21976
- * @overload
21977
- * @param {string} reason
21978
- * @param {MessageOptions | null | undefined} [options]
21979
- * @returns {never}
21980
- *
21981
- * @overload
21982
- * @param {string} reason
21983
- * @param {Node | NodeLike | null | undefined} parent
21984
- * @param {string | null | undefined} [origin]
21985
- * @returns {never}
21986
- *
21987
- * @overload
21988
- * @param {string} reason
21989
- * @param {Point | Position | null | undefined} place
21990
- * @param {string | null | undefined} [origin]
21991
- * @returns {never}
21992
- *
21993
- * @overload
21994
- * @param {string} reason
21995
- * @param {string | null | undefined} [origin]
21996
- * @returns {never}
21997
- *
21998
- * @overload
21999
- * @param {Error | VFileMessage} cause
22000
- * @param {Node | NodeLike | null | undefined} parent
22001
- * @param {string | null | undefined} [origin]
22002
- * @returns {never}
22003
- *
22004
- * @overload
22005
- * @param {Error | VFileMessage} cause
22006
- * @param {Point | Position | null | undefined} place
22007
- * @param {string | null | undefined} [origin]
22008
- * @returns {never}
22009
- *
22010
- * @overload
22011
- * @param {Error | VFileMessage} cause
22012
- * @param {string | null | undefined} [origin]
22013
- * @returns {never}
22014
- *
22015
- * @param {Error | VFileMessage | string} causeOrReason
22016
- * Reason for message, should use markdown.
22017
- * @param {Node | NodeLike | MessageOptions | Point | Position | string | null | undefined} [optionsOrParentOrPlace]
22018
- * Configuration (optional).
22019
- * @param {string | null | undefined} [origin]
22020
- * Place in code where the message originates (example:
22021
- * `'my-package:my-rule'` or `'my-rule'`).
22022
- * @returns {never}
22023
- * Never.
22024
- * @throws {VFileMessage}
22025
- * Message.
22026
- */
22027
- fail(causeOrReason, optionsOrParentOrPlace, origin) {
22028
- // @ts-expect-error: the overloads are fine.
22029
- const message = this.message(causeOrReason, optionsOrParentOrPlace, origin);
22030
-
22031
- message.fatal = true;
22032
-
22033
- throw message
22034
- }
22035
-
22036
- /**
22037
- * Create an info message for `reason` associated with the file.
22038
- *
22039
- * The `fatal` field of the message is set to `undefined` (info; change
22040
- * likely not needed) and the `file` field is set to the current file path.
22041
- * The message is added to the `messages` field on `file`.
22042
- *
22043
- * > 🪦 **Note**: also has obsolete signatures.
22044
- *
22045
- * @overload
22046
- * @param {string} reason
22047
- * @param {MessageOptions | null | undefined} [options]
22048
- * @returns {VFileMessage}
22049
- *
22050
- * @overload
22051
- * @param {string} reason
22052
- * @param {Node | NodeLike | null | undefined} parent
22053
- * @param {string | null | undefined} [origin]
22054
- * @returns {VFileMessage}
22055
- *
22056
- * @overload
22057
- * @param {string} reason
22058
- * @param {Point | Position | null | undefined} place
22059
- * @param {string | null | undefined} [origin]
22060
- * @returns {VFileMessage}
22061
- *
22062
- * @overload
22063
- * @param {string} reason
22064
- * @param {string | null | undefined} [origin]
22065
- * @returns {VFileMessage}
22066
- *
22067
- * @overload
22068
- * @param {Error | VFileMessage} cause
22069
- * @param {Node | NodeLike | null | undefined} parent
22070
- * @param {string | null | undefined} [origin]
22071
- * @returns {VFileMessage}
22072
- *
22073
- * @overload
22074
- * @param {Error | VFileMessage} cause
22075
- * @param {Point | Position | null | undefined} place
22076
- * @param {string | null | undefined} [origin]
22077
- * @returns {VFileMessage}
22078
- *
22079
- * @overload
22080
- * @param {Error | VFileMessage} cause
22081
- * @param {string | null | undefined} [origin]
22082
- * @returns {VFileMessage}
22083
- *
22084
- * @param {Error | VFileMessage | string} causeOrReason
22085
- * Reason for message, should use markdown.
22086
- * @param {Node | NodeLike | MessageOptions | Point | Position | string | null | undefined} [optionsOrParentOrPlace]
22087
- * Configuration (optional).
22088
- * @param {string | null | undefined} [origin]
22089
- * Place in code where the message originates (example:
22090
- * `'my-package:my-rule'` or `'my-rule'`).
22091
- * @returns {VFileMessage}
22092
- * Message.
22093
- */
22094
- info(causeOrReason, optionsOrParentOrPlace, origin) {
22095
- // @ts-expect-error: the overloads are fine.
22096
- const message = this.message(causeOrReason, optionsOrParentOrPlace, origin);
22097
-
22098
- message.fatal = undefined;
22099
-
22100
- return message
22101
- }
22102
-
22103
- /**
22104
- * Create a message for `reason` associated with the file.
22105
- *
22106
- * The `fatal` field of the message is set to `false` (warning; change may be
22107
- * needed) and the `file` field is set to the current file path.
22108
- * The message is added to the `messages` field on `file`.
22109
- *
22110
- * > 🪦 **Note**: also has obsolete signatures.
22111
- *
22112
- * @overload
22113
- * @param {string} reason
22114
- * @param {MessageOptions | null | undefined} [options]
22115
- * @returns {VFileMessage}
22116
- *
22117
- * @overload
22118
- * @param {string} reason
22119
- * @param {Node | NodeLike | null | undefined} parent
22120
- * @param {string | null | undefined} [origin]
22121
- * @returns {VFileMessage}
22122
- *
22123
- * @overload
22124
- * @param {string} reason
22125
- * @param {Point | Position | null | undefined} place
22126
- * @param {string | null | undefined} [origin]
22127
- * @returns {VFileMessage}
22128
- *
22129
- * @overload
22130
- * @param {string} reason
22131
- * @param {string | null | undefined} [origin]
22132
- * @returns {VFileMessage}
22133
- *
22134
- * @overload
22135
- * @param {Error | VFileMessage} cause
22136
- * @param {Node | NodeLike | null | undefined} parent
22137
- * @param {string | null | undefined} [origin]
22138
- * @returns {VFileMessage}
22139
- *
22140
- * @overload
22141
- * @param {Error | VFileMessage} cause
22142
- * @param {Point | Position | null | undefined} place
22143
- * @param {string | null | undefined} [origin]
22144
- * @returns {VFileMessage}
22145
- *
22146
- * @overload
22147
- * @param {Error | VFileMessage} cause
22148
- * @param {string | null | undefined} [origin]
22149
- * @returns {VFileMessage}
22150
- *
22151
- * @param {Error | VFileMessage | string} causeOrReason
22152
- * Reason for message, should use markdown.
22153
- * @param {Node | NodeLike | MessageOptions | Point | Position | string | null | undefined} [optionsOrParentOrPlace]
22154
- * Configuration (optional).
22155
- * @param {string | null | undefined} [origin]
22156
- * Place in code where the message originates (example:
22157
- * `'my-package:my-rule'` or `'my-rule'`).
22158
- * @returns {VFileMessage}
22159
- * Message.
20934
+ function visitParents(tree, test, visitor, reverse) {
20935
+ /** @type {Test} */
20936
+ let check;
20937
+
20938
+ if (typeof test === 'function' && typeof visitor !== 'function') {
20939
+ reverse = visitor;
20940
+ // @ts-expect-error no visitor given, so `visitor` is test.
20941
+ visitor = test;
20942
+ } else {
20943
+ // @ts-expect-error visitor given, so `test` isn’t a visitor.
20944
+ check = test;
20945
+ }
20946
+
20947
+ const is = convert(check);
20948
+ const step = reverse ? -1 : 1;
20949
+
20950
+ factory(tree, undefined, [])();
20951
+
20952
+ /**
20953
+ * @param {UnistNode} node
20954
+ * @param {number | undefined} index
20955
+ * @param {Array<UnistParent>} parents
22160
20956
  */
22161
- message(causeOrReason, optionsOrParentOrPlace, origin) {
22162
- const message = new VFileMessage(
22163
- // @ts-expect-error: the overloads are fine.
22164
- causeOrReason,
22165
- optionsOrParentOrPlace,
22166
- origin
20957
+ function factory(node, index, parents) {
20958
+ const value = /** @type {Record<string, unknown>} */ (
20959
+ node && typeof node === 'object' ? node : {}
22167
20960
  );
22168
20961
 
22169
- if (this.path) {
22170
- message.name = this.path + ':' + message.name;
22171
- message.file = this.path;
20962
+ if (typeof value.type === 'string') {
20963
+ const name =
20964
+ // `hast`
20965
+ typeof value.tagName === 'string'
20966
+ ? value.tagName
20967
+ : // `xast`
20968
+ typeof value.name === 'string'
20969
+ ? value.name
20970
+ : undefined;
20971
+
20972
+ Object.defineProperty(visit, 'name', {
20973
+ value:
20974
+ 'node (' + color(node.type + (name ? '<' + name + '>' : '')) + ')'
20975
+ });
22172
20976
  }
22173
20977
 
22174
- message.fatal = false;
20978
+ return visit
22175
20979
 
22176
- this.messages.push(message);
20980
+ function visit() {
20981
+ /** @type {Readonly<ActionTuple>} */
20982
+ let result = empty;
20983
+ /** @type {Readonly<ActionTuple>} */
20984
+ let subresult;
20985
+ /** @type {number} */
20986
+ let offset;
20987
+ /** @type {Array<UnistParent>} */
20988
+ let grandparents;
22177
20989
 
22178
- return message
22179
- }
20990
+ if (!test || is(node, index, parents[parents.length - 1] || undefined)) {
20991
+ // @ts-expect-error: `visitor` is now a visitor.
20992
+ result = toResult(visitor(node, parents));
22180
20993
 
22181
- /**
22182
- * Serialize the file.
22183
- *
22184
- * > **Note**: which encodings are supported depends on the engine.
22185
- * > For info on Node.js, see:
22186
- * > <https://nodejs.org/api/util.html#whatwg-supported-encodings>.
22187
- *
22188
- * @param {string | null | undefined} [encoding='utf8']
22189
- * Character encoding to understand `value` as when it’s a `Uint8Array`
22190
- * (default: `'utf-8'`).
22191
- * @returns {string}
22192
- * Serialized file.
22193
- */
22194
- toString(encoding) {
22195
- if (this.value === undefined) {
22196
- return ''
22197
- }
20994
+ if (result[0] === EXIT) {
20995
+ return result
20996
+ }
20997
+ }
22198
20998
 
22199
- if (typeof this.value === 'string') {
22200
- return this.value
22201
- }
20999
+ if ('children' in node && node.children) {
21000
+ const nodeAsParent = /** @type {UnistParent} */ (node);
22202
21001
 
22203
- const decoder = new TextDecoder(encoding || undefined);
22204
- return decoder.decode(this.value)
21002
+ if (nodeAsParent.children && result[0] !== SKIP) {
21003
+ offset = (reverse ? nodeAsParent.children.length : -1) + step;
21004
+ grandparents = parents.concat(nodeAsParent);
21005
+
21006
+ while (offset > -1 && offset < nodeAsParent.children.length) {
21007
+ const child = nodeAsParent.children[offset];
21008
+
21009
+ subresult = factory(child, offset, grandparents)();
21010
+
21011
+ if (subresult[0] === EXIT) {
21012
+ return subresult
21013
+ }
21014
+
21015
+ offset =
21016
+ typeof subresult[1] === 'number' ? subresult[1] : offset + step;
21017
+ }
21018
+ }
21019
+ }
21020
+
21021
+ return result
21022
+ }
22205
21023
  }
22206
21024
  }
22207
21025
 
22208
21026
  /**
22209
- * Assert that `part` is not a path (as in, does not contain `path.sep`).
21027
+ * Turn a return value into a clean result.
22210
21028
  *
22211
- * @param {string | null | undefined} part
22212
- * File path part.
22213
- * @param {string} name
22214
- * Part name.
22215
- * @returns {undefined}
22216
- * Nothing.
21029
+ * @param {VisitorResult} value
21030
+ * Valid return values from visitors.
21031
+ * @returns {Readonly<ActionTuple>}
21032
+ * Clean result.
22217
21033
  */
22218
- function assertPart(part, name) {
22219
- if (part && part.includes(minpath.sep)) {
22220
- throw new Error(
22221
- '`' + name + '` cannot be a path: did not expect `' + minpath.sep + '`'
22222
- )
21034
+ function toResult(value) {
21035
+ if (Array.isArray(value)) {
21036
+ return value
21037
+ }
21038
+
21039
+ if (typeof value === 'number') {
21040
+ return [CONTINUE, value]
22223
21041
  }
21042
+
21043
+ return value === null || value === undefined ? empty : [value]
22224
21044
  }
22225
21045
 
22226
21046
  /**
22227
- * Assert that `part` is not empty.
22228
- *
22229
- * @param {string | undefined} part
22230
- * Thing.
22231
- * @param {string} name
22232
- * Part name.
22233
- * @returns {asserts part is string}
22234
- * Nothing.
21047
+ * @typedef {import('unist').Node} UnistNode
21048
+ * @typedef {import('unist').Parent} UnistParent
21049
+ * @typedef {import('unist-util-visit-parents').VisitorResult} VisitorResult
22235
21050
  */
22236
- function assertNonEmpty(part, name) {
22237
- if (!part) {
22238
- throw new Error('`' + name + '` cannot be empty')
22239
- }
22240
- }
21051
+
22241
21052
 
22242
21053
  /**
22243
- * Assert `path` exists.
21054
+ * Visit nodes.
22244
21055
  *
22245
- * @param {string | undefined} path
22246
- * Path.
22247
- * @param {string} name
22248
- * Dependency name.
22249
- * @returns {asserts path is string}
21056
+ * This algorithm performs *depth-first* *tree traversal* in *preorder*
21057
+ * (**NLR**) or if `reverse` is given, in *reverse preorder* (**NRL**).
21058
+ *
21059
+ * You can choose for which nodes `visitor` is called by passing a `test`.
21060
+ * For complex tests, you should test yourself in `visitor`, as it will be
21061
+ * faster and will have improved type information.
21062
+ *
21063
+ * Walking the tree is an intensive task.
21064
+ * Make use of the return values of the visitor when possible.
21065
+ * Instead of walking a tree multiple times, walk it once, use `unist-util-is`
21066
+ * to check if a node matches, and then perform different operations.
21067
+ *
21068
+ * You can change the tree.
21069
+ * See `Visitor` for more info.
21070
+ *
21071
+ * @overload
21072
+ * @param {Tree} tree
21073
+ * @param {Check} check
21074
+ * @param {BuildVisitor<Tree, Check>} visitor
21075
+ * @param {boolean | null | undefined} [reverse]
21076
+ * @returns {undefined}
21077
+ *
21078
+ * @overload
21079
+ * @param {Tree} tree
21080
+ * @param {BuildVisitor<Tree>} visitor
21081
+ * @param {boolean | null | undefined} [reverse]
21082
+ * @returns {undefined}
21083
+ *
21084
+ * @param {UnistNode} tree
21085
+ * Tree to traverse.
21086
+ * @param {Visitor | Test} testOrVisitor
21087
+ * `unist-util-is`-compatible test (optional, omit to pass a visitor).
21088
+ * @param {Visitor | boolean | null | undefined} [visitorOrReverse]
21089
+ * Handle each node (when test is omitted, pass `reverse`).
21090
+ * @param {boolean | null | undefined} [maybeReverse=false]
21091
+ * Traverse in reverse preorder (NRL) instead of the default preorder (NLR).
21092
+ * @returns {undefined}
22250
21093
  * Nothing.
21094
+ *
21095
+ * @template {UnistNode} Tree
21096
+ * Node type.
21097
+ * @template {Test} Check
21098
+ * `unist-util-is`-compatible test.
22251
21099
  */
22252
- function assertPath(path, name) {
22253
- if (!path) {
22254
- throw new Error('Setting `' + name + '` requires `path` to be set too')
21100
+ function visit(tree, testOrVisitor, visitorOrReverse, maybeReverse) {
21101
+ /** @type {boolean | null | undefined} */
21102
+ let reverse;
21103
+ /** @type {Test} */
21104
+ let test;
21105
+ /** @type {Visitor} */
21106
+ let visitor;
21107
+
21108
+ if (
21109
+ typeof testOrVisitor === 'function' &&
21110
+ typeof visitorOrReverse !== 'function'
21111
+ ) {
21112
+ test = undefined;
21113
+ visitor = testOrVisitor;
21114
+ reverse = visitorOrReverse;
21115
+ } else {
21116
+ // @ts-expect-error: assume the overload with test was given.
21117
+ test = testOrVisitor;
21118
+ // @ts-expect-error: assume the overload with test was given.
21119
+ visitor = visitorOrReverse;
21120
+ reverse = maybeReverse;
22255
21121
  }
22256
- }
22257
21122
 
22258
- /**
22259
- * Assert `value` is an `Uint8Array`.
22260
- *
22261
- * @param {unknown} value
22262
- * thing.
22263
- * @returns {value is Uint8Array}
22264
- * Whether `value` is an `Uint8Array`.
22265
- */
22266
- function isUint8Array(value) {
22267
- return Boolean(
22268
- value &&
22269
- typeof value === 'object' &&
22270
- 'byteLength' in value &&
22271
- 'byteOffset' in value
22272
- )
21123
+ visitParents(tree, test, overload, reverse);
21124
+
21125
+ /**
21126
+ * @param {UnistNode} node
21127
+ * @param {Array<UnistParent>} parents
21128
+ */
21129
+ function overload(node, parents) {
21130
+ const parent = parents[parents.length - 1];
21131
+ const index = parent ? parent.children.indexOf(node) : undefined;
21132
+ return visitor(node, index, parent)
21133
+ }
22273
21134
  }
22274
21135
 
22275
21136
  /**