yini-parser 1.3.2-beta → 1.4.0-beta
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 +40 -1
- package/README.md +73 -186
- package/dist/YINI.d.ts +4 -4
- package/dist/YINI.js +0 -120
- package/dist/YINI.js.map +1 -1
- package/dist/core/astBuilder.d.ts +2 -0
- package/dist/core/astBuilder.js +97 -14
- package/dist/core/astBuilder.js.map +1 -1
- package/dist/core/internalTypes.d.ts +5 -0
- package/dist/core/options/defaultParserOptions.js +1 -7
- package/dist/core/options/defaultParserOptions.js.map +1 -1
- package/dist/core/options/optionsFunctions.js +7 -5
- package/dist/core/options/optionsFunctions.js.map +1 -1
- package/dist/core/resultMetadataBuilder.js +0 -1
- package/dist/core/resultMetadataBuilder.js.map +1 -1
- package/dist/dev/main.d.ts +1 -1
- package/dist/dev/main.js +27 -5
- package/dist/dev/main.js.map +1 -1
- package/dist/dev/quick-test-samples/defect-inputs.d.ts +37 -0
- package/dist/dev/quick-test-samples/defect-inputs.js +106 -0
- package/dist/dev/quick-test-samples/defect-inputs.js.map +1 -0
- package/dist/dev/quick-test-samples/valid-inputs.d.ts +21 -0
- package/dist/dev/quick-test-samples/valid-inputs.js +422 -0
- package/dist/dev/quick-test-samples/valid-inputs.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/parsers/parseString.d.ts +2 -1
- package/dist/parsers/parseString.js +132 -33
- package/dist/parsers/parseString.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/string.d.ts +2 -0
- package/dist/utils/string.js +12 -1
- package/dist/utils/string.js.map +1 -1
- package/examples/nested-output.js +1 -1
- package/examples/nested.yini +1 -1
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 1.4.0-beta - 2026 Feb
|
|
4
|
+
|
|
5
|
+
### ✨ Added
|
|
6
|
+
- Full implementation of **Classic (C) string literals** (`c"..."`, `C'...'`) according to specification section 6.2.
|
|
7
|
+
- Complete support for all defined escape sequences:
|
|
8
|
+
- `\\`, `\'`, `\"`, `\/`
|
|
9
|
+
- `\0`, `\?`, `\a`, `\b`, `\f`, `\n`, `\r`, `\t`, `\v`
|
|
10
|
+
- `\xhh` (2-digit hex)
|
|
11
|
+
- `\uhhhh` (UTF-16)
|
|
12
|
+
- `\Uhhhhhhhh` (UTF-32)
|
|
13
|
+
- `\oOOO` (octal, up to 3 digits, range `\o0`–`\o377`)
|
|
14
|
+
|
|
15
|
+
### 🔒 Improved
|
|
16
|
+
- Strict validation of invalid escape sequences (e.g. `\z`, malformed `\x`, `\u`, `\U`, `\o`).
|
|
17
|
+
- Enforcement of control character rules (U+0000–U+001F must be escaped in Classic strings).
|
|
18
|
+
- Proper handling of Classic string concatenation (`+`) including mixed raw + classic combinations.
|
|
19
|
+
|
|
20
|
+
### 🧪 Tests
|
|
21
|
+
- Expanded integration test coverage for Classic strings.
|
|
22
|
+
- Added validation tests for all escape types and error conditions.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 1.3.3-beta - 2025 Dec
|
|
27
|
+
This release strengthens correctness and reliability, while preserving the existing API and improving guarantees.
|
|
28
|
+
- **Added:**
|
|
29
|
+
- Added comprehensive smoke tests (F-5.a-d and F-6.a-d) matching YINI parsing against expected JSON output using two large, production-style configuration examples.
|
|
30
|
+
- **Corporate SaaS Platform** — [YINI](./tests/fixtures/smoke-fixtures/a-corporate-saas-platform.smoke.yini) and [JSON](./tests/fixtures/smoke-fixtures/a-corporate-saas-platform.smoke.json)
|
|
31
|
+
- **High-Security Distributed Control System** — [YINI](./tests/fixtures/smoke-fixtures/b-high-security-distributed-control-system.smoke.yini) and [JSON](./tests/fixtures/smoke-fixtures/b-high-security-distributed-control-system.smoke.json)
|
|
32
|
+
- Tests verify consistent results across:
|
|
33
|
+
- default parsing.
|
|
34
|
+
- strict mode parsing.
|
|
35
|
+
- strict mode with metadata enabled.
|
|
36
|
+
- These tests now serve as regression contracts for parser correctness, metadata inclusion, and cross-format consistency.
|
|
37
|
+
- **Added:** Smoke test (F-7) verifying that parsing a YINI file returns metadata when `includeMetadata: true` is enabled.
|
|
38
|
+
- **Added:** Smoke test (F-8) verifying that parsing a defect YINI produces diagnostics metadata given proper parse options.
|
|
39
|
+
- **Fixed:** Miscellaneous smaller fixes and improvements
|
|
40
|
+
|
|
3
41
|
## 1.3.2-beta - 2025 Dec
|
|
4
42
|
- **Added:** Implemented UTF-8 BOM support (safe U+FEFF stripping) and added complete test fixtures for BOM/no-BOM, BOM+newline, and mid-file scenarios.
|
|
5
|
-
- **Added:** Implemented support for shebang (`#!`), which is ignored by the parser.
|
|
43
|
+
- **Added:** Implemented support for shebang (`#!`), which is ignored by the parser and the line skipped.
|
|
44
|
+
(If the parser sees `#!` at first line, instead of breaking the parsing, the parsing will continue on the next line.)
|
|
6
45
|
- **Updated:** all (~14) project dependencies to their latest versions, including TypeScript and packages with reported security vulnerabilities. Node type definitions remain unchanged.
|
|
7
46
|
|
|
8
47
|
## 1.3.0-beta - 2025 Sep
|
package/README.md
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# YINI Parser for Node.js
|
|
2
|
+
> **Readable configuration without YAML foot-guns or JSON noise.**
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
The official TypeScript / Node.js parser for **YINI** — an INI-inspired, human-readable text format for structured information.
|
|
4
5
|
|
|
5
6
|
[](https://www.npmjs.com/package/yini-parser) [](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)
|
|
6
7
|
|
|
8
|
+
Designed to bring structure, clarity, and predictable behavior to real-world configuration needs. Well suited for applications, tools, and services that need readable yet structured configuration.
|
|
9
|
+
|
|
7
10
|
```sh
|
|
8
11
|
npm install yini-parser
|
|
9
12
|
```
|
|
@@ -13,45 +16,25 @@ import YINI from 'yini-parser'
|
|
|
13
16
|
const config = YINI.parseFile('./config.yini')
|
|
14
17
|
```
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
```sh
|
|
20
|
+
npm run test
|
|
21
|
+
```
|
|
17
22
|
|
|
18
23
|
➡️ See full [documentation or YINI format specification](https://github.com/YINI-lang/YINI-spec)
|
|
19
24
|
|
|
20
|
-
⭐ **Enjoying YINI?** If you think this project is interesting, [consider giving it a star on GitHub](https://github.com/YINI-lang/yini-parser-typescript) — it's greatly appreciated.
|
|
21
|
-
|
|
22
25
|
---
|
|
23
26
|
|
|
24
|
-
##
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
## Example of YINI code
|
|
28
|
+
> A basic YINI configuration example, showing a section, nested section, comments:
|
|
29
|
+

|
|
30
|
+
Source: [basic.yini](./samples/basic.yini)
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
YINI is a simple, human-friendly configuration format inspired by INI and JSON.
|
|
32
|
-
|
|
33
|
-
---
|
|
32
|
+
## YINI Parser – (source code in TypeScript)
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
- **YINI is an alternative** to other great config formats like INI, JSON, YAML, XML, and TOML — Supports section nesting and explicit syntax for configuration files.
|
|
37
|
-
- **Started as a personal project and a research challenge:** Provides structure similar to INI, with features inspired by JSON and YAML.
|
|
38
|
-
- **Built for clarity:**
|
|
39
|
-
* Uses a concise syntax to minimize unnecessary characters.
|
|
40
|
-
* Supports commonly used configuration structures.
|
|
41
|
-
- Developed to meet practical needs, driven by curiosity and a desire **for configuration clarity, simplicity, minimalism, and flexibility**.
|
|
34
|
+
A runtime parser for the official [YINI configuration file format](https://github.com/YINI-lang/YINI-spec).
|
|
42
35
|
|
|
43
|
-
|
|
36
|
+
The parser follows the official YINI specification and is implemented in TypeScript.
|
|
44
37
|
|
|
45
|
-
## 💡 What is YINI?
|
|
46
|
-
- **Simple like INI** — but with strong typing, comments, and nested sections.
|
|
47
|
-
- **Provides concise, structured syntax** for configuration.
|
|
48
|
-
- Supports section nesting **without requiring indentation or dot-delimited keys**.
|
|
49
|
-
- This repo/parser is built for both **JavaScript and TypeScript**.
|
|
50
|
-
- **Supports strict and lenient modes**, and all major data types.
|
|
51
|
-
- Can be **edited manually** or **processed programmatically**.
|
|
52
|
-
- 👉 See [how YINI compares with JSON, YAML, INI, and TOML](https://github.com/YINI-lang/yini-parser-typescript/tree/main/examples/compare-formats.md).
|
|
53
|
-
- Want the full syntax reference? See the [YINI Specification](https://github.com/YINI-lang/YINI-spec).
|
|
54
|
-
|
|
55
38
|
---
|
|
56
39
|
|
|
57
40
|
## Quick Start
|
|
@@ -63,8 +46,8 @@ import YINI from 'yini-parser'
|
|
|
63
46
|
const config = YINI.parse(`
|
|
64
47
|
// YINI is a simple, human-readable configuration file format.
|
|
65
48
|
|
|
66
|
-
// Note: In YINI, spaces and tabs
|
|
67
|
-
//
|
|
49
|
+
// Note: In YINI, spaces and tabs never change meaning.
|
|
50
|
+
// Indentation is only for readability.
|
|
68
51
|
|
|
69
52
|
^ App // Definition of section (group) "App"
|
|
70
53
|
name = 'My Title' // Keys and values are written as key = value
|
|
@@ -106,15 +89,51 @@ false
|
|
|
106
89
|
|
|
107
90
|
That's it!
|
|
108
91
|
|
|
109
|
-
- ▶️ Link to [examples/](https://github.com/YINI-lang/yini-parser-typescript/tree/main/examples) files.
|
|
110
92
|
- ▶️ Link to [Demo Apps](https://github.com/YINI-lang/yini-demo-apps/tree/main) with complete basic usage.
|
|
111
93
|
|
|
112
94
|
---
|
|
113
95
|
|
|
114
|
-
##
|
|
115
|
-
|
|
96
|
+
## Example 2
|
|
97
|
+
> A real-world YINI configuration example, showing sections, nesting, comments, and multiple data types:
|
|
98
|
+

|
|
99
|
+
Source: [config.yini](./samples/config.yini)
|
|
100
|
+
|
|
101
|
+
## 📂 More Examples
|
|
102
|
+
|
|
103
|
+
- ▶️ Explore more [YINI examples](https://yini-lang.org/learn-yini/examples/?utm_source=yini-parser-ts&utm_medium=github&utm_campaign=repo-link&utm_content=readme).
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### Who is this for?
|
|
108
|
+
|
|
109
|
+
YINI is designed as an ideal option for application developers, platform teams, DevOps engineers, and anyone maintaining complex configuration at scale.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 🙋♀️ Why YINI?
|
|
114
|
+
- **Indentation-independent structure:** The YINI config format is indentation-independent, meaning spaces and tabs never affect meaning.
|
|
115
|
+
- **Explicit nesting for easy refactoring & large configs:** It uses clear header markers (`^`, `^^`, `^^^`) to define hierarchy (like in Markdown), without long dotted keys.
|
|
116
|
+
- **Multiple data types:** Supports boolean literals (`true` / `false`, `Yes` / `No`, etc), numbers, arrays (lists), and JS-style objects natively, with explicit string syntax.
|
|
117
|
+
- **Comments support:** YINI supports multiple comment styles (`#`, `//`, `/* ... */`, and `;`). Allows you to document configuration directly in the file.
|
|
118
|
+
- **Predictable parsing rules:** Fewer production surprises, well-defined rules with optional strict and lenient modes, for different use cases.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## ✨ Features
|
|
123
|
+
- Simple syntax (supports both strict and lenient modes).
|
|
124
|
+
- Familiar config file style (inspired by INI, JSON, Python, and Markdown).
|
|
125
|
+
- Easy programmatic usage.
|
|
126
|
+
- Only the `YINI` class is exported; all internal details are private.
|
|
127
|
+
- Arrays/Lists (bracketed): `list = [10, 20, 30]`
|
|
128
|
+
- JavaScript-style objects (inline maps).
|
|
129
|
+
|
|
130
|
+
⭐ If you find this useful, please consider starring the project on GitHub.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 🧪 Stability & Guarantees
|
|
116
135
|
|
|
117
|
-
|
|
136
|
+
This parser is continuously validated through comprehensive regression and smoke tests, ensuring deterministic parsing behavior across default, strict, and metadata-enabled modes.
|
|
118
137
|
|
|
119
138
|
---
|
|
120
139
|
|
|
@@ -143,7 +162,7 @@ pnpm add yini-parser
|
|
|
143
162
|
const YINI = require('yini-parser').default;
|
|
144
163
|
// (!) If you get undefined, try:
|
|
145
164
|
// (Some Node.js setups require the .default property, others don't, due to ESM/CommonJS interop quirks.)
|
|
146
|
-
const YINI = require('yini-parser');
|
|
165
|
+
// const YINI = require('yini-parser');
|
|
147
166
|
|
|
148
167
|
// Parse from string.
|
|
149
168
|
const config = YINI.parse(`
|
|
@@ -187,137 +206,6 @@ const configFromFile = YINI.parseFile('./config.yini');
|
|
|
187
206
|
|
|
188
207
|
---
|
|
189
208
|
|
|
190
|
-
## ✨ Features
|
|
191
|
-
- Simple syntax (supports both strict and lenient modes).
|
|
192
|
-
- Familiar config file style (inspired by INI, JSON, Python, and Markdown).
|
|
193
|
-
- Easy programmatic usage.
|
|
194
|
-
- Only the `YINI` class is exported; all internal details are private.
|
|
195
|
-
- Lists (bracketed): `list = [10, 20, 30]`
|
|
196
|
-
- 🚧 *(Planned – not yet implemented in parser)* Supports alternative list notation (colon‑style lists):
|
|
197
|
-
```yini
|
|
198
|
-
fruits:
|
|
199
|
-
'Pear',
|
|
200
|
-
'Cherry',
|
|
201
|
-
'Banana'
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
### Limitations
|
|
205
|
-
Not all features of the full YINI are implemented yet.
|
|
206
|
-
|
|
207
|
-
See [FEATURE-CHECKLIST.md](https://github.com/YINI-lang/yini-parser-typescript/blob/main/FEATURE-CHECKLIST.md) for the current list of implemented YINI features.
|
|
208
|
-
|
|
209
|
-
## 🚧 Missing or Upcoming Features
|
|
210
|
-
|
|
211
|
-
This parser currently supports all core YINI syntax for values, comments, section headers, and basic nesting.
|
|
212
|
-
|
|
213
|
-
The following features from the [YINI specification](https://github.com/YINI-lang/YINI-spec) are **planned but not yet fully implemented**:
|
|
214
|
-
|
|
215
|
-
- Object literals
|
|
216
|
-
- Advanced escape sequences
|
|
217
|
-
- String types and triple-quoted strings
|
|
218
|
-
- All number format literals
|
|
219
|
-
- Full strict mode validation
|
|
220
|
-
|
|
221
|
-
You can follow progress in the [YINI parser GitHub repo-FEATURE-CHECKLIST](https://github.com/YINI-lang/yini-parser-typescript/blob/main/FEATURE-CHECKLIST.md). Contributions and feature requests are welcome!
|
|
222
|
-
|
|
223
|
-
## 📂 Examples
|
|
224
|
-
|
|
225
|
-
See the [examples/](https://github.com/YINI-lang/yini-parser-typescript/tree/main/examples) folder for:
|
|
226
|
-
|
|
227
|
-
- Basic YINI file with common types and comments
|
|
228
|
-
- Nested sections example
|
|
229
|
-
- Comparison with JSON/YAML config
|
|
230
|
-
|
|
231
|
-
These examples are also included in the npm package.
|
|
232
|
-
|
|
233
|
-
---
|
|
234
|
-
|
|
235
|
-
## Bigger Example
|
|
236
|
-
|
|
237
|
-
```js
|
|
238
|
-
const YINI = require('yini-parser').default; // Or: import YINI from 'yini-parser';
|
|
239
|
-
|
|
240
|
-
const config = YINI.parse(`
|
|
241
|
-
// This is a comment in YINI
|
|
242
|
-
// YINI is a simple, human-readable configuration file format.
|
|
243
|
-
|
|
244
|
-
// Note: In YINI, spaces and tabs don't change meaning - indentation is just
|
|
245
|
-
// for readability.
|
|
246
|
-
|
|
247
|
-
/* This is a block comment
|
|
248
|
-
|
|
249
|
-
In YINI, section headers use repeated characters "^" at the start to
|
|
250
|
-
show their level: (Section header names are case-sensitive.)
|
|
251
|
-
|
|
252
|
-
^ SectionLevel1
|
|
253
|
-
^^ SectionLevel2
|
|
254
|
-
^^^ SectionLevel3
|
|
255
|
-
*/
|
|
256
|
-
|
|
257
|
-
^ App // Definition of section (group) "App"
|
|
258
|
-
title = 'My App'
|
|
259
|
-
items = 25
|
|
260
|
-
debug = ON // "true" and "YES" works too
|
|
261
|
-
|
|
262
|
-
^ Server // Definition of section (group) "Server"
|
|
263
|
-
host = 'localhost'
|
|
264
|
-
port = 8080
|
|
265
|
-
useTLS = OFF // "false" and "NO" works too
|
|
266
|
-
|
|
267
|
-
// Sub-section of "Server"
|
|
268
|
-
^^ Login
|
|
269
|
-
username = 'user_name'
|
|
270
|
-
password = 'your_password_here'
|
|
271
|
-
|
|
272
|
-
/END // (only optional)
|
|
273
|
-
`);
|
|
274
|
-
|
|
275
|
-
console.log(config);
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
### Output:
|
|
279
|
-
```js
|
|
280
|
-
// JS object
|
|
281
|
-
{
|
|
282
|
-
App: {
|
|
283
|
-
title: 'My App',
|
|
284
|
-
items: 25,
|
|
285
|
-
debug: true
|
|
286
|
-
},
|
|
287
|
-
Server: {
|
|
288
|
-
host: 'localhost',
|
|
289
|
-
port: 8080,
|
|
290
|
-
useTLS: false,
|
|
291
|
-
Login: {
|
|
292
|
-
username: 'user_name',
|
|
293
|
-
password: 'your_password_here'
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
### Output in JSON:
|
|
300
|
-
```json
|
|
301
|
-
{
|
|
302
|
-
"App": {
|
|
303
|
-
"title": "My App",
|
|
304
|
-
"items": 25,
|
|
305
|
-
"debug": true
|
|
306
|
-
},
|
|
307
|
-
"Server": {
|
|
308
|
-
"host": "localhost",
|
|
309
|
-
"port": 8080,
|
|
310
|
-
"useTLS": false,
|
|
311
|
-
"Login": {
|
|
312
|
-
"username": "user_name",
|
|
313
|
-
"password": "your_password_here"
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
---
|
|
320
|
-
|
|
321
209
|
## 🛠 Roadmap
|
|
322
210
|
|
|
323
211
|
1. **Improve existing functionality** — Ongoing improvements to core parsing, richer diagnostics, and expanded QA for areas not yet fully covered.
|
|
@@ -326,6 +214,11 @@ console.log(config);
|
|
|
326
214
|
3. **Schema validation (future)** — Possible future expansion to support schema/contract validation for stricter type-safe configs.
|
|
327
215
|
4. **Ecosystem integration** - Broader and additional support for tooling, and other ecosystem projects.
|
|
328
216
|
|
|
217
|
+
### Planned & Upcoming Features
|
|
218
|
+
Some advanced YINI features are still evolving and are tracked transparently.
|
|
219
|
+
|
|
220
|
+
You can follow progress in the [YINI parser FEATURE-CHECKLIST](https://github.com/YINI-lang/yini-parser-typescript/blob/main/FEATURE-CHECKLIST.md). Contributions and feature requests are welcome!
|
|
221
|
+
|
|
329
222
|
---
|
|
330
223
|
|
|
331
224
|
## 🤝 Contributing
|
|
@@ -333,35 +226,29 @@ We welcome feedback, bug reports, feature requests, and code contributions!
|
|
|
333
226
|
- [Open an Issue](https://github.com/YINI-lang/yini-parser-typescript/issues)
|
|
334
227
|
- [Start a Discussion](https://github.com/YINI-lang/yini-parser-typescript/discussions)
|
|
335
228
|
|
|
229
|
+
|
|
230
|
+
If this library is useful to you, a GitHub star helps guide future development.
|
|
231
|
+
|
|
336
232
|
---
|
|
337
233
|
|
|
338
234
|
## 📚 Documentation
|
|
339
|
-
- [
|
|
235
|
+
- [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.
|
|
340
236
|
- [Conventions](https://github.com/YINI-lang/yini-parser-typescript/blob/main/docs/Conventions.md) — Project conventions, naming patterns, etc.
|
|
341
237
|
|
|
342
238
|
---
|
|
343
239
|
|
|
344
240
|
## Links
|
|
345
|
-
- ➡️ [
|
|
346
|
-
*Beginner-friendly walkthrough and basic usage examples.*
|
|
347
|
-
|
|
348
|
-
- ➡️ [YINI Parser on npm](https://www.npmjs.com/package/yini-parser)
|
|
349
|
-
*Install and view package details.*
|
|
350
|
-
|
|
351
|
-
- ➡️ [Read the YINI Specification](https://github.com/YINI-lang/YINI-spec/blob/release/YINI-Specification.md#table-of-contents)
|
|
241
|
+
- ➡️ [Read the YINI Specification](https://github.com/YINI-lang/YINI-spec/tree/production/YINI-Specification.md#table-of-contents)
|
|
352
242
|
*Full formal spec for the YINI format, including syntax and features.*
|
|
353
243
|
|
|
354
244
|
- ➡️ [YINI CLI on GitHub](https://github.com/YINI-lang/yini-cli)
|
|
355
245
|
*TypeScript source code, issue tracker, and contributing guide.*
|
|
356
246
|
|
|
357
|
-
- ➡️ [YINI vs Other Formats](https://github.com/YINI-lang/YINI-spec/tree/release#-summary-difference-with-other-formats)
|
|
358
|
-
*How does YINI differ: comparison with INI, YAML, and JSON.*
|
|
359
|
-
|
|
360
|
-
- ➡️ [Why YINI? (Project Rationale)](https://github.com/YINI-lang/YINI-spec/blob/release/RATIONALE.md)
|
|
361
|
-
*Learn about the motivations and design decisions behind YINI.*
|
|
362
|
-
|
|
363
247
|
- ➡️ [YINI Project](https://github.com/YINI-lang)
|
|
364
|
-
*YINI home.*
|
|
248
|
+
*YINI home on GitHub.*
|
|
249
|
+
|
|
250
|
+
- ➡️ [YINI Homepage](https://yini-lang.org)
|
|
251
|
+
*Tutorials & Docs.*
|
|
365
252
|
|
|
366
253
|
---
|
|
367
254
|
|
|
@@ -373,6 +260,6 @@ In this project on GitHub, the `libs` directory contains third party software an
|
|
|
373
260
|
---
|
|
374
261
|
|
|
375
262
|
**^YINI ≡**
|
|
376
|
-
>
|
|
263
|
+
> An INI-inspired configuration format with clear structure.
|
|
377
264
|
|
|
378
|
-
[yini-lang.org](https://yini-lang.org) · [YINI on GitHub](https://github.com/YINI-lang)
|
|
265
|
+
[yini-lang.org](https://yini-lang.org/?utm_source=github&utm_medium=referral&utm_campaign=yini_parser_ts&utm_content=readme_footer) · [YINI on GitHub](https://github.com/YINI-lang)
|
package/dist/YINI.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export default class YINI {
|
|
|
23
23
|
* @param failLevel Preferred bail sensitivity level, controls if and when parsing should stop on problems:
|
|
24
24
|
* - `'auto'` (default) : Auto‑select level (strict → `'errors'`, lenient → `'ignore-errors'`)
|
|
25
25
|
* - `'ignore-errors'` : Continue parsing despite errors; log them and attempt recovery.
|
|
26
|
-
* - `'errors'` : Stop parsing on the first error.
|
|
26
|
+
* - `'errors'` : Stop parsing on the first error (fail-fast).
|
|
27
27
|
* - `'warnings-and-errors'` : Stop parsing on the first warning **or** error.
|
|
28
28
|
* @param includeMetadata If `true`, return additional metadata (e.g. warnings, statistics) alongside the parsed object.
|
|
29
29
|
*
|
|
@@ -56,7 +56,7 @@ export default class YINI {
|
|
|
56
56
|
* @param options.failLevel - Preferred bail sensitivity level, controls if and when parsing should stop on problems:
|
|
57
57
|
* Accepts:
|
|
58
58
|
* `'ignore-errors'` - Continue despite errors, persist and try to recover.
|
|
59
|
-
* `'errors'` - Stop parsing on the first error.
|
|
59
|
+
* `'errors'` - Stop parsing on the first error (fail-fast).
|
|
60
60
|
* `'warnings-and-errors'` - Stop parsing on the first warning or error.
|
|
61
61
|
* (Type: TPreferredFailLevel; exact behavior is implementation-defined.)
|
|
62
62
|
* @param options.includeDiagnostics - Include diagnostics in the returned metadata.
|
|
@@ -111,7 +111,7 @@ export default class YINI {
|
|
|
111
111
|
* @param failLevel Preferred bail sensitivity level, controls if and when parsing should stop on problems:
|
|
112
112
|
* - `'auto'` (default) : Auto‑select level (strict → `'errors'`, lenient → `'ignore-errors'`)
|
|
113
113
|
* - `'ignore-errors'` : Continue parsing despite errors; log them and attempt recovery.
|
|
114
|
-
* - `'errors'` : Stop parsing on the first error.
|
|
114
|
+
* - `'errors'` : Stop parsing on the first error (fail-fast).
|
|
115
115
|
* - `'warnings-and-errors'` : Stop parsing on the first warning **or** error.
|
|
116
116
|
* @param includeMetadata If `true`, return additional metadata (e.g. warnings, statistics) alongside the parsed object.
|
|
117
117
|
*
|
|
@@ -144,7 +144,7 @@ export default class YINI {
|
|
|
144
144
|
* @param options.failLevel - Preferred bail sensitivity level, controls if and when parsing should stop on problems:
|
|
145
145
|
* Accepts:
|
|
146
146
|
* `'ignore-errors'` - Continue despite errors, persist and try to recover.
|
|
147
|
-
* `'errors'` - Stop parsing on the first error.
|
|
147
|
+
* `'errors'` - Stop parsing on the first error (fail-fast).
|
|
148
148
|
* `'warnings-and-errors'` - Stop parsing on the first warning or error.
|
|
149
149
|
* (Type: TPreferredFailLevel; exact behavior is implementation-defined.)
|
|
150
150
|
* @param options.includeDiagnostics - Include diagnostics in the returned metadata.
|
package/dist/YINI.js
CHANGED
|
@@ -6,15 +6,6 @@ const optionsFunctions_1 = require("./core/options/optionsFunctions");
|
|
|
6
6
|
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
|
-
// let _runtimeInfo: IRuntimeInfo = {
|
|
10
|
-
// sourceType: 'Inline',
|
|
11
|
-
// fileName: undefined,
|
|
12
|
-
// fileByteSize: null,
|
|
13
|
-
// lineCount: null,
|
|
14
|
-
// timeIoMs: null,
|
|
15
|
-
// preferredBailSensitivity: null,
|
|
16
|
-
// sha256: null,
|
|
17
|
-
// }
|
|
18
9
|
/**
|
|
19
10
|
* This class is the public API, which exposes only parse(..) and
|
|
20
11
|
* parseFile(..), rest of the implementation details are hidden.
|
|
@@ -44,59 +35,8 @@ class YINI {
|
|
|
44
35
|
static parse(yiniContent, arg2, // strictMode | options
|
|
45
36
|
failLevel = 'auto', includeMetadata = false) {
|
|
46
37
|
(0, print_1.debugPrint)('-> Entered static parse(..) in class YINI\n');
|
|
47
|
-
// // Runtime guard to catch illegal/ambiguous calls coming from JS or any-cast code
|
|
48
|
-
// if (
|
|
49
|
-
// isOptionsObjectForm(arg2) &&
|
|
50
|
-
// (failLevel !== 'auto' || includeMetadata !== false)
|
|
51
|
-
// ) {
|
|
52
|
-
// throw new TypeError(
|
|
53
|
-
// 'Invalid call: when providing an options object, do not also pass positional parameters.',
|
|
54
|
-
// )
|
|
55
|
-
// }
|
|
56
|
-
// const mode: TParserMode = inferModeFromArgs(arg2)
|
|
57
|
-
// const defaultOptions = getDefaultOptions(mode)
|
|
58
|
-
// // Normalize to a fully-required options object.
|
|
59
|
-
// let userOpts: Required<ParseOptions>
|
|
60
|
-
// // Required, makes all properties in T required, no undefined.
|
|
61
|
-
// if (isOptionsObjectForm(arg2)) {
|
|
62
|
-
// userOpts = {
|
|
63
|
-
// ...defaultOptions, // Sets the default options.
|
|
64
|
-
// ...arg2,
|
|
65
|
-
// }
|
|
66
|
-
// } else {
|
|
67
|
-
// // Positional form.
|
|
68
|
-
// userOpts = {
|
|
69
|
-
// ...defaultOptions, // Sets the default options.
|
|
70
|
-
// strictMode:
|
|
71
|
-
// (arg2 as boolean | undefined) ?? defaultOptions.strictMode,
|
|
72
|
-
// failLevel,
|
|
73
|
-
// includeMetadata,
|
|
74
|
-
// }
|
|
75
|
-
// }
|
|
76
|
-
// if (userOpts.includeMetadata && _runtimeInfo.sourceType === 'Inline') {
|
|
77
|
-
// const lineCount = yiniContent.split(/\r?\n/).length // Counts the lines.
|
|
78
|
-
// const sha256 = computeSha256(yiniContent) // NOTE: Compute BEFORE any possible tampering of content.
|
|
79
|
-
// _runtimeInfo.lineCount = lineCount
|
|
80
|
-
// _runtimeInfo.preferredBailSensitivity = userOpts.failLevel
|
|
81
|
-
// _runtimeInfo.sha256 = sha256
|
|
82
|
-
// }
|
|
83
|
-
// // NOTE: Important: Do not trim or mutate the yiniContent here, due
|
|
84
|
-
// // to it will mess up the line numbers in error reporting.
|
|
85
|
-
// if (!yiniContent) {
|
|
86
|
-
// throw new Error('Syntax-Error: Unexpected blank YINI input')
|
|
87
|
-
// }
|
|
88
|
-
// if (!yiniContent.endsWith('\n')) {
|
|
89
|
-
// yiniContent += '\n'
|
|
90
|
-
// }
|
|
91
|
-
// let level: TBailSensitivityLevel = mapFailLevelToBail(
|
|
92
|
-
// userOpts.strictMode,
|
|
93
|
-
// userOpts.failLevel,
|
|
94
|
-
// )
|
|
95
|
-
////////////////
|
|
96
|
-
// const coreOpts: IParseCoreOptions = toCoreOptions(userOpts,level)
|
|
97
38
|
(0, print_1.debugPrint)();
|
|
98
39
|
(0, print_1.debugPrint)('==== Call runParse(..) in runtime ==========================');
|
|
99
|
-
// const result = _parseMain(yiniContent, coreOpts, _runtimeInfo)
|
|
100
40
|
const runtime = new runtime_1.YiniRuntime('Inline');
|
|
101
41
|
const result = (0, optionsFunctions_1.isOptionsObjectForm)(arg2)
|
|
102
42
|
? runtime.runParse(yiniContent, arg2) // Overload #2: (content, options)
|
|
@@ -120,68 +60,8 @@ class YINI {
|
|
|
120
60
|
failLevel = 'auto', includeMetadata = false) {
|
|
121
61
|
(0, print_1.debugPrint)('-> Entered static parseFile(..) in class YINI\n');
|
|
122
62
|
(0, print_1.debugPrint)('Current directory = ' + process.cwd());
|
|
123
|
-
// // Runtime guard to catch illegal/ambiguous calls coming from JS or any-cast code
|
|
124
|
-
// if (
|
|
125
|
-
// isOptionsObjectForm(arg2) &&
|
|
126
|
-
// (failLevel !== 'auto' || includeMetadata !== false)
|
|
127
|
-
// ) {
|
|
128
|
-
// throw new TypeError(
|
|
129
|
-
// 'Invalid call: when providing an options object, do not also pass positional parameters.',
|
|
130
|
-
// )
|
|
131
|
-
// }
|
|
132
|
-
// const mode: TParserMode = inferModeFromArgs(arg2)
|
|
133
|
-
// const defaultOptions = getDefaultOptions(mode)
|
|
134
|
-
// // Normalize to a fully-required options object.
|
|
135
|
-
// let userOpts: Required<ParseOptions>
|
|
136
|
-
// // Required, makes all properties in T required, no undefined.
|
|
137
|
-
// if (isOptionsObjectForm(arg2)) {
|
|
138
|
-
// // Options-object Form.
|
|
139
|
-
// userOpts = {
|
|
140
|
-
// ...defaultOptions, // Sets the default options.
|
|
141
|
-
// ...arg2,
|
|
142
|
-
// }
|
|
143
|
-
// } else {
|
|
144
|
-
// // Positional form.
|
|
145
|
-
// userOpts = {
|
|
146
|
-
// ...defaultOptions, // Sets the default options.
|
|
147
|
-
// strictMode:
|
|
148
|
-
// (arg2 as boolean | undefined) ?? defaultOptions.strictMode,
|
|
149
|
-
// failLevel,
|
|
150
|
-
// includeMetadata,
|
|
151
|
-
// }
|
|
152
|
-
// }
|
|
153
|
-
// if (getFileNameExtension(filePath).toLowerCase() !== '.yini') {
|
|
154
|
-
// console.error('Invalid file extension for YINI file:')
|
|
155
|
-
// console.error(`"${filePath}"`)
|
|
156
|
-
// console.log(
|
|
157
|
-
// 'File does not have a valid ".yini" extension (case-insensitive).',
|
|
158
|
-
// )
|
|
159
|
-
// throw new Error('Error: Unexpected file extension for YINI file')
|
|
160
|
-
// }
|
|
161
|
-
// // ---- Phase 0: I/O ----
|
|
162
|
-
// const timeStartMs = performance.now()
|
|
163
|
-
// // let content = fs.readFileSync(filePath, 'utf8')
|
|
164
|
-
// const rawBuffer = fs.readFileSync(filePath) // Raw buffer for size.
|
|
165
|
-
// const fileByteSize = rawBuffer.byteLength // Byte size in UTF-8.
|
|
166
|
-
// let content = rawBuffer.toString('utf8')
|
|
167
|
-
// const timeEndMs = performance.now()
|
|
168
|
-
// _runtimeInfo.sourceType = 'File'
|
|
169
|
-
// _runtimeInfo.fileName = filePath
|
|
170
|
-
// if (userOpts.includeMetadata) {
|
|
171
|
-
// _runtimeInfo.lineCount = content.split(/\r?\n/).length // Counts the lines.
|
|
172
|
-
// _runtimeInfo.fileByteSize = fileByteSize
|
|
173
|
-
// _runtimeInfo.timeIoMs = +(timeEndMs - timeStartMs).toFixed(3)
|
|
174
|
-
// _runtimeInfo.preferredBailSensitivity = userOpts.failLevel
|
|
175
|
-
// _runtimeInfo.sha256 = computeSha256(content) // NOTE: Compute BEFORE any possible tampering of content.
|
|
176
|
-
// }
|
|
177
|
-
// let hasNoNewlineAtEOF = false
|
|
178
|
-
// if (!content.endsWith('\n')) {
|
|
179
|
-
// content += '\n'
|
|
180
|
-
// hasNoNewlineAtEOF = true
|
|
181
|
-
// }
|
|
182
63
|
(0, print_1.debugPrint)();
|
|
183
64
|
(0, print_1.debugPrint)('==== Call doParseFile(..) in runtime ==========================');
|
|
184
|
-
// const result = _parseMain(yiniContent, coreOpts, _runtimeInfo)
|
|
185
65
|
const runtime = new runtime_1.YiniRuntime('File');
|
|
186
66
|
const result = (0, optionsFunctions_1.isOptionsObjectForm)(arg2)
|
|
187
67
|
? runtime.doParseFile(filePath, arg2) // Overload #2: (content, options)
|
package/dist/YINI.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"YINI.js","sourceRoot":"","sources":["../src/YINI.ts"],"names":[],"mappings":";;AAAA,sCAA6C;AAC7C,8DAA0D;AAC1D,sEAAqE;AACrE,4CAA4C;AAO5C,yCAAiE;AAEjE,MAAM,gBAAgB,GAAG,CAAC,CAAA,CAAC,6EAA6E;AAExG
|
|
1
|
+
{"version":3,"file":"YINI.js","sourceRoot":"","sources":["../src/YINI.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,6 +30,8 @@ export default class ASTBuilder<Result> extends YiniParserVisitor<Result> {
|
|
|
30
30
|
constructor(errorHandler: ErrorDataHandler, options: IParseCoreOptions, sourceType: TSourceType, metaFileName: string | null);
|
|
31
31
|
private hasDefinedSectionTitle;
|
|
32
32
|
private setDefineSectionTitle;
|
|
33
|
+
private extractStringParts;
|
|
34
|
+
private extractStringKindAndValue;
|
|
33
35
|
/** Attach a section to the stack respecting up/down moves (Spec 5.3). :contentReference[oaicite:7]{index=7} */
|
|
34
36
|
private attachSection;
|
|
35
37
|
/** Insert a key/value into current section (duplicate handling per options). */
|