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.
Files changed (36) hide show
  1. package/CHANGELOG.md +40 -1
  2. package/README.md +73 -186
  3. package/dist/YINI.d.ts +4 -4
  4. package/dist/YINI.js +0 -120
  5. package/dist/YINI.js.map +1 -1
  6. package/dist/core/astBuilder.d.ts +2 -0
  7. package/dist/core/astBuilder.js +97 -14
  8. package/dist/core/astBuilder.js.map +1 -1
  9. package/dist/core/internalTypes.d.ts +5 -0
  10. package/dist/core/options/defaultParserOptions.js +1 -7
  11. package/dist/core/options/defaultParserOptions.js.map +1 -1
  12. package/dist/core/options/optionsFunctions.js +7 -5
  13. package/dist/core/options/optionsFunctions.js.map +1 -1
  14. package/dist/core/resultMetadataBuilder.js +0 -1
  15. package/dist/core/resultMetadataBuilder.js.map +1 -1
  16. package/dist/dev/main.d.ts +1 -1
  17. package/dist/dev/main.js +27 -5
  18. package/dist/dev/main.js.map +1 -1
  19. package/dist/dev/quick-test-samples/defect-inputs.d.ts +37 -0
  20. package/dist/dev/quick-test-samples/defect-inputs.js +106 -0
  21. package/dist/dev/quick-test-samples/defect-inputs.js.map +1 -0
  22. package/dist/dev/quick-test-samples/valid-inputs.d.ts +21 -0
  23. package/dist/dev/quick-test-samples/valid-inputs.js +422 -0
  24. package/dist/dev/quick-test-samples/valid-inputs.js.map +1 -0
  25. package/dist/index.js +1 -1
  26. package/dist/index.js.map +1 -1
  27. package/dist/parsers/parseString.d.ts +2 -1
  28. package/dist/parsers/parseString.js +132 -33
  29. package/dist/parsers/parseString.js.map +1 -1
  30. package/dist/types/index.d.ts +1 -1
  31. package/dist/utils/string.d.ts +2 -0
  32. package/dist/utils/string.js +12 -1
  33. package/dist/utils/string.js.map +1 -1
  34. package/examples/nested-output.js +1 -1
  35. package/examples/nested.yini +1 -1
  36. 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
- A TypeScript/Node.js parser for YINI — A type-safe, structured, and human-readable config format with nested sections, types, comments, and support for strict validation.
4
+ The official TypeScript / Node.js parser for **YINI**an INI-inspired, human-readable text format for structured information.
4
5
 
5
6
  [![npm version](https://img.shields.io/npm/v/yini-parser.svg)](https://www.npmjs.com/package/yini-parser) [![All Test Suites](https://github.com/YINI-lang/yini-parser-typescript/actions/workflows/run-all-tests.yml/badge.svg)](https://github.com/YINI-lang/yini-parser-typescript/actions/workflows/run-all-tests.yml) [![All Regression Tests](https://github.com/YINI-lang/yini-parser-typescript/actions/workflows/run-regression-tests.yml/badge.svg)](https://github.com/YINI-lang/yini-parser-typescript/actions/workflows/run-regression-tests.yml) [![Grammar Drift Check](https://github.com/YINI-lang/yini-parser-typescript/actions/workflows/run-grammar-drift-check.yml/badge.svg)](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
- YINI (Yet another INI): YINI is a configuration format designed for readability and structure, inspired by INI and YAML.
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
- ## YINI Parser (source code in TypeScript)
25
-
26
- **YINI Parser in TypeScript** — a runtime library for Node.js.
27
- A parser / reader for the [YINI configuration file format](https://github.com/YINI-lang/YINI-spec).
27
+ ## Example of YINI code
28
+ > A basic YINI configuration example, showing a section, nested section, comments:
29
+ ![YINI Config Example](./samples/basic.yini.png)
30
+ Source: [basic.yini](./samples/basic.yini)
28
31
 
29
- This library implements the official YINI specification using TypeScript + ANTLR4.
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
- ## 🙋‍♀️ Why YINI?
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 don't change meaning -
67
- // indentation is just for readability.
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
- ## Intro to YINI Config Format
115
- **YINI** is a simple and readable configuration format. Sections are defined with `^ SectionName`, and values are assigned using `key = value`. The format supports common data types (same as those found in JSON), including strings, numbers, booleans, nulls, and lists.
96
+ ## Example 2
97
+ > A real-world YINI configuration example, showing sections, nesting, comments, and multiple data types:
98
+ ![YINI Config Example](./samples/config.yini.png)
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
- To learn more, see the [Getting Started: Intro to YINI Config Format](https://github.com/YINI-lang/YINI-spec/blob/develop/Docs/Intro-to-YINI-Config-Format.md) tutorial.
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
- - [Development Setup](https://github.com/YINI-lang/yini-parser-typescript/blob/main/docs/Development-Setup.md) — How to run, test, and build the project, etc.
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
- - ➡️ [Getting Started: Intro to YINI Config Format](https://github.com/YINI-lang/YINI-spec/blob/develop/Docs/Intro-to-YINI-Config-Format.md)
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
- > A simple, structured, and human-friendly configuration format.
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":"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"}
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;;;;GAIG;AACH,MAAqB,IAAI;IAIrB;;OAEG;IACI,MAAM,CAAC,UAAU;QACpB,OAAO,IAAI,CAAC,SAAS,CAAA;IACzB,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,UAAU,CAAC,MAAc;QACnC,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,EAAE,EAAE,CAAC;YAC5B,IAAI,mCAAgB,CAAC,aAAa,CAAC,CAAC,UAAU,CAC1C,IAAI,EACJ,aAAa,EACb,oBAAoB,MAAM,mBAAmB,EAC7C,2CAA2C,CAC9C,CAAA;YACD,MAAM,IAAI,UAAU,CAAC,YAAY,MAAM,0BAA0B,CAAC,CAAA;QACtE,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,MAAM,CAAA;IAC3B,CAAC;IA6GD,yEAAyE;IACzE,gGAAgG;IAChG,6HAA6H;IACtH,MAAM,CAAC,KAAK,CACf,WAAmB,EACnB,IAA6B,EAAE,uBAAuB;IACtD,YAAgC,MAAM,EACtC,eAAe,GAAG,KAAK;QAEvB,IAAA,kBAAU,EAAC,6CAA6C,CAAC,CAAA;QAEzD,IAAA,kBAAU,GAAE,CAAA;QACZ,IAAA,kBAAU,EACN,8DAA8D,CACjE,CAAA;QACD,MAAM,OAAO,GAAG,IAAI,qBAAW,CAAC,QAAQ,CAAC,CAAA;QAEzC,MAAM,MAAM,GAAG,IAAA,sCAAmB,EAAC,IAAI,CAAC;YACpC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,kCAAkC;YACxE,CAAC,CAAC,OAAO,CAAC,QAAQ;YACZ,4DAA4D;YAC5D,WAAW,EACX,IAA2B,EAC3B,SAAS,EACT,eAAe,CAClB,CAAA;QACP,IAAA,kBAAU,EAAC,kDAAkD,CAAC,CAAA;QAE9D,IAAI,IAAA,WAAK,GAAE,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,EAAE,CAAA;YACb,IAAA,gBAAQ,EAAC,yBAAyB,CAAC,CAAA;YACnC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YAEnB,IAAA,gBAAQ,EAAC,kBAAkB,CAAC,CAAA;YAC5B,IAAA,mBAAW,EAAC,MAAM,CAAC,CAAA;QACvB,CAAC;QAED,OAAO,MAAM,CAAA;IACjB,CAAC;IA6GD,yEAAyE;IACzE,gGAAgG;IAChG,6HAA6H;IACtH,MAAM,CAAC,SAAS,CACnB,QAAgB,EAChB,IAA6B,EAAE,uBAAuB;IACtD,YAAgC,MAAM,EACtC,eAAe,GAAG,KAAK;QAEvB,IAAA,kBAAU,EAAC,iDAAiD,CAAC,CAAA;QAC7D,IAAA,kBAAU,EAAC,sBAAsB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;QAElD,IAAA,kBAAU,GAAE,CAAA;QACZ,IAAA,kBAAU,EACN,iEAAiE,CACpE,CAAA;QACD,MAAM,OAAO,GAAG,IAAI,qBAAW,CAAC,MAAM,CAAC,CAAA;QAEvC,MAAM,MAAM,GAAG,IAAA,sCAAmB,EAAC,IAAI,CAAC;YACpC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,kCAAkC;YACxE,CAAC,CAAC,OAAO,CAAC,WAAW;YACf,4DAA4D;YAC5D,QAAQ,EACR,IAA2B,EAC3B,SAAS,EACT,eAAe,CAClB,CAAA;QAEP,IAAA,kBAAU,EAAC,kDAAkD,CAAC,CAAA;QAC9D,OAAO,MAAM,CAAA;IACjB,CAAC;;AAvTD,2IAA2I;AAC5H,cAAS,GAAG,gBAAgB,CAAA,CAAC,0CAA0C;kBAFrE,IAAI"}
@@ -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). */