links-notation 0.27.0 → 0.28.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 +60 -1
- package/README.ru.md +45 -0
- package/dist/index.js +401 -97
- package/index.d.ts +103 -1
- package/package.json +2 -2
- package/src/Cst.js +263 -0
- package/src/Emitter.js +134 -0
- package/src/Link.js +41 -1
- package/src/Parser.js +49 -10
- package/src/StreamParser.js +2 -2
- package/src/grammar.pegjs +15 -4
- package/src/index.js +6 -1
- package/src/parser-generated.js +73 -53
- package/src/references.js +18 -0
- package/tests/BrowserBundle.test.js +187 -0
- package/tests/Cst.test.js +109 -0
- package/tests/SharedSyntaxParity.test.js +47 -0
- package/tests/SyntaxMetadata.test.js +102 -0
package/src/Parser.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Link } from './Link.js';
|
|
|
2
2
|
import { LinksGroup } from './LinksGroup.js';
|
|
3
3
|
import { ParseError } from './ParseError.js';
|
|
4
4
|
import { stripComments } from './comments.js';
|
|
5
|
+
import { buildCst } from './Cst.js';
|
|
5
6
|
import * as parserModule from './parser-generated.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -18,11 +19,13 @@ export class Parser {
|
|
|
18
19
|
* @param {number} options.maxInputSize - Maximum input size in bytes (default: 10MB)
|
|
19
20
|
* @param {number} options.maxDepth - How deep links may nest: every parenthesized group and every indentation level is one level (default: 64)
|
|
20
21
|
* @param {boolean} options.comments - If false, read `#` as an ordinary character instead of the start of a comment (default: true)
|
|
22
|
+
* @param {boolean} options.syntax - If false, read links as a bare abstract syntax tree: they do not record how their IDs were written, so `rawId` and `quote` are null (default: true)
|
|
21
23
|
*/
|
|
22
24
|
constructor(options = {}) {
|
|
23
25
|
this.maxInputSize = options.maxInputSize || 10 * 1024 * 1024; // 10MB default
|
|
24
26
|
this.maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
25
27
|
this.comments = options.comments ?? true;
|
|
28
|
+
this.syntax = options.syntax ?? true;
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
/**
|
|
@@ -48,6 +51,20 @@ export class Parser {
|
|
|
48
51
|
);
|
|
49
52
|
}
|
|
50
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Read the document as a lossless concrete syntax tree: every character of
|
|
56
|
+
* the input, comments and whitespace included, belongs to exactly one token,
|
|
57
|
+
* so `parseCst(input).toString() === input`. The document is first parsed
|
|
58
|
+
* with this parser's options, so it is refused exactly when `parse()` would
|
|
59
|
+
* refuse it.
|
|
60
|
+
* @param {string} input - The Lino document
|
|
61
|
+
* @returns {CstNode} The `document` node
|
|
62
|
+
*/
|
|
63
|
+
parseCst(input) {
|
|
64
|
+
this.parse(input);
|
|
65
|
+
return buildCst(input, { comments: this.comments });
|
|
66
|
+
}
|
|
67
|
+
|
|
51
68
|
_transformGroup(item) {
|
|
52
69
|
return new LinksGroup(
|
|
53
70
|
this.transformLink(item),
|
|
@@ -74,6 +91,7 @@ export class Parser {
|
|
|
74
91
|
try {
|
|
75
92
|
const rawResult = parserModule.parse(prepared, {
|
|
76
93
|
maxDepth: this.maxDepth,
|
|
94
|
+
source: input,
|
|
77
95
|
});
|
|
78
96
|
return transform(rawResult);
|
|
79
97
|
} catch (error) {
|
|
@@ -119,6 +137,7 @@ export class Parser {
|
|
|
119
137
|
);
|
|
120
138
|
const linkWithChildren = {
|
|
121
139
|
id: item.id,
|
|
140
|
+
rawId: item.rawId,
|
|
122
141
|
values: childValues,
|
|
123
142
|
};
|
|
124
143
|
const currentLink = this.transformLink(linkWithChildren);
|
|
@@ -163,18 +182,24 @@ export class Parser {
|
|
|
163
182
|
transformIndentedValue(item) {
|
|
164
183
|
const children = item.children || [];
|
|
165
184
|
if (children.length && item.id != null && !item.values?.length) {
|
|
166
|
-
return
|
|
167
|
-
|
|
168
|
-
|
|
185
|
+
return this._withRawId(
|
|
186
|
+
new Link(
|
|
187
|
+
item.id,
|
|
188
|
+
children.map((child) => this.transformIndentedValue(child))
|
|
189
|
+
),
|
|
190
|
+
item
|
|
169
191
|
);
|
|
170
192
|
}
|
|
171
193
|
|
|
172
194
|
const current = this.transformLink(item);
|
|
173
195
|
if (children.length) {
|
|
174
|
-
return
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
196
|
+
return this._withRawId(
|
|
197
|
+
new Link(current.id, [
|
|
198
|
+
...current.values,
|
|
199
|
+
...children.map((child) => this.transformIndentedValue(child)),
|
|
200
|
+
]),
|
|
201
|
+
item
|
|
202
|
+
);
|
|
178
203
|
}
|
|
179
204
|
if (
|
|
180
205
|
item.id == null &&
|
|
@@ -252,18 +277,32 @@ export class Parser {
|
|
|
252
277
|
|
|
253
278
|
// Handle simple reference objects like {id: 'a'}
|
|
254
279
|
if (item.id !== undefined && !item.values && !item.children) {
|
|
255
|
-
return new Link(item.id);
|
|
280
|
+
return this._withRawId(new Link(item.id), item);
|
|
256
281
|
}
|
|
257
282
|
|
|
258
283
|
// For items with values, create a link with those values
|
|
259
284
|
if (item.values && Array.isArray(item.values)) {
|
|
260
285
|
// Create a link with id (if present) and transformed values
|
|
261
|
-
const link = new Link(item.id ?? null, []);
|
|
286
|
+
const link = this._withRawId(new Link(item.id ?? null, []), item);
|
|
262
287
|
link.values = item.values.map((v) => this.transformLink(v));
|
|
263
288
|
return link;
|
|
264
289
|
}
|
|
265
290
|
|
|
266
291
|
// Default case
|
|
267
|
-
return new Link(item.id ?? null, []);
|
|
292
|
+
return this._withRawId(new Link(item.id ?? null, []), item);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Record how the parsed item wrote its ID, unless this parser reads a bare
|
|
297
|
+
* abstract syntax tree.
|
|
298
|
+
* @param {Link} link - The link made from the item
|
|
299
|
+
* @param {Object} item - The parsed item, with the `rawId` the grammar read
|
|
300
|
+
* @returns {Link} The same link
|
|
301
|
+
*/
|
|
302
|
+
_withRawId(link, item) {
|
|
303
|
+
if (this.syntax && link.id !== null && typeof item.rawId === 'string') {
|
|
304
|
+
link.rawId = item.rawId;
|
|
305
|
+
}
|
|
306
|
+
return link;
|
|
268
307
|
}
|
|
269
308
|
}
|
package/src/StreamParser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Emitter } from './Emitter.js';
|
|
2
2
|
import { Parser } from './Parser.js';
|
|
3
3
|
import { DelimitedReferences } from './quotes.js';
|
|
4
4
|
|
|
@@ -39,7 +39,7 @@ export class StreamParseError extends Error {
|
|
|
39
39
|
* uses the regular Parser as the source of truth, which keeps quoted strings,
|
|
40
40
|
* nested contexts, comments, and future grammar changes in one place.
|
|
41
41
|
*/
|
|
42
|
-
export class StreamParser extends
|
|
42
|
+
export class StreamParser extends Emitter {
|
|
43
43
|
constructor(options = {}) {
|
|
44
44
|
super();
|
|
45
45
|
this.parser = options.parser ?? new Parser(options);
|
package/src/grammar.pegjs
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
// until the stack overflows.
|
|
17
17
|
let contextDepth = 0;
|
|
18
18
|
const maxDepth = options.maxDepth ?? Infinity;
|
|
19
|
+
// The document as the caller wrote it, comments included.
|
|
20
|
+
const source = options.source ?? input;
|
|
19
21
|
// Lines already found unreadable, keyed by where they start and whether they
|
|
20
22
|
// are inside a parenthesised group. Reading a line depends on nothing else: a
|
|
21
23
|
// group starts a fresh indentation context, and indentation only decides
|
|
@@ -164,7 +166,7 @@ element = &{ return !unreadableLines.has(lineKey(offset())); }
|
|
|
164
166
|
// succeed without consuming input.
|
|
165
167
|
/ &{ unreadableLines.add(lineKey(offset())); return false; } .
|
|
166
168
|
|
|
167
|
-
referenceOrLink = l:multiLineAnyLink { return l; } /
|
|
169
|
+
referenceOrLink = l:multiLineAnyLink { return l; } / r:reference { return { id: r.value, rawId: r.raw }; }
|
|
168
170
|
|
|
169
171
|
// A line that starts with a parenthesised group reads that group once and then
|
|
170
172
|
// branches on what follows it: the end of the line makes the group the whole
|
|
@@ -210,15 +212,24 @@ singleLineValueAndWhitespace = __ value:referenceOrLink { return value; }
|
|
|
210
212
|
|
|
211
213
|
singleLineValues = list:singleLineValueAndWhitespace+ { return list; }
|
|
212
214
|
|
|
213
|
-
singleLineLink = __ id:reference __ ":" v:singleLineValues { return { id: id, values: v }; }
|
|
215
|
+
singleLineLink = __ id:reference __ ":" v:singleLineValues { return { id: id.value, rawId: id.raw, values: v }; }
|
|
214
216
|
|
|
215
217
|
singleLineValueLink = v:singleLineValues { return { values: v }; }
|
|
216
218
|
|
|
217
|
-
indentedIdLink = id:reference __ ":" eol { return { id: id, values: [] }; }
|
|
219
|
+
indentedIdLink = id:reference __ ":" eol { return { id: id.value, rawId: id.raw, values: [] }; }
|
|
220
|
+
|
|
221
|
+
// A reference is read as its value together with the text it was written as,
|
|
222
|
+
// so a parsed link can say whether its ID was bare, quoted or a literal. The
|
|
223
|
+
// text is taken from the document as the caller wrote it, which keeps the same
|
|
224
|
+
// offsets as the document with its comments blanked out.
|
|
225
|
+
reference = value:referenceValue {
|
|
226
|
+
const { start, end } = range();
|
|
227
|
+
return { value: value, raw: source.slice(start, end) };
|
|
228
|
+
}
|
|
218
229
|
|
|
219
230
|
// Reference can be quoted (with any number of quotes N >= 1) or simple unquoted
|
|
220
231
|
// Universal approach: use procedural parsing for all quote types and counts
|
|
221
|
-
|
|
232
|
+
referenceValue = referenceLiteral / quotedReference / simpleReference
|
|
222
233
|
|
|
223
234
|
// Versioned literals reserve ~<version>{<UTF-8 hex>} at a reference boundary.
|
|
224
235
|
// A malformed reserved token must fail rather than fall back to a bare name.
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export { Link, formatLinks } from './Link.js';
|
|
2
|
-
export {
|
|
2
|
+
export {
|
|
3
|
+
escapeReference,
|
|
4
|
+
unescapeReference,
|
|
5
|
+
referenceQuote,
|
|
6
|
+
} from './references.js';
|
|
7
|
+
export { CstKind, CstNode } from './Cst.js';
|
|
3
8
|
export {
|
|
4
9
|
parseIndentedDocument,
|
|
5
10
|
formatIndentedDocument,
|
package/src/parser-generated.js
CHANGED
|
@@ -224,7 +224,7 @@ function peg$parse(input, options) {
|
|
|
224
224
|
}
|
|
225
225
|
function peg$f10() { unreadableLines.add(lineKey(offset())); return false; }
|
|
226
226
|
function peg$f11(l) { return l; }
|
|
227
|
-
function peg$f12(
|
|
227
|
+
function peg$f12(r) { return { id: r.value, rawId: r.raw }; }
|
|
228
228
|
function peg$f13(g, rest) {
|
|
229
229
|
return rest === null ? g : { values: [g].concat(rest) };
|
|
230
230
|
}
|
|
@@ -243,18 +243,22 @@ function peg$parse(input, options) {
|
|
|
243
243
|
function peg$f23() { return location(); }
|
|
244
244
|
function peg$f24(value) { return value; }
|
|
245
245
|
function peg$f25(list) { return list; }
|
|
246
|
-
function peg$f26(id, v) { return { id: id, values: v }; }
|
|
246
|
+
function peg$f26(id, v) { return { id: id.value, rawId: id.raw, values: v }; }
|
|
247
247
|
function peg$f27(v) { return { values: v }; }
|
|
248
|
-
function peg$f28(id) { return { id: id, values: [] }; }
|
|
249
|
-
function peg$f29() {
|
|
248
|
+
function peg$f28(id) { return { id: id.value, rawId: id.raw, values: [] }; }
|
|
249
|
+
function peg$f29(value) {
|
|
250
|
+
const { start, end } = range();
|
|
251
|
+
return { value: value, raw: source.slice(start, end) };
|
|
252
|
+
}
|
|
253
|
+
function peg$f30() {
|
|
250
254
|
return hasReferenceLiteralPrefix(input, offset());
|
|
251
255
|
}
|
|
252
|
-
function peg$
|
|
256
|
+
function peg$f31(literal) {
|
|
253
257
|
return decodeReferenceLiteral(literal);
|
|
254
258
|
}
|
|
255
|
-
function peg$
|
|
256
|
-
function peg$
|
|
257
|
-
function peg$
|
|
259
|
+
function peg$f32() { return !hasReferenceLiteralPrefix(input, offset()); }
|
|
260
|
+
function peg$f33(chars) { return chars.join(''); }
|
|
261
|
+
function peg$f34() {
|
|
258
262
|
const pos = offset();
|
|
259
263
|
const result = parseQuotedStringAt(input, pos, '"');
|
|
260
264
|
if (result) {
|
|
@@ -264,11 +268,11 @@ function peg$parse(input, options) {
|
|
|
264
268
|
}
|
|
265
269
|
return false;
|
|
266
270
|
}
|
|
267
|
-
function peg$
|
|
268
|
-
function peg$
|
|
269
|
-
function peg$
|
|
270
|
-
function peg$
|
|
271
|
-
function peg$
|
|
271
|
+
function peg$f35(chars) { return parsedValue; }
|
|
272
|
+
function peg$f36(c, cs) { return [c].concat(cs).join(''); }
|
|
273
|
+
function peg$f37() { return parsedLength > 1 && (parsedLength--, true); }
|
|
274
|
+
function peg$f38(c) { return c; }
|
|
275
|
+
function peg$f39() {
|
|
272
276
|
const pos = offset();
|
|
273
277
|
const result = parseQuotedStringAt(input, pos, "'");
|
|
274
278
|
if (result) {
|
|
@@ -278,11 +282,11 @@ function peg$parse(input, options) {
|
|
|
278
282
|
}
|
|
279
283
|
return false;
|
|
280
284
|
}
|
|
281
|
-
function peg$
|
|
282
|
-
function peg$
|
|
283
|
-
function peg$
|
|
284
|
-
function peg$
|
|
285
|
-
function peg$
|
|
285
|
+
function peg$f40(chars) { return parsedValue; }
|
|
286
|
+
function peg$f41(c, cs) { return [c].concat(cs).join(''); }
|
|
287
|
+
function peg$f42() { return parsedLength > 1 && (parsedLength--, true); }
|
|
288
|
+
function peg$f43(c) { return c; }
|
|
289
|
+
function peg$f44() {
|
|
286
290
|
const pos = offset();
|
|
287
291
|
const result = parseQuotedStringAt(input, pos, '`');
|
|
288
292
|
if (result) {
|
|
@@ -292,16 +296,16 @@ function peg$parse(input, options) {
|
|
|
292
296
|
}
|
|
293
297
|
return false;
|
|
294
298
|
}
|
|
295
|
-
function peg$
|
|
296
|
-
function peg$
|
|
297
|
-
function peg$
|
|
298
|
-
function peg$
|
|
299
|
-
function peg$
|
|
300
|
-
function peg$
|
|
301
|
-
function peg$
|
|
302
|
-
function peg$
|
|
303
|
-
function peg$
|
|
304
|
-
function peg$
|
|
299
|
+
function peg$f45(chars) { return parsedValue; }
|
|
300
|
+
function peg$f46(c, cs) { return [c].concat(cs).join(''); }
|
|
301
|
+
function peg$f47() { return parsedLength > 1 && (parsedLength--, true); }
|
|
302
|
+
function peg$f48(c) { return c; }
|
|
303
|
+
function peg$f49() { return indentationStack.slice(); }
|
|
304
|
+
function peg$f50(spaces) { setBaseIndentation(spaces); }
|
|
305
|
+
function peg$f51(spaces) { return normalizeIndentation(spaces) > getCurrentIndentation(); }
|
|
306
|
+
function peg$f52(spaces) { pushIndentation(spaces); }
|
|
307
|
+
function peg$f53(spaces) { return checkIndentation(spaces); }
|
|
308
|
+
function peg$f54() { return isInsideNestedContext(); }
|
|
305
309
|
let peg$currPos = options.peg$currPos | 0;
|
|
306
310
|
let peg$savedPos = peg$currPos;
|
|
307
311
|
const peg$posDetailsCache = [{ line: 1, column: 1 }];
|
|
@@ -1218,6 +1222,20 @@ function peg$parse(input, options) {
|
|
|
1218
1222
|
}
|
|
1219
1223
|
|
|
1220
1224
|
function peg$parsereference() {
|
|
1225
|
+
let s0, s1;
|
|
1226
|
+
|
|
1227
|
+
s0 = peg$currPos;
|
|
1228
|
+
s1 = peg$parsereferenceValue();
|
|
1229
|
+
if (s1 !== peg$FAILED) {
|
|
1230
|
+
peg$savedPos = s0;
|
|
1231
|
+
s1 = peg$f29(s1);
|
|
1232
|
+
}
|
|
1233
|
+
s0 = s1;
|
|
1234
|
+
|
|
1235
|
+
return s0;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
function peg$parsereferenceValue() {
|
|
1221
1239
|
let s0;
|
|
1222
1240
|
|
|
1223
1241
|
s0 = peg$parsereferenceLiteral();
|
|
@@ -1253,7 +1271,7 @@ function peg$parse(input, options) {
|
|
|
1253
1271
|
}
|
|
1254
1272
|
if (s1 !== peg$FAILED) {
|
|
1255
1273
|
peg$savedPos = peg$currPos;
|
|
1256
|
-
s2 = peg$
|
|
1274
|
+
s2 = peg$f30();
|
|
1257
1275
|
if (s2) {
|
|
1258
1276
|
s2 = undefined;
|
|
1259
1277
|
} else {
|
|
@@ -1352,7 +1370,7 @@ function peg$parse(input, options) {
|
|
|
1352
1370
|
}
|
|
1353
1371
|
if (s3 !== peg$FAILED) {
|
|
1354
1372
|
peg$savedPos = s0;
|
|
1355
|
-
s0 = peg$
|
|
1373
|
+
s0 = peg$f31(s3);
|
|
1356
1374
|
} else {
|
|
1357
1375
|
peg$currPos = s0;
|
|
1358
1376
|
s0 = peg$FAILED;
|
|
@@ -1374,7 +1392,7 @@ function peg$parse(input, options) {
|
|
|
1374
1392
|
|
|
1375
1393
|
s0 = peg$currPos;
|
|
1376
1394
|
peg$savedPos = peg$currPos;
|
|
1377
|
-
s1 = peg$
|
|
1395
|
+
s1 = peg$f32();
|
|
1378
1396
|
if (s1) {
|
|
1379
1397
|
s1 = undefined;
|
|
1380
1398
|
} else {
|
|
@@ -1393,7 +1411,7 @@ function peg$parse(input, options) {
|
|
|
1393
1411
|
}
|
|
1394
1412
|
if (s2 !== peg$FAILED) {
|
|
1395
1413
|
peg$savedPos = s0;
|
|
1396
|
-
s0 = peg$
|
|
1414
|
+
s0 = peg$f33(s2);
|
|
1397
1415
|
} else {
|
|
1398
1416
|
peg$currPos = s0;
|
|
1399
1417
|
s0 = peg$FAILED;
|
|
@@ -1442,7 +1460,7 @@ function peg$parse(input, options) {
|
|
|
1442
1460
|
}
|
|
1443
1461
|
if (s1 !== peg$FAILED) {
|
|
1444
1462
|
peg$savedPos = peg$currPos;
|
|
1445
|
-
s2 = peg$
|
|
1463
|
+
s2 = peg$f34();
|
|
1446
1464
|
if (s2) {
|
|
1447
1465
|
s2 = undefined;
|
|
1448
1466
|
} else {
|
|
@@ -1452,7 +1470,7 @@ function peg$parse(input, options) {
|
|
|
1452
1470
|
s3 = peg$parseconsumeDouble();
|
|
1453
1471
|
if (s3 !== peg$FAILED) {
|
|
1454
1472
|
peg$savedPos = s0;
|
|
1455
|
-
s0 = peg$
|
|
1473
|
+
s0 = peg$f35(s3);
|
|
1456
1474
|
} else {
|
|
1457
1475
|
peg$currPos = s0;
|
|
1458
1476
|
s0 = peg$FAILED;
|
|
@@ -1488,7 +1506,7 @@ function peg$parse(input, options) {
|
|
|
1488
1506
|
s3 = peg$parseconsumeDoubleMore();
|
|
1489
1507
|
}
|
|
1490
1508
|
peg$savedPos = s0;
|
|
1491
|
-
s0 = peg$
|
|
1509
|
+
s0 = peg$f36(s1, s2);
|
|
1492
1510
|
} else {
|
|
1493
1511
|
peg$currPos = s0;
|
|
1494
1512
|
s0 = peg$FAILED;
|
|
@@ -1502,7 +1520,7 @@ function peg$parse(input, options) {
|
|
|
1502
1520
|
|
|
1503
1521
|
s0 = peg$currPos;
|
|
1504
1522
|
peg$savedPos = peg$currPos;
|
|
1505
|
-
s1 = peg$
|
|
1523
|
+
s1 = peg$f37();
|
|
1506
1524
|
if (s1) {
|
|
1507
1525
|
s1 = undefined;
|
|
1508
1526
|
} else {
|
|
@@ -1518,7 +1536,7 @@ function peg$parse(input, options) {
|
|
|
1518
1536
|
}
|
|
1519
1537
|
if (s2 !== peg$FAILED) {
|
|
1520
1538
|
peg$savedPos = s0;
|
|
1521
|
-
s0 = peg$
|
|
1539
|
+
s0 = peg$f38(s2);
|
|
1522
1540
|
} else {
|
|
1523
1541
|
peg$currPos = s0;
|
|
1524
1542
|
s0 = peg$FAILED;
|
|
@@ -1553,7 +1571,7 @@ function peg$parse(input, options) {
|
|
|
1553
1571
|
}
|
|
1554
1572
|
if (s1 !== peg$FAILED) {
|
|
1555
1573
|
peg$savedPos = peg$currPos;
|
|
1556
|
-
s2 = peg$
|
|
1574
|
+
s2 = peg$f39();
|
|
1557
1575
|
if (s2) {
|
|
1558
1576
|
s2 = undefined;
|
|
1559
1577
|
} else {
|
|
@@ -1563,7 +1581,7 @@ function peg$parse(input, options) {
|
|
|
1563
1581
|
s3 = peg$parseconsumeSingle();
|
|
1564
1582
|
if (s3 !== peg$FAILED) {
|
|
1565
1583
|
peg$savedPos = s0;
|
|
1566
|
-
s0 = peg$
|
|
1584
|
+
s0 = peg$f40(s3);
|
|
1567
1585
|
} else {
|
|
1568
1586
|
peg$currPos = s0;
|
|
1569
1587
|
s0 = peg$FAILED;
|
|
@@ -1599,7 +1617,7 @@ function peg$parse(input, options) {
|
|
|
1599
1617
|
s3 = peg$parseconsumeSingleMore();
|
|
1600
1618
|
}
|
|
1601
1619
|
peg$savedPos = s0;
|
|
1602
|
-
s0 = peg$
|
|
1620
|
+
s0 = peg$f41(s1, s2);
|
|
1603
1621
|
} else {
|
|
1604
1622
|
peg$currPos = s0;
|
|
1605
1623
|
s0 = peg$FAILED;
|
|
@@ -1613,7 +1631,7 @@ function peg$parse(input, options) {
|
|
|
1613
1631
|
|
|
1614
1632
|
s0 = peg$currPos;
|
|
1615
1633
|
peg$savedPos = peg$currPos;
|
|
1616
|
-
s1 = peg$
|
|
1634
|
+
s1 = peg$f42();
|
|
1617
1635
|
if (s1) {
|
|
1618
1636
|
s1 = undefined;
|
|
1619
1637
|
} else {
|
|
@@ -1629,7 +1647,7 @@ function peg$parse(input, options) {
|
|
|
1629
1647
|
}
|
|
1630
1648
|
if (s2 !== peg$FAILED) {
|
|
1631
1649
|
peg$savedPos = s0;
|
|
1632
|
-
s0 = peg$
|
|
1650
|
+
s0 = peg$f43(s2);
|
|
1633
1651
|
} else {
|
|
1634
1652
|
peg$currPos = s0;
|
|
1635
1653
|
s0 = peg$FAILED;
|
|
@@ -1664,7 +1682,7 @@ function peg$parse(input, options) {
|
|
|
1664
1682
|
}
|
|
1665
1683
|
if (s1 !== peg$FAILED) {
|
|
1666
1684
|
peg$savedPos = peg$currPos;
|
|
1667
|
-
s2 = peg$
|
|
1685
|
+
s2 = peg$f44();
|
|
1668
1686
|
if (s2) {
|
|
1669
1687
|
s2 = undefined;
|
|
1670
1688
|
} else {
|
|
@@ -1674,7 +1692,7 @@ function peg$parse(input, options) {
|
|
|
1674
1692
|
s3 = peg$parseconsumeBacktick();
|
|
1675
1693
|
if (s3 !== peg$FAILED) {
|
|
1676
1694
|
peg$savedPos = s0;
|
|
1677
|
-
s0 = peg$
|
|
1695
|
+
s0 = peg$f45(s3);
|
|
1678
1696
|
} else {
|
|
1679
1697
|
peg$currPos = s0;
|
|
1680
1698
|
s0 = peg$FAILED;
|
|
@@ -1710,7 +1728,7 @@ function peg$parse(input, options) {
|
|
|
1710
1728
|
s3 = peg$parseconsumeBacktickMore();
|
|
1711
1729
|
}
|
|
1712
1730
|
peg$savedPos = s0;
|
|
1713
|
-
s0 = peg$
|
|
1731
|
+
s0 = peg$f46(s1, s2);
|
|
1714
1732
|
} else {
|
|
1715
1733
|
peg$currPos = s0;
|
|
1716
1734
|
s0 = peg$FAILED;
|
|
@@ -1724,7 +1742,7 @@ function peg$parse(input, options) {
|
|
|
1724
1742
|
|
|
1725
1743
|
s0 = peg$currPos;
|
|
1726
1744
|
peg$savedPos = peg$currPos;
|
|
1727
|
-
s1 = peg$
|
|
1745
|
+
s1 = peg$f47();
|
|
1728
1746
|
if (s1) {
|
|
1729
1747
|
s1 = undefined;
|
|
1730
1748
|
} else {
|
|
@@ -1740,7 +1758,7 @@ function peg$parse(input, options) {
|
|
|
1740
1758
|
}
|
|
1741
1759
|
if (s2 !== peg$FAILED) {
|
|
1742
1760
|
peg$savedPos = s0;
|
|
1743
|
-
s0 = peg$
|
|
1761
|
+
s0 = peg$f48(s2);
|
|
1744
1762
|
} else {
|
|
1745
1763
|
peg$currPos = s0;
|
|
1746
1764
|
s0 = peg$FAILED;
|
|
@@ -1759,7 +1777,7 @@ function peg$parse(input, options) {
|
|
|
1759
1777
|
s0 = peg$currPos;
|
|
1760
1778
|
s1 = '';
|
|
1761
1779
|
peg$savedPos = s0;
|
|
1762
|
-
s1 = peg$
|
|
1780
|
+
s1 = peg$f49();
|
|
1763
1781
|
s0 = s1;
|
|
1764
1782
|
|
|
1765
1783
|
return s0;
|
|
@@ -1788,7 +1806,7 @@ function peg$parse(input, options) {
|
|
|
1788
1806
|
}
|
|
1789
1807
|
}
|
|
1790
1808
|
peg$savedPos = s0;
|
|
1791
|
-
s1 = peg$
|
|
1809
|
+
s1 = peg$f50(s1);
|
|
1792
1810
|
s0 = s1;
|
|
1793
1811
|
|
|
1794
1812
|
return s0;
|
|
@@ -1817,7 +1835,7 @@ function peg$parse(input, options) {
|
|
|
1817
1835
|
}
|
|
1818
1836
|
}
|
|
1819
1837
|
peg$savedPos = peg$currPos;
|
|
1820
|
-
s2 = peg$
|
|
1838
|
+
s2 = peg$f51(s1);
|
|
1821
1839
|
if (s2) {
|
|
1822
1840
|
s2 = undefined;
|
|
1823
1841
|
} else {
|
|
@@ -1825,7 +1843,7 @@ function peg$parse(input, options) {
|
|
|
1825
1843
|
}
|
|
1826
1844
|
if (s2 !== peg$FAILED) {
|
|
1827
1845
|
peg$savedPos = s0;
|
|
1828
|
-
s0 = peg$
|
|
1846
|
+
s0 = peg$f52(s1);
|
|
1829
1847
|
} else {
|
|
1830
1848
|
peg$currPos = s0;
|
|
1831
1849
|
s0 = peg$FAILED;
|
|
@@ -1857,7 +1875,7 @@ function peg$parse(input, options) {
|
|
|
1857
1875
|
}
|
|
1858
1876
|
}
|
|
1859
1877
|
peg$savedPos = peg$currPos;
|
|
1860
|
-
s2 = peg$
|
|
1878
|
+
s2 = peg$f53(s1);
|
|
1861
1879
|
if (s2) {
|
|
1862
1880
|
s2 = undefined;
|
|
1863
1881
|
} else {
|
|
@@ -2057,7 +2075,7 @@ function peg$parse(input, options) {
|
|
|
2057
2075
|
|
|
2058
2076
|
s0 = peg$currPos;
|
|
2059
2077
|
peg$savedPos = peg$currPos;
|
|
2060
|
-
s1 = peg$
|
|
2078
|
+
s1 = peg$f54();
|
|
2061
2079
|
if (s1) {
|
|
2062
2080
|
s1 = undefined;
|
|
2063
2081
|
} else {
|
|
@@ -2197,6 +2215,8 @@ function peg$parse(input, options) {
|
|
|
2197
2215
|
// until the stack overflows.
|
|
2198
2216
|
let contextDepth = 0;
|
|
2199
2217
|
const maxDepth = options.maxDepth ?? Infinity;
|
|
2218
|
+
// The document as the caller wrote it, comments included.
|
|
2219
|
+
const source = options.source ?? input;
|
|
2200
2220
|
// Lines already found unreadable, keyed by where they start and whether they
|
|
2201
2221
|
// are inside a parenthesised group. Reading a line depends on nothing else: a
|
|
2202
2222
|
// group starts a fresh indentation context, and indentation only decides
|
package/src/references.js
CHANGED
|
@@ -61,3 +61,21 @@ export function unescapeReference(reference) {
|
|
|
61
61
|
}
|
|
62
62
|
return reading.value;
|
|
63
63
|
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The delimiter a reference was written between, read from the reference as it
|
|
67
|
+
* was written: `'`, `"` or `` ` `` for a quoted reference (however many of them
|
|
68
|
+
* open it), and null for a bare reference, a versioned literal, or no text.
|
|
69
|
+
* @param {string|null|undefined} raw - One reference exactly as written
|
|
70
|
+
* @returns {string|null} The delimiter character, or null
|
|
71
|
+
* @example
|
|
72
|
+
* referenceQuote("'1'"); // "'"
|
|
73
|
+
* referenceQuote('""a b""'); // '"'
|
|
74
|
+
* referenceQuote('1'); // null
|
|
75
|
+
* referenceQuote("'unclosed"); // null: a bare reference that starts with '
|
|
76
|
+
*/
|
|
77
|
+
export function referenceQuote(raw) {
|
|
78
|
+
if (typeof raw !== 'string' || !QUOTES.includes(raw[0])) return null;
|
|
79
|
+
const reading = readReference(raw, 0);
|
|
80
|
+
return reading !== null && reading.length === raw.length ? raw[0] : null;
|
|
81
|
+
}
|