links-notation 0.28.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.
@@ -158,3 +158,34 @@ test('a hash that cannot open a comment is left unquoted', () => {
158
158
  expect(Link.escapeReference('#')).toBe("'#'");
159
159
  expect(Link.escapeReference('#ff0000')).toBe("'#ff0000'");
160
160
  });
161
+
162
+ // Issue #377: the comment reader and the grammar must agree on where every
163
+ // delimited reference starts and how far it reaches, or a comment is blanked
164
+ // inside what the grammar then reads as a reference.
165
+
166
+ test('a hash inside a reference that follows a group is content', () => {
167
+ expect(parsesAs('(a)" #b"\n')).toBe('((<a>) < #b>)');
168
+ });
169
+
170
+ test('a hash inside a reference that follows another reference is content', () => {
171
+ expect(parsesAs('"x"\' #y\'\n')).toBe('(<x> < #y>)');
172
+ expect(parsesAs('```q```"" #c\n"""\n')).toBe('(<q> < #c\n">)');
173
+ });
174
+
175
+ test('a hash inside a reference that follows a literal is content', () => {
176
+ expect(parsesAs('~1{62}" #b"\n')).toBe('(<b> < #b>)');
177
+ });
178
+
179
+ test('a reference is read in the document as written, comments included', () => {
180
+ // The body of the first `""` straddles a parenthesis, so it is the empty
181
+ // reference and the `#` after it opens a comment. Blanking that comment
182
+ // must not turn the `""` into a reference that holds the blanked text.
183
+ expect(parsesAs('"" a #)b\n""\n')).toBe('(<> <a>)\n(<>)');
184
+ });
185
+
186
+ test('the comment reader skips the references the grammar reads', () => {
187
+ expect(stripComments('(a)" #b"\n')).toBe('(a)" #b"\n');
188
+ expect(stripComments('"x"\' #y\'\n')).toBe('"x"\' #y\'\n');
189
+ expect(stripComments('~1{62}" #b"\n')).toBe('~1{62}" #b"\n');
190
+ expect(stripComments('a"b #c"\n')).toBe('a"b \n');
191
+ });
@@ -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 { Parser, StreamParser, formatLinks } from '../src/index.js';
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
+ });
@@ -162,4 +162,17 @@ describe('StreamParser', () => {
162
162
  buffered: 2,
163
163
  });
164
164
  });
165
+
166
+ test('waits for the line that closes an even run of quotes (issue #377)', () => {
167
+ // `""` is the empty reference only when nothing closes it, and here the
168
+ // next line does, so the first line cannot be emitted on its own.
169
+ const input = 'a "" b\n"" c\n';
170
+ const stream = new StreamParser();
171
+ for (const character of input) {
172
+ expect(stream.write(character)).toEqual([]);
173
+ }
174
+ expect(formatLinks(stream.end())).toBe(
175
+ formatLinks(new Parser().parse(input))
176
+ );
177
+ });
165
178
  });