agent-sanitizer 2.60.3 → 2.61.1

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.
@@ -53,16 +53,24 @@ export function isBenignAnsiKinds(kinds: readonly string[] | Set<string>): boole
53
53
  /**
54
54
  * True when the SGR sequences in `text` do more than style visible text — the
55
55
  * question a consumer must answer before PRESERVING escapes rather than
56
- * stripping them. Two arms, both model-sees/human-sees divergences:
56
+ * stripping them. Three arms, all model-sees/human-sees divergences:
57
57
  *
58
- * 1. CONCEAL is on while text that would otherwise render goes by, or the text
59
- * ENDS concealed (hiding its own tail, and everything the terminal prints
60
- * afterwards). Only SGR moves that state (see {@link sgrConcealState}) — a
61
- * cursor move or an erase leaves a terminal exactly as concealed as it was.
62
- * 2. {@link SGR_RUN_THRESHOLD} sequences with nothing that renders between
58
+ * 1. CONCEAL is on while text that would otherwise render goes by. Only SGR
59
+ * moves that state (see {@link sgrRendition}) — a cursor move or an erase
60
+ * leaves a terminal exactly as concealed as it was.
61
+ * 2. The foreground is the background while a glyph goes by (`ESC[30;40m`):
62
+ * concealment by colour, judged only where the match is unambiguous (see
63
+ * {@link foregroundMatchesBackground}). Block Elements are the one
64
+ * exception judged across the whole text rather than per glyph (see
65
+ * {@link drawsSecondBlockElement}).
66
+ * 3. {@link SGR_RUN_THRESHOLD} sequences with nothing that renders between
63
67
  * them: the run puts no glyph on the screen, so it carries data rather than
64
68
  * styling.
65
69
  *
70
+ * Either still in force when the text ENDS is a refusal too: rendition
71
+ * outlives its bytes, so a file ending in `ESC[8m` blanks whatever the terminal
72
+ * prints after it.
73
+ *
66
74
  * What it does NOT claim: a message spread thinly through legitimately coloured
67
75
  * text — one sequence per line, say — is indistinguishable from styling, and
68
76
  * this answers no for it. That is the same bargain the invisible layer's
@@ -85,6 +93,26 @@ export function sgrCarriesPayload(text: string): boolean;
85
93
  * @returns {boolean}
86
94
  */
87
95
  export function isBenignAnsi(text: string): boolean;
96
+ /**
97
+ * True when the escapes in `text` may be let through: every removed kind is
98
+ * inert ({@link isBenignAnsiKinds}) AND the SGR is just styling
99
+ * ({@link sgrCarriesPayload}). THE answer for every surface that preserves
100
+ * escapes, so `ESC[8m` cannot be inert to one and hiding text in another.
101
+ * @param {string} text the raw text, as a terminal would receive it
102
+ * @param {Iterable<string>} [kinds] the {@link TOKEN_KIND}s a strip of `text`
103
+ * removed, when the caller already has them; defaults to Layer 1's
104
+ * @returns {boolean}
105
+ */
106
+ export function escapesPreservable(text: string, kinds?: Iterable<string>): boolean;
107
+ /**
108
+ * Remove every complete ANSI sequence and then every raw control introducer
109
+ * left over. The output holds no introducer, so no later pass can find an
110
+ * escape in it: a fixed point by construction.
111
+ * @param {string} text
112
+ * @param {Set<string>} [kinds] collects the {@link TOKEN_KIND} of every removal
113
+ * @returns {string}
114
+ */
115
+ export function stripTerminalFully(text: string, kinds?: Set<string>): string;
88
116
  /**
89
117
  * Layer 1: ANSI + invisible-char strip with a result guaranteed free of every
90
118
  * raw ANSI control introducer (7-bit ESC U+001B and the whole 8-bit C1 control
@@ -103,9 +131,10 @@ export function isBenignAnsi(text: string): boolean;
103
131
  *
104
132
  * The residual sweep runs only once the composition is STABLE, because sweeping
105
133
  * an introducer early destroys the sequence a later ANSI pass would have removed
106
- * whole, promoting a hidden control to visible text. A final UNCONDITIONAL sweep
107
- * follows the loop so the no-raw-introducer guarantee does not depend on the
108
- * pass bound.
134
+ * whole, promoting a hidden control to visible text. A composition that has not
135
+ * converged within the pass bound falls back to a carve-out-free strip whose
136
+ * output holds no invisible and no introducer, so both the no-raw-introducer
137
+ * guarantee and idempotence hold whatever the bound.
109
138
  *
110
139
  * `deAnsi` is the ANSI strip of the ORIGINAL text (invisible runs intact), the
111
140
  * scope a LONG_RUN payload check needs — not an intermediate of the loop.
@@ -187,3 +216,4 @@ export const INERT_ANSI_NOTE: string;
187
216
  * threshold and sits well above what a real emitter chains.
188
217
  */
189
218
  export const SGR_RUN_THRESHOLD: 10;
219
+ export type SgrRendition = import("./ansi.mjs").SgrRendition;
@@ -49,15 +49,12 @@ export function isCancelledOrphan(text: string, token: AnsiToken): boolean;
49
49
  */
50
50
  export function scanAnsi(text: string): AnsiToken[];
51
51
  /**
52
- * The CONCEAL state after the SGR token `token` is applied to a terminal already
53
- * in state `concealed` — the state in which a terminal renders what follows as
54
- * blank while its bytes stay readable to anything reading the file.
52
+ * The rendition after the SGR token `token` is applied to a terminal already in
53
+ * `state`.
55
54
  *
56
- * A TRANSITION, not a property of the token: conceal is terminal state that
55
+ * A TRANSITION, not a property of the token: rendition is terminal state that
57
56
  * outlives the sequence that set it, so `ESC[8m` followed by `ESC[31m` is still
58
- * concealed — a per-token predicate would read the second token as "no conceal
59
- * here" and lose the state. Only `8` (set), `28` (reveal) and `0` (reset all)
60
- * move it, and the token's parameters are applied in order, so a later reveal or
57
+ * concealed. The token's parameters are applied in order, so a later reveal or
61
58
  * reset in the SAME token cancels an earlier `8`: `ESC[8;28;31m` renders red and
62
59
  * visible.
63
60
  *
@@ -65,18 +62,26 @@ export function scanAnsi(text: string): AnsiToken[];
65
62
  * the digit. `38`/`48`/`58` take their colour arguments from the parameters that
66
63
  * FOLLOW them in the semicolon form, so `ESC[38;5;8m` is bright-black foreground
67
64
  * and its `8` is a palette index; a parameter carrying its arguments as ITU T.416
68
- * sub-parameters (`38:5:8`) is self-contained, so only its head counts and
69
- * nothing after it is consumed. A colour-space selector T.416 gives no argument
70
- * count for is malformed, and a terminal that ignores the colour form still
71
- * applies what follows it, so the scan CONTINUES from the next parameter rather
72
- * than consuming arguments it cannot size — reading one parameter too many costs
73
- * a token shape no emitter produces, while stopping there would hand
74
- * `ESC[38;9;8m` a pass.
65
+ * sub-parameters (`38:5:8`) is self-contained, so nothing after it is consumed.
66
+ * A colour-space selector T.416 gives no argument count for is malformed, and a
67
+ * terminal that ignores the colour form still applies what follows it, so the
68
+ * scan CONTINUES from the next parameter rather than consuming arguments it
69
+ * cannot size — stopping there would hand `ESC[38;9;8m` a pass.
75
70
  * @param {string} token a token {@link scanAnsi} classified {@link TOKEN_KIND.SGR}
76
- * @param {boolean} concealed the state before this token
71
+ * @param {Readonly<SgrRendition>} state the rendition before this token
72
+ * @returns {SgrRendition}
73
+ */
74
+ export function sgrRendition(token: string, state: Readonly<SgrRendition>): SgrRendition;
75
+ /**
76
+ * True when text drawn in `rendition` is invisible to a human because its
77
+ * foreground IS its background (`ESC[30;40m`, `ESC[38;5;7;48;5;7m`). Only an
78
+ * unambiguous match counts: a default colour is unknown, so it matches nothing,
79
+ * and BOLD over a basic colour is drawn brighter by many terminals, so
80
+ * `ESC[1;30;40m` is not called hidden — the precision direction.
81
+ * @param {Readonly<SgrRendition>} rendition
77
82
  * @returns {boolean}
78
83
  */
79
- export function sgrConcealState(token: string, concealed: boolean): boolean;
84
+ export function foregroundMatchesBackground({ bold, fg, bg }: Readonly<SgrRendition>): boolean;
80
85
  /**
81
86
  * The ONE ANSI grammar: the raw control-introducer charset and the tokenizer
82
87
  * every consumer scans with.
@@ -170,6 +175,17 @@ export const TOKEN_KIND: Readonly<{
170
175
  */
171
176
  ORPHAN_C1: "orphan-c1-introducer";
172
177
  }>;
178
+ /**
179
+ * What a terminal's graphic rendition looks like after an SGR token: whether
180
+ * CONCEAL is on, whether BOLD is (which many terminals render as a brighter
181
+ * foreground), and the foreground/background colour as a comparable key — `i<n>`
182
+ * for a palette index (`31` and `38;5;1` are both `i1`), `rgb:<r>,<g>,<b>` for
183
+ * direct colour, `null` for the default or a colour this reader cannot size.
184
+ * @typedef {{ concealed: boolean, bold: boolean, fg: string | null, bg: string | null }} SgrRendition
185
+ */
186
+ /** The rendition of a terminal no SGR has touched (and of `ESC[0m`).
187
+ * @type {Readonly<SgrRendition>} */
188
+ export const DEFAULT_RENDITION: Readonly<SgrRendition>;
173
189
  export type AnsiToken = {
174
190
  /**
175
191
  * Index of the introducer.
@@ -184,3 +200,16 @@ export type AnsiToken = {
184
200
  */
185
201
  kind: string;
186
202
  };
203
+ /**
204
+ * What a terminal's graphic rendition looks like after an SGR token: whether
205
+ * CONCEAL is on, whether BOLD is (which many terminals render as a brighter
206
+ * foreground), and the foreground/background colour as a comparable key — `i<n>`
207
+ * for a palette index (`31` and `38;5;1` are both `i1`), `rgb:<r>,<g>,<b>` for
208
+ * direct colour, `null` for the default or a colour this reader cannot size.
209
+ */
210
+ export type SgrRendition = {
211
+ concealed: boolean;
212
+ bold: boolean;
213
+ fg: string | null;
214
+ bg: string | null;
215
+ };
@@ -1,14 +1,14 @@
1
1
  /**
2
- * GENERATED by scripts/gen-invisible-charset.mjs from Node's Unicode data
3
- * (\p{Cf}, Unicode 17.0) — DO NOT EDIT.
2
+ * GENERATED by scripts/gen-invisible-charset.mjs from the pinned UCD
3
+ * (General_Category=Cf, Unicode 17.0.0) — DO NOT EDIT.
4
4
  *
5
5
  * The general-category Cf code points, PINNED at generation time. invisible.mjs
6
- * strips exactly this set instead of testing \p{Cf} live, and the Python port
6
+ * strips exactly this set instead of asking the runtime for Cf, and the Python port
7
7
  * reads the SAME set from data/invisible-charset.json's `cf_codepoints`, so both
8
8
  * layers strip an identical Cf set regardless of each runtime's own Unicode
9
9
  * version. Regenerate with `node scripts/gen-invisible-charset.mjs`;
10
- * test/invisible-charset.test.mjs fails if this drifts from Node's \p{Cf}.
10
+ * test/invisible-charset.test.mjs fails if this drifts from the pinned UCD.
11
11
  */
12
- export const UNICODE_VERSION: "17.0";
12
+ export const UNICODE_VERSION: "17.0.0";
13
13
  /** @type {readonly number[]} Sorted ascending. */
14
14
  export const CF_CODEPOINTS: readonly number[];
@@ -14,9 +14,13 @@ export function decodeRun(run: string): {
14
14
  decoded: string;
15
15
  };
16
16
  /**
17
- * Scan a file's text for hidden-Unicode injection. Reports each long invisible
17
+ * Scan a file's text for hidden-Unicode injection. Reports each payload long
18
18
  * run (with its decoded payload) plus a single scattered-chars finding when the
19
- * non-run invisible count crosses the threshold-evasion floor.
19
+ * effective invisible count outside those runs crosses the threshold-evasion
20
+ * floor.
21
+ *
22
+ * Whether there is anything to report is {@link payloadVerdict}'s call, the
23
+ * one every other surface makes.
20
24
  * @param {string} content
21
25
  * @returns {Array<{ line: number | null, charCount: number, method: string, decoded: string }>}
22
26
  * `line` is the 1-based line of a long-run finding, or `null` for the
@@ -68,11 +68,13 @@ export function describeStripped(invisFound: string[], deAnsi: string): string;
68
68
  */
69
69
  export function countPayloadInvisible(text: string): number;
70
70
  /**
71
- * The `text` with every carve-out-PRESERVABLE invisible (joiners/selectors/tags/
72
- * blank fillers doing real rendering work) replaced by a space, leaving only the
73
- * PAYLOAD invisibles in place. The LONG_RUN injection probe runs over this so a
74
- * legitimate emoji/flag/variation sequence never trips the "possible injection
75
- * payload" marker (alert fatigue), while a genuine hidden run still surfaces.
71
+ * The `text` with every visible character and every carve-out-PRESERVABLE
72
+ * invisible (joiners/selectors/tags/blank fillers doing real rendering work)
73
+ * replaced by spaces — one per UTF-16 unit, so the view is index-aligned with
74
+ * `text` — leaving only the PAYLOAD invisibles in place. The LONG_RUN injection
75
+ * probe runs over this so a legitimate emoji/flag/variation sequence never trips
76
+ * the "possible injection payload" marker (alert fatigue), while a genuine
77
+ * hidden run still surfaces.
76
78
  * @param {string} text
77
79
  * @returns {string}
78
80
  */
@@ -143,6 +145,25 @@ export function countEffectiveInvisible(text: string): number;
143
145
  * @returns {boolean}
144
146
  */
145
147
  export function isIncidentalInvisible(text: string): boolean;
148
+ /**
149
+ * THE decision whether `text` carries a payload-capable invisible channel: a
150
+ * payload LONG RUN, or {@link SCATTERED_THRESHOLD} or more effective payload
151
+ * invisibles. Every gate reads this one verdict, so a Persian paragraph cannot
152
+ * be a payload to one and clean to another. It stops at the first run, so an
153
+ * 8 MB field of short runs costs one record.
154
+ * @param {string} text the text a consumer acts on, ANSI-stripped where its
155
+ * surface can carry escapes (a sequence can hide invisibles)
156
+ * @returns {{ firstRun: { index: number, text: string, charCount: number } | null, invisibleCount: number, payloadCapable: boolean }}
157
+ */
158
+ export function payloadVerdict(text: string): {
159
+ firstRun: {
160
+ index: number;
161
+ text: string;
162
+ charCount: number;
163
+ } | null;
164
+ invisibleCount: number;
165
+ payloadCapable: boolean;
166
+ };
146
167
  /**
147
168
  * Strip payload-capable invisible chars and report which categories were
148
169
  * removed. A single leading U+FEFF (BOM) is preserved as a legitimate marker;
@@ -155,11 +176,17 @@ export function isIncidentalInvisible(text: string): boolean;
155
176
  * decide whether a leading BOM is genuinely leading: an interior BOM that an
156
177
  * ANSI-strip left at index 0 of `text` (e.g. `ESC[m + interior U+FEFF`) must NOT be treated as a
157
178
  * legitimate leading marker. Defaults to `text` for the common single-arg call.
179
+ *
180
+ * `carveOut: false` strips EVERY payload-capable invisible, preserved ones
181
+ * included — the monotone fallback for a composition that fails to converge.
158
182
  * @param {string} text
159
183
  * @param {string} [originalText]
184
+ * @param {{ carveOut?: boolean }} [options]
160
185
  * @returns {{ cleaned: string, found: string[] }}
161
186
  */
162
- export function stripInvisibleWithReport(text: string, originalText?: string): {
187
+ export function stripInvisibleWithReport(text: string, originalText?: string, { carveOut }?: {
188
+ carveOut?: boolean;
189
+ }): {
163
190
  cleaned: string;
164
191
  found: string[];
165
192
  };
@@ -215,3 +242,31 @@ export const TOTAL_PRESERVED_BLANK_BUDGET: 16;
215
242
  export const PRESERVED_BLANK_PER_ANCHOR: 2;
216
243
  export const LINGUISTIC_SCRIPTS: string[];
217
244
  export { BRAHMIC_CONSONANT_RANGES } from "./joining-type.mjs";
245
+ export type CarveEntry = {
246
+ body: string;
247
+ cps: Int32Array;
248
+ analysis: ReturnType<typeof analyzeCarve>;
249
+ strip: {
250
+ cleaned: string;
251
+ found: string[];
252
+ removed: number;
253
+ } | null;
254
+ removed: number | null;
255
+ };
256
+ /**
257
+ * Per-invisible carve-out analysis, shared by carveStrip and
258
+ * countPayloadInvisible: for each code point, its CODE_* class (CODE_VISIBLE
259
+ * when visible) and its preserve KIND_* (KIND_NONE when the char is payload).
260
+ * Everything invisible that is NOT preserve-eligible is payload; the scatter
261
+ * floor counts only that, so meaningful joiners/selectors never push honest
262
+ * prose over the threshold.
263
+ * @param {Int32Array} cps
264
+ * @returns {{ codes: Uint8Array, kind: Uint8Array, invisible: Int32Array, payloadInvis: number, visibleLen: number }}
265
+ */
266
+ declare function analyzeCarve(cps: Int32Array): {
267
+ codes: Uint8Array;
268
+ kind: Uint8Array;
269
+ invisible: Int32Array;
270
+ payloadInvis: number;
271
+ visibleLen: number;
272
+ };
@@ -15,13 +15,16 @@ export function isVirama(cp: number): boolean;
15
15
  /**
16
16
  * True when `cp` is a Brahmic consonant — the only base a virama attaches to,
17
17
  * and therefore the only base after which a ZWJ/ZWNJ is a real conjunct
18
- * request rather than a zero-width payload.
18
+ * request rather than a zero-width payload. A binary search, like
19
+ * `lookup`: the spans are sorted and disjoint, and the carve analysis asks
20
+ * this of every visible code point of a long document, where a scan of all the
21
+ * spans per code point was the dominant cost.
19
22
  * @param {number} cp
20
23
  * @returns {boolean}
21
24
  */
22
25
  export function isBrahmicConsonant(cp: number): boolean;
23
26
  /**
24
- * GENERATED by scripts/gen-joining-type.mjs from ucd-full@17.0.0 — DO NOT EDIT.
27
+ * GENERATED by scripts/gen-joining-type.mjs from the pinned UCD 17.0.0 — DO NOT EDIT.
25
28
  *
26
29
  * Unicode Joining_Type, Indic virama and Brahmic consonant range tables backing
27
30
  * the ZWNJ/ZWJ carve-out in invisible.mjs. Regenerate with `pnpm gen:joining-type`;
@@ -1,6 +1,6 @@
1
1
  /**
2
- * True when `base` followed by `selector` (a U+FE00–U+FE0D code point) is a
3
- * registered standardized variation sequence.
2
+ * True when `base` followed by `selector` is a registered standardized
3
+ * variation sequence.
4
4
  * @param {number} base
5
5
  * @param {number} selector
6
6
  * @returns {boolean}
@@ -10,12 +10,12 @@ export function isStandardizedVariant(base: number, selector: number): boolean;
10
10
  * GENERATED by scripts/gen-standardized-variants.mjs from UCD
11
11
  * StandardizedVariants.txt (Unicode 17.0.0) — DO NOT EDIT.
12
12
  *
13
- * Registered standardized variation sequences: a base code point followed by a
14
- * variation selector in U+FE00–U+FE0D. invisible.mjs preserves such a selector
15
- * only when the immediately preceding base appears here; every other FE00–FE0D
16
- * selector is stripped as a hidden-payload byte. Regenerate with
17
- * `node scripts/gen-standardized-variants.mjs`; test/invisible-charset.test.mjs
18
- * fails if this drifts from the pinned UCD slice.
13
+ * Registered standardized variation sequences: a base code point followed by the
14
+ * variation selector the UCD registers for it. invisible.mjs preserves such a
15
+ * selector only when the immediately preceding base appears here; every other
16
+ * one is stripped as a hidden-payload byte. Regenerate with
17
+ * `node scripts/gen-standardized-variants.mjs`;
18
+ * test/invisible-charset.test.mjs fails if this drifts from the pinned UCD.
19
19
  */
20
20
  export const UNICODE_VERSION: "17.0.0";
21
21
  /** @type {Array<[number, number]>} [base, selector], sorted by base then selector. */
@@ -0,0 +1,29 @@
1
+ /**
2
+ * True when `cp` lies in one of `spans` (sorted, non-overlapping). A negative
3
+ * `cp` — the "no neighbour" sentinel — lies in none.
4
+ * @param {ReadonlyArray<readonly [number, number]>} spans
5
+ * @param {number} cp
6
+ * @returns {boolean}
7
+ */
8
+ export function inSpans(spans: ReadonlyArray<readonly [number, number]>, cp: number): boolean;
9
+ /**
10
+ * GENERATED by scripts/gen-unicode-properties.mjs from the pinned UCD 17.0.0 — DO NOT EDIT.
11
+ *
12
+ * The Unicode properties src/invisible.mjs's carve-out reads, PINNED so the
13
+ * carve-out answers the same on every Node whatever its ICU's Unicode version.
14
+ * Regenerate with `node scripts/gen-unicode-properties.mjs`;
15
+ * test/unicode-properties.test.mjs fails if this drifts from the pinned package.
16
+ */
17
+ export const UNICODE_VERSION: "17.0.0";
18
+ /** @type {ReadonlyArray<readonly [number, number]>} */
19
+ export const EXTENDED_PICTOGRAPHIC: ReadonlyArray<readonly [number, number]>;
20
+ /** @type {ReadonlyArray<readonly [number, number]>} */
21
+ export const EMOJI_MODIFIER: ReadonlyArray<readonly [number, number]>;
22
+ /** @type {ReadonlyArray<readonly [number, number]>} */
23
+ export const EMOJI_TEXT_DEFAULT: ReadonlyArray<readonly [number, number]>;
24
+ /** @type {ReadonlyArray<readonly [number, number]>} */
25
+ export const UNIFIED_IDEOGRAPH: ReadonlyArray<readonly [number, number]>;
26
+ /** @type {ReadonlyArray<readonly [number, number]>} */
27
+ export const SCRIPT_BRAILLE: ReadonlyArray<readonly [number, number]>;
28
+ /** @type {ReadonlyArray<readonly [number, number]>} */
29
+ export const SCRIPT_HANGUL: ReadonlyArray<readonly [number, number]>;
@@ -1,6 +1,6 @@
1
1
  /**
2
- * True when `base` followed by `selector` (a U+FE00–U+FE0D code point) is a
3
- * registered standardized variation sequence.
2
+ * True when `base` followed by `selector` is a registered standardized
3
+ * variation sequence.
4
4
  * @param {number} base
5
5
  * @param {number} selector
6
6
  * @returns {boolean}
@@ -10,12 +10,12 @@ export function isStandardizedVariant(base: number, selector: number): boolean;
10
10
  * GENERATED by scripts/gen-standardized-variants.mjs from UCD
11
11
  * StandardizedVariants.txt (Unicode 17.0.0) — DO NOT EDIT.
12
12
  *
13
- * Registered standardized variation sequences: a base code point followed by a
14
- * variation selector in U+FE00–U+FE0D. invisible.mjs preserves such a selector
15
- * only when the immediately preceding base appears here; every other FE00–FE0D
16
- * selector is stripped as a hidden-payload byte. Regenerate with
17
- * `node scripts/gen-standardized-variants.mjs`; test/invisible-charset.test.mjs
18
- * fails if this drifts from the pinned UCD slice.
13
+ * Registered standardized variation sequences: a base code point followed by the
14
+ * variation selector the UCD registers for it. invisible.mjs preserves such a
15
+ * selector only when the immediately preceding base appears here; every other
16
+ * one is stripped as a hidden-payload byte. Regenerate with
17
+ * `node scripts/gen-standardized-variants.mjs`;
18
+ * test/invisible-charset.test.mjs fails if this drifts from the pinned UCD.
19
19
  */
20
20
  export const UNICODE_VERSION: "17.0.0";
21
21
  /** @type {Array<[number, number]>} [base, selector], sorted by base then selector. */
@@ -0,0 +1,29 @@
1
+ /**
2
+ * True when `cp` lies in one of `spans` (sorted, non-overlapping). A negative
3
+ * `cp` — the "no neighbour" sentinel — lies in none.
4
+ * @param {ReadonlyArray<readonly [number, number]>} spans
5
+ * @param {number} cp
6
+ * @returns {boolean}
7
+ */
8
+ export function inSpans(spans: ReadonlyArray<readonly [number, number]>, cp: number): boolean;
9
+ /**
10
+ * GENERATED by scripts/gen-unicode-properties.mjs from the pinned UCD 17.0.0 — DO NOT EDIT.
11
+ *
12
+ * The Unicode properties src/invisible.mjs's carve-out reads, PINNED so the
13
+ * carve-out answers the same on every Node whatever its ICU's Unicode version.
14
+ * Regenerate with `node scripts/gen-unicode-properties.mjs`;
15
+ * test/unicode-properties.test.mjs fails if this drifts from the pinned package.
16
+ */
17
+ export const UNICODE_VERSION: "17.0.0";
18
+ /** @type {ReadonlyArray<readonly [number, number]>} */
19
+ export const EXTENDED_PICTOGRAPHIC: ReadonlyArray<readonly [number, number]>;
20
+ /** @type {ReadonlyArray<readonly [number, number]>} */
21
+ export const EMOJI_MODIFIER: ReadonlyArray<readonly [number, number]>;
22
+ /** @type {ReadonlyArray<readonly [number, number]>} */
23
+ export const EMOJI_TEXT_DEFAULT: ReadonlyArray<readonly [number, number]>;
24
+ /** @type {ReadonlyArray<readonly [number, number]>} */
25
+ export const UNIFIED_IDEOGRAPH: ReadonlyArray<readonly [number, number]>;
26
+ /** @type {ReadonlyArray<readonly [number, number]>} */
27
+ export const SCRIPT_BRAILLE: ReadonlyArray<readonly [number, number]>;
28
+ /** @type {ReadonlyArray<readonly [number, number]>} */
29
+ export const SCRIPT_HANGUL: ReadonlyArray<readonly [number, number]>;