links-notation 0.8.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.
@@ -0,0 +1,118 @@
1
+ import { test, expect } from 'bun:test';
2
+ import { Parser } from '../src/Parser.js';
3
+ import { formatLinks } from '../src/Link.js';
4
+
5
+ const parser = new Parser();
6
+
7
+ test('TwoLinksTest', () => {
8
+ const source = `(first: x y)
9
+ (second: a b)`;
10
+ const links = parser.parse(source);
11
+ const target = formatLinks(links);
12
+ expect(target).toBe(source);
13
+ });
14
+
15
+ test('ParseAndStringifyTest', () => {
16
+ const source = `(papa (lovesMama: loves mama))
17
+ (son lovesMama)
18
+ (daughter lovesMama)
19
+ (all (love mama))`;
20
+ const links = parser.parse(source);
21
+ const target = formatLinks(links);
22
+ expect(target).toBe(source);
23
+ });
24
+
25
+ test('ParseAndStringifyTest2', () => {
26
+ const source = `father (lovesMom: loves mom)
27
+ son lovesMom
28
+ daughter lovesMom
29
+ all (love mom)`;
30
+ const links = parser.parse(source);
31
+ const target = formatLinks(links, true); // lessParentheses = true
32
+ expect(target).toBe(source);
33
+ });
34
+
35
+ test('ParseAndStringifyWithLessParenthesesTest', () => {
36
+ const source = `lovesMama: loves mama
37
+ papa lovesMama
38
+ son lovesMama
39
+ daughter lovesMama
40
+ all (love mama)`;
41
+ const links = parser.parse(source);
42
+ const target = formatLinks(links, true); // lessParentheses = true
43
+ expect(target).toBe(source);
44
+ });
45
+
46
+ test('DuplicateIdentifiersTest', () => {
47
+ const source = `(a: a b)
48
+ (a: b c)`;
49
+ const target = `(a: a b)
50
+ (a: b c)`;
51
+ const links = parser.parse(source);
52
+ const formattedLinks = formatLinks(links);
53
+ expect(formattedLinks).toBe(target);
54
+ });
55
+
56
+ test('Test complex structure', () => {
57
+ const input = `(Type: Type Type)
58
+ Number
59
+ String
60
+ Array
61
+ Value
62
+ (property: name type)
63
+ (method: name params return)`;
64
+
65
+ const result = parser.parse(input);
66
+ expect(result.length).toBeGreaterThan(0);
67
+ });
68
+
69
+ test('Test mixed formats', () => {
70
+ // Mix of single-line and multi-line formats
71
+ const input = `id1: value1
72
+ (id2: value2 value3)
73
+ simple_ref
74
+ (complex:
75
+ nested1
76
+ nested2
77
+ )`;
78
+
79
+ const result = parser.parse(input);
80
+ expect(result.length).toBeGreaterThan(0);
81
+ });
82
+
83
+ test('Test multiline with id', () => {
84
+ // Test multi-line link with id
85
+ const input = "(id: value1 value2)";
86
+ const result = parser.parse(input);
87
+ expect(result.length).toBeGreaterThan(0);
88
+ });
89
+
90
+ test('Test multiple top level elements', () => {
91
+ // Test multiple top-level elements
92
+ const input = "(elem1: val1)\n(elem2: val2)";
93
+ const result = parser.parse(input);
94
+ expect(result.length).toBeGreaterThan(0);
95
+ });
96
+
97
+ test('Test multiline simple links', () => {
98
+ const input = "(1: 1 1)\n(2: 2 2)";
99
+ const parsed = parser.parse(input);
100
+ expect(parsed.length).toBeGreaterThan(0);
101
+
102
+ // Validate regular formatting
103
+ const output = formatLinks(parsed);
104
+ expect(output).toContain("(1: 1 1)");
105
+ expect(output).toContain("(2: 2 2)");
106
+
107
+ // Validate alternate formatting matches input
108
+ const outputAlternate = formatLinks(parsed);
109
+ expect(outputAlternate).toBe(input);
110
+ });
111
+
112
+ test('Test indented children', () => {
113
+ const input = "parent\n child1\n child2";
114
+ const parsed = parser.parse(input);
115
+
116
+ // The parsed structure should have parent with children
117
+ expect(parsed.length).toBeGreaterThan(0);
118
+ });
@@ -0,0 +1,78 @@
1
+ import { test, expect } from "bun:test";
2
+ import { Parser } from "../src/Parser.js";
3
+
4
+ const parser = new Parser();
5
+
6
+ test("TestMultilineDoubleQuotedReference", () => {
7
+ const input = `(
8
+ "long
9
+ string literal representing
10
+ the reference"
11
+
12
+ 'another
13
+ long string literal
14
+ as another reference'
15
+ )`;
16
+ const result = parser.parse(input);
17
+
18
+ expect(result.length).toBeGreaterThan(0);
19
+ expect(result.length).toBe(1);
20
+
21
+ const link = result[0];
22
+ expect(link.id).toBe(null);
23
+ expect(link.values).toBeTruthy();
24
+ expect(link.values.length).toBe(2);
25
+
26
+ expect(link.values[0].id).toBe(`long
27
+ string literal representing
28
+ the reference`);
29
+
30
+ expect(link.values[1].id).toBe(`another
31
+ long string literal
32
+ as another reference`);
33
+ });
34
+
35
+ test("TestSimpleMultilineDoubleQuoted", () => {
36
+ const input = `("line1
37
+ line2")`;
38
+ const result = parser.parse(input);
39
+
40
+ expect(result.length).toBeGreaterThan(0);
41
+ expect(result.length).toBe(1);
42
+
43
+ const link = result[0];
44
+ expect(link.id).toBe(null);
45
+ expect(link.values).toBeTruthy();
46
+ expect(link.values.length).toBe(1);
47
+ expect(link.values[0].id).toBe("line1\nline2");
48
+ });
49
+
50
+ test("TestSimpleMultilineSingleQuoted", () => {
51
+ const input = `('line1
52
+ line2')`;
53
+ const result = parser.parse(input);
54
+
55
+ expect(result.length).toBeGreaterThan(0);
56
+ expect(result.length).toBe(1);
57
+
58
+ const link = result[0];
59
+ expect(link.id).toBe(null);
60
+ expect(link.values).toBeTruthy();
61
+ expect(link.values.length).toBe(1);
62
+ expect(link.values[0].id).toBe("line1\nline2");
63
+ });
64
+
65
+ test("TestMultilineQuotedAsId", () => {
66
+ const input = `("multi
67
+ line
68
+ id": value1 value2)`;
69
+ const result = parser.parse(input);
70
+
71
+ expect(result.length).toBeGreaterThan(0);
72
+ expect(result.length).toBe(1);
73
+
74
+ const link = result[0];
75
+ expect(link.id).toBe("multi\nline\nid");
76
+ expect(link.values).toBeTruthy();
77
+ expect(link.values.length).toBe(2);
78
+ });
@@ -0,0 +1,166 @@
1
+ import { test, expect } from 'bun:test';
2
+ import { Parser } from '../src/Parser.js';
3
+ import { formatLinks } from '../src/Link.js';
4
+
5
+ const parser = new Parser();
6
+
7
+ test('SignificantWhitespaceTest', () => {
8
+ const source = `
9
+ users
10
+ user1
11
+ id
12
+ 43
13
+ name
14
+ first
15
+ John
16
+ last
17
+ Williams
18
+ location
19
+ New York
20
+ age
21
+ 23
22
+ user2
23
+ id
24
+ 56
25
+ name
26
+ first
27
+ Igor
28
+ middle
29
+ Petrovich
30
+ last
31
+ Ivanov
32
+ location
33
+ Moscow
34
+ age
35
+ 20`;
36
+
37
+ const target = `(users)
38
+ ((users) (user1))
39
+ (((users) (user1)) (id))
40
+ ((((users) (user1)) (id)) (43))
41
+ (((users) (user1)) (name))
42
+ ((((users) (user1)) (name)) (first))
43
+ (((((users) (user1)) (name)) (first)) (John))
44
+ ((((users) (user1)) (name)) (last))
45
+ (((((users) (user1)) (name)) (last)) (Williams))
46
+ (((users) (user1)) (location))
47
+ ((((users) (user1)) (location)) (New York))
48
+ (((users) (user1)) (age))
49
+ ((((users) (user1)) (age)) (23))
50
+ ((users) (user2))
51
+ (((users) (user2)) (id))
52
+ ((((users) (user2)) (id)) (56))
53
+ (((users) (user2)) (name))
54
+ ((((users) (user2)) (name)) (first))
55
+ (((((users) (user2)) (name)) (first)) (Igor))
56
+ ((((users) (user2)) (name)) (middle))
57
+ (((((users) (user2)) (name)) (middle)) (Petrovich))
58
+ ((((users) (user2)) (name)) (last))
59
+ (((((users) (user2)) (name)) (last)) (Ivanov))
60
+ (((users) (user2)) (location))
61
+ ((((users) (user2)) (location)) (Moscow))
62
+ (((users) (user2)) (age))
63
+ ((((users) (user2)) (age)) (20))`;
64
+
65
+ const links = parser.parse(source);
66
+ const formattedLinks = formatLinks(links);
67
+ expect(formattedLinks).toBe(target);
68
+ });
69
+
70
+ test('SimpleSignificantWhitespaceTest', () => {
71
+ const source = `a
72
+ b
73
+ c`;
74
+ const target = `(a)
75
+ ((a) (b))
76
+ ((a) (c))`;
77
+ const links = parser.parse(source);
78
+ const formattedLinks = formatLinks(links);
79
+ expect(formattedLinks).toBe(target);
80
+ });
81
+
82
+ test('TwoSpacesSizedWhitespaceTest', () => {
83
+ const source = `
84
+ users
85
+ user1`;
86
+ const target = `(users)
87
+ ((users) (user1))`;
88
+ const links = parser.parse(source);
89
+ const formattedLinks = formatLinks(links);
90
+ expect(formattedLinks).toBe(target);
91
+ });
92
+
93
+ test('Parse nested structure with indentation', () => {
94
+ const input = `parent
95
+ child1
96
+ child2`;
97
+ const result = parser.parse(input);
98
+ expect(result.length).toBe(3);
99
+ // The parser creates (parent), ((parent) (child1)), ((parent) (child2))
100
+ expect(result[0].id).toBe(null);
101
+ expect(result[0].values[0].id).toBe('parent');
102
+ expect(result[1].id).toBe(null);
103
+ expect(result[1].values.length).toBe(2);
104
+ expect(result[2].id).toBe(null);
105
+ expect(result[2].values.length).toBe(2);
106
+ });
107
+
108
+ test('Test indentation consistency', () => {
109
+ // Test that indentation must be consistent
110
+ const input = `parent
111
+ child1
112
+ child2`; // Inconsistent indentation
113
+ const result = parser.parse(input);
114
+ // This should parse but child2 won't be a child of parent due to different indentation
115
+ expect(result.length).toBeGreaterThan(0);
116
+ });
117
+
118
+ test('Indentation-based children', () => {
119
+ const input = `parent
120
+ child1
121
+ child2
122
+ grandchild`;
123
+ const result = parser.parse(input);
124
+ expect(result.length).toBe(4);
125
+ });
126
+
127
+ test('Complex indentation', () => {
128
+ const input = `root
129
+ level1a
130
+ level2a
131
+ level2b
132
+ level1b
133
+ level2c`;
134
+ const result = parser.parse(input);
135
+ expect(result.length).toBe(6);
136
+ });
137
+
138
+ test('Test nested links', () => {
139
+ const input = '(1: (2: (3: 3)))';
140
+ const parsed = parser.parse(input);
141
+ expect(parsed.length).toBeGreaterThan(0);
142
+
143
+ // Validate regular formatting
144
+ const output = formatLinks(parsed);
145
+ expect(output).toBeTruthy();
146
+
147
+ // Validate that the structure is properly nested
148
+ expect(parsed.length).toBe(1);
149
+ });
150
+
151
+ test('Test indentation (parser)', () => {
152
+ const input = 'parent\n child1\n child2';
153
+ const result = parser.parse(input);
154
+ expect(result.length).toBeGreaterThan(0);
155
+ // Should have parent link
156
+ const hasParentLink = result.some(l => l.values && l.values.some(v => v.id === 'parent'));
157
+ expect(hasParentLink).toBe(true);
158
+ });
159
+
160
+ test('Test nested indentation (parser)', () => {
161
+ const input = 'parent\n child\n grandchild';
162
+ const result = parser.parse(input);
163
+ expect(result.length).toBeGreaterThan(0);
164
+ // Should create nested structure with proper hierarchy
165
+ expect(result.length).toBeGreaterThanOrEqual(1);
166
+ });
@@ -0,0 +1,229 @@
1
+ import { test, expect } from 'bun:test';
2
+ import { Parser } from '../src/Parser.js';
3
+ import { formatLinks } from '../src/Link.js';
4
+
5
+ const parser = new Parser();
6
+
7
+ test('SingleLinkTest', () => {
8
+ const source = '(address: source target)';
9
+ const links = parser.parse(source);
10
+ const target = formatLinks(links);
11
+ expect(target).toBe(source);
12
+ });
13
+
14
+ test('TripletSingleLinkTest', () => {
15
+ const source = '(papa has car)';
16
+ const links = parser.parse(source);
17
+ const target = formatLinks(links);
18
+ expect(target).toBe(source);
19
+ });
20
+
21
+ test('BugTest1', () => {
22
+ const source = '(ignore conan-center-index repository)';
23
+ const links = parser.parse(source);
24
+ const target = formatLinks(links);
25
+ expect(target).toBe(source);
26
+ });
27
+
28
+ test('QuotedReferencesTest', () => {
29
+ const source = `(a: 'b' "c")`;
30
+ const target = `(a: b c)`;
31
+ const links = parser.parse(source);
32
+ const formattedLinks = formatLinks(links);
33
+ expect(formattedLinks).toBe(target);
34
+ });
35
+
36
+ test('QuotedReferencesWithSpacesTest', () => {
37
+ const source = `('a a': 'b b' "c c")`;
38
+ const target = `('a a': 'b b' 'c c')`;
39
+ const links = parser.parse(source);
40
+ const formattedLinks = formatLinks(links);
41
+ expect(formattedLinks).toBe(target);
42
+ });
43
+
44
+ test('Parse simple reference', () => {
45
+ const input = 'test';
46
+ const result = parser.parse(input);
47
+ expect(result.length).toBe(1);
48
+ expect(result[0].id).toBe(null);
49
+ expect(result[0].values.length).toBe(1);
50
+ expect(result[0].values[0].id).toBe('test');
51
+ expect(result[0].values[0].values).toEqual([]);
52
+ });
53
+
54
+ test('Parse reference with colon and values', () => {
55
+ const input = 'parent: child1 child2';
56
+ const result = parser.parse(input);
57
+ expect(result.length).toBe(1);
58
+ expect(result[0].id).toBe('parent');
59
+ expect(result[0].values.length).toBe(2);
60
+ expect(result[0].values[0].id).toBe('child1');
61
+ expect(result[0].values[1].id).toBe('child2');
62
+ });
63
+
64
+ test('Parse multiline link', () => {
65
+ const input = '(parent: child1 child2)';
66
+ const result = parser.parse(input);
67
+ expect(result.length).toBe(1);
68
+ expect(result[0].id).toBe('parent');
69
+ expect(result[0].values.length).toBe(2);
70
+ });
71
+
72
+ test('Parse quoted references', () => {
73
+ const input = `"has space" 'has:colon'`;
74
+ const result = parser.parse(input);
75
+ expect(result.length).toBe(1);
76
+ expect(result[0].id).toBe(null);
77
+ expect(result[0].values.length).toBe(2);
78
+ expect(result[0].values[0].id).toBe('has space');
79
+ expect(result[0].values[1].id).toBe('has:colon');
80
+ // Ensure formatting matches C# expectation
81
+ expect(formatLinks(result)).toBe(`('has space' 'has:colon')`);
82
+ });
83
+
84
+ test('Parse values only', () => {
85
+ const input = ': value1 value2';
86
+ // Standalone ':' is now forbidden and should throw an error
87
+ expect(() => parser.parse(input)).toThrow();
88
+ });
89
+
90
+ test('Test single-line link with id', () => {
91
+ const input = 'id: value1 value2';
92
+ const result = parser.parse(input);
93
+ expect(result.length).toBeGreaterThan(0);
94
+ });
95
+
96
+ test('Test multi-line link with id', () => {
97
+ const input = '(id: value1 value2)';
98
+ const result = parser.parse(input);
99
+ expect(result.length).toBeGreaterThan(0);
100
+ });
101
+
102
+ test('Test link without id (single-line)', () => {
103
+ const input = ': value1 value2';
104
+ // Standalone ':' is now forbidden and should throw an error
105
+ expect(() => parser.parse(input)).toThrow();
106
+ });
107
+
108
+ test('Test link without id (multi-line)', () => {
109
+ const input = '(: value1 value2)';
110
+ // '(:)' syntax is now forbidden and should throw an error
111
+ expect(() => parser.parse(input)).toThrow();
112
+ });
113
+
114
+ test('Test singlet link', () => {
115
+ const input = '(singlet)';
116
+ const result = parser.parse(input);
117
+ expect(result.length).toBe(1);
118
+ expect(result[0].id).toBe(null);
119
+ expect(result[0].values.length).toBe(1);
120
+ expect(result[0].values[0].id).toBe('singlet');
121
+ expect(result[0].values[0].values).toEqual([]);
122
+ });
123
+
124
+ test('Test value link', () => {
125
+ const input = '(value1 value2 value3)';
126
+ const result = parser.parse(input);
127
+ expect(result.length).toBeGreaterThan(0);
128
+ });
129
+
130
+ test('ParseQuotedReferencesValuesOnly', () => {
131
+ const source = `"has space" 'has:colon'`;
132
+ const parser = new Parser();
133
+ const links = parser.parse(source);
134
+ expect(links).toBeTruthy();
135
+ expect(links.length).toBe(1);
136
+ expect(links[0].id).toBe(null);
137
+ expect(links[0].values.length).toBe(2);
138
+ expect(links[0].values[0].id).toBe('has space');
139
+ expect(links[0].values[1].id).toBe('has:colon');
140
+ });
141
+
142
+ test('Test quoted references', () => {
143
+ const input = '("id with spaces": "value with spaces")';
144
+ const result = parser.parse(input);
145
+ expect(result.length).toBeGreaterThan(0);
146
+ });
147
+
148
+ test('Test single-quoted references', () => {
149
+ const input = "('id': 'value')";
150
+ const result = parser.parse(input);
151
+ expect(result.length).toBeGreaterThan(0);
152
+ });
153
+
154
+ test('Test nested links', () => {
155
+ const input = '(outer: (inner: value))';
156
+ const result = parser.parse(input);
157
+ expect(result.length).toBeGreaterThan(0);
158
+ });
159
+
160
+ test('Test special characters in quotes', () => {
161
+ let input = '("key:with:colons": "value(with)parens")';
162
+ let result = parser.parse(input);
163
+ expect(result.length).toBeGreaterThan(0);
164
+
165
+ input = "('key with spaces': 'value: with special chars')";
166
+ result = parser.parse(input);
167
+ expect(result.length).toBeGreaterThan(0);
168
+ });
169
+
170
+ test('Test deeply nested', () => {
171
+ const input = '(a: (b: (c: (d: (e: value)))))';
172
+ const result = parser.parse(input);
173
+ expect(result.length).toBeGreaterThan(0);
174
+ });
175
+
176
+ test('Test hyphenated identifiers', () => {
177
+ const input = '(conan-center-index: repository info)';
178
+ const result = parser.parse(input);
179
+ expect(result.length).toBeGreaterThan(0);
180
+ });
181
+
182
+ test('Test multiple words in quotes', () => {
183
+ const input = '("New York": city state)';
184
+ const result = parser.parse(input);
185
+ expect(result.length).toBeGreaterThan(0);
186
+ expect(JSON.stringify(result)).toContain('New York');
187
+ });
188
+
189
+ test('Test simple ref', () => {
190
+ const input = 'simple_ref';
191
+ const result = parser.parse(input);
192
+ expect(result.length).toBeGreaterThan(0);
193
+ });
194
+
195
+ test('Test simple reference (parser)', () => {
196
+ const input = 'hello';
197
+ const result = parser.parse(input);
198
+ expect(result.length).toBe(1);
199
+ expect(result[0].id).toBe(null);
200
+ expect(result[0].values.length).toBe(1);
201
+ expect(result[0].values[0].id).toBe('hello');
202
+ });
203
+
204
+ test('Test quoted reference (parser)', () => {
205
+ const input = '"hello world"';
206
+ const result = parser.parse(input);
207
+ expect(result.length).toBe(1);
208
+ expect(result[0].id).toBe(null);
209
+ expect(result[0].values.length).toBe(1);
210
+ expect(result[0].values[0].id).toBe('hello world');
211
+ });
212
+
213
+ test('Test singlet link (parser)', () => {
214
+ const input = '(singlet)';
215
+ const result = parser.parse(input);
216
+ expect(result.length).toBe(1);
217
+ expect(result[0].id).toBe(null);
218
+ expect(result[0].values.length).toBe(1);
219
+ expect(result[0].values[0].id).toBe('singlet');
220
+ expect(result[0].values[0].values).toEqual([]);
221
+ });
222
+
223
+ test('Test value link (parser)', () => {
224
+ const input = '(a b c)';
225
+ const result = parser.parse(input);
226
+ expect(result.length).toBe(1);
227
+ expect(result[0].id).toBe(null);
228
+ expect(result[0].values.length).toBe(3);
229
+ });