yini-parser 1.5.0 → 1.6.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.
- package/CHANGELOG.md +41 -0
- package/LICENSE +1 -1
- package/README.md +199 -37
- package/dist/YINI.d.ts +22 -7
- package/dist/YINI.js +104 -0
- package/dist/core/astBuilder.d.ts +94 -15
- package/dist/core/astBuilder.js +396 -364
- package/dist/core/errorDataHandler.d.ts +29 -1
- package/dist/core/errorDataHandler.js +120 -63
- package/dist/core/internalTypes.d.ts +10 -1
- package/dist/core/objectBuilder.js +21 -6
- package/dist/core/options/defaultParserOptions.d.ts +3 -2
- package/dist/core/options/defaultParserOptions.js +2 -1
- package/dist/core/options/optionsFunctions.js +5 -1
- package/dist/core/pipeline/pipeline.js +31 -12
- package/dist/core/runtime.js +29 -34
- package/dist/grammar/generated/YiniLexer.d.ts +28 -35
- package/dist/grammar/generated/YiniLexer.js +323 -310
- package/dist/grammar/generated/YiniParser.d.ts +158 -80
- package/dist/grammar/generated/YiniParser.js +1141 -620
- package/dist/grammar/generated/YiniParserVisitor.d.ts +77 -14
- package/dist/grammar/generated/YiniParserVisitor.js +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +6 -3
- package/dist/parsers/extractHeaderParts.d.ts +12 -19
- package/dist/parsers/extractHeaderParts.js +57 -46
- package/dist/parsers/parseNumber.d.ts +24 -6
- package/dist/parsers/parseNumber.js +114 -49
- package/dist/parsers/parseSectionHeader.d.ts +11 -3
- package/dist/parsers/parseSectionHeader.js +55 -43
- package/dist/parsers/parseString.js +42 -21
- package/dist/parsers/validateShebangPlacement.d.ts +4 -0
- package/dist/parsers/validateShebangPlacement.js +115 -0
- package/dist/types/index.d.ts +19 -2
- package/dist/utils/print.d.ts +1 -0
- package/dist/utils/print.js +5 -1
- package/dist/utils/string.d.ts +1 -0
- package/dist/utils/string.js +17 -1
- package/dist/utils/system.d.ts +1 -0
- package/dist/utils/system.js +6 -1
- package/dist/utils/yiniHelpers.d.ts +44 -2
- package/dist/utils/yiniHelpers.js +134 -46
- package/examples/basic.yini +1 -0
- package/examples/compare-formats.md +1 -1
- package/examples/nested.yini +1 -1
- package/examples/parse-example.ts +1 -0
- package/package.json +11 -3
- package/dist/YINI.js.map +0 -1
- package/dist/config/env.js.map +0 -1
- package/dist/core/astBuilder.js.map +0 -1
- package/dist/core/errorDataHandler.js.map +0 -1
- package/dist/core/internalTypes.js.map +0 -1
- package/dist/core/objectBuilder.js.map +0 -1
- package/dist/core/options/defaultParserOptions.js.map +0 -1
- package/dist/core/options/failLevel.js.map +0 -1
- package/dist/core/options/optionsFunctions.js.map +0 -1
- package/dist/core/parsingRules/modeFromRulesMatcher.js.map +0 -1
- package/dist/core/parsingRules/rulesConstAndGuards.js.map +0 -1
- package/dist/core/pipeline/errorListeners.js.map +0 -1
- package/dist/core/pipeline/pipeline.js.map +0 -1
- package/dist/core/resultMetadataBuilder.js.map +0 -1
- package/dist/core/runtime.js.map +0 -1
- package/dist/dev/main.d.ts +0 -1
- package/dist/dev/main.js +0 -139
- package/dist/dev/main.js.map +0 -1
- package/dist/dev/quick-test-samples/defect-inputs.d.ts +0 -37
- package/dist/dev/quick-test-samples/defect-inputs.js +0 -106
- package/dist/dev/quick-test-samples/defect-inputs.js.map +0 -1
- package/dist/dev/quick-test-samples/valid-inputs.d.ts +0 -21
- package/dist/dev/quick-test-samples/valid-inputs.js +0 -422
- package/dist/dev/quick-test-samples/valid-inputs.js.map +0 -1
- package/dist/grammar/generated/YiniLexer.js.map +0 -1
- package/dist/grammar/generated/YiniParser.js.map +0 -1
- package/dist/grammar/generated/YiniParserVisitor.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/parsers/extractHeaderParts.js.map +0 -1
- package/dist/parsers/extractSignificantYiniLine.js.map +0 -1
- package/dist/parsers/parseBoolean.js.map +0 -1
- package/dist/parsers/parseNull.js.map +0 -1
- package/dist/parsers/parseNumber.js.map +0 -1
- package/dist/parsers/parseSectionHeader.js.map +0 -1
- package/dist/parsers/parseString.js.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/dist/utils/number.js.map +0 -1
- package/dist/utils/object.js.map +0 -1
- package/dist/utils/pathAndFileName.js.map +0 -1
- package/dist/utils/print.js.map +0 -1
- package/dist/utils/string.js.map +0 -1
- package/dist/utils/system.js.map +0 -1
- package/dist/utils/yiniHelpers.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 1.6.1 - 2026 June
|
|
4
|
+
- **Fixed:** Aligned parser behavior with the external `yini-test` conformance suite for shebang-like comment lines, misplaced `@yini` directives, and triple-quoted string line endings.
|
|
5
|
+
- **Fixed:** `#!` lines after an opening `@yini` marker are now treated as comment trivia, while `@yini` directives after document content are reported as syntax errors in both lenient and strict mode.
|
|
6
|
+
- **Fixed:** Triple-quoted raw and Classic strings now normalize physical `CRLF`/`CR` line endings to `LF`, producing stable output across platforms.
|
|
7
|
+
- **Fixed:** Diagnostic line numbers no longer shift by one after a valid shebang line; strict-mode trailing-comma errors now point to the actual physical source line.
|
|
8
|
+
- **Fixed:** Removed the outdated warning `Warning: Strict initialMode is not yet fully implemented.` Strict mode is now implemented against the latest YINI Specification RC 6.
|
|
9
|
+
- **Improved:** Parse errors now use a concise `YiniParseError`, and missing `/END` messages clearly explain that `/END` is required in strict mode but optional in the default lenient mode.
|
|
10
|
+
|
|
11
|
+
## 1.6.0 - 2026 May
|
|
12
|
+
- **Improved:** Reduced the published npm package contents by excluding development-only build output, internal tool output, and duplicate `dist/src` declaration files from the package tarball.
|
|
13
|
+
- **Added:** Implemented a `yini-test` adapter (`tools/yini-test-adapter.ts`) for testing this parser against an external conformance corpus. The `yini-test` corpus/test runner is planned to be made public and released separately in the future.
|
|
14
|
+
- **Updated:** Parser behavior aligned with YINI Specification `v1.0.0-RC.6`, including:
|
|
15
|
+
* **Changed:** `#` now always starts a comment outside string literals. No whitespace is required before or after `#`.
|
|
16
|
+
* **Added:** Support for explicit hexadecimal notation using `hex:` as an alternative to `0x...`.
|
|
17
|
+
* **Removed:** Support for `#` as a hexadecimal number prefix. Hexadecimal numbers must now use `0x...` or `hex:...`.
|
|
18
|
+
* **Removed:** Internal handling of Hyper Strings (H-Strings), simplifying string parsing and reducing parser complexity.
|
|
19
|
+
* **Added:** Lenient mode now accepts `=` as an alternative inline object member separator. The canonical form remains `key: value`.
|
|
20
|
+
* **Changed:** Strict mode rejects `=` inside inline objects; inline object members must use `:`.
|
|
21
|
+
* **Changed:** String concatenation now uses the updated grammar model:
|
|
22
|
+
- `+` performs explicit string concatenation only; it does not define numeric addition.
|
|
23
|
+
- In strict mode, all operands must be string literals.
|
|
24
|
+
- In lenient mode, the first operand must be a string literal; later operands may be string, number, boolean, or null literals.
|
|
25
|
+
- If the expression does not begin with a string literal, it is rejected rather than treated as arithmetic.
|
|
26
|
+
- A line break is allowed after `+`, but not before it.
|
|
27
|
+
- Lists and inline objects are invalid concatenation operands.
|
|
28
|
+
* **Added:** Empty-document handling by mode:
|
|
29
|
+
- In lenient mode, empty documents now parse successfully with a warning.
|
|
30
|
+
- In strict mode, empty documents now produce an error.
|
|
31
|
+
* **Improved:** Orphan root-level members in lenient mode are mounted directly on the resulting top-level object.
|
|
32
|
+
* **Improved:** Parser/runtime handling of empty inline input and final newline normalization.
|
|
33
|
+
* **Updated:** Tests for string concatenation, empty documents, inline object separators, hash comments, and hex notation.
|
|
34
|
+
* **Added:** Support for YINI mode declarations: `@yini strict` and `@yini lenient`. Mode declarations validate the active parser mode; they do not switch parser mode. `@yini strict` parsed in lenient mode produces a mode-mismatch error, while `@yini lenient` parsed in strict mode remains valid but produces a mode-mismatch warning.
|
|
35
|
+
* **Updated:** Shebang handling. A shebang is recognized only when `#!` is the first two non-BOM characters of the document. Valid shebang lines are ignored. Misplaced shebang-like sequences are no longer treated as shebangs; they may produce warnings in lenient mode and errors in strict mode. Only the first misplaced sequence is reported.
|
|
36
|
+
* **Updated:** Section marker handling. Repeated section markers now support levels 1–9; level 10 and deeper must use numeric shorthand, for example `^10 Section`. Marker separators using `_` are supported inside repeated marker sequences, invalid separator placement and mixed marker characters are rejected, the obsolete `€` marker has been removed, and `>` is supported as an alternative marker.
|
|
37
|
+
* **Updated:** Numeric shorthand section headers. Numeric shorthand now keeps marker and depth parsing separate, requires a positive section depth, uses a single marker followed by a number, and rejects repeated markers combined with numeric shorthand, such as `^^1 Section`.
|
|
38
|
+
* **Improved:** Section header parsing and validation. Backticked section names are normalized, invalid simple names such as names with dots, hyphens, or leading digits are rejected, and parsing is aligned with the updated marker separator and alternative marker rules.
|
|
39
|
+
* **Updated:** String literal handling. Raw strings remain the default; `R`/`r` explicit raw prefixes, `C`/`c` Classic prefixes, raw triple-quoted strings, and C-triple-quoted strings are supported. C-triple-quoted strings preserve real line breaks while interpreting escape sequences. Invalid Classic string escapes are reported as errors, and invalid string members are omitted from recovered partial results in lenient `ignore-errors` mode.
|
|
40
|
+
* **Improved:** Escape sequence validation. Unicode escapes must represent valid Unicode scalar values, surrogate code points are rejected, and invalid hex, Unicode, UTF-32, and octal escapes are rejected.
|
|
41
|
+
* **Improved:** Duplicate inline object member handling. Duplicate members are no longer silently overwritten: lenient mode keeps the first member and reports duplicates; strict mode treats duplicates as errors.
|
|
42
|
+
* **Updated:** Comment and disabled-line handling. `;` is full-line only, `--` disables a line only when it is the first non-whitespace content, and `#` / `//` remain inline comment markers outside string literals.
|
|
43
|
+
|
|
3
44
|
## 1.5.0 - 2026 Apr
|
|
4
45
|
- **Updated:** Parser behavior aligned with YINI Specification `v1.0.0-RC.5`.
|
|
5
46
|
- **Changed:** In strict mode, YINI documents must now end with the document terminator `/END`.
|
package/LICENSE
CHANGED
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
|
187
187
|
identification within third-party archives.
|
|
188
188
|
|
|
189
|
-
Copyright
|
|
189
|
+
Copyright 2026 Marko K. Seppänen
|
|
190
190
|
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
192
|
you may not use this file except in compliance with the License.
|
package/README.md
CHANGED
|
@@ -1,12 +1,52 @@
|
|
|
1
1
|
# yini-parser
|
|
2
|
-
> **Readable configuration for Node.js and TypeScript/JavaScript — without YAML footguns or JSON noise.**
|
|
3
2
|
|
|
4
|
-
The official TypeScript / Node.js parser for **YINI** (by the YINI-lang project) — a human-
|
|
5
|
-
|
|
6
|
-
YINI is designed for applications, tools, and services that need configuration that stays readable for humans without becoming vague, fragile, or hard to maintain.
|
|
3
|
+
The official TypeScript / Node.js parser for **YINI** (by the YINI-lang project) — a human-readable, INI-inspired, indentation-insensitive configuration format with clear nested sections, explicit structure, comments, and predictable parsing.
|
|
7
4
|
|
|
8
5
|
[](https://www.npmjs.com/package/yini-parser) [](https://www.typescriptlang.org/) [](https://github.com/YINI-lang/yini-parser-typescript/actions/workflows/run-all-tests.yml) [](https://github.com/YINI-lang/yini-parser-typescript/actions/workflows/run-regression-tests.yml) [](https://github.com/YINI-lang/yini-parser-typescript/actions/workflows/run-grammar-drift-check.yml) [](https://www.npmjs.com/package/yini-parser)
|
|
9
6
|
|
|
7
|
+
YINI is intended to emphasize clarity, readability, explicit structure, and predictable parsing, while remaining simple, but not simplistic, and without relying on implicit or indentation-sensitive structure.
|
|
8
|
+
|
|
9
|
+
## Copy-paste test
|
|
10
|
+
|
|
11
|
+
Test the package in under one minute.
|
|
12
|
+
|
|
13
|
+
Install:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install yini-parser
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Parse a YINI string:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import YINI from 'yini-parser'
|
|
23
|
+
|
|
24
|
+
const data = YINI.parse(`
|
|
25
|
+
^ Application
|
|
26
|
+
name = "demo"
|
|
27
|
+
|
|
28
|
+
^^ Server
|
|
29
|
+
port = 8080
|
|
30
|
+
`)
|
|
31
|
+
|
|
32
|
+
console.log(data)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Expected output:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
{
|
|
39
|
+
Application: {
|
|
40
|
+
name: 'demo',
|
|
41
|
+
Server: {
|
|
42
|
+
port: 8080,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
10
50
|
## Quick Start
|
|
11
51
|
|
|
12
52
|
```sh
|
|
@@ -18,27 +58,43 @@ import YINI from 'yini-parser'
|
|
|
18
58
|
|
|
19
59
|
const config = YINI.parse(`
|
|
20
60
|
^ App
|
|
21
|
-
name
|
|
22
|
-
|
|
61
|
+
name = 'My App'
|
|
62
|
+
list = ['web', 'api']
|
|
63
|
+
darkMode = true // Yes/On works too
|
|
23
64
|
|
|
24
65
|
^^ Features
|
|
25
66
|
caching = on
|
|
67
|
+
object = { logging: true, mode: 'debug' }
|
|
26
68
|
`)
|
|
27
69
|
|
|
28
70
|
console.log(config.App.name) // My App
|
|
29
71
|
console.log(config.App.Features.caching) // true
|
|
30
72
|
```
|
|
31
73
|
|
|
32
|
-
|
|
74
|
+
### Modes and `/END`
|
|
75
|
+
|
|
76
|
+
`yini-parser` runs in lenient mode by default. In lenient mode, the document terminator `/END` is optional.
|
|
77
|
+
|
|
78
|
+
Strict mode requires `/END` unless you explicitly override `requireDocTerminator`:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
const config = YINI.parseFile('./config.yini', {
|
|
82
|
+
strictMode: true,
|
|
83
|
+
})
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
If strict mode reports a missing `/END`, either add `/END` as the final significant line or parse with the default lenient mode.
|
|
87
|
+
|
|
88
|
+
See the [YINI specification and documentation](https://yini-lang.org/refs/specification?utm_source=github&utm_medium=referral&utm_campaign=yini_parser_ts&utm_content=readme).
|
|
33
89
|
|
|
34
90
|
---
|
|
35
91
|
|
|
36
|
-
##
|
|
92
|
+
## Format characteristics
|
|
37
93
|
|
|
38
|
-
- **
|
|
39
|
-
- **Structured
|
|
40
|
-
- **Predictable parsing** — Explicit syntax with clear rules.
|
|
41
|
-
- **
|
|
94
|
+
- **Human-readable** — Uses explicit syntax and indentation-independent structure.
|
|
95
|
+
- **Structured configuration model** — Supports sections, nested sections, lists, objects, booleans, and null.
|
|
96
|
+
- **Predictable parsing** — Explicit syntax with clear rules and deterministic parsing behavior.
|
|
97
|
+
- **TypeScript and Node.js integration** — Supports parsing from strings and files.
|
|
42
98
|
|
|
43
99
|
---
|
|
44
100
|
|
|
@@ -47,16 +103,17 @@ console.log(config.App.Features.caching) // true
|
|
|
47
103
|

|
|
48
104
|
Source: [basic.yini](./samples/basic.yini)
|
|
49
105
|
|
|
50
|
-
-
|
|
106
|
+
- [Demo Apps](https://github.com/YINI-lang/yini-demo-apps/tree/main) with usage examples.
|
|
51
107
|
|
|
52
108
|
---
|
|
53
109
|
|
|
54
|
-
##
|
|
110
|
+
## Configuration-oriented design
|
|
55
111
|
- **Indentation-independent structure:** Spaces and tabs never change meaning, so files can be reformatted without changing structure.
|
|
56
|
-
- **Explicit nesting:** Hierarchy is defined with section markers
|
|
112
|
+
- **Explicit nesting:** Hierarchy is defined with section markers such as `^`, `^^`, and `^^^`, rather than by indentation.
|
|
57
113
|
- **Multiple data types:** Supports booleans (`true` / `false`, `yes` / `no`, etc.), numbers, lists, and inline objects, with explicit string syntax.
|
|
58
|
-
- **Comment support:** YINI supports
|
|
59
|
-
- **
|
|
114
|
+
- **Comment support:** YINI supports `//`, `#`, block comments (`/* ... */`), and full-line `;` comments for documenting configuration directly in the file.
|
|
115
|
+
- **Clear hash comments:** Outside string literals, `#` always starts a comment; hexadecimal values use `0x...` or `hex:...`.
|
|
116
|
+
- **Predictable parsing:** Clear rules with optional strict and lenient modes (enforced by the parser) for different use cases.
|
|
60
117
|
|
|
61
118
|
---
|
|
62
119
|
|
|
@@ -80,7 +137,7 @@ pnpm add yini-parser
|
|
|
80
137
|
```
|
|
81
138
|
|
|
82
139
|
### Node.js (CommonJS)
|
|
83
|
-
**Note:**
|
|
140
|
+
**Note:** The default export is the main API. Named exports such as `parse`, `parseFile`, and `parseForTooling` are also available from the package entry.
|
|
84
141
|
```js
|
|
85
142
|
const YINI = require('yini-parser').default;
|
|
86
143
|
// If your setup handles default interop differently, try:
|
|
@@ -130,7 +187,7 @@ const configFromFile = YINI.parseFile('./config.yini');
|
|
|
130
187
|
|
|
131
188
|
## 📂 More Examples
|
|
132
189
|
|
|
133
|
-
-
|
|
190
|
+
- Additional [YINI examples](https://yini-lang.org/learn-yini/examples/?utm_source=yini-parser-ts&utm_medium=github&utm_campaign=repo-link&utm_content=readme).
|
|
134
191
|
|
|
135
192
|
### Example 2
|
|
136
193
|
> A real-world YINI configuration example, showing sections, nesting, comments, and multiple data types:
|
|
@@ -139,36 +196,141 @@ Source: [config.yini](./samples/config.yini)
|
|
|
139
196
|
|
|
140
197
|
---
|
|
141
198
|
|
|
142
|
-
##
|
|
199
|
+
## Why YINI?
|
|
200
|
+
|
|
201
|
+
YINI is intended for configuration files where human readability, explicit structure, and predictable parsing are more important than minimal syntax or maximum flexibility.
|
|
143
202
|
|
|
144
|
-
|
|
203
|
+
Compared with common configuration formats:
|
|
204
|
+
- **INI:** YINI supports clearer nested sections and typed values.
|
|
205
|
+
- **JSON:** YINI supports comments and is easier to edit by hand.
|
|
206
|
+
- **YAML:** YINI does not use indentation to define structure.
|
|
207
|
+
- **TOML:** YINI uses explicit section markers for hierarchy instead of dotted table names.
|
|
208
|
+
|
|
209
|
+
The same small configuration can be written in several formats:
|
|
210
|
+
|
|
211
|
+
### YINI
|
|
212
|
+
```ini
|
|
213
|
+
^ Application
|
|
214
|
+
name = 'demo'
|
|
215
|
+
environment = 'dev'
|
|
216
|
+
|
|
217
|
+
^^ Server
|
|
218
|
+
host = 'localhost'
|
|
219
|
+
ports = [8080, 8081]
|
|
220
|
+
|
|
221
|
+
^^^ TLS
|
|
222
|
+
enabled = true
|
|
223
|
+
mode = 'optional'
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
- `Application` contains the top-level application settings.
|
|
227
|
+
- `Server` is nested under `Application`.
|
|
228
|
+
- `TLS` is nested under `Server`.
|
|
229
|
+
- The section markers `^` make the nesting explicit. Indentation is optional and not required for structure.
|
|
230
|
+
- Strings can use either `'` or `"`.
|
|
231
|
+
|
|
232
|
+
### JSON
|
|
233
|
+
```json
|
|
234
|
+
{
|
|
235
|
+
"Application": {
|
|
236
|
+
"name": "demo",
|
|
237
|
+
"environment": "dev",
|
|
238
|
+
"Server": {
|
|
239
|
+
"host": "localhost",
|
|
240
|
+
"ports": [8080, 8081],
|
|
241
|
+
"TLS": {
|
|
242
|
+
"enabled": true,
|
|
243
|
+
"mode": "optional"
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### YAML
|
|
251
|
+
```yaml
|
|
252
|
+
Application:
|
|
253
|
+
name: demo
|
|
254
|
+
environment: dev
|
|
255
|
+
Server:
|
|
256
|
+
host: localhost
|
|
257
|
+
ports:
|
|
258
|
+
- 8080
|
|
259
|
+
- 8081
|
|
260
|
+
TLS:
|
|
261
|
+
enabled: true
|
|
262
|
+
mode: optional
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### TOML
|
|
266
|
+
```toml
|
|
267
|
+
[Application]
|
|
268
|
+
name = "demo"
|
|
269
|
+
environment = "dev"
|
|
270
|
+
|
|
271
|
+
[Application.Server]
|
|
272
|
+
host = "localhost"
|
|
273
|
+
ports = [8080, 8081]
|
|
274
|
+
|
|
275
|
+
[Application.Server.TLS]
|
|
276
|
+
enabled = true
|
|
277
|
+
mode = "optional"
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Note: YINI may not be the right choice when you need mature ecosystem support, existing schema tooling, or maximum compatibility with infrastructure that already expects JSON, YAML, or TOML.
|
|
145
281
|
|
|
146
282
|
---
|
|
147
283
|
|
|
148
|
-
##
|
|
149
|
-
|
|
150
|
-
|
|
284
|
+
## Parser implementation
|
|
285
|
+
|
|
286
|
+
`yini-parser` uses TypeScript/JavaScript parser code generated by ANTLR.
|
|
287
|
+
|
|
288
|
+
The generated parser files are included in the published npm package. Users do **not** need Java or the ANTLR generator tool to install or use `yini-parser`.
|
|
151
289
|
|
|
152
|
-
|
|
153
|
-
*Full syntax and format reference.*
|
|
290
|
+
The package depends on the ANTLR JavaScript/TypeScript runtime used by the generated lexer and parser while parsing.
|
|
154
291
|
|
|
155
|
-
|
|
156
|
-
|
|
292
|
+
The ANTLR generator JAR is only needed by maintainers when regenerating parser sources from the grammar, and it is not included in the published npm package.
|
|
293
|
+
|
|
294
|
+
---
|
|
157
295
|
|
|
158
|
-
|
|
159
|
-
*Complete basic usage examples.*
|
|
296
|
+
## Feedback and bug reports
|
|
160
297
|
|
|
161
|
-
|
|
162
|
-
|
|
298
|
+
If you find a problem, please open an issue on GitHub:
|
|
299
|
+
|
|
300
|
+
- [Report a bug or issue](https://github.com/YINI-lang/yini-parser-typescript/issues)
|
|
301
|
+
|
|
302
|
+
When reporting parser behavior, it is helpful to include:
|
|
303
|
+
- The YINI input that caused the issue.
|
|
304
|
+
- The expected result.
|
|
305
|
+
- The actual result or error message.
|
|
306
|
+
- The installed `yini-parser` version.
|
|
307
|
+
- The Node.js version used.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## 🧪 Testing and Stability
|
|
312
|
+
|
|
313
|
+
This parser is covered by smoke, integration, and regression tests across lenient, strict, and metadata-enabled modes.
|
|
314
|
+
|
|
315
|
+
It has also been run against `yini-test-suite` v0.3.0, the external [YINI conformance test suite](https://github.com/YINI-lang/yini-test-suite), with all TypeScript parser cases passing.
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## Links
|
|
320
|
+
- [YINI Homepage](https://yini-lang.org)
|
|
321
|
+
- [YINI Specification](https://yini-lang.org/refs/specification)
|
|
322
|
+
- [YINI CLI on GitHub](https://github.com/YINI-lang/yini-cli)
|
|
323
|
+
- [YINI Demo Apps](https://github.com/YINI-lang/yini-demo-apps/tree/main)
|
|
324
|
+
- [YINI-lang Project](https://github.com/YINI-lang)
|
|
163
325
|
|
|
164
326
|
---
|
|
165
327
|
|
|
166
328
|
## 🤝 Contributing
|
|
167
|
-
|
|
329
|
+
Bug reports, feature requests, discussions, and code contributions are welcome.
|
|
168
330
|
- [Open an Issue](https://github.com/YINI-lang/yini-parser-typescript/issues)
|
|
169
331
|
- [Start a Discussion](https://github.com/YINI-lang/yini-parser-typescript/discussions)
|
|
170
332
|
|
|
171
|
-
|
|
333
|
+
GitHub Issues and Discussions are available for feedback and project discussion.
|
|
172
334
|
|
|
173
335
|
### Documentation
|
|
174
336
|
- [Project Setup](https://github.com/YINI-lang/yini-parser-typescript/blob/main/docs/Project-Setup.md) — How to run, test, and build the project, etc.
|
|
@@ -179,13 +341,13 @@ If this library is useful to you, a GitHub star helps more people discover the p
|
|
|
179
341
|
## License
|
|
180
342
|
This project is licensed under the Apache License 2.0 — see the [LICENSE](./LICENSE) file for details.
|
|
181
343
|
|
|
182
|
-
In this project on GitHub, the `libs` directory contains third-party software and each is licensed under its own license
|
|
344
|
+
In this project on GitHub, the `libs` directory contains third-party software and each is licensed under its own license which is described in its own license file under the respective directory under `libs`.
|
|
183
345
|
|
|
184
346
|
---
|
|
185
347
|
|
|
186
348
|
**^YINI ≡**
|
|
187
|
-
>
|
|
349
|
+
> YINI is a human-readable configuration format designed for clarity, readability, explicit structure, and predictable parsing.
|
|
188
350
|
>
|
|
189
|
-
>
|
|
351
|
+
> See the specification for syntax and format details.
|
|
190
352
|
|
|
191
353
|
[yini-lang.org](https://yini-lang.org/?utm_source=github&utm_medium=referral&utm_campaign=yini_parser_ts&utm_content=readme_footer) · [YINI-lang on GitHub](https://github.com/YINI-lang)
|
package/dist/YINI.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ParsedObject, ParseOptions, PreferredFailLevel, YiniParseResult } from './types';
|
|
1
|
+
import { ParsedObject, ParseForToolingOptions, ParseOptions, PreferredFailLevel, YiniParseResult, YiniToolingParseResult } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* This class is the main public API. It exposes `parse(..)` and `parseFile(..)`
|
|
4
4
|
* as the primary entry points, while the implementation details remain internal.
|
|
@@ -69,11 +69,13 @@ export default class YINI {
|
|
|
69
69
|
* Allowed values: `'warn-and-keep-first'` | `'warn-and-overwrite'` | `'keep-first'` (silent, first wins) | `'overwrite'` (silent, last wins) | `'error'`.
|
|
70
70
|
* @param options.preserveUndefinedInMeta - Keep properties with value `undefined` inside
|
|
71
71
|
* the returned metadata. Requires: `includeMetadata = true`. Ignored otherwise.
|
|
72
|
-
* @param options.
|
|
73
|
-
*
|
|
72
|
+
* @param options.logDiagnostics - Opt in to writing diagnostics to stderr.
|
|
73
|
+
* Library calls do not write diagnostics by default.
|
|
74
|
+
* @param options.quiet - When `logDiagnostics = true`, show only errors.
|
|
75
|
+
* Does not affect diagnostics included in returned metadata.
|
|
74
76
|
* @param options.requireDocTerminator - Controls whether a document terminator is required.
|
|
75
77
|
* Allowed values: `'optional'` | `'warn-if-missing'` | `'required'`.
|
|
76
|
-
* @param options.silent - Suppress
|
|
78
|
+
* @param options.silent - Suppress diagnostic output, even when `logDiagnostics = true`.
|
|
77
79
|
* @param options.strictMode - Sets the baseline ruleset (true = strict, false = lenient).
|
|
78
80
|
* This is only a starting point: rule-specific options (e.g., `treatEmptyValueAsNull`,
|
|
79
81
|
* `onDuplicateKey`, etc.) can override parts of that ruleset. If any overrides are given,
|
|
@@ -101,6 +103,17 @@ export default class YINI {
|
|
|
101
103
|
* `
|
|
102
104
|
*/
|
|
103
105
|
static parse(yiniContent: string, options?: ParseOptions): ParsedObject | YiniParseResult;
|
|
106
|
+
/**
|
|
107
|
+
* Parse inline YINI content for tools, editors, linters, and test runners.
|
|
108
|
+
*
|
|
109
|
+
* This API always returns a stable result object and structured diagnostics.
|
|
110
|
+
* It does not write diagnostics to stdout/stderr and does not throw for
|
|
111
|
+
* normal parse errors.
|
|
112
|
+
*/
|
|
113
|
+
static parseForTooling(yiniContent: string, options?: ParseForToolingOptions): YiniToolingParseResult;
|
|
114
|
+
private static toToolingDiagnostics;
|
|
115
|
+
private static toToolingDiagnostic;
|
|
116
|
+
private static toDiagnosticCode;
|
|
104
117
|
/**
|
|
105
118
|
* Parse a YINI file into a JavaScript object.
|
|
106
119
|
*
|
|
@@ -155,11 +168,13 @@ export default class YINI {
|
|
|
155
168
|
* Allowed values: `'warn-and-keep-first'` | `'warn-and-overwrite'` | `'keep-first'` (silent, first wins) | `'overwrite'` (silent, last wins) | `'error'`.
|
|
156
169
|
* @param options.preserveUndefinedInMeta - Keep properties with value `undefined` inside
|
|
157
170
|
* the returned metadata. Requires: `includeMetadata = true`. Ignored otherwise.
|
|
158
|
-
* @param options.
|
|
159
|
-
*
|
|
171
|
+
* @param options.logDiagnostics - Opt in to writing diagnostics to stderr.
|
|
172
|
+
* Library calls do not write diagnostics by default.
|
|
173
|
+
* @param options.quiet - When `logDiagnostics = true`, show only errors.
|
|
174
|
+
* Does not affect diagnostics included in returned metadata.
|
|
160
175
|
* @param options.requireDocTerminator - Controls whether a document terminator is required.
|
|
161
176
|
* Allowed values: `'optional'` | `'warn-if-missing'` | `'required'`.
|
|
162
|
-
* @param options.silent - Suppress
|
|
177
|
+
* @param options.silent - Suppress diagnostic output, even when `logDiagnostics = true`.
|
|
163
178
|
* @param options.strictMode - Sets the baseline ruleset (true = strict, false = lenient).
|
|
164
179
|
* This is only a starting point: rule-specific options (e.g., `treatEmptyValueAsNull`,
|
|
165
180
|
* `onDuplicateKey`, etc.) can override parts of that ruleset. If any overrides are given,
|
package/dist/YINI.js
CHANGED
|
@@ -53,6 +53,110 @@ class YINI {
|
|
|
53
53
|
}
|
|
54
54
|
return result;
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Parse inline YINI content for tools, editors, linters, and test runners.
|
|
58
|
+
*
|
|
59
|
+
* This API always returns a stable result object and structured diagnostics.
|
|
60
|
+
* It does not write diagnostics to stdout/stderr and does not throw for
|
|
61
|
+
* normal parse errors.
|
|
62
|
+
*/
|
|
63
|
+
static parseForTooling(yiniContent, options = {}) {
|
|
64
|
+
try {
|
|
65
|
+
const parsed = this.parse(yiniContent, {
|
|
66
|
+
...options,
|
|
67
|
+
failLevel: 'ignore-errors',
|
|
68
|
+
includeMetadata: true,
|
|
69
|
+
includeDiagnostics: true,
|
|
70
|
+
logDiagnostics: false,
|
|
71
|
+
silent: true,
|
|
72
|
+
throwOnError: false,
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
ok: parsed.meta.totalErrors === 0,
|
|
76
|
+
result: parsed.result,
|
|
77
|
+
diagnostics: this.toToolingDiagnostics(parsed),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
return {
|
|
82
|
+
ok: false,
|
|
83
|
+
result: {},
|
|
84
|
+
diagnostics: [
|
|
85
|
+
{
|
|
86
|
+
severity: 'error',
|
|
87
|
+
code: 'parser-error',
|
|
88
|
+
message: error instanceof Error
|
|
89
|
+
? error.message
|
|
90
|
+
: String(error),
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
static toToolingDiagnostics(parsed) {
|
|
97
|
+
const diagnostics = parsed.meta.diagnostics;
|
|
98
|
+
if (!diagnostics) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
return [
|
|
102
|
+
...diagnostics.errors.payload.map((issue) => this.toToolingDiagnostic(issue, 'error')),
|
|
103
|
+
...diagnostics.warnings.payload.map((issue) => this.toToolingDiagnostic(issue, 'warning')),
|
|
104
|
+
...diagnostics.notices.payload.map((issue) => this.toToolingDiagnostic(issue, 'notice')),
|
|
105
|
+
...diagnostics.infos.payload.map((issue) => this.toToolingDiagnostic(issue, 'info')),
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
static toToolingDiagnostic(issue, severity) {
|
|
109
|
+
const diagnostic = {
|
|
110
|
+
severity,
|
|
111
|
+
code: this.toDiagnosticCode(issue),
|
|
112
|
+
message: issue.message,
|
|
113
|
+
};
|
|
114
|
+
if (issue.line !== undefined) {
|
|
115
|
+
diagnostic.line = issue.line;
|
|
116
|
+
}
|
|
117
|
+
if (issue.column !== undefined) {
|
|
118
|
+
diagnostic.column = issue.column;
|
|
119
|
+
}
|
|
120
|
+
return diagnostic;
|
|
121
|
+
}
|
|
122
|
+
static toDiagnosticCode(issue) {
|
|
123
|
+
const text = [issue.message, issue.advice, issue.hint]
|
|
124
|
+
.filter((part) => Boolean(part))
|
|
125
|
+
.join(' ')
|
|
126
|
+
.toLowerCase();
|
|
127
|
+
if (text.includes('empty yini document')) {
|
|
128
|
+
return 'empty-document';
|
|
129
|
+
}
|
|
130
|
+
if (text.includes('duplicate key')) {
|
|
131
|
+
return 'duplicate-key';
|
|
132
|
+
}
|
|
133
|
+
if (text.includes('duplicate section')) {
|
|
134
|
+
return 'duplicate-section';
|
|
135
|
+
}
|
|
136
|
+
if (text.includes('yini mode declaration') &&
|
|
137
|
+
text.includes('active parser mode')) {
|
|
138
|
+
return 'YINI_MODE_MISMATCH';
|
|
139
|
+
}
|
|
140
|
+
if (text.includes('directive') && text.includes('wrong place')) {
|
|
141
|
+
return 'misplaced-directive';
|
|
142
|
+
}
|
|
143
|
+
if (text.includes('invalid escape sequence')) {
|
|
144
|
+
return 'invalid-escape-sequence';
|
|
145
|
+
}
|
|
146
|
+
if (text.includes('unterminated') && text.includes('string')) {
|
|
147
|
+
return 'unterminated-string';
|
|
148
|
+
}
|
|
149
|
+
if (text.includes('/end') && text.includes('missing')) {
|
|
150
|
+
return 'missing-document-terminator';
|
|
151
|
+
}
|
|
152
|
+
if (text.includes('shebang')) {
|
|
153
|
+
return 'misplaced-shebang';
|
|
154
|
+
}
|
|
155
|
+
if (text.includes('trailing comma')) {
|
|
156
|
+
return 'trailing-comma';
|
|
157
|
+
}
|
|
158
|
+
return issue.typeKey.replace(/_/g, '-');
|
|
159
|
+
}
|
|
56
160
|
// --- Single implementation --------------------------------------------
|
|
57
161
|
// Implementation method (not declared with arrow function) for both method overload signatures.
|
|
58
162
|
// NOTE: Must be method declaration with NO =, arrow functions not (currently) supported for this type of method overloading.
|