links-notation 0.27.1 → 0.30.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 CHANGED
@@ -234,6 +234,47 @@ call it on already decoded `Link.id` values.
234
234
 
235
235
  See the [Q&A document example](../examples/js_indented_document.js).
236
236
 
237
+ ### How a Document Was Written (CST)
238
+
239
+ Parsing keeps how every ID was written. Quoting never changes a reference:
240
+ `1` and `'1'` are the same reference, so equality, formatting and JSON stay as
241
+ they were. Each parsed link also carries `rawId`, the ID exactly as written,
242
+ and `quote`, the delimiter it was written between:
243
+
244
+ ```javascript
245
+ import { Parser } from 'links-notation';
246
+
247
+ const [link] = new Parser().parse("(t 1 '1')");
248
+ const [, bare, quoted] = link.values;
249
+ bare.equals(quoted); // true: the same reference
250
+ [bare.rawId, bare.quote]; // ['1', null]
251
+ [quoted.rawId, quoted.quote]; // ["'1'", "'"]
252
+ link.format(); // '(t 1 1)'
253
+ ```
254
+
255
+ `rawId` is `null` for links without an ID, links built in code, and links
256
+ made by indentation path combination. Use `new Parser({ syntax: false })` (AST
257
+ mode) to leave it out.
258
+
259
+ `parseCst(input)` returns the lossless concrete syntax tree. Every character,
260
+ including comments, blank lines, indentation, quotes and line endings, belongs
261
+ to exactly one token, so the original text is always recovered:
262
+
263
+ ```javascript
264
+ const cst = new Parser().parseCst("(t 1 '1') # note\n");
265
+ cst.toString(); // "(t 1 '1') # note\n"
266
+ cst.tokens().map((token) => [token.kind, token.text]);
267
+ // [['open_paren', '('], ['reference', 't'], ['whitespace', ' '], ...]
268
+ cst.toSExpression();
269
+ // (document (line (group open_paren:"(" (line reference:"t" ...) close_paren:")") whitespace:" " comment:"# note" newline:"\n"))
270
+ ```
271
+
272
+ A `document` node holds `line` nodes. A line holds its tokens up to and
273
+ including its line ending. A `group` node holds `(`, the lines inside it, and
274
+ `)`. Reference tokens carry `value` (what the reference means) and `quote`.
275
+ `parseCst` refuses exactly what `parse` refuses. See
276
+ [the issue 364 case study](../docs/case-studies/issue-364/README.md).
277
+
237
278
  ### Streaming Parser (for Large Messages)
238
279
 
239
280
  The `StreamParser` allows you to parse Links Notation incrementally, processing data as it arrives without loading the entire message into memory. This is ideal for:
@@ -429,6 +470,9 @@ Main parser class for converting strings to links.
429
470
  - `initialize()` - Initialize the parser (async)
430
471
  - `parse(input)` - Parse a Lino string and return links
431
472
  - `parseGroups(input)` - Read an indentation tree as `LinksGroup` instances
473
+ - `parseCst(input)` - Read the lossless concrete syntax tree (`CstNode`)
474
+ - `options.syntax` - If `false` (AST mode), parsed links leave `rawId` null
475
+ (default: `true`)
432
476
 
433
477
  #### `Link`
434
478
 
@@ -438,6 +482,9 @@ Represents a single link with ID and values.
438
482
  - `toString()` - Convert link to string format
439
483
  - `id` - Link identifier
440
484
  - `values` - Array of child values/links
485
+ - `rawId` - The ID exactly as the parsed document wrote it, or `null`; ignored
486
+ by `equals`, `format` and JSON
487
+ - `quote` - `'`, `"` or `` ` `` when `rawId` is quoted, otherwise `null`
441
488
  - `escapeReference(reference, options)` - Quote a reference; `minimal: true`
442
489
  allows ordinary prose on a text document line
443
490
  - `unescapeReference(reference)` - Decode a complete serialized reference
package/README.ru.md CHANGED
@@ -153,6 +153,38 @@ const group = new LinksGroup(parsed);
153
153
  console.log(group.format());
154
154
  ```
155
155
 
156
+ ### Как документ был записан (CST)
157
+
158
+ Парсер сохраняет, как была записана каждая ссылка. Кавычки не меняют ссылку:
159
+ `1` и `'1'` - одна и та же ссылка, поэтому сравнение, форматирование и JSON
160
+ остаются прежними. Каждая разобранная связь хранит `rawId` - ID в точности
161
+ так, как он записан, и `quote` - кавычку, в которую он заключён:
162
+
163
+ ```javascript
164
+ import { Parser } from 'links-notation';
165
+
166
+ const [link] = new Parser().parse("(t 1 '1')");
167
+ const [, bare, quoted] = link.values;
168
+ bare.equals(quoted); // true: это одна ссылка
169
+ [bare.rawId, bare.quote]; // ['1', null]
170
+ [quoted.rawId, quoted.quote]; // ["'1'", "'"]
171
+ link.format(); // '(t 1 1)'
172
+ ```
173
+
174
+ `rawId` равен `null` у связей без ID, у связей, созданных в коде, и у связей,
175
+ построенных объединением путей по отступам. `new Parser({ syntax: false })`
176
+ (режим AST) не сохраняет его.
177
+
178
+ `parseCst(input)` возвращает конкретное синтаксическое дерево без потерь:
179
+ каждый символ, включая комментарии, пустые строки, отступы, кавычки и
180
+ переводы строк, принадлежит ровно одному токену, поэтому исходный текст
181
+ всегда восстанавливается: `new Parser().parseCst(text).toString() === text`.
182
+ Узел `document` содержит узлы `line`; строка содержит свои токены вместе с
183
+ переводом строки; узел `group` содержит `(`, строки внутри и `)`. Токены
184
+ ссылок хранят `value` (что означает ссылка) и `quote`. `parseCst` отклоняет
185
+ ровно то, что отклоняет `parse`. Подробности - в
186
+ [разборе issue 364](../docs/case-studies/issue-364/README.md).
187
+
156
188
  ### Потоковый парсер
157
189
 
158
190
  `StreamParser` принимает произвольные порции данных и отправляет события только
@@ -298,6 +330,9 @@ console.log(formatLinks(plain.parse('# a b\n'))); // (# a b)
298
330
  отклоняется с `ParseError`, а не разбирается рекурсивно, пока не кончится стек
299
331
  - `initialize()` - Инициализация парсера (асинхронно)
300
332
  - `parse(input)` - Парсинг строки Lino и возвращение связей
333
+ - `parseCst(input)` - Конкретное синтаксическое дерево без потерь (`CstNode`)
334
+ - `options.syntax` - Со значением `false` (режим AST) связи не хранят `rawId`
335
+ (по умолчанию: `true`)
301
336
 
302
337
  #### `Link`
303
338
 
@@ -307,6 +342,9 @@ console.log(formatLinks(plain.parse('# a b\n'))); // (# a b)
307
342
  - `toString()` - Преобразование связи в строковый формат
308
343
  - `id` - Идентификатор связи
309
344
  - `values` - Массив дочерних значений/связей
345
+ - `rawId` - ID в точности так, как он записан в документе, или `null`;
346
+ `equals`, `format` и JSON его не учитывают
347
+ - `quote` - `'`, `"` или `` ` ``, если `rawId` в кавычках, иначе `null`
310
348
 
311
349
  #### `LinksGroup`
312
350