links-notation 0.12.0 → 0.13.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/.eslintrc.json +28 -0
- package/.prettierignore +4 -0
- package/.prettierrc +4 -0
- package/README.md +52 -7
- package/README.ru.md +3 -6
- package/bun.lock +199 -0
- package/dist/index.js +391 -98
- package/package.json +6 -3
- package/src/FormatOptions.js +1 -1
- package/src/Link.js +71 -33
- package/src/LinksGroup.js +2 -2
- package/src/Parser.js +15 -15
- package/src/grammar.pegjs +105 -4
- package/src/index.js +1 -1
- package/src/parser-generated.js +401 -88
- package/tests/ApiTests.test.js +2 -2
- package/tests/EdgeCaseParser.test.js +3 -3
- package/tests/FormatConfig.test.js +32 -10
- package/tests/IndentedIdSyntax.test.js +39 -39
- package/tests/Link.test.js +2 -2
- package/tests/LinksGroup.test.js +8 -5
- package/tests/MixedIndentationModes.test.js +35 -35
- package/tests/MultiQuoteParser.test.js +463 -0
- package/tests/MultilineParser.test.js +12 -12
- package/tests/MultilineQuotedString.test.js +9 -9
- package/tests/NestedParser.test.js +5 -3
- package/tests/NestedSelfReference.test.js +4 -2
- package/tests/SingleLineParser.test.js +2 -2
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
import { test, expect } from 'bun:test';
|
|
2
|
+
import { Parser } from '../src/Parser.js';
|
|
3
|
+
|
|
4
|
+
const parser = new Parser();
|
|
5
|
+
|
|
6
|
+
// Helper to extract the reference ID from a single-value link
|
|
7
|
+
function getSingleRefId(result) {
|
|
8
|
+
// Single reference parses as: { id: null, values: [{ id: "the-id", values: [] }] }
|
|
9
|
+
if (
|
|
10
|
+
result.length === 1 &&
|
|
11
|
+
result[0].id === null &&
|
|
12
|
+
result[0].values.length === 1
|
|
13
|
+
) {
|
|
14
|
+
return result[0].values[0].id;
|
|
15
|
+
}
|
|
16
|
+
return result[0]?.id;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Backtick Quote Tests (Single Backtick)
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
test('TestBacktickQuotedReference', () => {
|
|
24
|
+
const input = '`backtick quoted`';
|
|
25
|
+
const result = parser.parse(input);
|
|
26
|
+
|
|
27
|
+
expect(result.length).toBe(1);
|
|
28
|
+
expect(getSingleRefId(result)).toBe('backtick quoted');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('TestBacktickQuotedWithSpaces', () => {
|
|
32
|
+
const input = '`text with spaces`';
|
|
33
|
+
const result = parser.parse(input);
|
|
34
|
+
|
|
35
|
+
expect(result.length).toBe(1);
|
|
36
|
+
expect(getSingleRefId(result)).toBe('text with spaces');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('TestBacktickQuotedMultiline', () => {
|
|
40
|
+
const input = '(`line1\nline2`)';
|
|
41
|
+
const result = parser.parse(input);
|
|
42
|
+
|
|
43
|
+
expect(result.length).toBe(1);
|
|
44
|
+
expect(result[0].values[0].id).toBe('line1\nline2');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('TestBacktickQuotedWithEscapedBacktick', () => {
|
|
48
|
+
const input = '`text with `` escaped backtick`';
|
|
49
|
+
const result = parser.parse(input);
|
|
50
|
+
|
|
51
|
+
expect(result.length).toBe(1);
|
|
52
|
+
expect(getSingleRefId(result)).toBe('text with ` escaped backtick');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// Single Quote Tests (with escaping)
|
|
57
|
+
// ============================================================================
|
|
58
|
+
|
|
59
|
+
test('TestSingleQuoteWithEscapedSingleQuote', () => {
|
|
60
|
+
const input = "'text with '' escaped quote'";
|
|
61
|
+
const result = parser.parse(input);
|
|
62
|
+
|
|
63
|
+
expect(result.length).toBe(1);
|
|
64
|
+
expect(getSingleRefId(result)).toBe("text with ' escaped quote");
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// ============================================================================
|
|
68
|
+
// Double Quote Tests (with escaping)
|
|
69
|
+
// ============================================================================
|
|
70
|
+
|
|
71
|
+
test('TestDoubleQuoteWithEscapedDoubleQuote', () => {
|
|
72
|
+
const input = '"text with "" escaped quote"';
|
|
73
|
+
const result = parser.parse(input);
|
|
74
|
+
|
|
75
|
+
expect(result.length).toBe(1);
|
|
76
|
+
expect(getSingleRefId(result)).toBe('text with " escaped quote');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// ============================================================================
|
|
80
|
+
// Double Quotes (2 quote chars) Tests
|
|
81
|
+
// ============================================================================
|
|
82
|
+
|
|
83
|
+
test('TestDoubleDoubleQuotes', () => {
|
|
84
|
+
const input = '""double double quotes""';
|
|
85
|
+
const result = parser.parse(input);
|
|
86
|
+
|
|
87
|
+
expect(result.length).toBe(1);
|
|
88
|
+
expect(getSingleRefId(result)).toBe('double double quotes');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('TestDoubleDoubleQuotesWithSingleQuoteInside', () => {
|
|
92
|
+
const input = '""text with " inside""';
|
|
93
|
+
const result = parser.parse(input);
|
|
94
|
+
|
|
95
|
+
expect(result.length).toBe(1);
|
|
96
|
+
expect(getSingleRefId(result)).toBe('text with " inside');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('TestDoubleDoubleQuotesWithEscape', () => {
|
|
100
|
+
const input = '""text with """" escaped double""';
|
|
101
|
+
const result = parser.parse(input);
|
|
102
|
+
|
|
103
|
+
expect(result.length).toBe(1);
|
|
104
|
+
expect(getSingleRefId(result)).toBe('text with "" escaped double');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('TestDoubleSingleQuotes', () => {
|
|
108
|
+
const input = "''double single quotes''";
|
|
109
|
+
const result = parser.parse(input);
|
|
110
|
+
|
|
111
|
+
expect(result.length).toBe(1);
|
|
112
|
+
expect(getSingleRefId(result)).toBe('double single quotes');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('TestDoubleSingleQuotesWithSingleQuoteInside', () => {
|
|
116
|
+
const input = "''text with ' inside''";
|
|
117
|
+
const result = parser.parse(input);
|
|
118
|
+
|
|
119
|
+
expect(result.length).toBe(1);
|
|
120
|
+
expect(getSingleRefId(result)).toBe("text with ' inside");
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test('TestDoubleSingleQuotesWithEscape', () => {
|
|
124
|
+
const input = "''text with '''' escaped single''";
|
|
125
|
+
const result = parser.parse(input);
|
|
126
|
+
|
|
127
|
+
expect(result.length).toBe(1);
|
|
128
|
+
expect(getSingleRefId(result)).toBe("text with '' escaped single");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test('TestDoubleBacktickQuotes', () => {
|
|
132
|
+
const input = '``double backtick quotes``';
|
|
133
|
+
const result = parser.parse(input);
|
|
134
|
+
|
|
135
|
+
expect(result.length).toBe(1);
|
|
136
|
+
expect(getSingleRefId(result)).toBe('double backtick quotes');
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test('TestDoubleBacktickQuotesWithBacktickInside', () => {
|
|
140
|
+
const input = '``text with ` inside``';
|
|
141
|
+
const result = parser.parse(input);
|
|
142
|
+
|
|
143
|
+
expect(result.length).toBe(1);
|
|
144
|
+
expect(getSingleRefId(result)).toBe('text with ` inside');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test('TestDoubleBacktickQuotesWithEscape', () => {
|
|
148
|
+
const input = '``text with ```` escaped backtick``';
|
|
149
|
+
const result = parser.parse(input);
|
|
150
|
+
|
|
151
|
+
expect(result.length).toBe(1);
|
|
152
|
+
expect(getSingleRefId(result)).toBe('text with `` escaped backtick');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// ============================================================================
|
|
156
|
+
// Triple Quotes (3 quote chars) Tests
|
|
157
|
+
// ============================================================================
|
|
158
|
+
|
|
159
|
+
test('TestTripleDoubleQuotes', () => {
|
|
160
|
+
const input = '"""triple double quotes"""';
|
|
161
|
+
const result = parser.parse(input);
|
|
162
|
+
|
|
163
|
+
expect(result.length).toBe(1);
|
|
164
|
+
expect(getSingleRefId(result)).toBe('triple double quotes');
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('TestTripleDoubleQuotesWithDoubleQuoteInside', () => {
|
|
168
|
+
const input = '"""text with "" inside"""';
|
|
169
|
+
const result = parser.parse(input);
|
|
170
|
+
|
|
171
|
+
expect(result.length).toBe(1);
|
|
172
|
+
expect(getSingleRefId(result)).toBe('text with "" inside');
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test('TestTripleDoubleQuotesWithEscape', () => {
|
|
176
|
+
const input = '"""text with """""" escaped triple"""';
|
|
177
|
+
const result = parser.parse(input);
|
|
178
|
+
|
|
179
|
+
expect(result.length).toBe(1);
|
|
180
|
+
expect(getSingleRefId(result)).toBe('text with """ escaped triple');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
test('TestTripleSingleQuotes', () => {
|
|
184
|
+
const input = "'''triple single quotes'''";
|
|
185
|
+
const result = parser.parse(input);
|
|
186
|
+
|
|
187
|
+
expect(result.length).toBe(1);
|
|
188
|
+
expect(getSingleRefId(result)).toBe('triple single quotes');
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test('TestTripleSingleQuotesWithDoubleQuoteInside', () => {
|
|
192
|
+
const input = "'''text with '' inside'''";
|
|
193
|
+
const result = parser.parse(input);
|
|
194
|
+
|
|
195
|
+
expect(result.length).toBe(1);
|
|
196
|
+
expect(getSingleRefId(result)).toBe("text with '' inside");
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test('TestTripleSingleQuotesWithEscape', () => {
|
|
200
|
+
const input = "'''text with '''''' escaped triple'''";
|
|
201
|
+
const result = parser.parse(input);
|
|
202
|
+
|
|
203
|
+
expect(result.length).toBe(1);
|
|
204
|
+
expect(getSingleRefId(result)).toBe("text with ''' escaped triple");
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test('TestTripleBacktickQuotes', () => {
|
|
208
|
+
const input = '```triple backtick quotes```';
|
|
209
|
+
const result = parser.parse(input);
|
|
210
|
+
|
|
211
|
+
expect(result.length).toBe(1);
|
|
212
|
+
expect(getSingleRefId(result)).toBe('triple backtick quotes');
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test('TestTripleBacktickQuotesWithDoubleBacktickInside', () => {
|
|
216
|
+
const input = '```text with `` inside```';
|
|
217
|
+
const result = parser.parse(input);
|
|
218
|
+
|
|
219
|
+
expect(result.length).toBe(1);
|
|
220
|
+
expect(getSingleRefId(result)).toBe('text with `` inside');
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test('TestTripleBacktickQuotesWithEscape', () => {
|
|
224
|
+
const input = '```text with `````` escaped triple```';
|
|
225
|
+
const result = parser.parse(input);
|
|
226
|
+
|
|
227
|
+
expect(result.length).toBe(1);
|
|
228
|
+
expect(getSingleRefId(result)).toBe('text with ``` escaped triple');
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// ============================================================================
|
|
232
|
+
// Quadruple Quotes (4 quote chars) Tests
|
|
233
|
+
// ============================================================================
|
|
234
|
+
|
|
235
|
+
test('TestQuadrupleDoubleQuotes', () => {
|
|
236
|
+
const input = '""""quadruple double quotes""""';
|
|
237
|
+
const result = parser.parse(input);
|
|
238
|
+
|
|
239
|
+
expect(result.length).toBe(1);
|
|
240
|
+
expect(getSingleRefId(result)).toBe('quadruple double quotes');
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test('TestQuadrupleDoubleQuotesWithTripleQuoteInside', () => {
|
|
244
|
+
const input = '""""text with """ inside""""';
|
|
245
|
+
const result = parser.parse(input);
|
|
246
|
+
|
|
247
|
+
expect(result.length).toBe(1);
|
|
248
|
+
expect(getSingleRefId(result)).toBe('text with """ inside');
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
test('TestQuadrupleDoubleQuotesWithEscape', () => {
|
|
252
|
+
const input = '""""text with """""""" escaped quad""""';
|
|
253
|
+
const result = parser.parse(input);
|
|
254
|
+
|
|
255
|
+
expect(result.length).toBe(1);
|
|
256
|
+
expect(getSingleRefId(result)).toBe('text with """" escaped quad');
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test('TestQuadrupleSingleQuotes', () => {
|
|
260
|
+
const input = "''''quadruple single quotes''''";
|
|
261
|
+
const result = parser.parse(input);
|
|
262
|
+
|
|
263
|
+
expect(result.length).toBe(1);
|
|
264
|
+
expect(getSingleRefId(result)).toBe('quadruple single quotes');
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
test('TestQuadrupleBacktickQuotes', () => {
|
|
268
|
+
const input = '````quadruple backtick quotes````';
|
|
269
|
+
const result = parser.parse(input);
|
|
270
|
+
|
|
271
|
+
expect(result.length).toBe(1);
|
|
272
|
+
expect(getSingleRefId(result)).toBe('quadruple backtick quotes');
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// ============================================================================
|
|
276
|
+
// Quintuple Quotes (5 quote chars) Tests
|
|
277
|
+
// ============================================================================
|
|
278
|
+
|
|
279
|
+
test('TestQuintupleDoubleQuotes', () => {
|
|
280
|
+
const input = '"""""quintuple double quotes"""""';
|
|
281
|
+
const result = parser.parse(input);
|
|
282
|
+
|
|
283
|
+
expect(result.length).toBe(1);
|
|
284
|
+
expect(getSingleRefId(result)).toBe('quintuple double quotes');
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
test('TestQuintupleDoubleQuotesWithQuadQuoteInside', () => {
|
|
288
|
+
const input = '"""""text with """" inside"""""';
|
|
289
|
+
const result = parser.parse(input);
|
|
290
|
+
|
|
291
|
+
expect(result.length).toBe(1);
|
|
292
|
+
expect(getSingleRefId(result)).toBe('text with """" inside');
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test('TestQuintupleDoubleQuotesWithEscape', () => {
|
|
296
|
+
const input = '"""""text with """""""""" escaped quint"""""';
|
|
297
|
+
const result = parser.parse(input);
|
|
298
|
+
|
|
299
|
+
expect(result.length).toBe(1);
|
|
300
|
+
expect(getSingleRefId(result)).toBe('text with """"" escaped quint');
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
test('TestQuintupleSingleQuotes', () => {
|
|
304
|
+
const input = "'''''quintuple single quotes'''''";
|
|
305
|
+
const result = parser.parse(input);
|
|
306
|
+
|
|
307
|
+
expect(result.length).toBe(1);
|
|
308
|
+
expect(getSingleRefId(result)).toBe('quintuple single quotes');
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test('TestQuintupleBacktickQuotes', () => {
|
|
312
|
+
const input = '`````quintuple backtick quotes`````';
|
|
313
|
+
const result = parser.parse(input);
|
|
314
|
+
|
|
315
|
+
expect(result.length).toBe(1);
|
|
316
|
+
expect(getSingleRefId(result)).toBe('quintuple backtick quotes');
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// ============================================================================
|
|
320
|
+
// Complex Scenarios Tests
|
|
321
|
+
// ============================================================================
|
|
322
|
+
|
|
323
|
+
test('TestMixedQuotesInLink', () => {
|
|
324
|
+
const input = '("double" \'single\' `backtick`)';
|
|
325
|
+
const result = parser.parse(input);
|
|
326
|
+
|
|
327
|
+
expect(result.length).toBe(1);
|
|
328
|
+
expect(result[0].values.length).toBe(3);
|
|
329
|
+
expect(result[0].values[0].id).toBe('double');
|
|
330
|
+
expect(result[0].values[1].id).toBe('single');
|
|
331
|
+
expect(result[0].values[2].id).toBe('backtick');
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
test('TestBacktickAsIdInLink', () => {
|
|
335
|
+
const input = '(`myId`: value1 value2)';
|
|
336
|
+
const result = parser.parse(input);
|
|
337
|
+
|
|
338
|
+
expect(result.length).toBe(1);
|
|
339
|
+
expect(result[0].id).toBe('myId');
|
|
340
|
+
expect(result[0].values.length).toBe(2);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
test('TestCodeBlockLikeContent', () => {
|
|
344
|
+
// This demonstrates using triple backticks for code-like content
|
|
345
|
+
const input = '```const x = 1;```';
|
|
346
|
+
const result = parser.parse(input);
|
|
347
|
+
|
|
348
|
+
expect(result.length).toBe(1);
|
|
349
|
+
expect(getSingleRefId(result)).toBe('const x = 1;');
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
test('TestNestedQuotesInMarkdown', () => {
|
|
353
|
+
// Using double backticks to include single backtick
|
|
354
|
+
const input = '``Use `code` in markdown``';
|
|
355
|
+
const result = parser.parse(input);
|
|
356
|
+
|
|
357
|
+
expect(result.length).toBe(1);
|
|
358
|
+
expect(getSingleRefId(result)).toBe('Use `code` in markdown');
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
test('TestSQLWithQuotes', () => {
|
|
362
|
+
// Using double single quotes to include single quote in SQL-like string
|
|
363
|
+
// Inside '', to get a single quote, we need '''' (4 single quotes = escaped pair)
|
|
364
|
+
const input = "''SELECT * FROM users WHERE name = ''''John''''''";
|
|
365
|
+
const result = parser.parse(input);
|
|
366
|
+
|
|
367
|
+
expect(result.length).toBe(1);
|
|
368
|
+
expect(getSingleRefId(result)).toBe(
|
|
369
|
+
"SELECT * FROM users WHERE name = ''John''"
|
|
370
|
+
);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
test('TestJSONStringWithQuotes', () => {
|
|
374
|
+
// Using double double quotes to include double quote in JSON-like string
|
|
375
|
+
const input = '""{"key": "value"}""';
|
|
376
|
+
const result = parser.parse(input);
|
|
377
|
+
|
|
378
|
+
expect(result.length).toBe(1);
|
|
379
|
+
expect(getSingleRefId(result)).toBe('{"key": "value"}');
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
// ============================================================================
|
|
383
|
+
// Edge Cases
|
|
384
|
+
// ============================================================================
|
|
385
|
+
|
|
386
|
+
test('TestEmptySingleQuotedReference', () => {
|
|
387
|
+
const input = "''";
|
|
388
|
+
// Empty quoted reference should not match - becomes simple reference or fails
|
|
389
|
+
// Let's verify what happens
|
|
390
|
+
try {
|
|
391
|
+
const result = parser.parse(input);
|
|
392
|
+
// If it parses, check what we get
|
|
393
|
+
expect(result.length).toBeGreaterThanOrEqual(0);
|
|
394
|
+
} catch (e) {
|
|
395
|
+
// Expected for empty quotes
|
|
396
|
+
expect(e).toBeTruthy();
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
test('TestWhitespacePreservedInQuotes', () => {
|
|
401
|
+
const input = '" spaces "';
|
|
402
|
+
const result = parser.parse(input);
|
|
403
|
+
|
|
404
|
+
expect(result.length).toBe(1);
|
|
405
|
+
expect(getSingleRefId(result)).toBe(' spaces ');
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
test('TestMultilineInDoubleDoubleQuotes', () => {
|
|
409
|
+
const input = '(""line1\nline2"")';
|
|
410
|
+
const result = parser.parse(input);
|
|
411
|
+
|
|
412
|
+
expect(result.length).toBe(1);
|
|
413
|
+
expect(result[0].values[0].id).toBe('line1\nline2');
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
// ============================================================================
|
|
417
|
+
// Unlimited Quotes (6+ quote chars) Tests
|
|
418
|
+
// ============================================================================
|
|
419
|
+
|
|
420
|
+
test('TestUnlimitedQuotes6', () => {
|
|
421
|
+
// Test 6-quote strings
|
|
422
|
+
const input = '""""""hello""""""';
|
|
423
|
+
const result = parser.parse(input);
|
|
424
|
+
|
|
425
|
+
expect(result.length).toBe(1);
|
|
426
|
+
expect(getSingleRefId(result)).toBe('hello');
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
test('TestUnlimitedQuotes10', () => {
|
|
430
|
+
// Test 10-quote strings
|
|
431
|
+
const input = '""""""""""very deeply quoted""""""""""';
|
|
432
|
+
const result = parser.parse(input);
|
|
433
|
+
|
|
434
|
+
expect(result.length).toBe(1);
|
|
435
|
+
expect(getSingleRefId(result)).toBe('very deeply quoted');
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
test('TestUnlimitedQuotes6WithInnerQuotes', () => {
|
|
439
|
+
// Test 6-quote strings with inner 5-quote sequences
|
|
440
|
+
const input = '""""""hello with """"" five quotes inside""""""';
|
|
441
|
+
const result = parser.parse(input);
|
|
442
|
+
|
|
443
|
+
expect(result.length).toBe(1);
|
|
444
|
+
expect(getSingleRefId(result)).toBe('hello with """"" five quotes inside');
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
test('TestUnlimitedSingleQuotes7', () => {
|
|
448
|
+
// Test 7-quote single quote strings
|
|
449
|
+
const input = "'''''''seven single quotes'''''''";
|
|
450
|
+
const result = parser.parse(input);
|
|
451
|
+
|
|
452
|
+
expect(result.length).toBe(1);
|
|
453
|
+
expect(getSingleRefId(result)).toBe('seven single quotes');
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
test('TestUnlimitedBackticks8', () => {
|
|
457
|
+
// Test 8-quote backtick strings
|
|
458
|
+
const input = '````````eight backticks````````';
|
|
459
|
+
const result = parser.parse(input);
|
|
460
|
+
|
|
461
|
+
expect(result.length).toBe(1);
|
|
462
|
+
expect(getSingleRefId(result)).toBe('eight backticks');
|
|
463
|
+
});
|
|
@@ -61,7 +61,7 @@ test('Test complex structure', () => {
|
|
|
61
61
|
Value
|
|
62
62
|
(property: name type)
|
|
63
63
|
(method: name params return)`;
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
const result = parser.parse(input);
|
|
66
66
|
expect(result.length).toBeGreaterThan(0);
|
|
67
67
|
});
|
|
@@ -75,44 +75,44 @@ simple_ref
|
|
|
75
75
|
nested1
|
|
76
76
|
nested2
|
|
77
77
|
)`;
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
const result = parser.parse(input);
|
|
80
80
|
expect(result.length).toBeGreaterThan(0);
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
test('Test multiline with id', () => {
|
|
84
84
|
// Test multi-line link with id
|
|
85
|
-
const input =
|
|
85
|
+
const input = '(id: value1 value2)';
|
|
86
86
|
const result = parser.parse(input);
|
|
87
87
|
expect(result.length).toBeGreaterThan(0);
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
test('Test multiple top level elements', () => {
|
|
91
91
|
// Test multiple top-level elements
|
|
92
|
-
const input =
|
|
92
|
+
const input = '(elem1: val1)\n(elem2: val2)';
|
|
93
93
|
const result = parser.parse(input);
|
|
94
94
|
expect(result.length).toBeGreaterThan(0);
|
|
95
95
|
});
|
|
96
96
|
|
|
97
97
|
test('Test multiline simple links', () => {
|
|
98
|
-
const input =
|
|
98
|
+
const input = '(1: 1 1)\n(2: 2 2)';
|
|
99
99
|
const parsed = parser.parse(input);
|
|
100
100
|
expect(parsed.length).toBeGreaterThan(0);
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
// Validate regular formatting
|
|
103
103
|
const output = formatLinks(parsed);
|
|
104
|
-
expect(output).toContain(
|
|
105
|
-
expect(output).toContain(
|
|
106
|
-
|
|
104
|
+
expect(output).toContain('(1: 1 1)');
|
|
105
|
+
expect(output).toContain('(2: 2 2)');
|
|
106
|
+
|
|
107
107
|
// Validate alternate formatting matches input
|
|
108
108
|
const outputAlternate = formatLinks(parsed);
|
|
109
109
|
expect(outputAlternate).toBe(input);
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
test('Test indented children', () => {
|
|
113
|
-
const input =
|
|
113
|
+
const input = 'parent\n child1\n child2';
|
|
114
114
|
const parsed = parser.parse(input);
|
|
115
|
-
|
|
115
|
+
|
|
116
116
|
// The parsed structure should have parent with children
|
|
117
117
|
expect(parsed.length).toBeGreaterThan(0);
|
|
118
|
-
});
|
|
118
|
+
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { test, expect } from
|
|
2
|
-
import { Parser } from
|
|
1
|
+
import { test, expect } from 'bun:test';
|
|
2
|
+
import { Parser } from '../src/Parser.js';
|
|
3
3
|
|
|
4
4
|
const parser = new Parser();
|
|
5
5
|
|
|
6
|
-
test(
|
|
6
|
+
test('TestMultilineDoubleQuotedReference', () => {
|
|
7
7
|
const input = `(
|
|
8
8
|
"long
|
|
9
9
|
string literal representing
|
|
@@ -32,7 +32,7 @@ long string literal
|
|
|
32
32
|
as another reference`);
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
test(
|
|
35
|
+
test('TestSimpleMultilineDoubleQuoted', () => {
|
|
36
36
|
const input = `("line1
|
|
37
37
|
line2")`;
|
|
38
38
|
const result = parser.parse(input);
|
|
@@ -44,10 +44,10 @@ line2")`;
|
|
|
44
44
|
expect(link.id).toBe(null);
|
|
45
45
|
expect(link.values).toBeTruthy();
|
|
46
46
|
expect(link.values.length).toBe(1);
|
|
47
|
-
expect(link.values[0].id).toBe(
|
|
47
|
+
expect(link.values[0].id).toBe('line1\nline2');
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
test(
|
|
50
|
+
test('TestSimpleMultilineSingleQuoted', () => {
|
|
51
51
|
const input = `('line1
|
|
52
52
|
line2')`;
|
|
53
53
|
const result = parser.parse(input);
|
|
@@ -59,10 +59,10 @@ line2')`;
|
|
|
59
59
|
expect(link.id).toBe(null);
|
|
60
60
|
expect(link.values).toBeTruthy();
|
|
61
61
|
expect(link.values.length).toBe(1);
|
|
62
|
-
expect(link.values[0].id).toBe(
|
|
62
|
+
expect(link.values[0].id).toBe('line1\nline2');
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
-
test(
|
|
65
|
+
test('TestMultilineQuotedAsId', () => {
|
|
66
66
|
const input = `("multi
|
|
67
67
|
line
|
|
68
68
|
id": value1 value2)`;
|
|
@@ -72,7 +72,7 @@ id": value1 value2)`;
|
|
|
72
72
|
expect(result.length).toBe(1);
|
|
73
73
|
|
|
74
74
|
const link = result[0];
|
|
75
|
-
expect(link.id).toBe(
|
|
75
|
+
expect(link.id).toBe('multi\nline\nid');
|
|
76
76
|
expect(link.values).toBeTruthy();
|
|
77
77
|
expect(link.values.length).toBe(2);
|
|
78
78
|
});
|
|
@@ -143,7 +143,7 @@ test('Nested links', () => {
|
|
|
143
143
|
// Validate regular formatting
|
|
144
144
|
const output = formatLinks(parsed);
|
|
145
145
|
expect(output).toBeTruthy();
|
|
146
|
-
|
|
146
|
+
|
|
147
147
|
// Validate that the structure is properly nested
|
|
148
148
|
expect(parsed.length).toBe(1);
|
|
149
149
|
});
|
|
@@ -153,7 +153,9 @@ test('Indentation parser', () => {
|
|
|
153
153
|
const result = parser.parse(input);
|
|
154
154
|
expect(result.length).toBeGreaterThan(0);
|
|
155
155
|
// Should have parent link
|
|
156
|
-
const hasParentLink = result.some(
|
|
156
|
+
const hasParentLink = result.some(
|
|
157
|
+
(l) => l.values && l.values.some((v) => v.id === 'parent')
|
|
158
|
+
);
|
|
157
159
|
expect(hasParentLink).toBe(true);
|
|
158
160
|
});
|
|
159
161
|
|
|
@@ -190,4 +192,4 @@ test('Multiple nested links roundtrip', () => {
|
|
|
190
192
|
// Validate round-trip
|
|
191
193
|
const output = formatLinks(parsed);
|
|
192
194
|
expect(output).toBe(input);
|
|
193
|
-
});
|
|
195
|
+
});
|
|
@@ -5,7 +5,8 @@ test('Nested self-referenced object in pair value', () => {
|
|
|
5
5
|
// Test case from PARSER_BUG.md
|
|
6
6
|
// This should parse a dict with two pairs, where the second pair's value
|
|
7
7
|
// is itself a self-referenced dict definition (obj_1: dict ...)
|
|
8
|
-
const notation =
|
|
8
|
+
const notation =
|
|
9
|
+
'(obj_0: dict ((str bmFtZQ==) (str ZGljdDE=)) ((str b3RoZXI=) (obj_1: dict ((str bmFtZQ==) (str ZGljdDI=)) ((str b3RoZXI=) obj_0))))';
|
|
9
10
|
|
|
10
11
|
const parser = new Parser();
|
|
11
12
|
const links = parser.parse(notation);
|
|
@@ -85,7 +86,8 @@ test('Nested self-referenced object in pair value', () => {
|
|
|
85
86
|
|
|
86
87
|
test('Self-reference as direct child works correctly', () => {
|
|
87
88
|
// This pattern should work (and did work before)
|
|
88
|
-
const notation =
|
|
89
|
+
const notation =
|
|
90
|
+
'(obj_0: list (int 1) (int 2) (obj_1: list (int 3) (int 4) obj_0))';
|
|
89
91
|
|
|
90
92
|
const parser = new Parser();
|
|
91
93
|
const links = parser.parse(notation);
|
|
@@ -161,7 +161,7 @@ test('Test special characters in quotes', () => {
|
|
|
161
161
|
let input = '("key:with:colons": "value(with)parens")';
|
|
162
162
|
let result = parser.parse(input);
|
|
163
163
|
expect(result.length).toBeGreaterThan(0);
|
|
164
|
-
|
|
164
|
+
|
|
165
165
|
input = "('key with spaces': 'value: with special chars')";
|
|
166
166
|
result = parser.parse(input);
|
|
167
167
|
expect(result.length).toBeGreaterThan(0);
|
|
@@ -306,4 +306,4 @@ test('Single line with id', () => {
|
|
|
306
306
|
const result = parser.parse(input);
|
|
307
307
|
expect(result.length).toBeGreaterThan(0);
|
|
308
308
|
expect(result[0].id).toBe('myid');
|
|
309
|
-
});
|
|
309
|
+
});
|