links-notation 0.13.0 → 0.16.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/README.md +55 -0
- package/bun.lock +74 -94
- package/dist/index.js +238 -166
- package/eslint.config.js +34 -0
- package/examples/empty_reference.js +43 -0
- package/examples/typescript-example.ts +95 -0
- package/index.d.ts +312 -0
- package/package.json +19 -7
- package/src/Link.js +7 -1
- package/src/Parser.js +36 -3
- package/src/grammar.pegjs +86 -12
- package/src/parser-generated.js +221 -147
- package/tests/EmptyReference.test.js +91 -0
- package/tests/Link.test.js +2 -2
- package/tests/MultilineQuotedString.test.js +4 -2
- package/tests/NestedIndentation.test.js +114 -0
- package/tests/SingleLineParser.test.js +7 -7
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,114 @@
|
|
|
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
|
+
const format = (source) => formatLinks(parser.parse(source), false);
|
|
8
|
+
|
|
9
|
+
// https://github.com/link-foundation/links-notation/issues/282
|
|
10
|
+
// Indentation is structural at the root, so it must be structural inside
|
|
11
|
+
// parentheses too: a parenthesised group opens a nested context that starts
|
|
12
|
+
// fresh at indentation level zero and follows exactly the root's rules.
|
|
13
|
+
|
|
14
|
+
test('TestParenthesesReproduceRootIndentation', () => {
|
|
15
|
+
const root = format(`a
|
|
16
|
+
b
|
|
17
|
+
c
|
|
18
|
+
d`);
|
|
19
|
+
|
|
20
|
+
expect(root).toBe(`(a)
|
|
21
|
+
((a) (b))
|
|
22
|
+
(c)
|
|
23
|
+
((c) (d))`);
|
|
24
|
+
|
|
25
|
+
// The same lines inside parentheses keep the same structure, nested under the
|
|
26
|
+
// link the group belongs to.
|
|
27
|
+
const nested = format(`array (
|
|
28
|
+
a
|
|
29
|
+
b
|
|
30
|
+
c
|
|
31
|
+
d
|
|
32
|
+
)`);
|
|
33
|
+
|
|
34
|
+
expect(nested).toBe('(array ((a) ((a) (b)) (c) ((c) (d))))');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('TestParenthesesKeepRecordBoundaries', () => {
|
|
38
|
+
expect(
|
|
39
|
+
format(`value (
|
|
40
|
+
id "1"
|
|
41
|
+
label "one"
|
|
42
|
+
)`)
|
|
43
|
+
).toBe('(value ((id 1) (label one)))');
|
|
44
|
+
|
|
45
|
+
const links = parser.parse(`value (
|
|
46
|
+
id "1"
|
|
47
|
+
label "one"
|
|
48
|
+
)`);
|
|
49
|
+
expect(links.length).toBe(1);
|
|
50
|
+
|
|
51
|
+
const group = links[0].values[1];
|
|
52
|
+
expect(group.id).toBe(null);
|
|
53
|
+
expect(group.values.length).toBe(2);
|
|
54
|
+
expect(group.values[0].values[0].id).toBe('id');
|
|
55
|
+
expect(group.values[0].values[1].id).toBe('1');
|
|
56
|
+
expect(group.values[1].values[0].id).toBe('label');
|
|
57
|
+
expect(group.values[1].values[1].id).toBe('one');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('TestParenthesesKeepSeveralRecordsSeparate', () => {
|
|
61
|
+
expect(
|
|
62
|
+
format(`value (
|
|
63
|
+
(id "1" label "one")
|
|
64
|
+
(id "2" label "two")
|
|
65
|
+
)`)
|
|
66
|
+
).toBe('(value ((id 1 label one) (id 2 label two)))');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('TestParenthesesNestDeeply', () => {
|
|
70
|
+
expect(
|
|
71
|
+
format(`outer (
|
|
72
|
+
inner (
|
|
73
|
+
x 1
|
|
74
|
+
y 2
|
|
75
|
+
)
|
|
76
|
+
z 3
|
|
77
|
+
)`)
|
|
78
|
+
).toBe('(outer ((inner ((x 1) (y 2))) (z 3)))');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('TestSingleLineParenthesesAreUnchanged', () => {
|
|
82
|
+
expect(format('(a b c)')).toBe('(a b c)');
|
|
83
|
+
expect(format('(1: 2 3)')).toBe('(1: 2 3)');
|
|
84
|
+
expect(format('(a: b c)')).toBe('(a: b c)');
|
|
85
|
+
expect(format('((a b))')).toBe('((a b))');
|
|
86
|
+
expect(format('(a)')).toBe('(a)');
|
|
87
|
+
expect(format('()')).toBe('()');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('TestParenthesesWithIndentedIdSyntax', () => {
|
|
91
|
+
expect(
|
|
92
|
+
format(`(
|
|
93
|
+
a:
|
|
94
|
+
b
|
|
95
|
+
c
|
|
96
|
+
)`)
|
|
97
|
+
).toBe('(a: b c)');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('TestEmployeeRecordsKeepTheirFields', () => {
|
|
101
|
+
expect(
|
|
102
|
+
format(`empInfo
|
|
103
|
+
employees:
|
|
104
|
+
(
|
|
105
|
+
name (James Kirk)
|
|
106
|
+
age 40
|
|
107
|
+
)
|
|
108
|
+
(
|
|
109
|
+
name (Jean-Luc Picard)
|
|
110
|
+
age 45
|
|
111
|
+
)`)
|
|
112
|
+
).toBe(`(empInfo)
|
|
113
|
+
((empInfo) (employees: ((name (James Kirk)) (age 40)) ((name (Jean-Luc Picard)) (age 45))))`);
|
|
114
|
+
});
|
|
@@ -26,16 +26,16 @@ test('Bug test 1', () => {
|
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
test('Quoted references', () => {
|
|
29
|
-
const source =
|
|
30
|
-
const target =
|
|
29
|
+
const source = '(a: \'b\' "c")';
|
|
30
|
+
const target = '(a: b c)';
|
|
31
31
|
const links = parser.parse(source);
|
|
32
32
|
const formattedLinks = formatLinks(links);
|
|
33
33
|
expect(formattedLinks).toBe(target);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
test('Quoted references with spaces', () => {
|
|
37
|
-
const source =
|
|
38
|
-
const target =
|
|
37
|
+
const source = "('a a': 'b b' \"c c\")";
|
|
38
|
+
const target = "('a a': 'b b' 'c c')";
|
|
39
39
|
const links = parser.parse(source);
|
|
40
40
|
const formattedLinks = formatLinks(links);
|
|
41
41
|
expect(formattedLinks).toBe(target);
|
|
@@ -70,7 +70,7 @@ test('Parse multiline link', () => {
|
|
|
70
70
|
});
|
|
71
71
|
|
|
72
72
|
test('Parse quoted references', () => {
|
|
73
|
-
const input =
|
|
73
|
+
const input = '"has space" \'has:colon\'';
|
|
74
74
|
const result = parser.parse(input);
|
|
75
75
|
expect(result.length).toBe(1);
|
|
76
76
|
expect(result[0].id).toBe(null);
|
|
@@ -78,7 +78,7 @@ test('Parse quoted references', () => {
|
|
|
78
78
|
expect(result[0].values[0].id).toBe('has space');
|
|
79
79
|
expect(result[0].values[1].id).toBe('has:colon');
|
|
80
80
|
// Ensure formatting matches C# expectation
|
|
81
|
-
expect(formatLinks(result)).toBe(
|
|
81
|
+
expect(formatLinks(result)).toBe("('has space' 'has:colon')");
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
test('Parse values only', () => {
|
|
@@ -128,7 +128,7 @@ test('Test value link', () => {
|
|
|
128
128
|
});
|
|
129
129
|
|
|
130
130
|
test('Parse quoted references values only', () => {
|
|
131
|
-
const source =
|
|
131
|
+
const source = '"has space" \'has:colon\'';
|
|
132
132
|
const parser = new Parser();
|
|
133
133
|
const links = parser.parse(source);
|
|
134
134
|
expect(links).toBeTruthy();
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ES2020",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"allowJs": true,
|
|
7
|
+
"checkJs": false,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"strict": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"resolveJsonModule": true
|
|
13
|
+
},
|
|
14
|
+
"include": ["examples/**/*.ts"]
|
|
15
|
+
}
|