links-notation 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.lock +1 -0
- package/dist/index.js +484 -143
- package/examples/debug_indentation.js +16 -0
- package/examples/test_leading_spaces.js +33 -0
- package/package.json +1 -1
- package/src/FormatConfig.js +19 -0
- package/src/FormatOptions.js +52 -0
- package/src/Link.js +287 -25
- package/src/Parser.js +43 -8
- package/src/grammar.pegjs +30 -10
- package/src/index.js +3 -1
- package/src/parser-generated.js +276 -123
- package/tests/ApiTests.test.js +104 -7
- package/tests/EdgeCaseParser.test.js +9 -9
- package/tests/FormatConfig.test.js +126 -0
- package/tests/IndentationConsistency.test.js +128 -0
- package/tests/IndentedIdSyntax.test.js +2 -2
- package/tests/Link.test.js +1 -1
- package/tests/LinksGroup.test.js +28 -1
- package/tests/MixedIndentationModes.test.js +5 -5
- package/tests/MultilineParser.test.js +5 -5
- package/tests/NestedParser.test.js +31 -4
- package/tests/NestedSelfReference.test.js +102 -0
- package/tests/SingleLineParser.test.js +86 -6
package/tests/ApiTests.test.js
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
import { test, expect } from 'bun:test';
|
|
2
2
|
import { Parser } from '../src/Parser.js';
|
|
3
|
-
import { Link } from '../src/Link.js';
|
|
3
|
+
import { Link, formatLinks } from '../src/Link.js';
|
|
4
|
+
import { FormatOptions } from '../src/FormatOptions.js';
|
|
4
5
|
|
|
5
6
|
const parser = new Parser();
|
|
6
7
|
|
|
8
|
+
test('test_is_ref', () => {
|
|
9
|
+
// JS doesn't have separate Ref/Link types, but we can test simple link behavior
|
|
10
|
+
const simpleLink = new Link('some_value');
|
|
11
|
+
expect(simpleLink.id).toBe('some_value');
|
|
12
|
+
expect(simpleLink.values).toEqual([]);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('test_is_link', () => {
|
|
16
|
+
// Test link with values
|
|
17
|
+
const link = new Link('id', [new Link('child')]);
|
|
18
|
+
expect(link.id).toBe('id');
|
|
19
|
+
expect(link.values.length).toBe(1);
|
|
20
|
+
expect(link.values[0].id).toBe('child');
|
|
21
|
+
});
|
|
22
|
+
|
|
7
23
|
test('test_is_ref equivalent', () => {
|
|
8
24
|
// JS doesn't have separate Ref/Link types, but we can test simple link behavior
|
|
9
25
|
const simpleLink = new Link('some_value');
|
|
@@ -28,7 +44,7 @@ test('test_empty_link', () => {
|
|
|
28
44
|
test('test_simple_link', () => {
|
|
29
45
|
const input = '(1: 1 1)';
|
|
30
46
|
const parsed = parser.parse(input);
|
|
31
|
-
|
|
47
|
+
|
|
32
48
|
// Validate regular formatting
|
|
33
49
|
const output = parsed[0].format();
|
|
34
50
|
const expected = '(1: 1 1)'; // JS format matches input
|
|
@@ -38,7 +54,7 @@ test('test_simple_link', () => {
|
|
|
38
54
|
test('test_link_with_source_target', () => {
|
|
39
55
|
const input = '(index: source target)';
|
|
40
56
|
const parsed = parser.parse(input);
|
|
41
|
-
|
|
57
|
+
|
|
42
58
|
// Validate regular formatting
|
|
43
59
|
const output = parsed[0].format();
|
|
44
60
|
expect(output).toBe(input);
|
|
@@ -47,7 +63,7 @@ test('test_link_with_source_target', () => {
|
|
|
47
63
|
test('test_link_with_source_type_target', () => {
|
|
48
64
|
const input = '(index: source type target)';
|
|
49
65
|
const parsed = parser.parse(input);
|
|
50
|
-
|
|
66
|
+
|
|
51
67
|
// Validate regular formatting
|
|
52
68
|
const output = parsed[0].format();
|
|
53
69
|
expect(output).toBe(input);
|
|
@@ -56,7 +72,7 @@ test('test_link_with_source_type_target', () => {
|
|
|
56
72
|
test('test_single_line_format', () => {
|
|
57
73
|
const input = 'id: value1 value2';
|
|
58
74
|
const parsed = parser.parse(input);
|
|
59
|
-
|
|
75
|
+
|
|
60
76
|
// The parser should handle single-line format
|
|
61
77
|
const output = parsed[0].format(true); // lessParentheses mode
|
|
62
78
|
expect(output).toContain('id');
|
|
@@ -67,8 +83,89 @@ test('test_single_line_format', () => {
|
|
|
67
83
|
test('test_quoted_references', () => {
|
|
68
84
|
const input = '("quoted id": "value with spaces")';
|
|
69
85
|
const parsed = parser.parse(input);
|
|
70
|
-
|
|
86
|
+
|
|
71
87
|
const output = parsed[0].format();
|
|
72
88
|
expect(output).toContain('quoted id');
|
|
73
89
|
expect(output).toContain('value with spaces');
|
|
74
|
-
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('test_quoted_references_parsing', () => {
|
|
93
|
+
// Test that quoted references are parsed correctly
|
|
94
|
+
const input = '("quoted id": "value with spaces")';
|
|
95
|
+
const parsed = parser.parse(input);
|
|
96
|
+
|
|
97
|
+
// Verify parsing worked correctly
|
|
98
|
+
const output = formatLinks(parsed);
|
|
99
|
+
expect(output).toContain('quoted id');
|
|
100
|
+
expect(output).toContain('value with spaces');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('test_indented_id_syntax_parsing', () => {
|
|
104
|
+
// Test that indented ID syntax is parsed correctly
|
|
105
|
+
const indented = `id:
|
|
106
|
+
value1
|
|
107
|
+
value2`;
|
|
108
|
+
const inline = '(id: value1 value2)';
|
|
109
|
+
|
|
110
|
+
const indentedParsed = parser.parse(indented);
|
|
111
|
+
const inlineParsed = parser.parse(inline);
|
|
112
|
+
|
|
113
|
+
// Both should produce equivalent structures
|
|
114
|
+
const indentedOutput = formatLinks(indentedParsed);
|
|
115
|
+
const inlineOutput = formatLinks(inlineParsed);
|
|
116
|
+
expect(indentedOutput).toBe(inlineOutput);
|
|
117
|
+
expect(indentedOutput).toBe('(id: value1 value2)');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('test_indented_id_syntax_roundtrip', () => {
|
|
121
|
+
const input = `id:
|
|
122
|
+
value1
|
|
123
|
+
value2`;
|
|
124
|
+
const parsed = parser.parse(input);
|
|
125
|
+
|
|
126
|
+
// Validate that we can format with indented syntax using FormatOptions
|
|
127
|
+
const options = new FormatOptions();
|
|
128
|
+
options.maxInlineRefs = 1; // Force indentation with more than 1 ref
|
|
129
|
+
options.preferInline = false;
|
|
130
|
+
const output = formatLinks(parsed, options);
|
|
131
|
+
expect(output).toBe(input);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test('test_multiple_indented_id_syntax_parsing', () => {
|
|
135
|
+
// Test that multiple indented ID links are parsed correctly
|
|
136
|
+
const indented = `id1:
|
|
137
|
+
a
|
|
138
|
+
b
|
|
139
|
+
id2:
|
|
140
|
+
c
|
|
141
|
+
d`;
|
|
142
|
+
const inline = `(id1: a b)
|
|
143
|
+
(id2: c d)`;
|
|
144
|
+
|
|
145
|
+
const indentedParsed = parser.parse(indented);
|
|
146
|
+
const inlineParsed = parser.parse(inline);
|
|
147
|
+
|
|
148
|
+
// Both should produce equivalent structures
|
|
149
|
+
const indentedOutput = formatLinks(indentedParsed);
|
|
150
|
+
const inlineOutput = formatLinks(inlineParsed);
|
|
151
|
+
expect(indentedOutput).toBe(inlineOutput);
|
|
152
|
+
expect(indentedOutput).toBe(`(id1: a b)
|
|
153
|
+
(id2: c d)`);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test('test_multiple_indented_id_syntax_roundtrip', () => {
|
|
157
|
+
const input = `id1:
|
|
158
|
+
a
|
|
159
|
+
b
|
|
160
|
+
id2:
|
|
161
|
+
c
|
|
162
|
+
d`;
|
|
163
|
+
const parsed = parser.parse(input);
|
|
164
|
+
|
|
165
|
+
// Validate that we can format with indented syntax using FormatOptions
|
|
166
|
+
const options = new FormatOptions();
|
|
167
|
+
options.maxInlineRefs = 1; // Force indentation with more than 1 ref
|
|
168
|
+
options.preferInline = false;
|
|
169
|
+
const output = formatLinks(parsed, options);
|
|
170
|
+
expect(output).toBe(input);
|
|
171
|
+
});
|
|
@@ -4,13 +4,13 @@ import { formatLinks } from '../src/Link.js';
|
|
|
4
4
|
|
|
5
5
|
const parser = new Parser();
|
|
6
6
|
|
|
7
|
-
test('
|
|
7
|
+
test('Empty link', () => {
|
|
8
8
|
const source = ':';
|
|
9
9
|
// Standalone ':' is now forbidden and should throw an error
|
|
10
10
|
expect(() => parser.parse(source)).toThrow();
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
test('
|
|
13
|
+
test('Empty link with parentheses', () => {
|
|
14
14
|
const source = '()';
|
|
15
15
|
const target = '()';
|
|
16
16
|
const links = parser.parse(source);
|
|
@@ -18,13 +18,13 @@ test('EmptyLinkWithParenthesesTest', () => {
|
|
|
18
18
|
expect(formattedLinks).toBe(target);
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
test('
|
|
21
|
+
test('Empty link with empty self reference', () => {
|
|
22
22
|
const source = '(:)';
|
|
23
23
|
// '(:)' is now forbidden and should throw an error
|
|
24
24
|
expect(() => parser.parse(source)).toThrow();
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
test('
|
|
27
|
+
test('All features', () => {
|
|
28
28
|
// Test single-line link with id
|
|
29
29
|
let input = 'id: value1 value2';
|
|
30
30
|
let result = parser.parse(input);
|
|
@@ -73,21 +73,21 @@ test('TestAllFeaturesTest', () => {
|
|
|
73
73
|
expect(result.length).toBeGreaterThan(0);
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
test('
|
|
76
|
+
test('Empty document', () => {
|
|
77
77
|
const input = '';
|
|
78
78
|
// Empty document should return empty array
|
|
79
79
|
const result = parser.parse(input);
|
|
80
80
|
expect(result).toEqual([]);
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
test('
|
|
83
|
+
test('Whitespace only', () => {
|
|
84
84
|
const input = ' \n \n ';
|
|
85
85
|
// Whitespace-only document should return empty array
|
|
86
86
|
const result = parser.parse(input);
|
|
87
87
|
expect(result).toEqual([]);
|
|
88
88
|
});
|
|
89
89
|
|
|
90
|
-
test('
|
|
90
|
+
test('Empty links', () => {
|
|
91
91
|
let input = '()';
|
|
92
92
|
let result = parser.parse(input);
|
|
93
93
|
expect(result.length).toBe(1);
|
|
@@ -105,7 +105,7 @@ test('TestEmptyLinksTest', () => {
|
|
|
105
105
|
expect(result[0].values).toEqual([]);
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
-
test('
|
|
108
|
+
test('Singlet links', () => {
|
|
109
109
|
// Test singlet (1)
|
|
110
110
|
let input = '(1)';
|
|
111
111
|
let result = parser.parse(input);
|
|
@@ -155,7 +155,7 @@ test('TestSingletLinksTest', () => {
|
|
|
155
155
|
expect(result[0].values[3].values).toEqual([]);
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
-
test('
|
|
158
|
+
test('Invalid input', () => {
|
|
159
159
|
const input = '(invalid';
|
|
160
160
|
// Unclosed parentheses should throw an error
|
|
161
161
|
expect(() => parser.parse(input)).toThrow();
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { test, expect } from 'bun:test';
|
|
2
|
+
import { Parser, Link, formatLinks, FormatConfig } from '../src/index.js';
|
|
3
|
+
|
|
4
|
+
const parser = new Parser();
|
|
5
|
+
|
|
6
|
+
test('Format config basic', () => {
|
|
7
|
+
const config = new FormatConfig();
|
|
8
|
+
expect(config.lessParentheses).toBe(false);
|
|
9
|
+
expect(config.maxLineLength).toBe(80);
|
|
10
|
+
expect(config.indentLongLines).toBe(false);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('Format with line length limit', () => {
|
|
14
|
+
// Create a link with many references that exceeds line length
|
|
15
|
+
const link = new Link('sequence', [
|
|
16
|
+
new Link('1'), new Link('2'), new Link('3'), new Link('4'), new Link('5'),
|
|
17
|
+
new Link('6'), new Link('7'), new Link('8'), new Link('9'), new Link('10')
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
// Format with line length limit
|
|
21
|
+
// The line '(sequence: 1 2 3 4 5 6 7 8 9 10)' is 32 chars, so use threshold of 30
|
|
22
|
+
const config = new FormatConfig({
|
|
23
|
+
indentLongLines: true,
|
|
24
|
+
maxLineLength: 30,
|
|
25
|
+
preferInline: false
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const output = link.format(config);
|
|
29
|
+
expect(output).toContain('sequence:');
|
|
30
|
+
expect(output).toContain('\n'); // Should be indented across multiple lines
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('Format with max inline refs', () => {
|
|
34
|
+
// Create a link with 4 references
|
|
35
|
+
const link = new Link('id', [new Link('1'), new Link('2'), new Link('3'), new Link('4')]);
|
|
36
|
+
|
|
37
|
+
// Format with maxInlineRefs=3 (should trigger indentation)
|
|
38
|
+
const config = new FormatConfig({
|
|
39
|
+
maxInlineRefs: 3,
|
|
40
|
+
preferInline: false
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const output = link.format(config);
|
|
44
|
+
expect(output).toContain('id:');
|
|
45
|
+
expect(output).toContain('\n'); // Should be indented
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('Format with consecutive grouping', () => {
|
|
49
|
+
const links = [
|
|
50
|
+
new Link('SetA', [new Link('a')]),
|
|
51
|
+
new Link('SetA', [new Link('b')]),
|
|
52
|
+
new Link('SetA', [new Link('c')])
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
const config = new FormatConfig({ groupConsecutive: true });
|
|
56
|
+
|
|
57
|
+
const output = formatLinks(links, config);
|
|
58
|
+
|
|
59
|
+
// Should group consecutive SetA links
|
|
60
|
+
// The output should have SetA with all values a, b, c
|
|
61
|
+
expect(output).toContain('SetA');
|
|
62
|
+
expect(output).toContain('a');
|
|
63
|
+
expect(output).toContain('b');
|
|
64
|
+
expect(output).toContain('c');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('Format config less parentheses', () => {
|
|
68
|
+
const link = new Link('id', [new Link('value')]);
|
|
69
|
+
|
|
70
|
+
const config = new FormatConfig({ lessParentheses: true });
|
|
71
|
+
|
|
72
|
+
const output = link.format(config);
|
|
73
|
+
// Should not have outer parentheses
|
|
74
|
+
expect(output).toBe('id: value');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('Format config custom indent', () => {
|
|
78
|
+
const link = new Link('id', [new Link('1'), new Link('2'), new Link('3'), new Link('4')]);
|
|
79
|
+
|
|
80
|
+
const config = new FormatConfig({
|
|
81
|
+
maxInlineRefs: 3,
|
|
82
|
+
preferInline: false,
|
|
83
|
+
indentString: ' ' // 4 spaces
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const output = link.format(config);
|
|
87
|
+
// Check for custom indentation
|
|
88
|
+
expect(output).toContain(' '); // Should use 4 spaces
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('Roundtrip with line length formatting', () => {
|
|
92
|
+
// Create a simple link
|
|
93
|
+
const originalLink = new Link('test', [new Link('a'), new Link('b'), new Link('c')]);
|
|
94
|
+
|
|
95
|
+
// Format with indentation
|
|
96
|
+
const config = new FormatConfig({
|
|
97
|
+
maxInlineRefs: 2,
|
|
98
|
+
preferInline: false
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const formatted = originalLink.format(config);
|
|
102
|
+
|
|
103
|
+
// Parse it back
|
|
104
|
+
const parsed = parser.parse(formatted);
|
|
105
|
+
|
|
106
|
+
// Should preserve the structure (though format may differ)
|
|
107
|
+
expect(parsed.length).toBeGreaterThan(0);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test('Should indent by length', () => {
|
|
111
|
+
const config = new FormatConfig({ indentLongLines: true, maxLineLength: 80 });
|
|
112
|
+
|
|
113
|
+
const shortLine = 'short';
|
|
114
|
+
const longLine = 'a'.repeat(100);
|
|
115
|
+
|
|
116
|
+
expect(config.shouldIndentByLength(shortLine)).toBe(false);
|
|
117
|
+
expect(config.shouldIndentByLength(longLine)).toBe(true);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('Should indent by ref count', () => {
|
|
121
|
+
const config = new FormatConfig({ maxInlineRefs: 3 });
|
|
122
|
+
|
|
123
|
+
expect(config.shouldIndentByRefCount(2)).toBe(false);
|
|
124
|
+
expect(config.shouldIndentByRefCount(3)).toBe(false);
|
|
125
|
+
expect(config.shouldIndentByRefCount(4)).toBe(true);
|
|
126
|
+
});
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Parser } from '../src/Parser.js';
|
|
2
|
+
import { formatLinks } from '../src/Link.js';
|
|
3
|
+
|
|
4
|
+
describe('Indentation Consistency Tests (Issue #135)', () => {
|
|
5
|
+
let parser;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
parser = new Parser();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('Leading spaces vs no leading spaces', () => {
|
|
12
|
+
// Example with 2 leading spaces (from issue #135)
|
|
13
|
+
const withLeading = ` TELEGRAM_BOT_TOKEN: '849...355:AAG...rgk_YZk...aPU'
|
|
14
|
+
TELEGRAM_ALLOWED_CHATS:
|
|
15
|
+
-1002975819706
|
|
16
|
+
-1002861722681
|
|
17
|
+
TELEGRAM_HIVE_OVERRIDES:
|
|
18
|
+
--all-issues
|
|
19
|
+
--once
|
|
20
|
+
TELEGRAM_BOT_VERBOSE: true`;
|
|
21
|
+
|
|
22
|
+
// Example without leading spaces (from issue #135)
|
|
23
|
+
const withoutLeading = `TELEGRAM_BOT_TOKEN: '849...355:AAG...rgk_YZk...aPU'
|
|
24
|
+
TELEGRAM_ALLOWED_CHATS:
|
|
25
|
+
-1002975819706
|
|
26
|
+
-1002861722681
|
|
27
|
+
TELEGRAM_HIVE_OVERRIDES:
|
|
28
|
+
--all-issues
|
|
29
|
+
--once
|
|
30
|
+
TELEGRAM_BOT_VERBOSE: true`;
|
|
31
|
+
|
|
32
|
+
const resultWith = parser.parse(withLeading);
|
|
33
|
+
const resultWithout = parser.parse(withoutLeading);
|
|
34
|
+
|
|
35
|
+
// Compare the entire formatted output (complete round trip test)
|
|
36
|
+
expect(formatLinks(resultWith)).toBe(formatLinks(resultWithout));
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('two spaces vs four spaces indentation', () => {
|
|
40
|
+
// Example with 2 spaces per level
|
|
41
|
+
const twoSpaces = `TELEGRAM_BOT_TOKEN: '849...355:AAG...rgk_YZk...aPU'
|
|
42
|
+
TELEGRAM_ALLOWED_CHATS:
|
|
43
|
+
-1002975819706
|
|
44
|
+
-1002861722681
|
|
45
|
+
TELEGRAM_HIVE_OVERRIDES:
|
|
46
|
+
--all-issues
|
|
47
|
+
--once
|
|
48
|
+
--auto-fork
|
|
49
|
+
--skip-issues-with-prs
|
|
50
|
+
--attach-logs
|
|
51
|
+
--verbose
|
|
52
|
+
--no-tool-check
|
|
53
|
+
TELEGRAM_SOLVE_OVERRIDES:
|
|
54
|
+
--auto-fork
|
|
55
|
+
--auto-continue
|
|
56
|
+
--attach-logs
|
|
57
|
+
--verbose
|
|
58
|
+
--no-tool-check
|
|
59
|
+
TELEGRAM_BOT_VERBOSE: true`;
|
|
60
|
+
|
|
61
|
+
// Example with 4 spaces per level
|
|
62
|
+
const fourSpaces = `TELEGRAM_BOT_TOKEN: '849...355:AAG...rgk_YZk...aPU'
|
|
63
|
+
TELEGRAM_ALLOWED_CHATS:
|
|
64
|
+
-1002975819706
|
|
65
|
+
-1002861722681
|
|
66
|
+
TELEGRAM_HIVE_OVERRIDES:
|
|
67
|
+
--all-issues
|
|
68
|
+
--once
|
|
69
|
+
--auto-fork
|
|
70
|
+
--skip-issues-with-prs
|
|
71
|
+
--attach-logs
|
|
72
|
+
--verbose
|
|
73
|
+
--no-tool-check
|
|
74
|
+
TELEGRAM_SOLVE_OVERRIDES:
|
|
75
|
+
--auto-fork
|
|
76
|
+
--auto-continue
|
|
77
|
+
--attach-logs
|
|
78
|
+
--verbose
|
|
79
|
+
--no-tool-check
|
|
80
|
+
TELEGRAM_BOT_VERBOSE: true`;
|
|
81
|
+
|
|
82
|
+
const resultTwo = parser.parse(twoSpaces);
|
|
83
|
+
const resultFour = parser.parse(fourSpaces);
|
|
84
|
+
|
|
85
|
+
// Compare the entire formatted output (complete round trip test)
|
|
86
|
+
expect(formatLinks(resultTwo)).toBe(formatLinks(resultFour));
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test('simple two vs four spaces indentation', () => {
|
|
90
|
+
// Simple example with 2 spaces
|
|
91
|
+
const twoSpaces = `parent:
|
|
92
|
+
child1
|
|
93
|
+
child2`;
|
|
94
|
+
|
|
95
|
+
// Simple example with 4 spaces
|
|
96
|
+
const fourSpaces = `parent:
|
|
97
|
+
child1
|
|
98
|
+
child2`;
|
|
99
|
+
|
|
100
|
+
const resultTwo = parser.parse(twoSpaces);
|
|
101
|
+
const resultFour = parser.parse(fourSpaces);
|
|
102
|
+
|
|
103
|
+
// Compare the entire formatted output (complete round trip test)
|
|
104
|
+
expect(formatLinks(resultTwo)).toBe(formatLinks(resultFour));
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('three level nesting with different indentation', () => {
|
|
108
|
+
// Three levels with 2 spaces
|
|
109
|
+
const twoSpaces = `level1:
|
|
110
|
+
level2:
|
|
111
|
+
level3a
|
|
112
|
+
level3b
|
|
113
|
+
level2b`;
|
|
114
|
+
|
|
115
|
+
// Three levels with 4 spaces
|
|
116
|
+
const fourSpaces = `level1:
|
|
117
|
+
level2:
|
|
118
|
+
level3a
|
|
119
|
+
level3b
|
|
120
|
+
level2b`;
|
|
121
|
+
|
|
122
|
+
const resultTwo = parser.parse(twoSpaces);
|
|
123
|
+
const resultFour = parser.parse(fourSpaces);
|
|
124
|
+
|
|
125
|
+
// Compare the entire formatted output (complete round trip test)
|
|
126
|
+
expect(formatLinks(resultTwo)).toBe(formatLinks(resultFour));
|
|
127
|
+
});
|
|
128
|
+
});
|
|
@@ -4,7 +4,7 @@ import { formatLinks } from "../src/Link.js";
|
|
|
4
4
|
|
|
5
5
|
const parser = new Parser();
|
|
6
6
|
|
|
7
|
-
test("Basic indented ID syntax
|
|
7
|
+
test("Basic indented ID syntax", () => {
|
|
8
8
|
const indentedSyntax = `3:
|
|
9
9
|
papa
|
|
10
10
|
loves
|
|
@@ -145,7 +145,7 @@ test("Empty indented ID should work", () => {
|
|
|
145
145
|
expect(formatted).toBe("(empty)");
|
|
146
146
|
});
|
|
147
147
|
|
|
148
|
-
test("Equivalence test
|
|
148
|
+
test("Equivalence test comprehensive", () => {
|
|
149
149
|
const testCases = [
|
|
150
150
|
{
|
|
151
151
|
indented: "test:\n one",
|
package/tests/Link.test.js
CHANGED
|
@@ -30,7 +30,7 @@ test('Link toString with id and values', () => {
|
|
|
30
30
|
expect(link.toString()).toBe('(parent: child1 child2)');
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
test('Link escapeReference
|
|
33
|
+
test('Link escapeReference simple', () => {
|
|
34
34
|
expect(Link.escapeReference('simple')).toBe('simple');
|
|
35
35
|
});
|
|
36
36
|
|
package/tests/LinksGroup.test.js
CHANGED
|
@@ -32,9 +32,36 @@ test('LinksGroup toString', () => {
|
|
|
32
32
|
const element = new Link('root');
|
|
33
33
|
const children = [new Link('child1'), new Link('child2')];
|
|
34
34
|
const group = new LinksGroup(element, children);
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
const str = group.toString();
|
|
37
37
|
expect(str).toContain('(root)');
|
|
38
38
|
expect(str).toContain('(child1)');
|
|
39
39
|
expect(str).toContain('(child2)');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('LinksGroup constructor equivalent test', () => {
|
|
43
|
+
// Test creating a LinksGroup structure in an equivalent way
|
|
44
|
+
const root = new Link('root');
|
|
45
|
+
const children = [new Link('child1'), new Link('child2')];
|
|
46
|
+
|
|
47
|
+
// Create a group with an id
|
|
48
|
+
const group = new LinksGroup(new Link('group'), [new LinksGroup(root), ...children.map(c => new LinksGroup(c))]);
|
|
49
|
+
|
|
50
|
+
expect(group.element.id).toBe('group');
|
|
51
|
+
expect(group.children.length).toBe(3);
|
|
52
|
+
expect(group.children[0].element).toBe(root);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('LinksGroup append to links list test', () => {
|
|
56
|
+
const element = new Link('root');
|
|
57
|
+
const children = [new Link('child1'), new Link('child2')];
|
|
58
|
+
const group = new LinksGroup(element, children);
|
|
59
|
+
|
|
60
|
+
const list = [];
|
|
61
|
+
group._appendToList(list);
|
|
62
|
+
|
|
63
|
+
expect(list.length).toBe(3);
|
|
64
|
+
expect(list[0]).toBe(element);
|
|
65
|
+
expect(list[1]).toBe(children[0]);
|
|
66
|
+
expect(list[2]).toBe(children[1]);
|
|
40
67
|
});
|
|
@@ -4,7 +4,7 @@ import { formatLinks } from "../src/Link.js";
|
|
|
4
4
|
|
|
5
5
|
const parser = new Parser();
|
|
6
6
|
|
|
7
|
-
test("Hero example
|
|
7
|
+
test("Hero example mixed modes", () => {
|
|
8
8
|
const input = `empInfo
|
|
9
9
|
employees:
|
|
10
10
|
(
|
|
@@ -31,7 +31,7 @@ test("Hero example - mixed modes - issue #105", () => {
|
|
|
31
31
|
expect(formatted).toContain("Wesley Crusher");
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
test("Hero example
|
|
34
|
+
test("Hero example alternative format", () => {
|
|
35
35
|
const input = `empInfo
|
|
36
36
|
(
|
|
37
37
|
employees:
|
|
@@ -60,7 +60,7 @@ test("Hero example - alternative format - issue #105", () => {
|
|
|
60
60
|
expect(formatted).toContain("Wesley Crusher");
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
-
test("Hero example
|
|
63
|
+
test("Hero example equivalence", () => {
|
|
64
64
|
const version1 = `empInfo
|
|
65
65
|
employees:
|
|
66
66
|
(
|
|
@@ -102,7 +102,7 @@ test("Hero example - equivalence test - issue #105", () => {
|
|
|
102
102
|
expect(formatted1).toBe(formatted2);
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
-
test("Set
|
|
105
|
+
test("Set context without colon", () => {
|
|
106
106
|
const input = `empInfo
|
|
107
107
|
employees`;
|
|
108
108
|
|
|
@@ -114,7 +114,7 @@ test("Set/object context without colon", () => {
|
|
|
114
114
|
expect(formatted).toContain("employees");
|
|
115
115
|
});
|
|
116
116
|
|
|
117
|
-
test("Sequence
|
|
117
|
+
test("Sequence context with colon", () => {
|
|
118
118
|
const input = `employees:
|
|
119
119
|
James Kirk
|
|
120
120
|
Jean-Luc Picard
|
|
@@ -4,7 +4,7 @@ import { formatLinks } from '../src/Link.js';
|
|
|
4
4
|
|
|
5
5
|
const parser = new Parser();
|
|
6
6
|
|
|
7
|
-
test('
|
|
7
|
+
test('Two links', () => {
|
|
8
8
|
const source = `(first: x y)
|
|
9
9
|
(second: a b)`;
|
|
10
10
|
const links = parser.parse(source);
|
|
@@ -12,7 +12,7 @@ test('TwoLinksTest', () => {
|
|
|
12
12
|
expect(target).toBe(source);
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
-
test('
|
|
15
|
+
test('Parse and stringify', () => {
|
|
16
16
|
const source = `(papa (lovesMama: loves mama))
|
|
17
17
|
(son lovesMama)
|
|
18
18
|
(daughter lovesMama)
|
|
@@ -22,7 +22,7 @@ test('ParseAndStringifyTest', () => {
|
|
|
22
22
|
expect(target).toBe(source);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
test('
|
|
25
|
+
test('Parse and stringify test 2', () => {
|
|
26
26
|
const source = `father (lovesMom: loves mom)
|
|
27
27
|
son lovesMom
|
|
28
28
|
daughter lovesMom
|
|
@@ -32,7 +32,7 @@ all (love mom)`;
|
|
|
32
32
|
expect(target).toBe(source);
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
test('
|
|
35
|
+
test('Parse and stringify with less parentheses', () => {
|
|
36
36
|
const source = `lovesMama: loves mama
|
|
37
37
|
papa lovesMama
|
|
38
38
|
son lovesMama
|
|
@@ -43,7 +43,7 @@ all (love mama)`;
|
|
|
43
43
|
expect(target).toBe(source);
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
-
test('
|
|
46
|
+
test('Duplicate identifiers', () => {
|
|
47
47
|
const source = `(a: a b)
|
|
48
48
|
(a: b c)`;
|
|
49
49
|
const target = `(a: a b)
|