@effected/yaml 0.10.0 → 0.12.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.
- package/README.md +43 -7
- package/Yaml.js +32 -3
- package/YamlDocument.js +2 -0
- package/YamlFormat.js +77 -9
- package/YamlLint.js +0 -0
- package/YamlLintRule.js +50 -1
- package/YamlNode.js +16 -1
- package/index.d.ts +300 -7
- package/index.js +4 -4
- package/internal/requote.js +48 -0
- package/internal/rules/comments-spacing.js +48 -9
- package/internal/rules/document-end.js +48 -18
- package/internal/rules/document-start.js +31 -5
- package/internal/rules/empty-lines.js +21 -1
- package/internal/rules/indentation.js +76 -23
- package/internal/rules/line-length.js +9 -1
- package/internal/rules/quoted-strings.js +29 -11
- package/internal/stringifier.js +30 -7
- package/package.json +1 -1
- package/tsdoc-metadata.json +1 -1
package/index.d.ts
CHANGED
|
@@ -175,6 +175,33 @@ declare const YamlStringifyOptions_base: Schema.Class<YamlStringifyOptions, Sche
|
|
|
175
175
|
* `"double-quoted"` is unaffected.
|
|
176
176
|
*/
|
|
177
177
|
readonly quoteStyle: Schema.optionalKey<Schema.Literals<readonly ["single", "double"]>>;
|
|
178
|
+
/**
|
|
179
|
+
* Additionally quote plain scalars a foreign resolution dialect would
|
|
180
|
+
* coerce to a non-string. Absent (the default) adds no quoting beyond the
|
|
181
|
+
* YAML 1.2 Core Schema rules — byte-identical to the released output.
|
|
182
|
+
*
|
|
183
|
+
* `"yaml-1.1"` quotes every plain scalar a YAML 1.1 parser (js-yaml,
|
|
184
|
+
* PyYAML, libyaml, and the `yaml` npm package's YAML 1.1 schema, whose
|
|
185
|
+
* lenient resolvers set the outer bound) would implicitly resolve to a
|
|
186
|
+
* non-string: the extended
|
|
187
|
+
* boolean spellings (`y`/`yes`/`on`/`off` and case variants — the "Norway
|
|
188
|
+
* problem"), timestamps (`2024-01-15`, `2001-12-15T02:59:43.1Z`, the
|
|
189
|
+
* space-separated 1.1 forms), sexagesimal numbers (`1:30`,
|
|
190
|
+
* `190:20:30.15`), underscore-separated numbers (`1_000`) and the
|
|
191
|
+
* base-2/8/16 integer forms (`0b1010_0111`, `0777`, `0x_FF`). Use it when
|
|
192
|
+
* emitted output is parsed downstream by a YAML 1.1 consumer and blanket
|
|
193
|
+
* `defaultScalarStyle` quoting is too noisy.
|
|
194
|
+
*
|
|
195
|
+
* Strictly additive: it never un-quotes anything the 1.2 rules require
|
|
196
|
+
* quoted, strings no 1.1 parser coerces stay plain, and the quote
|
|
197
|
+
* character stays governed by `quoteStyle`. Scalars carrying an explicit
|
|
198
|
+
* tag are exempt, exactly like the 1.2 type-conflict check. Applies
|
|
199
|
+
* wherever the plain fallback renders — values, mapping keys, flow items —
|
|
200
|
+
* on both the value path ({@link Yaml.stringify},
|
|
201
|
+
* {@link Yaml.stringifyResult}) and the node path (`YamlDocument#stringify`
|
|
202
|
+
* and the `YamlFormat` helpers).
|
|
203
|
+
*/
|
|
204
|
+
readonly quoteCompat: Schema.optionalKey<Schema.Literals<readonly ["yaml-1.1"]>>;
|
|
178
205
|
readonly finalNewline: Schema.optionalKey<Schema.Boolean>;
|
|
179
206
|
readonly forceDefaultStyles: Schema.optionalKey<Schema.Boolean>;
|
|
180
207
|
}>, {}>;
|
|
@@ -182,8 +209,9 @@ declare const YamlStringifyOptions_base: Schema.Class<YamlStringifyOptions, Sche
|
|
|
182
209
|
* Options controlling stringify behavior. All fields are omissible; absent
|
|
183
210
|
* fields resolve to `indent` `2`, `lineWidth` `0`, `defaultScalarStyle`
|
|
184
211
|
* `"plain"`, `defaultCollectionStyle` `"block"`, `sortKeys` `false`,
|
|
185
|
-
* `indentSequences` `false`, `quoteStyle` `"single"`, `
|
|
186
|
-
* and `forceDefaultStyles`
|
|
212
|
+
* `indentSequences` `false`, `quoteStyle` `"single"`, `quoteCompat` absent
|
|
213
|
+
* (no dialect-compat quoting), `finalNewline` `true` and `forceDefaultStyles`
|
|
214
|
+
* `false`.
|
|
187
215
|
*
|
|
188
216
|
* `lineWidth` controls column-based scalar folding. The default `0` (and any
|
|
189
217
|
* value `<= 0`) never wraps, emitting byte-identical output to the historic
|
|
@@ -641,6 +669,27 @@ declare const QuoteStyle: Schema.Literals<readonly ["single", "double"]>;
|
|
|
641
669
|
* @public
|
|
642
670
|
*/
|
|
643
671
|
type QuoteStyle = typeof QuoteStyle.Type;
|
|
672
|
+
/**
|
|
673
|
+
* Foreign resolution dialects the stringifier's plain-scalar fallback can
|
|
674
|
+
* defend against: setting the `quoteCompat` field of `YamlStringifyOptions`
|
|
675
|
+
* to `"yaml-1.1"` additionally quotes every plain scalar a YAML 1.1 parser
|
|
676
|
+
* (js-yaml, PyYAML, libyaml, and the `yaml` npm package's YAML 1.1 schema,
|
|
677
|
+
* whose lenient resolvers set the outer bound) would implicitly resolve to a
|
|
678
|
+
* non-string —
|
|
679
|
+
* `yes`/`no`/`on`/`off` booleans, ISO 8601 and space-separated timestamps,
|
|
680
|
+
* sexagesimal `1:30`, underscored `1_000` and base-2/8/16 numbers. Like
|
|
681
|
+
* `QuoteStyle` it is a stringify-option vocabulary, never a property of a
|
|
682
|
+
* composed node.
|
|
683
|
+
*
|
|
684
|
+
* @public
|
|
685
|
+
*/
|
|
686
|
+
declare const QuoteCompat: Schema.Literals<readonly ["yaml-1.1"]>;
|
|
687
|
+
/**
|
|
688
|
+
* The union of all quote-compat dialect string literals.
|
|
689
|
+
*
|
|
690
|
+
* @public
|
|
691
|
+
*/
|
|
692
|
+
type QuoteCompat = typeof QuoteCompat.Type;
|
|
644
693
|
/**
|
|
645
694
|
* Block-scalar chomping indicators (`-` strip, default clip, `+` keep).
|
|
646
695
|
* Referenced by the {@link YamlScalar} `chomp` field schema.
|
|
@@ -1005,18 +1054,36 @@ declare const YamlFormattingOptions_base: Schema.Class<YamlFormattingOptions, Sc
|
|
|
1005
1054
|
readonly sortKeys: Schema.optionalKey<Schema.Boolean>;
|
|
1006
1055
|
readonly indentSequences: Schema.optionalKey<Schema.Boolean>;
|
|
1007
1056
|
readonly quoteStyle: Schema.optionalKey<Schema.Literals<readonly ["single", "double"]>>;
|
|
1057
|
+
readonly quoteCompat: Schema.optionalKey<Schema.Literals<readonly ["yaml-1.1"]>>;
|
|
1008
1058
|
readonly finalNewline: Schema.optionalKey<Schema.Boolean>;
|
|
1009
1059
|
readonly forceDefaultStyles: Schema.optionalKey<Schema.Boolean>;
|
|
1010
1060
|
readonly preserveComments: Schema.optionalKey<Schema.Boolean>;
|
|
1011
1061
|
readonly range: Schema.optionalKey<typeof YamlRange>;
|
|
1062
|
+
readonly requoteScalars: Schema.optionalKey<Schema.Boolean>;
|
|
1012
1063
|
}>, {}>;
|
|
1013
1064
|
/**
|
|
1014
1065
|
* Options controlling formatting behavior: every {@link YamlStringifyOptions}
|
|
1015
|
-
* field (derived, not hand-duplicated — including `indentSequences
|
|
1016
|
-
* `quoteStyle`) plus
|
|
1017
|
-
* `preserveComments` (default `true`)
|
|
1066
|
+
* field (derived, not hand-duplicated — including `indentSequences`,
|
|
1067
|
+
* `quoteStyle` and `quoteCompat`) plus
|
|
1068
|
+
* `preserveComments` (default `true`), `range` (restrict edits to a
|
|
1018
1069
|
* region; see the module-level remarks on the `range` parameter vs. this
|
|
1019
|
-
* field).
|
|
1070
|
+
* field) and `requoteScalars` (default `false`).
|
|
1071
|
+
*
|
|
1072
|
+
* `requoteScalars` makes `quoteStyle` apply to scalars **already quoted in
|
|
1073
|
+
* the source** on the format path — by default formatting preserves an
|
|
1074
|
+
* existing scalar's own quote style, and `quoteStyle` governs only quotes the
|
|
1075
|
+
* stringifier introduces. When enabled, a re-quote happens only when it
|
|
1076
|
+
* provably preserves the parsed value: single→double applies proper
|
|
1077
|
+
* double-quote escaping, double→single is skipped whenever the value carries
|
|
1078
|
+
* characters single quotes cannot express (newlines, tabs, control and other
|
|
1079
|
+
* non-printable characters — single-quoted style can escape nothing but
|
|
1080
|
+
* `'`). Plain scalars stay plain, block scalars stay block, and scalars
|
|
1081
|
+
* carrying a tag or anchor — or spanning multiple source lines — are left
|
|
1082
|
+
* untouched. The option exists only where a source quote exists to re-quote:
|
|
1083
|
+
* it is read by {@link YamlFormat.format} / {@link YamlFormat.formatToString}
|
|
1084
|
+
* and is deliberately absent from `Yaml.stringify` (which serializes plain
|
|
1085
|
+
* values) and {@link YamlFormat.modify} (which takes a bare
|
|
1086
|
+
* {@link YamlStringifyOptions}).
|
|
1020
1087
|
*
|
|
1021
1088
|
* Construct with the validated `YamlFormattingOptions.make({ ... })` static —
|
|
1022
1089
|
* the kit convention (never `new`). Call sites that take a
|
|
@@ -1122,6 +1189,12 @@ declare class YamlFormat {
|
|
|
1122
1189
|
* `{ offset, length }` object as well as a {@link YamlRange} instance, so
|
|
1123
1190
|
* callers do not need `YamlRange.make(...)` for the common case.
|
|
1124
1191
|
*
|
|
1192
|
+
* Formatting preserves an existing scalar's own quote style by default —
|
|
1193
|
+
* `quoteStyle` governs only quotes the stringifier introduces. The opt-in
|
|
1194
|
+
* `options.requoteScalars` makes `quoteStyle` apply to already-quoted
|
|
1195
|
+
* source scalars too, re-quoting only where the parsed value is provably
|
|
1196
|
+
* preserved; see {@link YamlFormattingOptions} for the exact skip rules.
|
|
1197
|
+
*
|
|
1125
1198
|
* A plain `<<` mapping key is preserved unquoted, keeping its merge-key
|
|
1126
1199
|
* meaning (`tag:yaml.org,2002:merge`) — quoting it to `'<<'` would produce
|
|
1127
1200
|
* an ordinary string key that merges nothing, changing what the document
|
|
@@ -1337,6 +1410,60 @@ interface LintContext {
|
|
|
1337
1410
|
readonly tokens: ReadonlyArray<YamlToken>;
|
|
1338
1411
|
readonly document: YamlDocument;
|
|
1339
1412
|
}
|
|
1413
|
+
declare const StyleVote_base: Schema.Class<StyleVote, Schema.TaggedStruct<"StyleVote", {
|
|
1414
|
+
readonly dimension: Schema.String;
|
|
1415
|
+
readonly value: Schema.Union<readonly [Schema.String, Schema.Number, Schema.Boolean]>;
|
|
1416
|
+
readonly offset: Schema.Number;
|
|
1417
|
+
readonly length: Schema.Number;
|
|
1418
|
+
readonly line: Schema.Number;
|
|
1419
|
+
readonly character: Schema.Number;
|
|
1420
|
+
}>, {}>;
|
|
1421
|
+
/**
|
|
1422
|
+
* One categorical style observation (#345): a single occurrence of a style
|
|
1423
|
+
* choice in the source, voting a `value` for an inference `dimension`.
|
|
1424
|
+
*
|
|
1425
|
+
* The `dimension` IS the rule's option key and the `value` IS that option's
|
|
1426
|
+
* value (`"double"` for `quoteType`, `2` for `spaces`, `false` for
|
|
1427
|
+
* `present`), so the inference resolvers can turn unanimous or dominant
|
|
1428
|
+
* votes into a config entry with no per-rule knowledge — which is what lets
|
|
1429
|
+
* custom rules participate in inference for free. The position points at the
|
|
1430
|
+
* occurrence that voted, so a strict-resolution conflict can name where each
|
|
1431
|
+
* spelling was seen.
|
|
1432
|
+
*
|
|
1433
|
+
* The `_tag` literal is the RUNTIME discriminator between the two
|
|
1434
|
+
* observation kinds: class instances are structurally assignable, so a
|
|
1435
|
+
* custom rule may yield a plain object shaped like a vote, and the evidence
|
|
1436
|
+
* builder must still sort it into the right tally without `instanceof`.
|
|
1437
|
+
* `.make` defaults it — construction sites never pass `_tag`.
|
|
1438
|
+
*
|
|
1439
|
+
* @public
|
|
1440
|
+
*/
|
|
1441
|
+
declare class StyleVote extends StyleVote_base {}
|
|
1442
|
+
declare const StyleFloor_base: Schema.Class<StyleFloor, Schema.TaggedStruct<"StyleFloor", {
|
|
1443
|
+
readonly dimension: Schema.String;
|
|
1444
|
+
readonly value: Schema.Number;
|
|
1445
|
+
}>, {}>;
|
|
1446
|
+
/**
|
|
1447
|
+
* One measured style floor (#345): a value the source PROVES is at least
|
|
1448
|
+
* `value`, without proving what the configured limit should be — the longest
|
|
1449
|
+
* observed line proves `line-length.max` is at least that long, not what it
|
|
1450
|
+
* is. Floors are carried in the evidence for callers that want them and are
|
|
1451
|
+
* never resolved into config options; fabricating a max from the largest
|
|
1452
|
+
* value one happened to see would be lying with a straight face.
|
|
1453
|
+
*
|
|
1454
|
+
* The `_tag` literal discriminates a floor from a {@link StyleVote} at
|
|
1455
|
+
* runtime (see there); `.make` defaults it.
|
|
1456
|
+
*
|
|
1457
|
+
* @public
|
|
1458
|
+
*/
|
|
1459
|
+
declare class StyleFloor extends StyleFloor_base {}
|
|
1460
|
+
/**
|
|
1461
|
+
* What a rule's `infer` hook yields per occurrence: a categorical
|
|
1462
|
+
* {@link StyleVote} or a measured {@link StyleFloor}.
|
|
1463
|
+
*
|
|
1464
|
+
* @public
|
|
1465
|
+
*/
|
|
1466
|
+
type StyleObservation = StyleVote | StyleFloor;
|
|
1340
1467
|
/**
|
|
1341
1468
|
* The public rule interface — built-ins and custom rules are the same
|
|
1342
1469
|
* shape, and config references either by `id`; there is no privileged
|
|
@@ -1347,11 +1474,19 @@ interface LintContext {
|
|
|
1347
1474
|
* rules receive options already validated against their exported options
|
|
1348
1475
|
* schema, custom rules validate their own.
|
|
1349
1476
|
*
|
|
1477
|
+
* `infer` is the optional config-inference hook (#345): it reports the style
|
|
1478
|
+
* the source already follows as per-occurrence {@link StyleObservation}s, so
|
|
1479
|
+
* detection logic lives beside the check logic that polices the same
|
|
1480
|
+
* dimension (and shares its fixtures). Rules with no detectable style — the
|
|
1481
|
+
* policy rules, whose only evidence is violations — simply omit the hook and
|
|
1482
|
+
* stay default-driven under every resolver.
|
|
1483
|
+
*
|
|
1350
1484
|
* @public
|
|
1351
1485
|
*/
|
|
1352
1486
|
interface YamlRule {
|
|
1353
1487
|
readonly id: string;
|
|
1354
1488
|
readonly check: (ctx: LintContext, options: unknown) => Iterable<YamlLintDiagnostic>;
|
|
1489
|
+
readonly infer?: (ctx: LintContext) => Iterable<StyleObservation>;
|
|
1355
1490
|
}
|
|
1356
1491
|
//#endregion
|
|
1357
1492
|
//#region src/YamlLint.d.ts
|
|
@@ -1399,6 +1534,118 @@ declare class YamlLintConfig extends YamlLintConfig_base {
|
|
|
1399
1534
|
/** The relaxed preset: style rules demoted to warnings. */
|
|
1400
1535
|
static readonly relaxed: YamlLintConfig;
|
|
1401
1536
|
}
|
|
1537
|
+
declare const StyleVoteTally_base: Schema.Class<StyleVoteTally, Schema.Struct<{
|
|
1538
|
+
readonly rule: Schema.String;
|
|
1539
|
+
readonly dimension: Schema.String;
|
|
1540
|
+
readonly value: Schema.Union<readonly [Schema.String, Schema.Number, Schema.Boolean]>;
|
|
1541
|
+
readonly count: Schema.Number;
|
|
1542
|
+
readonly offset: Schema.Number;
|
|
1543
|
+
readonly length: Schema.Number;
|
|
1544
|
+
readonly line: Schema.Number;
|
|
1545
|
+
readonly character: Schema.Number;
|
|
1546
|
+
}>, {}>;
|
|
1547
|
+
/**
|
|
1548
|
+
* An accumulated tally of one {@link StyleVote} spelling: how many times a
|
|
1549
|
+
* `value` was voted for a `(rule, dimension)` pair, and the position of the
|
|
1550
|
+
* FIRST occurrence seen (merging keeps the left operand's position, so on a
|
|
1551
|
+
* multi-file merge the first file that exhibited the spelling names it).
|
|
1552
|
+
*
|
|
1553
|
+
* @public
|
|
1554
|
+
*/
|
|
1555
|
+
declare class StyleVoteTally extends StyleVoteTally_base {}
|
|
1556
|
+
declare const StyleFloorTally_base: Schema.Class<StyleFloorTally, Schema.Struct<{
|
|
1557
|
+
readonly rule: Schema.String;
|
|
1558
|
+
readonly dimension: Schema.String;
|
|
1559
|
+
readonly value: Schema.Number;
|
|
1560
|
+
}>, {}>;
|
|
1561
|
+
/**
|
|
1562
|
+
* An accumulated {@link StyleFloor} for a `(rule, dimension)` pair: the
|
|
1563
|
+
* largest value the observed sources prove the limit is AT LEAST. Merging
|
|
1564
|
+
* takes the maximum. Floors are informational — never resolved into config
|
|
1565
|
+
* options (see {@link StyleFloor}).
|
|
1566
|
+
*
|
|
1567
|
+
* @public
|
|
1568
|
+
*/
|
|
1569
|
+
declare class StyleFloorTally extends StyleFloorTally_base {}
|
|
1570
|
+
declare const StyleEvidence_base: Schema.Class<StyleEvidence, Schema.Struct<{
|
|
1571
|
+
readonly votes: Schema.$Array<typeof StyleVoteTally>;
|
|
1572
|
+
readonly floors: Schema.$Array<typeof StyleFloorTally>;
|
|
1573
|
+
}>, {}>;
|
|
1574
|
+
/**
|
|
1575
|
+
* Per-dimension style evidence (#345): what the observed sources say about
|
|
1576
|
+
* each inferable `(rule, dimension)` — vote histograms with first-seen
|
|
1577
|
+
* positions, and measured floors.
|
|
1578
|
+
*
|
|
1579
|
+
* Evidence is a MONOID: {@link StyleEvidence.empty} is the identity and
|
|
1580
|
+
* {@link StyleEvidence.combine} is associative, so multi-file inference is
|
|
1581
|
+
* observe-per-file, merge, resolve — and the N-file loop stays the caller's
|
|
1582
|
+
* (no IO enters the package). `combine` normalizes: counts of the same
|
|
1583
|
+
* `(rule, dimension, value)` add, the left operand's first-seen position
|
|
1584
|
+
* wins, floors take the maximum, and the result is canonically sorted — so
|
|
1585
|
+
* every value `observe`/`combine`/`fromObservations` produces is canonical
|
|
1586
|
+
* and the monoid laws hold structurally over them.
|
|
1587
|
+
*
|
|
1588
|
+
* @public
|
|
1589
|
+
*/
|
|
1590
|
+
declare class StyleEvidence extends StyleEvidence_base {
|
|
1591
|
+
/** The monoid identity: no observations. */
|
|
1592
|
+
static readonly empty: StyleEvidence;
|
|
1593
|
+
/**
|
|
1594
|
+
* Merge two bodies of evidence (associative; {@link StyleEvidence.empty}
|
|
1595
|
+
* is the identity). Vote counts add, the left operand's first-seen
|
|
1596
|
+
* position wins per spelling, floors take the maximum.
|
|
1597
|
+
*/
|
|
1598
|
+
static combine(a: StyleEvidence, b: StyleEvidence): StyleEvidence;
|
|
1599
|
+
/**
|
|
1600
|
+
* Build canonical evidence from one rule's raw observations — the
|
|
1601
|
+
* homomorphism from observation lists into the monoid
|
|
1602
|
+
* (`fromObservations(r, [...a, ...b])` equals
|
|
1603
|
+
* `combine(fromObservations(r, a), fromObservations(r, b))`). `observe`
|
|
1604
|
+
* uses it per rule; it is public so custom tooling can construct evidence
|
|
1605
|
+
* without a {@link LintContext}.
|
|
1606
|
+
*/
|
|
1607
|
+
static fromObservations(rule: string, observations: Iterable<StyleObservation>): StyleEvidence;
|
|
1608
|
+
}
|
|
1609
|
+
declare const StyleConflict_base: Schema.Class<StyleConflict, Schema.Struct<{
|
|
1610
|
+
readonly rule: Schema.String;
|
|
1611
|
+
readonly dimension: Schema.String;
|
|
1612
|
+
readonly candidates: Schema.$Array<typeof StyleVoteTally>;
|
|
1613
|
+
}>, {}>;
|
|
1614
|
+
/**
|
|
1615
|
+
* One strict-resolution conflict: a `(rule, dimension)` whose observed
|
|
1616
|
+
* spellings disagree. `candidates` carries every spelling with its count and
|
|
1617
|
+
* first-seen position, ordered by count descending (dominant first).
|
|
1618
|
+
*
|
|
1619
|
+
* @public
|
|
1620
|
+
*/
|
|
1621
|
+
declare class StyleConflict extends StyleConflict_base {}
|
|
1622
|
+
declare const YamlStyleConflictError_base: Schema.Class<YamlStyleConflictError, Schema.TaggedStruct<"YamlStyleConflictError", {
|
|
1623
|
+
readonly conflicts: Schema.$Array<typeof StyleConflict>;
|
|
1624
|
+
}>, import("effect/Cause").YieldableError>;
|
|
1625
|
+
/**
|
|
1626
|
+
* Raised by strict config inference when observed evidence is not unanimous:
|
|
1627
|
+
* carries every conflicting `(rule, dimension)` as a structured
|
|
1628
|
+
* {@link StyleConflict} — dimension, all spellings, counts and positions —
|
|
1629
|
+
* never a collapsed `reason` string (the structure-preserving-errors house
|
|
1630
|
+
* rule). Unobserved dimensions never conflict: they fall back to the base
|
|
1631
|
+
* config's defaults.
|
|
1632
|
+
*
|
|
1633
|
+
* @public
|
|
1634
|
+
*/
|
|
1635
|
+
declare class YamlStyleConflictError extends YamlStyleConflictError_base {
|
|
1636
|
+
get message(): string;
|
|
1637
|
+
}
|
|
1638
|
+
/**
|
|
1639
|
+
* A lenient inference report: the inferred config plus the residual — the
|
|
1640
|
+
* diagnostics that config still produces on the observed text ("here is your
|
|
1641
|
+
* config, and the places that do not match it").
|
|
1642
|
+
*
|
|
1643
|
+
* @public
|
|
1644
|
+
*/
|
|
1645
|
+
interface YamlLintInference {
|
|
1646
|
+
readonly config: YamlLintConfig;
|
|
1647
|
+
readonly residual: ReadonlyArray<YamlLintDiagnostic>;
|
|
1648
|
+
}
|
|
1402
1649
|
/**
|
|
1403
1650
|
* Linting statics. Not instantiable.
|
|
1404
1651
|
*
|
|
@@ -1447,6 +1694,52 @@ declare class YamlLint {
|
|
|
1447
1694
|
* is dropped (its diagnostic remains reported by {@link YamlLint.run}).
|
|
1448
1695
|
*/
|
|
1449
1696
|
static fix(text: string, rules: ReadonlyArray<YamlRule>, config: YamlLintConfig): Result.Result<string, YamlParseError>;
|
|
1697
|
+
/**
|
|
1698
|
+
* Observe the style `text` already follows (#345): run every rule's
|
|
1699
|
+
* optional `infer` hook over one eagerly-built context and merge the
|
|
1700
|
+
* observations into canonical {@link StyleEvidence}. Pure and total —
|
|
1701
|
+
* strings in, evidence out; observing N files is N `observe` calls merged
|
|
1702
|
+
* with {@link StyleEvidence.combine}, and the N-file loop stays the
|
|
1703
|
+
* caller's (no IO enters the package).
|
|
1704
|
+
*/
|
|
1705
|
+
static observe(text: string, rules: ReadonlyArray<YamlRule>): StyleEvidence;
|
|
1706
|
+
/**
|
|
1707
|
+
* Strict resolution: every OBSERVED dimension must be unanimous, and the
|
|
1708
|
+
* unanimous picks overlay `base` (default {@link YamlLintConfig.default})
|
|
1709
|
+
* into an exact config. Conflicting evidence fails with
|
|
1710
|
+
* {@link YamlStyleConflictError} naming every conflicting dimension, all
|
|
1711
|
+
* spellings, counts and first-seen positions. Unobserved is NOT
|
|
1712
|
+
* conflicting: a corpus with no comments says nothing about
|
|
1713
|
+
* `comments-spacing`, so that dimension falls back to `base` rather than
|
|
1714
|
+
* failing. A rule `base` sets to `"off"` stays off — an explicit disable
|
|
1715
|
+
* outranks inference.
|
|
1716
|
+
*/
|
|
1717
|
+
static resolveStrict(evidence: StyleEvidence, base?: YamlLintConfig): Result.Result<YamlLintConfig, YamlStyleConflictError>;
|
|
1718
|
+
/**
|
|
1719
|
+
* Lenient resolution: the dominant (plurality) spelling per observed
|
|
1720
|
+
* dimension overlays `base` (default {@link YamlLintConfig.default}); a
|
|
1721
|
+
* tie breaks deterministically to the first candidate in canonical
|
|
1722
|
+
* value order. Total — lenient resolution cannot fail; the places that do
|
|
1723
|
+
* not match the inferred config surface as the residual report (run the
|
|
1724
|
+
* lint with the inferred config, or use {@link YamlLint.inferLenient}).
|
|
1725
|
+
*/
|
|
1726
|
+
static resolveLenient(evidence: StyleEvidence, base?: YamlLintConfig): YamlLintConfig;
|
|
1727
|
+
/**
|
|
1728
|
+
* Single-text strict inference: `observe` then {@link YamlLint.resolveStrict}
|
|
1729
|
+
* in one step. Multi-file callers observe each file and merge with
|
|
1730
|
+
* {@link StyleEvidence.combine} before resolving.
|
|
1731
|
+
*/
|
|
1732
|
+
static inferStrict(text: string, rules: ReadonlyArray<YamlRule>, base?: YamlLintConfig): Result.Result<YamlLintConfig, YamlStyleConflictError>;
|
|
1733
|
+
/**
|
|
1734
|
+
* Single-text lenient inference: `observe`, resolve dominant picks over
|
|
1735
|
+
* `base`, then run the lint with the inferred config — returning the
|
|
1736
|
+
* config AND the residual diagnostics it still produces ("here is your
|
|
1737
|
+
* config, and the places that do not match it"). One context serves both
|
|
1738
|
+
* the observation and the residual run. Multi-file callers compose the
|
|
1739
|
+
* primitives instead: observe each file, {@link StyleEvidence.combine},
|
|
1740
|
+
* {@link YamlLint.resolveLenient}, then {@link YamlLint.run} per file.
|
|
1741
|
+
*/
|
|
1742
|
+
static inferLenient(text: string, rules: ReadonlyArray<YamlRule>, base?: YamlLintConfig): YamlLintInference;
|
|
1450
1743
|
}
|
|
1451
1744
|
//#endregion
|
|
1452
1745
|
//#region src/YamlVisitor.d.ts
|
|
@@ -2051,5 +2344,5 @@ declare class YamlVisitor {
|
|
|
2051
2344
|
static visit(text: string, options?: YamlParseOptions): Stream.Stream<YamlVisitorEvent>;
|
|
2052
2345
|
}
|
|
2053
2346
|
//#endregion
|
|
2054
|
-
export { CollectionStyle, type LintContext, type LintLine, QuoteStyle, ScalarChomp, ScalarStyle, Yaml, YamlAlias, type YamlAliasEncoded, type YamlBoundCodec, YamlComposerErrorCode, YamlDiagnostic, YamlDirective, YamlDocument, YamlEdit, YamlErrorCode, YamlFormat, YamlFormattingOptions, YamlLexErrorCode, YamlLint, YamlLintConfig, YamlLintDiagnostic, YamlLintRuleSetting, YamlLintSeverity, YamlMap, type YamlMapEncoded, YamlModificationError, YamlModifyErrorCode, YamlNode, YamlPair, YamlParseError, YamlParseErrorCode, YamlParseOptions, type YamlPath, YamlRange, type YamlRangeLike, type YamlRule, YamlScalar, type YamlScalarEncoded, type YamlSegment, YamlSeq, type YamlSeqEncoded, YamlStringifyError, YamlStringifyErrorCode, YamlStringifyOptions, YamlToken, YamlTokenKind, YamlTokens, YamlVisitor, YamlVisitorEvent };
|
|
2347
|
+
export { CollectionStyle, type LintContext, type LintLine, QuoteCompat, QuoteStyle, ScalarChomp, ScalarStyle, StyleConflict, StyleEvidence, StyleFloor, StyleFloorTally, type StyleObservation, StyleVote, StyleVoteTally, Yaml, YamlAlias, type YamlAliasEncoded, type YamlBoundCodec, YamlComposerErrorCode, YamlDiagnostic, YamlDirective, YamlDocument, YamlEdit, YamlErrorCode, YamlFormat, YamlFormattingOptions, YamlLexErrorCode, YamlLint, YamlLintConfig, YamlLintDiagnostic, type YamlLintInference, YamlLintRuleSetting, YamlLintSeverity, YamlMap, type YamlMapEncoded, YamlModificationError, YamlModifyErrorCode, YamlNode, YamlPair, YamlParseError, YamlParseErrorCode, YamlParseOptions, type YamlPath, YamlRange, type YamlRangeLike, type YamlRule, YamlScalar, type YamlScalarEncoded, type YamlSegment, YamlSeq, type YamlSeqEncoded, YamlStringifyError, YamlStringifyErrorCode, YamlStringifyOptions, YamlStyleConflictError, YamlToken, YamlTokenKind, YamlTokens, YamlVisitor, YamlVisitorEvent };
|
|
2055
2348
|
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { CollectionStyle, QuoteStyle, ScalarChomp, ScalarStyle, YamlAlias, YamlMap, YamlNode, YamlPair, YamlScalar, YamlSeq } from "./YamlNode.js";
|
|
1
|
+
import { CollectionStyle, QuoteCompat, QuoteStyle, ScalarChomp, ScalarStyle, YamlAlias, YamlMap, YamlNode, YamlPair, YamlScalar, YamlSeq } from "./YamlNode.js";
|
|
2
2
|
import { YamlComposerErrorCode, YamlDiagnostic, YamlErrorCode, YamlLexErrorCode, YamlModifyErrorCode, YamlParseErrorCode, YamlStringifyErrorCode } from "./YamlDiagnostic.js";
|
|
3
3
|
import { Yaml, YamlParseError, YamlParseOptions, YamlStringifyError, YamlStringifyOptions } from "./Yaml.js";
|
|
4
4
|
import { YamlDirective, YamlDocument } from "./YamlDocument.js";
|
|
5
5
|
import { YamlEdit, YamlRange } from "./YamlEdit.js";
|
|
6
6
|
import { YamlFormat, YamlFormattingOptions, YamlModificationError } from "./YamlFormat.js";
|
|
7
|
-
import { YamlLintDiagnostic, YamlLintSeverity } from "./YamlLintRule.js";
|
|
7
|
+
import { StyleFloor, StyleVote, YamlLintDiagnostic, YamlLintSeverity } from "./YamlLintRule.js";
|
|
8
8
|
import { YamlToken, YamlTokenKind, YamlTokens } from "./YamlToken.js";
|
|
9
|
-
import { YamlLint, YamlLintConfig, YamlLintRuleSetting } from "./YamlLint.js";
|
|
9
|
+
import { StyleConflict, StyleEvidence, StyleFloorTally, StyleVoteTally, YamlLint, YamlLintConfig, YamlLintRuleSetting, YamlStyleConflictError } from "./YamlLint.js";
|
|
10
10
|
import { YamlVisitor, YamlVisitorEvent } from "./YamlVisitor.js";
|
|
11
11
|
|
|
12
|
-
export { CollectionStyle, QuoteStyle, ScalarChomp, ScalarStyle, Yaml, YamlAlias, YamlComposerErrorCode, YamlDiagnostic, YamlDirective, YamlDocument, YamlEdit, YamlErrorCode, YamlFormat, YamlFormattingOptions, YamlLexErrorCode, YamlLint, YamlLintConfig, YamlLintDiagnostic, YamlLintRuleSetting, YamlLintSeverity, YamlMap, YamlModificationError, YamlModifyErrorCode, YamlNode, YamlPair, YamlParseError, YamlParseErrorCode, YamlParseOptions, YamlRange, YamlScalar, YamlSeq, YamlStringifyError, YamlStringifyErrorCode, YamlStringifyOptions, YamlToken, YamlTokenKind, YamlTokens, YamlVisitor, YamlVisitorEvent };
|
|
12
|
+
export { CollectionStyle, QuoteCompat, QuoteStyle, ScalarChomp, ScalarStyle, StyleConflict, StyleEvidence, StyleFloor, StyleFloorTally, StyleVote, StyleVoteTally, Yaml, YamlAlias, YamlComposerErrorCode, YamlDiagnostic, YamlDirective, YamlDocument, YamlEdit, YamlErrorCode, YamlFormat, YamlFormattingOptions, YamlLexErrorCode, YamlLint, YamlLintConfig, YamlLintDiagnostic, YamlLintRuleSetting, YamlLintSeverity, YamlMap, YamlModificationError, YamlModifyErrorCode, YamlNode, YamlPair, YamlParseError, YamlParseErrorCode, YamlParseOptions, YamlRange, YamlScalar, YamlSeq, YamlStringifyError, YamlStringifyErrorCode, YamlStringifyOptions, YamlStyleConflictError, YamlToken, YamlTokenKind, YamlTokens, YamlVisitor, YamlVisitorEvent };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { isControlChar } from "./fold.js";
|
|
2
|
+
import { renderDoubleQuoted, renderSingleQuoted } from "./stringifier.js";
|
|
3
|
+
|
|
4
|
+
//#region src/internal/requote.ts
|
|
5
|
+
/**
|
|
6
|
+
* True when `value` can be carried by a single-quoted flow scalar on one
|
|
7
|
+
* line. Single-quoted style has exactly one escape (`''`), so any character
|
|
8
|
+
* double-quote escape sequences exist to encode — newline, carriage return,
|
|
9
|
+
* tab, C0 controls, DEL and the C1 range — has no single-quoted spelling and
|
|
10
|
+
* makes the conversion impossible rather than lossy-but-tempting.
|
|
11
|
+
*/
|
|
12
|
+
function isSingleQuotable(value) {
|
|
13
|
+
for (let i = 0; i < value.length; i++) {
|
|
14
|
+
const code = value.charCodeAt(i);
|
|
15
|
+
if (code === 9 || code === 10 || code === 13) return false;
|
|
16
|
+
if (isControlChar(code)) return false;
|
|
17
|
+
if (code === 127 || code >= 128 && code <= 159) return false;
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The replacement raw text that re-quotes `scalar` with `quote`, or
|
|
23
|
+
* `undefined` when no value-preserving replacement exists under `mode`
|
|
24
|
+
* (skipping is always correct; corrupting never is).
|
|
25
|
+
*/
|
|
26
|
+
function requoteScalarText(text, scalar, quote, mode) {
|
|
27
|
+
if (scalar.tag !== void 0 || scalar.anchor !== void 0) return void 0;
|
|
28
|
+
if (typeof scalar.value !== "string") return void 0;
|
|
29
|
+
const raw = text.slice(scalar.offset, scalar.offset + scalar.length);
|
|
30
|
+
if (raw.includes("\n") || raw.includes("\r")) return void 0;
|
|
31
|
+
if (mode === "conservative") {
|
|
32
|
+
const inner = scalar.style === "plain" ? raw : raw.slice(1, -1);
|
|
33
|
+
if (inner !== scalar.value) return void 0;
|
|
34
|
+
if (inner.includes(quote)) return void 0;
|
|
35
|
+
if (quote === "\"" && inner.includes("\\")) return void 0;
|
|
36
|
+
return `${quote}${inner}${quote}`;
|
|
37
|
+
}
|
|
38
|
+
if (quote === "\"") {
|
|
39
|
+
if (scalar.style !== "single-quoted") return void 0;
|
|
40
|
+
return renderDoubleQuoted(scalar.value);
|
|
41
|
+
}
|
|
42
|
+
if (scalar.style !== "double-quoted") return void 0;
|
|
43
|
+
if (!isSingleQuotable(scalar.value)) return void 0;
|
|
44
|
+
return renderSingleQuoted(scalar.value);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
export { requoteScalarText };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { YamlEdit } from "../../YamlEdit.js";
|
|
2
|
-
import { YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
2
|
+
import { StyleVote, YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
3
3
|
import { nonNegativeIntegerOption } from "./util.js";
|
|
4
4
|
import { Schema } from "effect";
|
|
5
5
|
|
|
@@ -14,6 +14,25 @@ const commentsSpacingOptions = Schema.Struct({
|
|
|
14
14
|
minSpacesBefore: Schema.optionalKey(nonNegativeIntegerOption),
|
|
15
15
|
requireSpaceAfter: Schema.optionalKey(Schema.Boolean)
|
|
16
16
|
});
|
|
17
|
+
/**
|
|
18
|
+
* The horizontal whitespace run directly before a comment token, and whether
|
|
19
|
+
* line content precedes it (a TRAILING comment) — shared by the check and
|
|
20
|
+
* the inference hook so the two cannot disagree about what "before" means.
|
|
21
|
+
*/
|
|
22
|
+
const spacingBefore = (ctx, token) => {
|
|
23
|
+
let i = token.offset - 1;
|
|
24
|
+
let spaces = 0;
|
|
25
|
+
while (i >= 0 && (ctx.text[i] === " " || ctx.text[i] === " ")) {
|
|
26
|
+
spaces++;
|
|
27
|
+
i--;
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
spaces,
|
|
31
|
+
hasContentBefore: i >= 0 && ctx.text[i] !== "\n" && ctx.text[i] !== "\r"
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
/** Shebang exemption: `#!` at the very start of the stream. */
|
|
35
|
+
const isShebang = (token) => token.offset === 0 && token.text.startsWith("#!");
|
|
17
36
|
/** Comment spacing: after the `#`, and before a trailing comment's `#`. */
|
|
18
37
|
const commentsSpacing = {
|
|
19
38
|
id: "comments-spacing",
|
|
@@ -24,7 +43,7 @@ const commentsSpacing = {
|
|
|
24
43
|
const out = [];
|
|
25
44
|
for (const token of ctx.tokens) {
|
|
26
45
|
if (token.kind !== "comment") continue;
|
|
27
|
-
if (token
|
|
46
|
+
if (isShebang(token)) continue;
|
|
28
47
|
if (requireAfter && token.text.length > 1 && !/[ \t]/.test(token.text[1])) out.push(new YamlLintDiagnostic({
|
|
29
48
|
rule: "comments-spacing",
|
|
30
49
|
severity: "error",
|
|
@@ -39,13 +58,8 @@ const commentsSpacing = {
|
|
|
39
58
|
content: " "
|
|
40
59
|
})
|
|
41
60
|
}));
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
while (i >= 0 && (ctx.text[i] === " " || ctx.text[i] === " ")) {
|
|
45
|
-
spaces++;
|
|
46
|
-
i--;
|
|
47
|
-
}
|
|
48
|
-
if (i >= 0 && ctx.text[i] !== "\n" && ctx.text[i] !== "\r" && spaces < minBefore) out.push(new YamlLintDiagnostic({
|
|
61
|
+
const { spaces, hasContentBefore } = spacingBefore(ctx, token);
|
|
62
|
+
if (hasContentBefore && spaces < minBefore) out.push(new YamlLintDiagnostic({
|
|
49
63
|
rule: "comments-spacing",
|
|
50
64
|
severity: "error",
|
|
51
65
|
message: `Too few spaces before comment (${spaces} < ${minBefore})`,
|
|
@@ -61,6 +75,31 @@ const commentsSpacing = {
|
|
|
61
75
|
}));
|
|
62
76
|
}
|
|
63
77
|
return out;
|
|
78
|
+
},
|
|
79
|
+
infer: (ctx) => {
|
|
80
|
+
const out = [];
|
|
81
|
+
for (const token of ctx.tokens) {
|
|
82
|
+
if (token.kind !== "comment") continue;
|
|
83
|
+
if (isShebang(token)) continue;
|
|
84
|
+
if (token.text.length > 1) out.push(StyleVote.make({
|
|
85
|
+
dimension: "requireSpaceAfter",
|
|
86
|
+
value: /[ \t]/.test(token.text[1]),
|
|
87
|
+
offset: token.offset,
|
|
88
|
+
length: token.length,
|
|
89
|
+
line: token.line,
|
|
90
|
+
character: token.character
|
|
91
|
+
}));
|
|
92
|
+
const { spaces, hasContentBefore } = spacingBefore(ctx, token);
|
|
93
|
+
if (hasContentBefore) out.push(StyleVote.make({
|
|
94
|
+
dimension: "minSpacesBefore",
|
|
95
|
+
value: spaces,
|
|
96
|
+
offset: token.offset - spaces,
|
|
97
|
+
length: spaces,
|
|
98
|
+
line: token.line,
|
|
99
|
+
character: token.character - spaces
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
64
103
|
}
|
|
65
104
|
};
|
|
66
105
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { YamlEdit } from "../../YamlEdit.js";
|
|
2
|
-
import { YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
2
|
+
import { StyleVote, YamlLintDiagnostic, YamlLintSeverity } from "../../YamlLintRule.js";
|
|
3
3
|
import { Schema } from "effect";
|
|
4
4
|
|
|
5
5
|
//#region src/internal/rules/document-end.ts
|
|
@@ -14,31 +14,43 @@ const TRIVIA = /* @__PURE__ */ new Set([
|
|
|
14
14
|
"comment",
|
|
15
15
|
"byte-order-mark"
|
|
16
16
|
]);
|
|
17
|
+
/** The last non-trivia token: it decides whether the stream ends with `...`. */
|
|
18
|
+
const tailToken = (ctx) => [...ctx.tokens].reverse().find((t) => !TRIVIA.has(t.kind));
|
|
19
|
+
/**
|
|
20
|
+
* The end-of-stream position, shared by the missing-marker diagnostic and
|
|
21
|
+
* the absent-marker vote so the two cannot drift apart. `line`/`character`
|
|
22
|
+
* must agree with `offset` (= text length): when the text ends with a
|
|
23
|
+
* newline, that offset sits at the head of the line AFTER the last content
|
|
24
|
+
* line `buildLines` kept.
|
|
25
|
+
*/
|
|
26
|
+
const endOfStreamPosition = (ctx) => {
|
|
27
|
+
const lastLine = ctx.lines[ctx.lines.length - 1];
|
|
28
|
+
const trailingNewline = ctx.text.endsWith("\n");
|
|
29
|
+
return {
|
|
30
|
+
offset: ctx.text.length,
|
|
31
|
+
length: 0,
|
|
32
|
+
line: (lastLine?.number ?? 0) + (trailingNewline ? 1 : 0),
|
|
33
|
+
character: trailingNewline ? 0 : lastLine?.text.length ?? 0
|
|
34
|
+
};
|
|
35
|
+
};
|
|
17
36
|
/** The `...` marker at the tail of the stream. */
|
|
18
37
|
const documentEnd = {
|
|
19
38
|
id: "document-end",
|
|
20
39
|
check: (ctx, options) => {
|
|
21
40
|
const present = options?.present ?? true;
|
|
22
|
-
const tail =
|
|
41
|
+
const tail = tailToken(ctx);
|
|
23
42
|
const ended = tail?.kind === "document-end";
|
|
24
|
-
if (present && !ended && ctx.text.trim() !== "") {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
message: "Missing \"...\" document end marker",
|
|
43
|
+
if (present && !ended && ctx.text.trim() !== "") return [new YamlLintDiagnostic({
|
|
44
|
+
rule: "document-end",
|
|
45
|
+
severity: "error",
|
|
46
|
+
message: "Missing \"...\" document end marker",
|
|
47
|
+
...endOfStreamPosition(ctx),
|
|
48
|
+
fix: YamlEdit.make({
|
|
31
49
|
offset: ctx.text.length,
|
|
32
50
|
length: 0,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
offset: ctx.text.length,
|
|
37
|
-
length: 0,
|
|
38
|
-
content: ctx.text.endsWith("\n") ? "...\n" : "\n...\n"
|
|
39
|
-
})
|
|
40
|
-
})];
|
|
41
|
-
}
|
|
51
|
+
content: ctx.text.endsWith("\n") ? "...\n" : "\n...\n"
|
|
52
|
+
})
|
|
53
|
+
})];
|
|
42
54
|
if (!present && tail !== void 0 && tail.kind === "document-end") {
|
|
43
55
|
const alone = (ctx.lines[tail.line]?.text ?? "").trim() === "...";
|
|
44
56
|
const terminator = ctx.text.startsWith("\r\n", tail.offset + tail.length) ? 2 : 1;
|
|
@@ -58,6 +70,24 @@ const documentEnd = {
|
|
|
58
70
|
})];
|
|
59
71
|
}
|
|
60
72
|
return [];
|
|
73
|
+
},
|
|
74
|
+
infer: (ctx) => {
|
|
75
|
+
if (ctx.text.trim() === "") return [];
|
|
76
|
+
const tail = tailToken(ctx);
|
|
77
|
+
if (tail === void 0) return [];
|
|
78
|
+
if (tail.kind === "document-end") return [StyleVote.make({
|
|
79
|
+
dimension: "present",
|
|
80
|
+
value: true,
|
|
81
|
+
offset: tail.offset,
|
|
82
|
+
length: tail.length,
|
|
83
|
+
line: tail.line,
|
|
84
|
+
character: tail.character
|
|
85
|
+
})];
|
|
86
|
+
return [StyleVote.make({
|
|
87
|
+
dimension: "present",
|
|
88
|
+
value: false,
|
|
89
|
+
...endOfStreamPosition(ctx)
|
|
90
|
+
})];
|
|
61
91
|
}
|
|
62
92
|
};
|
|
63
93
|
|