yini-parser 1.4.3 → 1.6.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 +52 -0
- package/README.md +187 -35
- package/dist/YINI.d.ts +29 -18
- package/dist/YINI.js +104 -3
- package/dist/core/astBuilder.d.ts +94 -18
- package/dist/core/astBuilder.js +439 -376
- package/dist/core/errorDataHandler.d.ts +6 -1
- package/dist/core/errorDataHandler.js +30 -43
- package/dist/core/internalTypes.d.ts +10 -1
- package/dist/core/objectBuilder.d.ts +8 -4
- package/dist/core/objectBuilder.js +47 -62
- package/dist/core/options/defaultParserOptions.d.ts +3 -2
- package/dist/core/options/defaultParserOptions.js +11 -2
- package/dist/core/options/optionsFunctions.js +6 -4
- package/dist/core/parsingRules/modeFromRulesMatcher.d.ts +1 -1
- package/dist/core/parsingRules/modeFromRulesMatcher.js +22 -13
- package/dist/core/pipeline/pipeline.js +35 -10
- package/dist/core/runtime.js +28 -19
- package/dist/grammar/generated/YiniLexer.d.ts +40 -53
- package/dist/grammar/generated/YiniLexer.js +357 -356
- package/dist/grammar/generated/YiniParser.d.ts +174 -118
- package/dist/grammar/generated/YiniParser.js +1185 -929
- package/dist/grammar/generated/YiniParserVisitor.d.ts +82 -19
- package/dist/grammar/generated/YiniParserVisitor.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -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 +39 -20
- package/dist/parsers/validateShebangPlacement.d.ts +3 -0
- package/dist/parsers/validateShebangPlacement.js +52 -0
- package/dist/types/index.d.ts +20 -3
- 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/compare-formats.md +1 -1
- package/examples/nested.yini +1 -1
- 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 -168
- 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,6 +1,58 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 1.6.0 - 2026 May
|
|
4
|
+
- **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.
|
|
5
|
+
- **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.
|
|
6
|
+
- **Updated:** Parser behavior aligned with YINI Specification `v1.0.0-RC.6`, including:
|
|
7
|
+
* **Changed:** `#` now always starts a comment outside string literals. No whitespace is required before or after `#`.
|
|
8
|
+
* **Added:** Support for explicit hexadecimal notation using `hex:` as an alternative to `0x...`.
|
|
9
|
+
* **Removed:** Support for `#` as a hexadecimal number prefix. Hexadecimal numbers must now use `0x...` or `hex:...`.
|
|
10
|
+
* **Removed:** Internal handling of Hyper Strings (H-Strings), simplifying string parsing and reducing parser complexity.
|
|
11
|
+
* **Added:** Lenient mode now accepts `=` as an alternative inline object member separator. The canonical form remains `key: value`.
|
|
12
|
+
* **Changed:** Strict mode rejects `=` inside inline objects; inline object members must use `:`.
|
|
13
|
+
* **Changed:** String concatenation now uses the updated grammar model:
|
|
14
|
+
- `+` performs explicit string concatenation only; it does not define numeric addition.
|
|
15
|
+
- In strict mode, all operands must be string literals.
|
|
16
|
+
- In lenient mode, the first operand must be a string literal; later operands may be string, number, boolean, or null literals.
|
|
17
|
+
- If the expression does not begin with a string literal, it is rejected rather than treated as arithmetic.
|
|
18
|
+
- A line break is allowed after `+`, but not before it.
|
|
19
|
+
- Lists and inline objects are invalid concatenation operands.
|
|
20
|
+
* **Added:** Empty-document handling by mode:
|
|
21
|
+
- In lenient mode, empty documents now parse successfully with a warning.
|
|
22
|
+
- In strict mode, empty documents now produce an error.
|
|
23
|
+
* **Improved:** Orphan root-level members in lenient mode are mounted directly on the resulting top-level object.
|
|
24
|
+
* **Improved:** Parser/runtime handling of empty inline input and final newline normalization.
|
|
25
|
+
* **Updated:** Tests for string concatenation, empty documents, inline object separators, hash comments, and hex notation.
|
|
26
|
+
* **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.
|
|
27
|
+
* **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.
|
|
28
|
+
* **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.
|
|
29
|
+
* **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`.
|
|
30
|
+
* **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.
|
|
31
|
+
* **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.
|
|
32
|
+
* **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.
|
|
33
|
+
* **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.
|
|
34
|
+
* **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.
|
|
35
|
+
|
|
36
|
+
## 1.5.0 - 2026 Apr
|
|
37
|
+
- **Updated:** Parser behavior aligned with YINI Specification `v1.0.0-RC.5`.
|
|
38
|
+
- **Changed:** In strict mode, YINI documents must now end with the document terminator `/END`.
|
|
39
|
+
- **Changed:** Strict mode now requires exactly one explicit top-level section.
|
|
40
|
+
- **Updated:** Section header parsing now reflects the latest horizontal whitespace (`HSPACE`) rules from the specification.
|
|
41
|
+
- **Improved:** Refined how members outside explicit sections are handled in lenient mode, and added stricter checks for top-level structure in strict mode.
|
|
42
|
+
- **Improved:** Clarified and tightened how empty values and explicit `null` are handled in lenient and strict mode.
|
|
43
|
+
- **Improved:** Fixed `throwOnError` option detection, clarified the related documentation, and cleaned up public parameter names.
|
|
44
|
+
- **Fixed:** Made `throwOnError` work consistently together with the selected fail level.
|
|
45
|
+
- **Updated:** Synced to the latest lexer and parser grammar files from the Specification Package `v1.0.0-RC.5`, with cleaned up and refined grammar files for better consistency and maintainability.
|
|
46
|
+
- **Added:** Expanded validation and tests for section headers, including shorthand markers, backticked names, and invalid dotted section names.
|
|
47
|
+
- **Expanded:** Improved integration and smoke test coverage for error recovery, throw behavior, null handling, fixture parsing, and section/header edge cases.
|
|
48
|
+
- **Updated:** Added and validated a new large smoke/golden fixture:
|
|
49
|
+
- `tests/fixtures/smoke-fixtures/c-industrial-monitoring-and-automation-platform.smoke.yini`
|
|
50
|
+
- **Improved:** Fixed and re-enabled previously skipped smoke tests:
|
|
51
|
+
- `tests/fixtures/smoke-fixtures/8-api-keys-integration.smoke.yini`
|
|
52
|
+
- `tests/fixtures/smoke-fixtures/9-app-preferences.smoke.yini`
|
|
53
|
+
|
|
3
54
|
## 1.4.3 - 2026 Apr
|
|
55
|
+
- **Promoted:** YINI Parser TypeScript is now considered stable (non-beta) after iterative beta releases and refinements.
|
|
4
56
|
- **Fixed:** Rebuilt the project and reduced reported vulnerabilities from 4 to 0.
|
|
5
57
|
|
|
6
58
|
## 1.4.3-beta - 2026 Mar
|
package/README.md
CHANGED
|
@@ -1,11 +1,51 @@
|
|
|
1
1
|
# yini-parser
|
|
2
|
-
> **Readable configuration for Node.js and TypeScript — without YAML foot-guns or JSON noise.**
|
|
3
2
|
|
|
4
|
-
The official TypeScript / Node.js parser for **YINI** (by the YINI-lang project) — a human-
|
|
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.
|
|
5
4
|
|
|
6
|
-
|
|
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)
|
|
7
6
|
|
|
8
|
-
|
|
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
|
+
---
|
|
9
49
|
|
|
10
50
|
## Quick Start
|
|
11
51
|
|
|
@@ -18,45 +58,48 @@ 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
|
+
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
75
|
|
|
34
76
|
---
|
|
35
77
|
|
|
36
|
-
##
|
|
78
|
+
## Format characteristics
|
|
37
79
|
|
|
38
|
-
- **
|
|
39
|
-
- **Structured
|
|
40
|
-
- **Predictable parsing** — Explicit syntax with clear rules.
|
|
41
|
-
- **
|
|
80
|
+
- **Human-readable** — Uses explicit syntax and indentation-independent structure.
|
|
81
|
+
- **Structured configuration model** — Supports sections, nested sections, lists, objects, booleans, and null.
|
|
82
|
+
- **Predictable parsing** — Explicit syntax with clear rules and deterministic parsing behavior.
|
|
83
|
+
- **TypeScript and Node.js integration** — Supports parsing from strings and files.
|
|
42
84
|
|
|
43
85
|
---
|
|
44
86
|
|
|
45
87
|
## What YINI looks like in practice
|
|
46
|
-
> A basic YINI configuration example, showing a section, nested section, comments:
|
|
88
|
+
> A basic YINI configuration example, showing a section, a nested section, and comments:
|
|
47
89
|

|
|
48
90
|
Source: [basic.yini](./samples/basic.yini)
|
|
49
91
|
|
|
50
|
-
-
|
|
92
|
+
- [Demo Apps](https://github.com/YINI-lang/yini-demo-apps/tree/main) with usage examples.
|
|
51
93
|
|
|
52
94
|
---
|
|
53
95
|
|
|
54
|
-
##
|
|
96
|
+
## Configuration-oriented design
|
|
55
97
|
- **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
|
|
98
|
+
- **Explicit nesting:** Hierarchy is defined with section markers such as `^`, `^^`, and `^^^`, rather than by indentation.
|
|
57
99
|
- **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
|
-
- **
|
|
100
|
+
- **Comment support:** YINI supports `//`, `#`, block comments (`/* ... */`), and full-line `;` comments for documenting configuration directly in the file.
|
|
101
|
+
- **Clear hash comments:** Outside string literals, `#` always starts a comment; hexadecimal values use `0x...` or `hex:...`.
|
|
102
|
+
- **Predictable parsing:** Clear rules with optional strict and lenient modes (enforced by the parser) for different use cases.
|
|
60
103
|
|
|
61
104
|
---
|
|
62
105
|
|
|
@@ -80,7 +123,7 @@ pnpm add yini-parser
|
|
|
80
123
|
```
|
|
81
124
|
|
|
82
125
|
### Node.js (CommonJS)
|
|
83
|
-
**Note:**
|
|
126
|
+
**Note:** The default export is the main API. Named exports such as `parse`, `parseFile`, and `parseForTooling` are also available from the package entry.
|
|
84
127
|
```js
|
|
85
128
|
const YINI = require('yini-parser').default;
|
|
86
129
|
// If your setup handles default interop differently, try:
|
|
@@ -130,7 +173,7 @@ const configFromFile = YINI.parseFile('./config.yini');
|
|
|
130
173
|
|
|
131
174
|
## 📂 More Examples
|
|
132
175
|
|
|
133
|
-
-
|
|
176
|
+
- 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
177
|
|
|
135
178
|
### Example 2
|
|
136
179
|
> A real-world YINI configuration example, showing sections, nesting, comments, and multiple data types:
|
|
@@ -139,30 +182,139 @@ Source: [config.yini](./samples/config.yini)
|
|
|
139
182
|
|
|
140
183
|
---
|
|
141
184
|
|
|
142
|
-
##
|
|
185
|
+
## Why YINI?
|
|
186
|
+
|
|
187
|
+
YINI is intended for configuration files where human readability, explicit structure, and predictable parsing are more important than minimal syntax or maximum flexibility.
|
|
188
|
+
|
|
189
|
+
Compared with common configuration formats:
|
|
190
|
+
- **INI:** YINI supports clearer nested sections and typed values.
|
|
191
|
+
- **JSON:** YINI supports comments and is easier to edit by hand.
|
|
192
|
+
- **YAML:** YINI does not use indentation to define structure.
|
|
193
|
+
- **TOML:** YINI uses explicit section markers for hierarchy instead of dotted table names.
|
|
194
|
+
|
|
195
|
+
The same small configuration can be written in several formats:
|
|
143
196
|
|
|
144
|
-
|
|
197
|
+
### YINI
|
|
198
|
+
```ini
|
|
199
|
+
^ Application
|
|
200
|
+
name = 'demo'
|
|
201
|
+
environment = 'dev'
|
|
202
|
+
|
|
203
|
+
^^ Server
|
|
204
|
+
host = 'localhost'
|
|
205
|
+
ports = [8080, 8081]
|
|
206
|
+
|
|
207
|
+
^^^ TLS
|
|
208
|
+
enabled = true
|
|
209
|
+
mode = 'optional'
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
- `Application` contains the top-level application settings.
|
|
213
|
+
- `Server` is nested under `Application`.
|
|
214
|
+
- `TLS` is nested under `Server`.
|
|
215
|
+
- The section markers `^` make the nesting explicit. Indentation is optional and not required for structure.
|
|
216
|
+
- Strings can use either `'` or `"`.
|
|
217
|
+
|
|
218
|
+
### JSON
|
|
219
|
+
```json
|
|
220
|
+
{
|
|
221
|
+
"Application": {
|
|
222
|
+
"name": "demo",
|
|
223
|
+
"environment": "dev",
|
|
224
|
+
"Server": {
|
|
225
|
+
"host": "localhost",
|
|
226
|
+
"ports": [8080, 8081],
|
|
227
|
+
"TLS": {
|
|
228
|
+
"enabled": true,
|
|
229
|
+
"mode": "optional"
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### YAML
|
|
237
|
+
```yaml
|
|
238
|
+
Application:
|
|
239
|
+
name: demo
|
|
240
|
+
environment: dev
|
|
241
|
+
Server:
|
|
242
|
+
host: localhost
|
|
243
|
+
ports:
|
|
244
|
+
- 8080
|
|
245
|
+
- 8081
|
|
246
|
+
TLS:
|
|
247
|
+
enabled: true
|
|
248
|
+
mode: optional
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### TOML
|
|
252
|
+
```toml
|
|
253
|
+
[Application]
|
|
254
|
+
name = "demo"
|
|
255
|
+
environment = "dev"
|
|
256
|
+
|
|
257
|
+
[Application.Server]
|
|
258
|
+
host = "localhost"
|
|
259
|
+
ports = [8080, 8081]
|
|
260
|
+
|
|
261
|
+
[Application.Server.TLS]
|
|
262
|
+
enabled = true
|
|
263
|
+
mode = "optional"
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
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
267
|
|
|
146
268
|
---
|
|
147
269
|
|
|
148
|
-
##
|
|
149
|
-
|
|
150
|
-
|
|
270
|
+
## Parser implementation
|
|
271
|
+
|
|
272
|
+
`yini-parser` uses TypeScript/JavaScript parser code generated by ANTLR.
|
|
273
|
+
|
|
274
|
+
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
275
|
|
|
152
|
-
|
|
153
|
-
*CLI tooling for working with YINI files.*
|
|
276
|
+
The package depends on the ANTLR JavaScript/TypeScript runtime used by the generated lexer and parser while parsing.
|
|
154
277
|
|
|
155
|
-
|
|
156
|
-
|
|
278
|
+
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.
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Feedback and bug reports
|
|
283
|
+
|
|
284
|
+
If you find a problem, please open an issue on GitHub:
|
|
285
|
+
|
|
286
|
+
- [Report a bug or issue](https://github.com/YINI-lang/yini-parser-typescript/issues)
|
|
287
|
+
|
|
288
|
+
When reporting parser behavior, it is helpful to include:
|
|
289
|
+
- The YINI input that caused the issue.
|
|
290
|
+
- The expected result.
|
|
291
|
+
- The actual result or error message.
|
|
292
|
+
- The installed `yini-parser` version.
|
|
293
|
+
- The Node.js version used.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## 🧪 Testing and Stability
|
|
298
|
+
|
|
299
|
+
This parser is covered by smoke, integration, and regression tests across lenient, strict, and metadata-enabled modes.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Links
|
|
304
|
+
- [YINI Homepage](https://yini-lang.org)
|
|
305
|
+
- [YINI Specification](https://yini-lang.org/refs/specification)
|
|
306
|
+
- [YINI CLI on GitHub](https://github.com/YINI-lang/yini-cli)
|
|
307
|
+
- [YINI Demo Apps](https://github.com/YINI-lang/yini-demo-apps/tree/main)
|
|
308
|
+
- [YINI-lang Project](https://github.com/YINI-lang)
|
|
157
309
|
|
|
158
310
|
---
|
|
159
311
|
|
|
160
312
|
## 🤝 Contributing
|
|
161
|
-
|
|
313
|
+
Bug reports, feature requests, discussions, and code contributions are welcome.
|
|
162
314
|
- [Open an Issue](https://github.com/YINI-lang/yini-parser-typescript/issues)
|
|
163
315
|
- [Start a Discussion](https://github.com/YINI-lang/yini-parser-typescript/discussions)
|
|
164
316
|
|
|
165
|
-
|
|
317
|
+
GitHub Issues and Discussions are available for feedback and project discussion.
|
|
166
318
|
|
|
167
319
|
### Documentation
|
|
168
320
|
- [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.
|
|
@@ -171,15 +323,15 @@ If this library is useful to you, a GitHub star helps more people discover the p
|
|
|
171
323
|
---
|
|
172
324
|
|
|
173
325
|
## License
|
|
174
|
-
This project is licensed under the Apache
|
|
326
|
+
This project is licensed under the Apache License 2.0 — see the [LICENSE](./LICENSE) file for details.
|
|
175
327
|
|
|
176
|
-
In this project on GitHub, the `libs` directory contains third
|
|
328
|
+
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`.
|
|
177
329
|
|
|
178
330
|
---
|
|
179
331
|
|
|
180
332
|
**^YINI ≡**
|
|
181
|
-
>
|
|
333
|
+
> YINI is a human-readable configuration format designed for clarity, readability, explicit structure, and predictable parsing.
|
|
182
334
|
>
|
|
183
|
-
>
|
|
335
|
+
> See the specification for syntax and format details.
|
|
184
336
|
|
|
185
337
|
[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,8 +1,8 @@
|
|
|
1
|
-
import { ParsedObject, ParseOptions, PreferredFailLevel, YiniParseResult } from './types';
|
|
1
|
+
import { ParsedObject, ParseForToolingOptions, ParseOptions, PreferredFailLevel, YiniParseResult, YiniToolingParseResult } from './types';
|
|
2
2
|
/**
|
|
3
|
-
* This class is the public API
|
|
4
|
-
*
|
|
5
|
-
* @note
|
|
3
|
+
* This class is the main public API. It exposes `parse(..)` and `parseFile(..)`
|
|
4
|
+
* as the primary entry points, while the implementation details remain internal.
|
|
5
|
+
* @note The public parsing API is exposed through `parse(..)` and `parseFile(..)`.
|
|
6
6
|
*/
|
|
7
7
|
export default class YINI {
|
|
8
8
|
private static g_tabSize;
|
|
@@ -69,20 +69,20 @@ 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,
|
|
80
82
|
* the effective mode becomes **custom** rather than purely strict/lenient.
|
|
81
83
|
* @param options.treatEmptyValueAsNull - How to treat an explicitly empty value on the
|
|
82
84
|
* right-hand side of '='. Allowed values: `'allow'` | `'allow-with-warning'` | `'disallow'`.
|
|
83
|
-
* @param options.throwOnError -
|
|
84
|
-
* NOTE: Current default is `true`. The default will change to `false` in the next
|
|
85
|
-
* release. To avoid breaking changes, set this option explicitly.
|
|
85
|
+
* @param options.throwOnError - Throw when a parse issue reaches the active bail threshold (for example, on errors if `failLevel = 'errors'`).
|
|
86
86
|
*
|
|
87
87
|
* @returns {ParsedObject | YiniParseResult} The parsed YINI content.
|
|
88
88
|
*
|
|
@@ -103,10 +103,21 @@ export default class YINI {
|
|
|
103
103
|
* `
|
|
104
104
|
*/
|
|
105
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;
|
|
106
117
|
/**
|
|
107
118
|
* Parse a YINI file into a JavaScript object.
|
|
108
119
|
*
|
|
109
|
-
* @param
|
|
120
|
+
* @param filePath Path to the YINI file.
|
|
110
121
|
* @param strictMode If `true`, enforce strict parsing rules (e.g. require `/END`, disallow trailing commas).
|
|
111
122
|
* @param failLevel Preferred bail sensitivity level, controls if and when parsing should stop on problems:
|
|
112
123
|
* - `'auto'` (default) : Auto‑select level (strict → `'errors'`, lenient → `'ignore-errors'`)
|
|
@@ -137,7 +148,7 @@ export default class YINI {
|
|
|
137
148
|
/**
|
|
138
149
|
* Parse a YINI file into a JavaScript object, using an options object for configuration.
|
|
139
150
|
*
|
|
140
|
-
* @param
|
|
151
|
+
* @param filePath Path to the YINI file.
|
|
141
152
|
* @param options Optional settings to customize parsing and/or results, useful if you need more control.
|
|
142
153
|
* For all options, see types/ParseOptions.
|
|
143
154
|
*
|
|
@@ -157,20 +168,20 @@ export default class YINI {
|
|
|
157
168
|
* Allowed values: `'warn-and-keep-first'` | `'warn-and-overwrite'` | `'keep-first'` (silent, first wins) | `'overwrite'` (silent, last wins) | `'error'`.
|
|
158
169
|
* @param options.preserveUndefinedInMeta - Keep properties with value `undefined` inside
|
|
159
170
|
* the returned metadata. Requires: `includeMetadata = true`. Ignored otherwise.
|
|
160
|
-
* @param options.
|
|
161
|
-
*
|
|
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.
|
|
162
175
|
* @param options.requireDocTerminator - Controls whether a document terminator is required.
|
|
163
176
|
* Allowed values: `'optional'` | `'warn-if-missing'` | `'required'`.
|
|
164
|
-
* @param options.silent - Suppress
|
|
177
|
+
* @param options.silent - Suppress diagnostic output, even when `logDiagnostics = true`.
|
|
165
178
|
* @param options.strictMode - Sets the baseline ruleset (true = strict, false = lenient).
|
|
166
179
|
* This is only a starting point: rule-specific options (e.g., `treatEmptyValueAsNull`,
|
|
167
180
|
* `onDuplicateKey`, etc.) can override parts of that ruleset. If any overrides are given,
|
|
168
181
|
* the effective mode becomes **custom** rather than purely strict/lenient.
|
|
169
182
|
* @param options.treatEmptyValueAsNull - How to treat an explicitly empty value on the
|
|
170
183
|
* right-hand side of '='. Allowed values: `'allow'` | `'allow-with-warning'` | `'disallow'`.
|
|
171
|
-
* @param options.throwOnError -
|
|
172
|
-
* NOTE: Current default is `true`. The default will change to `false` in the next
|
|
173
|
-
* release. To avoid breaking changes, set this option explicitly.
|
|
184
|
+
* @param options.throwOnError - Throw when a parse issue reaches the active bail threshold (for example, on errors if `failLevel = 'errors'`).
|
|
174
185
|
*
|
|
175
186
|
* @returns {ParsedObject | YiniParseResult} The parsed YINI content.
|
|
176
187
|
*
|
package/dist/YINI.js
CHANGED
|
@@ -7,9 +7,9 @@ const runtime_1 = require("./core/runtime");
|
|
|
7
7
|
const print_1 = require("./utils/print");
|
|
8
8
|
const DEFAULT_TAB_SIZE = 4; // De facto "modern default" (even though traditionally/historically it's 8).
|
|
9
9
|
/**
|
|
10
|
-
* This class is the public API
|
|
11
|
-
*
|
|
12
|
-
* @note
|
|
10
|
+
* This class is the main public API. It exposes `parse(..)` and `parseFile(..)`
|
|
11
|
+
* as the primary entry points, while the implementation details remain internal.
|
|
12
|
+
* @note The public parsing API is exposed through `parse(..)` and `parseFile(..)`.
|
|
13
13
|
*/
|
|
14
14
|
class YINI {
|
|
15
15
|
/**
|
|
@@ -53,6 +53,107 @@ 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('invalid escape sequence')) {
|
|
141
|
+
return 'invalid-escape-sequence';
|
|
142
|
+
}
|
|
143
|
+
if (text.includes('unterminated') && text.includes('string')) {
|
|
144
|
+
return 'unterminated-string';
|
|
145
|
+
}
|
|
146
|
+
if (text.includes('/end') && text.includes('missing')) {
|
|
147
|
+
return 'missing-document-terminator';
|
|
148
|
+
}
|
|
149
|
+
if (text.includes('shebang')) {
|
|
150
|
+
return 'misplaced-shebang';
|
|
151
|
+
}
|
|
152
|
+
if (text.includes('trailing comma')) {
|
|
153
|
+
return 'trailing-comma';
|
|
154
|
+
}
|
|
155
|
+
return issue.typeKey.replace(/_/g, '-');
|
|
156
|
+
}
|
|
56
157
|
// --- Single implementation --------------------------------------------
|
|
57
158
|
// Implementation method (not declared with arrow function) for both method overload signatures.
|
|
58
159
|
// NOTE: Must be method declaration with NO =, arrow functions not (currently) supported for this type of method overloading.
|