links-notation 0.30.0 → 0.30.1
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/dist/index.js +8 -5
- package/package.json +1 -1
- package/src/Link.js +18 -5
- package/tests/SharedTextParity.test.js +53 -1
package/dist/index.js
CHANGED
|
@@ -348,7 +348,7 @@ class Link {
|
|
|
348
348
|
return this._formatWithOptions(lessParentheses, isCompoundValue);
|
|
349
349
|
}
|
|
350
350
|
if (this.id === null && (!this.values || this.values.length === 0)) {
|
|
351
|
-
return
|
|
351
|
+
return "()";
|
|
352
352
|
}
|
|
353
353
|
if (!this.values || this.values.length === 0) {
|
|
354
354
|
const escapedId = Link.escapeReference(this.id);
|
|
@@ -359,7 +359,7 @@ class Link {
|
|
|
359
359
|
}
|
|
360
360
|
const valuesStr = this.values.map((v) => this.formatValue(v)).join(" ");
|
|
361
361
|
if (this.id === null) {
|
|
362
|
-
if (lessParentheses) {
|
|
362
|
+
if (lessParentheses && !this._hasLoneNestedValue()) {
|
|
363
363
|
const allSimple = this.values.every((v) => !v.values || v.values.length === 0);
|
|
364
364
|
if (allSimple) {
|
|
365
365
|
const simpleValuesStr = this.values.map((v) => Link.escapeReference(v.id)).join(" ");
|
|
@@ -389,9 +389,12 @@ class Link {
|
|
|
389
389
|
needsParentheses(str) {
|
|
390
390
|
return str && (str.includes(" ") || str.includes(":") || str.includes("(") || str.includes(")"));
|
|
391
391
|
}
|
|
392
|
+
_hasLoneNestedValue() {
|
|
393
|
+
return this.values.length === 1 && this.values[0].values?.length > 0;
|
|
394
|
+
}
|
|
392
395
|
_formatWithOptions(options, isCompoundValue = false) {
|
|
393
396
|
if (this.id === null && (!this.values || this.values.length === 0)) {
|
|
394
|
-
return
|
|
397
|
+
return "()";
|
|
395
398
|
}
|
|
396
399
|
if (!this.values || this.values.length === 0) {
|
|
397
400
|
const escapedId = Link.escapeReference(this.id);
|
|
@@ -410,7 +413,7 @@ class Link {
|
|
|
410
413
|
const idStr = Link.escapeReference(this.id);
|
|
411
414
|
testLine = options.lessParentheses ? `${idStr}: ${valuesStr}` : `(${idStr}: ${valuesStr})`;
|
|
412
415
|
} else {
|
|
413
|
-
testLine = options.lessParentheses ? valuesStr : `(${valuesStr})`;
|
|
416
|
+
testLine = options.lessParentheses && !this._hasLoneNestedValue() ? valuesStr : `(${valuesStr})`;
|
|
414
417
|
}
|
|
415
418
|
if (options.shouldIndentByLength(testLine)) {
|
|
416
419
|
shouldIndent = true;
|
|
@@ -421,7 +424,7 @@ class Link {
|
|
|
421
424
|
}
|
|
422
425
|
const valuesStr = this.values.map((v) => this.formatValue(v)).join(" ");
|
|
423
426
|
if (this.id === null) {
|
|
424
|
-
if (options.lessParentheses) {
|
|
427
|
+
if (options.lessParentheses && !this._hasLoneNestedValue()) {
|
|
425
428
|
const allSimple = this.values.every((v) => !v.values || v.values.length === 0);
|
|
426
429
|
if (allSimple) {
|
|
427
430
|
return this.values.map((v) => Link.escapeReference(v.id)).join(" ");
|
package/package.json
CHANGED
package/src/Link.js
CHANGED
|
@@ -196,7 +196,7 @@ export class Link {
|
|
|
196
196
|
// Original implementation for backward compatibility
|
|
197
197
|
// Empty link
|
|
198
198
|
if (this.id === null && (!this.values || this.values.length === 0)) {
|
|
199
|
-
return
|
|
199
|
+
return '()';
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
// Link with only ID, no values
|
|
@@ -217,7 +217,7 @@ export class Link {
|
|
|
217
217
|
// Link with values only (null id)
|
|
218
218
|
if (this.id === null) {
|
|
219
219
|
// For lessParentheses mode with simple values, don't wrap the whole thing
|
|
220
|
-
if (lessParentheses) {
|
|
220
|
+
if (lessParentheses && !this._hasLoneNestedValue()) {
|
|
221
221
|
// Check if all values are simple (no nested values)
|
|
222
222
|
const allSimple = this.values.every(
|
|
223
223
|
(v) => !v.values || v.values.length === 0
|
|
@@ -288,6 +288,16 @@ export class Link {
|
|
|
288
288
|
);
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
+
/**
|
|
292
|
+
* Whether this link holds exactly one link that has values. The parentheses
|
|
293
|
+
* of an anonymous link are what nest such a value: `((b c))` without them is
|
|
294
|
+
* `(b c)`, a different link, so lessParentheses has to keep them.
|
|
295
|
+
* @returns {boolean} True if the only value has values of its own
|
|
296
|
+
*/
|
|
297
|
+
_hasLoneNestedValue() {
|
|
298
|
+
return this.values.length === 1 && this.values[0].values?.length > 0;
|
|
299
|
+
}
|
|
300
|
+
|
|
291
301
|
/**
|
|
292
302
|
* Format the link using a FormatOptions object
|
|
293
303
|
* @param {FormatOptions} options - FormatOptions object with formatting options
|
|
@@ -297,7 +307,7 @@ export class Link {
|
|
|
297
307
|
_formatWithOptions(options, isCompoundValue = false) {
|
|
298
308
|
// Empty link
|
|
299
309
|
if (this.id === null && (!this.values || this.values.length === 0)) {
|
|
300
|
-
return
|
|
310
|
+
return '()';
|
|
301
311
|
}
|
|
302
312
|
|
|
303
313
|
// Link with only ID, no values
|
|
@@ -325,7 +335,10 @@ export class Link {
|
|
|
325
335
|
? `${idStr}: ${valuesStr}`
|
|
326
336
|
: `(${idStr}: ${valuesStr})`;
|
|
327
337
|
} else {
|
|
328
|
-
testLine =
|
|
338
|
+
testLine =
|
|
339
|
+
options.lessParentheses && !this._hasLoneNestedValue()
|
|
340
|
+
? valuesStr
|
|
341
|
+
: `(${valuesStr})`;
|
|
329
342
|
}
|
|
330
343
|
|
|
331
344
|
if (options.shouldIndentByLength(testLine)) {
|
|
@@ -343,7 +356,7 @@ export class Link {
|
|
|
343
356
|
|
|
344
357
|
// Link with values only (null id)
|
|
345
358
|
if (this.id === null) {
|
|
346
|
-
if (options.lessParentheses) {
|
|
359
|
+
if (options.lessParentheses && !this._hasLoneNestedValue()) {
|
|
347
360
|
const allSimple = this.values.every(
|
|
348
361
|
(v) => !v.values || v.values.length === 0
|
|
349
362
|
);
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { URL } from 'node:url';
|
|
3
3
|
import { expect, test } from 'bun:test';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
FormatOptions,
|
|
6
|
+
Link,
|
|
7
|
+
Parser,
|
|
8
|
+
StreamParser,
|
|
9
|
+
formatLinks,
|
|
10
|
+
} from '../src/index.js';
|
|
5
11
|
|
|
6
12
|
const fixtures = JSON.parse(
|
|
7
13
|
readFileSync(
|
|
@@ -25,3 +31,49 @@ test('shared text parity', () => {
|
|
|
25
31
|
expect(tree(stream.end()), fixture.id).toEqual(fixture.expected);
|
|
26
32
|
}
|
|
27
33
|
});
|
|
34
|
+
|
|
35
|
+
test('shared less parentheses round trip', () => {
|
|
36
|
+
const options = new FormatOptions({ lessParentheses: true });
|
|
37
|
+
for (const fixture of fixtures) {
|
|
38
|
+
const parsed = new Parser().parse(fixture.input);
|
|
39
|
+
expect(formatLinks(parsed, true), fixture.id).toBe(fixture.lessParentheses);
|
|
40
|
+
expect(formatLinks(parsed, options), fixture.id).toBe(
|
|
41
|
+
fixture.lessParentheses
|
|
42
|
+
);
|
|
43
|
+
expect(
|
|
44
|
+
tree(new Parser().parse(fixture.lessParentheses)),
|
|
45
|
+
fixture.id
|
|
46
|
+
).toEqual(fixture.expected);
|
|
47
|
+
for (const link of parsed) {
|
|
48
|
+
const [readBack] = new Parser().parse(link.format(true));
|
|
49
|
+
expect(link.equals(readBack), fixture.id).toBe(true);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('less parentheses keeps the parentheses of a lone nested value', () => {
|
|
55
|
+
const nested = new Link(null, [new Link('b'), new Link('c')]);
|
|
56
|
+
expect(new Link(null, [nested]).format(true)).toBe('((b c))');
|
|
57
|
+
expect(new Link(null, [new Link('b')]).format(true)).toBe('b');
|
|
58
|
+
expect(new Link(null, [new Link('a'), nested]).format(true)).toBe('a (b c)');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('less parentheses keeps the parentheses of an empty link', () => {
|
|
62
|
+
const options = new FormatOptions({ lessParentheses: true });
|
|
63
|
+
expect(new Link(null, []).format(true)).toBe('()');
|
|
64
|
+
expect(new Link(null, []).format(options)).toBe('()');
|
|
65
|
+
expect(formatLinks([], true)).toBe('');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('line length is measured on the parentheses a lone nested value keeps', () => {
|
|
69
|
+
const link = new Link(null, [new Link(null, [new Link('b'), new Link('c')])]);
|
|
70
|
+
const options = (maxLineLength) =>
|
|
71
|
+
new FormatOptions({
|
|
72
|
+
lessParentheses: true,
|
|
73
|
+
indentLongLines: true,
|
|
74
|
+
maxLineLength,
|
|
75
|
+
preferInline: false,
|
|
76
|
+
});
|
|
77
|
+
expect(link.format(options(7))).toBe('((b c))');
|
|
78
|
+
expect(link.format(options(6))).toBe(' (b c)');
|
|
79
|
+
});
|