mason-parser 1.0.0 → 1.0.2
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/README.md +114 -11
- package/dist/index.d.mts +19 -5
- package/dist/index.d.ts +19 -5
- package/dist/index.js +765 -128
- package/dist/index.mjs +761 -128
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,11 +1,37 @@
|
|
|
1
1
|
# mason-parser
|
|
2
2
|
|
|
3
|
-
> Markdown Structured Object Notation (
|
|
3
|
+
> Markdown Structured Object Notation (MaSON) — A human-centric serialization format bridging natural markdown visual hierarchy and structured JSON.
|
|
4
4
|
|
|
5
5
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
6
6
|
[](https://www.npmjs.com/package/mason-parser)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
MaSON is a lightweight serialization format designed for **human-authored hierarchical documents**, **application configurations**, and **clean context-sharing for Large Language Models (LLMs)**. It replaces structural punctuation (such as curly braces, brackets, and redundant double-quoted keys) with natural Markdown headings and bulleted lists.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 🎯 What Problem Does MaSON Solve?
|
|
13
|
+
|
|
14
|
+
MaSON fits a specific niche: **human-authored hierarchical documents where visual readability and writeability are more important than representing every complex or strict academic data type.**
|
|
15
|
+
|
|
16
|
+
### How it Compares:
|
|
17
|
+
* **Why not JSON?** JSON is a fantastic machine-to-machine format but is tedious for humans to author or edit. Forgetting a trailing comma, double quote, or bracket results in immediate syntax errors. MaSON allows writing hierarchy naturally.
|
|
18
|
+
* **Why not YAML?** YAML is powerful, but its specification is substantially more complex than MaSON's. Its indentation-sensitive syntax can also lead to subtle formatting errors when editing by hand. MaSON uses standard Markdown headings to nest structures safely.
|
|
19
|
+
* **Why not TOML?** TOML is highly readable for flat structures, but its readability degrades rapidly when representing deeply nested hierarchies (requiring verbose table brackets like `[servers.database.credentials]`). MaSON utilizes standard Markdown heading depths (`#`, `##`, `###`) to establish nesting levels.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 🎨 Design Philosophy
|
|
24
|
+
|
|
25
|
+
### Design Goals
|
|
26
|
+
- **Easy to read in plain text:** Looks like regular Markdown documentation.
|
|
27
|
+
- **Easy to author manually:** No strict whitespace parsing, bracket-matching, or comma rules.
|
|
28
|
+
- **Easy to parse:** Extremely small parser footprint (under 2KB gzipped) with a small, maintainable grammar.
|
|
29
|
+
- **Deterministic & Round-trip Safe:** Standard structures parse and stringify back-and-forth cleanly.
|
|
30
|
+
|
|
31
|
+
### Non-Goals
|
|
32
|
+
- **Full YAML/JSON feature-parity:** No support for advanced data types or custom type tagging.
|
|
33
|
+
- **Anchors, aliases, or references:** No complex object graphs or internal links.
|
|
34
|
+
- **YAML-style indentation rules:** No complex multi-space layout rules. MaSON prefers simple explicit visual suffixes (`[]`) or top-level annotations over indentation-sensitive arrays.
|
|
9
35
|
|
|
10
36
|
---
|
|
11
37
|
|
|
@@ -13,9 +39,9 @@ MSON is a super-lightweight alternative to JSON/YAML/TOML designed specifically
|
|
|
13
39
|
|
|
14
40
|
- **Zero-Bracket Nesting:** Structure child objects implicitly via standard Markdown headings (`#`, `##`, `###`).
|
|
15
41
|
- **Natural Array Triggers:** Bulleted lists (`*`, `-`, `+`) automatically morph parent containers into ordered arrays.
|
|
16
|
-
- **Implicit Type
|
|
17
|
-
- **
|
|
18
|
-
- **Bi-directional Integrity:** Safely stringifies
|
|
42
|
+
- **Implicit Type Inference:** Native detection of numbers, floats, booleans (`true`/`false`), and `null` values without tedious string conversions.
|
|
43
|
+
- **Grounded Token Efficiency:** In nested configuration files and content-rich documents, MaSON can reduce raw characters compared to equivalent JSON by eliminating repeated brackets, braces, and quotation marks. This is especially useful in LLM workflows, where concise representations can help maximize available context and minimize token overhead.
|
|
44
|
+
- **Bi-directional Integrity:** Safely stringifies standard JavaScript objects back to MaSON, complete with sorted parameters and clean spacing.
|
|
19
45
|
|
|
20
46
|
---
|
|
21
47
|
|
|
@@ -52,7 +78,7 @@ host: localhost
|
|
|
52
78
|
* BackupNode2
|
|
53
79
|
```
|
|
54
80
|
|
|
55
|
-
### 2. Parse
|
|
81
|
+
### 2. Parse MaSON into JSON
|
|
56
82
|
```typescript
|
|
57
83
|
import { parse } from 'mason-parser';
|
|
58
84
|
import fs from 'fs';
|
|
@@ -86,7 +112,7 @@ console.log(data);
|
|
|
86
112
|
*/
|
|
87
113
|
```
|
|
88
114
|
|
|
89
|
-
### 3. Stringify back to
|
|
115
|
+
### 3. Stringify back to MaSON
|
|
90
116
|
```typescript
|
|
91
117
|
import { stringify } from 'mason-parser';
|
|
92
118
|
|
|
@@ -112,14 +138,91 @@ active: true
|
|
|
112
138
|
|
|
113
139
|
## 📜 Grammar & Formatting Rules
|
|
114
140
|
|
|
115
|
-
|
|
116
|
-
|
|
141
|
+
At a high level, a MaSON document is parsed line-by-line using a small, deterministic grammar.
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
Document
|
|
145
|
+
├── Line (Comment / Empty) -> Ignored
|
|
146
|
+
├── Line (Top-Level Array: []) -> Initializes the document as an anonymous Array
|
|
147
|
+
├── Line (Heading: #+) -> Opens a nested Object or Object within an Array
|
|
148
|
+
├── Line (Bullet: *, -, +) -> Pushes a primitive value to an active array
|
|
149
|
+
└── Line (Property: k: v) -> Sets a property on the active container
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
1. **Parameters:** Represented by `key: value` pairs. The value is implicitly parsed as a primitive (`number`, `boolean`, `null`, or `string`).
|
|
153
|
+
2. **Quoting:** To force any numerical sequence or boolean value to remain a string, wrap it in double or single quotes: `zipCode: "16801"`.
|
|
117
154
|
3. **Headings:**
|
|
118
155
|
- Any property before the first `#` is declared at the root level.
|
|
119
156
|
- `#` headings denote level 1 object parameters.
|
|
120
157
|
- `##` headings nest themselves inside the active `#` parent object.
|
|
121
|
-
- If there is no active
|
|
122
|
-
4. **Lists:** Bullet elements (`*`, `-`, `+`) immediately
|
|
158
|
+
- If there is no active parent at the required depth, headings fall back to root or nearest sibling.
|
|
159
|
+
4. **Lists:** Bullet elements (`*`, `-`, `+`) immediately convert the nearest active heading key into an ordered array of typed primitives.
|
|
160
|
+
5. **Explicit Array Suffix (`[]`):** To define an array of complex objects, append `[]` to the heading name (e.g., `# Users[]`). Any nested heading under it (e.g. `## User` or `##`) pushes a new object into that array.
|
|
161
|
+
6. **Top-Level Anonymous Arrays:** To make the entire document parse as a top-level array, define `[]` on the very first non-empty line of the file. Each subsequent item header (like `##`) directly pushes a new anonymous object into this array.
|
|
162
|
+
7. **Anonymous & Descriptive Heading Labels:** When defining elements of an array (explicit or top-level), heading names are fully optional. You can use empty heading lines (e.g., `## ` or `##`) or descriptive notes (e.g., `## Alice (Admin)`) without affecting the structured JSON properties.
|
|
163
|
+
8. **Multiline Values:** Wrap any multi-line text block or formatted string in backticks (`` ` ``). The parser will automatically preserve formatting and newlines within the block.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 🔍 Edge-Case Specification
|
|
168
|
+
|
|
169
|
+
To ensure predictable behavior, `mason-parser` handles edge cases according to the following rules:
|
|
170
|
+
|
|
171
|
+
### 1. Duplicate Headings
|
|
172
|
+
```markdown
|
|
173
|
+
# User
|
|
174
|
+
name: Alice
|
|
175
|
+
|
|
176
|
+
# User
|
|
177
|
+
name: Bob
|
|
178
|
+
```
|
|
179
|
+
* **Behavior:** Overwrites. The second `# User` initializes a fresh object under the `User` key, overwriting the first one. To represent list-like collections, use bullet points under a single heading instead.
|
|
180
|
+
|
|
181
|
+
### 2. Mixed-Type Arrays
|
|
182
|
+
```markdown
|
|
183
|
+
# Items
|
|
184
|
+
* 1
|
|
185
|
+
* true
|
|
186
|
+
* hello
|
|
187
|
+
```
|
|
188
|
+
* **Behavior:** Allowed. Bullets are parsed individually. The parser yields `[1, true, "hello"]`.
|
|
189
|
+
|
|
190
|
+
### 3. Arrays of Objects
|
|
191
|
+
* **Behavior:** MaSON supports arrays of complex objects using the explicit array suffix (`[]`) or a top-level array modifier (`[]`). Inside these arrays, heading names can be customized with descriptive labels or left completely empty (anonymous objects). For example:
|
|
192
|
+
```markdown
|
|
193
|
+
# Users[]
|
|
194
|
+
|
|
195
|
+
## Administrator
|
|
196
|
+
name: Alice
|
|
197
|
+
role: admin
|
|
198
|
+
|
|
199
|
+
##
|
|
200
|
+
name: Bob
|
|
201
|
+
role: user
|
|
202
|
+
```
|
|
203
|
+
This parses directly into an array containing both objects under the key `"Users"`.
|
|
204
|
+
|
|
205
|
+
### 4. Empty Headings
|
|
206
|
+
```markdown
|
|
207
|
+
# Settings
|
|
208
|
+
```
|
|
209
|
+
* **Behavior:** Resolves to `{}`. Encountering a heading immediately instantiates an empty object placeholder in the parent node.
|
|
210
|
+
|
|
211
|
+
### 5. Backtick Delimiters (Matching)
|
|
212
|
+
MaSON handles backticks dynamically based on matching the count of opening and closing backticks:
|
|
213
|
+
* **Matching Delimiters & Language Tags:** A block or string starts with any count of backticks `N` (e.g. `1` backtick or `3` backticks) and ends with exactly `N` backticks. The surrounding delimiters on both ends are completely stripped.
|
|
214
|
+
* **Language Tag Stripping:** If opening with 3 or more backticks (e.g. ```` ```javascript ````), a single alphanumeric language identifier following the backticks is automatically stripped to enable seamless Markdown copying.
|
|
215
|
+
```markdown
|
|
216
|
+
script: ```javascript
|
|
217
|
+
function calculateTotal() {}
|
|
218
|
+
```
|
|
219
|
+
```
|
|
220
|
+
* **Behavior:** Resolves to `"function calculateTotal() {}"`.
|
|
221
|
+
* **Embedding Backticks:** By using `N` backticks as the delimiter, you can easily embed backticks of other lengths (such as code spans of length `1`) without them being treated as delimiters.
|
|
222
|
+
```markdown
|
|
223
|
+
literalText: `` `code` ``
|
|
224
|
+
```
|
|
225
|
+
* **Behavior:** Resolves to `"`code`"`.
|
|
123
226
|
|
|
124
227
|
---
|
|
125
228
|
|
package/dist/index.d.mts
CHANGED
|
@@ -24,11 +24,21 @@ interface ParseResult {
|
|
|
24
24
|
tokenSavingsPercent: number;
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
interface ParseOptions {
|
|
28
|
+
noTrace?: boolean;
|
|
29
|
+
}
|
|
27
30
|
/**
|
|
28
31
|
* Casts a string value to its implicit primitive type or returns the string.
|
|
29
|
-
* Strips quotes if they enclose the string explicitly.
|
|
32
|
+
* Strips quotes if they enclose the string explicitly and restores escaped characters.
|
|
30
33
|
*/
|
|
31
34
|
declare function parsePrimitiveValue(val: string): any;
|
|
35
|
+
/**
|
|
36
|
+
* Parses a single-line or multiline value, advancing the line reader index if needed.
|
|
37
|
+
*/
|
|
38
|
+
declare function parseValueWithMultiline(initialValStr: string, lines: string[], currentLineIndex: number): {
|
|
39
|
+
value: any;
|
|
40
|
+
nextLineIndex: number;
|
|
41
|
+
};
|
|
32
42
|
/**
|
|
33
43
|
* Formats a value for MSON stringification.
|
|
34
44
|
* Wraps in quotes if it has special characters or looks like a keyword but is a string.
|
|
@@ -37,14 +47,18 @@ declare function stringifyPrimitiveValue(val: any): string;
|
|
|
37
47
|
/**
|
|
38
48
|
* Parses MSON text into a JavaScript Object / Array.
|
|
39
49
|
*/
|
|
40
|
-
declare function parse(text: string): any;
|
|
50
|
+
declare function parse(text: string, options?: ParseOptions): any;
|
|
51
|
+
/**
|
|
52
|
+
* Ultra-performance, trace-free parser for MSON.
|
|
53
|
+
*/
|
|
54
|
+
declare function fastParseWithTrace(text: string): ParseResult;
|
|
41
55
|
/**
|
|
42
56
|
* Parses MSON text into a JavaScript Object / Array with step-by-step trace info.
|
|
43
57
|
*/
|
|
44
|
-
declare function parseWithTrace(text: string): ParseResult;
|
|
58
|
+
declare function parseWithTrace(text: string, options?: ParseOptions): ParseResult;
|
|
45
59
|
/**
|
|
46
60
|
* Stringifies a JavaScript object/array back into MSON text recursively.
|
|
47
61
|
*/
|
|
48
|
-
declare function stringify(obj: any, level?: number): string;
|
|
62
|
+
declare function stringify(obj: any, level?: number, parentKey?: string): string;
|
|
49
63
|
|
|
50
|
-
export { type ParseResult, type ParserTraceStep, parse, parse as parseMSON, parsePrimitiveValue, parseWithTrace, stringify, stringify as stringifyMSON, stringifyPrimitiveValue };
|
|
64
|
+
export { type ParseOptions, type ParseResult, type ParserTraceStep, fastParseWithTrace, parse, parse as parseMSON, parseWithTrace as parseMaSON, parsePrimitiveValue, parseValueWithMultiline, parseWithTrace, stringify, stringify as stringifyMSON, stringify as stringifyMaSON, stringifyPrimitiveValue };
|
package/dist/index.d.ts
CHANGED
|
@@ -24,11 +24,21 @@ interface ParseResult {
|
|
|
24
24
|
tokenSavingsPercent: number;
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
interface ParseOptions {
|
|
28
|
+
noTrace?: boolean;
|
|
29
|
+
}
|
|
27
30
|
/**
|
|
28
31
|
* Casts a string value to its implicit primitive type or returns the string.
|
|
29
|
-
* Strips quotes if they enclose the string explicitly.
|
|
32
|
+
* Strips quotes if they enclose the string explicitly and restores escaped characters.
|
|
30
33
|
*/
|
|
31
34
|
declare function parsePrimitiveValue(val: string): any;
|
|
35
|
+
/**
|
|
36
|
+
* Parses a single-line or multiline value, advancing the line reader index if needed.
|
|
37
|
+
*/
|
|
38
|
+
declare function parseValueWithMultiline(initialValStr: string, lines: string[], currentLineIndex: number): {
|
|
39
|
+
value: any;
|
|
40
|
+
nextLineIndex: number;
|
|
41
|
+
};
|
|
32
42
|
/**
|
|
33
43
|
* Formats a value for MSON stringification.
|
|
34
44
|
* Wraps in quotes if it has special characters or looks like a keyword but is a string.
|
|
@@ -37,14 +47,18 @@ declare function stringifyPrimitiveValue(val: any): string;
|
|
|
37
47
|
/**
|
|
38
48
|
* Parses MSON text into a JavaScript Object / Array.
|
|
39
49
|
*/
|
|
40
|
-
declare function parse(text: string): any;
|
|
50
|
+
declare function parse(text: string, options?: ParseOptions): any;
|
|
51
|
+
/**
|
|
52
|
+
* Ultra-performance, trace-free parser for MSON.
|
|
53
|
+
*/
|
|
54
|
+
declare function fastParseWithTrace(text: string): ParseResult;
|
|
41
55
|
/**
|
|
42
56
|
* Parses MSON text into a JavaScript Object / Array with step-by-step trace info.
|
|
43
57
|
*/
|
|
44
|
-
declare function parseWithTrace(text: string): ParseResult;
|
|
58
|
+
declare function parseWithTrace(text: string, options?: ParseOptions): ParseResult;
|
|
45
59
|
/**
|
|
46
60
|
* Stringifies a JavaScript object/array back into MSON text recursively.
|
|
47
61
|
*/
|
|
48
|
-
declare function stringify(obj: any, level?: number): string;
|
|
62
|
+
declare function stringify(obj: any, level?: number, parentKey?: string): string;
|
|
49
63
|
|
|
50
|
-
export { type ParseResult, type ParserTraceStep, parse, parse as parseMSON, parsePrimitiveValue, parseWithTrace, stringify, stringify as stringifyMSON, stringifyPrimitiveValue };
|
|
64
|
+
export { type ParseOptions, type ParseResult, type ParserTraceStep, fastParseWithTrace, parse, parse as parseMSON, parseWithTrace as parseMaSON, parsePrimitiveValue, parseValueWithMultiline, parseWithTrace, stringify, stringify as stringifyMSON, stringify as stringifyMaSON, stringifyPrimitiveValue };
|