@domorium/validator 1.2.0 → 1.4.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/CHANGELOG.md CHANGED
@@ -2,6 +2,69 @@
2
2
 
3
3
  All notable changes to `@domorium/validator` are documented here.
4
4
 
5
+ ## 1.4.0 - 2026-08-09
6
+
7
+ - Read a `HEAD.SCHMA` tag whose URI is a standard one as the structure it names.
8
+ A tag definition makes its tag an abbreviation for that URI, so a record
9
+ written under an alias now answers a pointer to the standard tag, a date in an
10
+ aliased calendar carries that calendar's months, and an aliased structure is
11
+ validated as the standard one — payload and substructures alike. Its position
12
+ is not checked: a relocated standard structure may only appear under a
13
+ superstructure the specification does not document it under.
14
+ - Accept an extension tag as an enumeration value. Every one was reported as an
15
+ error, though the specification permits extending an enumeration with values
16
+ matching `extTag`. A value borrowed from another standard set, which the same
17
+ paragraph forbids, is still refused. An undocumented extension value reports
18
+ `VAL008`, as an undocumented tag already did.
19
+ - Stop requiring a payload GEDCOM 5.5.1 does not define. `1 EVEN` with a `TYPE`
20
+ beneath it was reported as missing a value; the individual event structure
21
+ gives it no payload at all, and the family one spells it
22
+ `[<EVENT_DESCRIPTOR> | <NULL>]`.
23
+ - **Reject a whole-number payload that is not a number.** `1 NCHI abc` was
24
+ accepted, and so were `3.7`, `12abc`, `1e3` and `Infinity`: the check compared
25
+ `parseInt(value) < 0`, and `NaN` fails every comparison.
26
+ - An event with neither a payload nor substructures is a warning, `VAL010`,
27
+ rather than an error reading "should be Y or null" — null is what it had, and
28
+ the payload is optional. It is not silent either: 5.5.1 introduces the `Y`
29
+ convention precisely to protect against processors that prune lines having
30
+ neither a value nor a subordinate line.
31
+ - A pointer whose target record type appears nowhere in the document no longer
32
+ reads `should be in set []`.
33
+ - **Each kind of problem now has its own code.** Every payload problem shipped as
34
+ the bare string `VAL`, so a consumer could not tell a missing value from a
35
+ malformed one, and `VAL003` to `VAL006` sat declared and unused. See the code
36
+ table in the README. `unresolved-xref` and `invalid-level` keep their strings.
37
+ - Export `GedcomError`, `GedcomErrorCode`, `Range` and `Position`. `getErrors()`
38
+ returns `GedcomError[]` and the type could not be named by a consumer.
39
+
40
+ ## 1.3.0 - 2026-08-08
41
+
42
+ - Read GEDCOM 7 dates against the calendar they name. `JULIAN 1401`,
43
+ `HEBREW 1 TSH 5761`, `FRENCH_R 2 VEND 8` and even `GREGORIAN 1 JAN 2000` were
44
+ all reported as invalid, because only v5.5.1's `@#D…@` escape was understood.
45
+ Each calendar's own months and epochs now apply, so `HEBREW 1 JAN 5761` is
46
+ refused and `BCE` is confined to the two calendars that permit it. A calendar
47
+ binds to the date after it, so `FROM JULIAN 1670 TO GREGORIAN 1800` is two
48
+ dates in two calendars.
49
+ - **Three v5.5.1 date forms are now refused inside a 7.0 document**, which may
50
+ make a file that was quiet noisy: the `@#D…@` calendar escape, a slashed year
51
+ such as `1 JAN 1857/58`, and the `INT 1950 (around 1950)` and `(unknown)`
52
+ phrase forms. Version 7.0 removed all three; a date phrase belongs in a
53
+ `PHRASE` substructure. GEDCOM 5.5.1 documents keep them.
54
+ - Stop reporting a payload the specification allows to be omitted. A payload may
55
+ be left out whenever its data type admits the empty string, which covers 61 of
56
+ the 182 payload types — `1 EVEN` with only a `TYPE` beneath it was being
57
+ flagged. `AGE`, `DateValue` and `DatePeriod` have their own explicit
58
+ permission: omitting the payload and giving a `PHRASE` instead is the
59
+ specification's own way to record that something happened but not what.
60
+ - Accept a leading UTF-8 byte order mark instead of reporting it as an
61
+ unexpected character. This was invisible in a browser, which strips the mark
62
+ while decoding, and affected anyone reading a file from disk.
63
+ - Say what belongs in a pointer slot. `Value for SOUR should be POINTER` named
64
+ the rule rather than the problem; a payload that is not a pointer at all now
65
+ reads `should be a pointer to a SOUR record, written as "@xref@"`, while an
66
+ xref that resolves to nothing names the records it could have meant.
67
+
5
68
  ## 1.2.0 - 2026-08-07
6
69
 
7
70
  - Keep the spaces that belong to a value. The lexer treated the delimiter after
package/README.md CHANGED
@@ -25,6 +25,54 @@ const document = new GedcomDocument().createDocument(gedcomString);
25
25
  const errors = document.getErrors();
26
26
  ```
27
27
 
28
+ ## Diagnostics
29
+
30
+ `getErrors()` returns `GedcomError[]`:
31
+
32
+ ```typescript
33
+ import type { GedcomError, Position, Range } from "@domorium/validator";
34
+
35
+ interface GedcomError {
36
+ code: string;
37
+ message: string;
38
+ hint?: string;
39
+ data?: { xref?: string; requiredRecordTag?: string; expectedLevel?: number };
40
+ range: Range;
41
+ level: "error" | "warning" | "info";
42
+ }
43
+ ```
44
+
45
+ `data` carries the facts a quick fix is built from — which xref failed to
46
+ resolve, and what record tag it needed.
47
+
48
+ Match on `code` rather than on `message`; messages are written for people and
49
+ change. `GedcomErrorCode` is exported for this:
50
+
51
+ ```typescript
52
+ import { GedcomErrorCode } from "@domorium/validator";
53
+
54
+ const unresolved = errors.filter(
55
+ (error) => error.code === GedcomErrorCode.UnresolvedXref,
56
+ );
57
+ ```
58
+
59
+ | Code | Member | Reported when |
60
+ | ----------------- | ---------------------- | ----------------------------------------------------------- |
61
+ | `VAL001` | `UnknownTag` | a tag the schema does not define in this position |
62
+ | `VAL002` | `MissingTag` | a structure the schema requires is absent |
63
+ | `VAL003` | `MissingValue` | the payload is absent where one is required |
64
+ | `VAL004` | `IncorrectValue` | the payload does not match its data type |
65
+ | `VAL005` | `ShouldBeSetValue` | the payload is not one of the permitted values |
66
+ | `VAL006` | `MissingRef` | a pointer payload that is not written as a pointer |
67
+ | `VAL007` | `ManyOccurrences` | more occurrences than the cardinality allows |
68
+ | `VAL008` | `UndocumentedTag` | a GEDCOM 7 extension tag with no `HEAD`.`SCHMA` declaration |
69
+ | `VAL009` | `DuplicateDeclaration` | a tag declared more than once in `HEAD`.`SCHMA` |
70
+ | `VAL010` | `EmptyEvent` | an event with neither a payload nor substructures |
71
+ | `unresolved-xref` | `UnresolvedXref` | an xref naming no record of the required type |
72
+ | `invalid-level` | `InvalidLevel` | a level that cannot follow the line above it |
73
+ | `LEXER` | `Lexer` | the text could not be tokenized |
74
+ | `PARSER` | `Parser` | the tokens could not be assembled into a tree |
75
+
28
76
  ## Scripts
29
77
 
30
78
  | Command | Description |