tsondb 0.11.1 → 0.11.3

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.
@@ -0,0 +1,2 @@
1
+ export declare const detectIndentation: (text: string, excludeFirstLineForDetection?: boolean) => number;
2
+ export declare const removeIndentation: (text: string, excludeFirstLineForDetection?: boolean, fixedIndentation?: number) => string;
@@ -0,0 +1,14 @@
1
+ const emptyLinePattern = /^ *$$/;
2
+ export const detectIndentation = (text, excludeFirstLineForDetection) => {
3
+ const nonEmptyLines = text.split("\n").filter(line => !emptyLinePattern.test(line));
4
+ return nonEmptyLines[excludeFirstLineForDetection ? 1 : 0]?.match(/^ +/)?.[0].length ?? 0;
5
+ };
6
+ const mapLines = (text, lineMapper) => text.split("\n").map(lineMapper).join("\n");
7
+ export const removeIndentation = (text, excludeFirstLineForDetection, fixedIndentation) => {
8
+ const indentation = fixedIndentation ?? detectIndentation(text, excludeFirstLineForDetection);
9
+ if (indentation < 1) {
10
+ return text;
11
+ }
12
+ const regex = new RegExp(`^ {${indentation.toString()}}`);
13
+ return mapLines(text, line => line.replace(regex, ""));
14
+ };
@@ -53,7 +53,8 @@ export type ListBlockNode = {
53
53
  };
54
54
  export type ListItemNode = {
55
55
  kind: "listItem";
56
- content: InlineMarkdownNode[];
56
+ inlineLabel?: InlineMarkdownNode[];
57
+ content: BlockMarkdownNode[];
57
58
  };
58
59
  export type TableBlockNode = {
59
60
  kind: "table";
@@ -1,4 +1,5 @@
1
1
  import { chunk } from "./array.js";
2
+ import { detectIndentation, removeIndentation } from "./markdown/indentation.js";
2
3
  import { omitUndefinedKeys } from "./object.js";
3
4
  import { assertExhaustive } from "./typeSafety.js";
4
5
  const codeRule = {
@@ -229,26 +230,56 @@ const nodesForTrailingWhitespace = (text) => {
229
230
  return trailingWhitespace.length === 0 ? [] : [textNode(trailingWhitespace)];
230
231
  };
231
232
  const listRule = {
232
- pattern: /^((?:(?:\d+\.|[-*]) [^\n]+?)(?:\n(?:\d+\.|[-*]) [^\n]+?)*)(\n{2,}|\s*$)/,
233
- map: result => ({
234
- kind: "list",
235
- ordered: /^\d+\. /.test(result[0]),
236
- content: (result[1] ?? "").split("\n").map(item => ({
237
- kind: "listItem",
238
- content: parseInlineMarkdown(item.replace(/^\d+\. |[-*] /, "")),
239
- })),
240
- }),
241
- mapHighlighting: result => [
242
- ...(result[1] ?? "").split("\n").flatMap((item, index, array) => [
243
- {
244
- kind: "listItemMarker",
245
- content: /^(\d+\. |[-*] )/.exec(item)?.[1] ?? "",
246
- },
247
- ...parseInlineMarkdownForSyntaxHighlighting(item.replace(/^\d+\. |[-*] /, "")),
248
- ...(index < array.length - 1 ? [textNode("\n")] : []),
249
- ]),
250
- ...nodesForTrailingWhitespace(result[2]),
251
- ],
233
+ // pattern: /^((?:(?:\d+\.|[-*]) [^\n]+?)(?:\n(?:\d+\.|[-*]) [^\n]+?)*)(\n{2,}|\s*$)/,
234
+ pattern: /^((?:(?:\d+\. +[^\n]+(?:\n\d+\. +[^\n]+|\n {2,}[^\n]+|\n)*)|(?:- +[^\n]+(?:\n- +[^\n]+|\n {2,}[^\n]+|\n)*)))(\n{2,}|\s*$)/,
235
+ map: result => {
236
+ const listItemPairs = (result[1] ?? "").split(/(?:^|\n)(?:\d+\.|-)/).slice(1);
237
+ const listItems = listItemPairs.map((itemText) => {
238
+ const [primaryContent = "", _separator, ...additionalContents] = itemText.split(/(\n *\n|\n(?= +(?:\d+\.|-) ))/);
239
+ const additionalContent = additionalContents.join("");
240
+ const primaryContentNodes = parseInlineMarkdown(primaryContent.trim());
241
+ const additionalContentNodes = additionalContent
242
+ ? parseBlockMarkdown(removeIndentation(additionalContent))
243
+ : [];
244
+ if (additionalContentNodes.length < 2 &&
245
+ (additionalContentNodes[0] === undefined || additionalContentNodes[0].kind === "list")) {
246
+ return omitUndefinedKeys({
247
+ kind: "listItem",
248
+ inlineLabel: primaryContentNodes,
249
+ content: [additionalContentNodes[0]].filter(element => element !== undefined),
250
+ });
251
+ }
252
+ else {
253
+ return omitUndefinedKeys({
254
+ kind: "listItem",
255
+ content: additionalContentNodes,
256
+ });
257
+ }
258
+ });
259
+ return {
260
+ kind: "list",
261
+ ordered: /^\d+\. /.test(result[0]),
262
+ content: listItems,
263
+ };
264
+ },
265
+ mapHighlighting: result => {
266
+ const listItemPairs = chunk((result[1] ?? "").split(/(?:^|\n)(\d+\.|-)/).slice(1), 2);
267
+ const listItems = listItemPairs.flatMap(([marker = "", itemText = ""], itemIndex, itemArray) => {
268
+ const [primaryContent = "", separator, ...additionalContents] = itemText.split(/(\n *\n|\n(?= +(?:\d+\.|-) ))/);
269
+ const additionalContent = additionalContents.join("");
270
+ return [
271
+ {
272
+ kind: "listItemMarker",
273
+ content: marker,
274
+ },
275
+ ...parseInlineMarkdownForSyntaxHighlighting(primaryContent),
276
+ ...(separator ? [textNode(separator)] : []),
277
+ ...addIndentationToSyntax(parseBlockMarkdownForSyntaxHighlighting(removeIndentation(additionalContent)), detectIndentation(additionalContent)),
278
+ ...(itemIndex < itemArray.length - 1 ? [textNode("\n")] : []),
279
+ ];
280
+ });
281
+ return [...listItems, ...nodesForTrailingWhitespace(result[2])];
282
+ },
252
283
  };
253
284
  const paragraphRule = {
254
285
  pattern: /^((?:[^\n]+?)(?:\n[^\n]+?)*)(\n{2,}|\s*$)/,
@@ -444,10 +475,6 @@ const containerRule = {
444
475
  ...nodesForTrailingWhitespace(trailingWhitespace),
445
476
  ],
446
477
  };
447
- const removeIndentation = (text) => text
448
- .split("\n")
449
- .map(line => line.replace(/^ {2}/, ""))
450
- .join("\n");
451
478
  export const syntaxNodeToString = (node) => {
452
479
  switch (node.kind) {
453
480
  case "bold":
@@ -471,7 +498,7 @@ export const syntaxNodeToString = (node) => {
471
498
  return assertExhaustive(node);
472
499
  }
473
500
  };
474
- const addIndentationToSyntax = (nodes, nextUpperNode) => nodes.reduce((accNodes, currentNode, index) => {
501
+ const addIndentationToSyntax = (nodes, indentation, excludeFirstLine = false) => nodes.reduce((accNodes, currentNode) => {
475
502
  switch (currentNode.kind) {
476
503
  case "bold":
477
504
  case "italic":
@@ -482,7 +509,7 @@ const addIndentationToSyntax = (nodes, nextUpperNode) => nodes.reduce((accNodes,
482
509
  ...accNodes,
483
510
  {
484
511
  ...currentNode,
485
- content: addIndentationToSyntax(currentNode.content, nodes[index + 1] ?? nextUpperNode),
512
+ content: addIndentationToSyntax(currentNode.content, indentation, excludeFirstLine),
486
513
  },
487
514
  ];
488
515
  case "text":
@@ -493,15 +520,12 @@ const addIndentationToSyntax = (nodes, nextUpperNode) => nodes.reduce((accNodes,
493
520
  case "sectionMarker":
494
521
  case "footnoteMarker":
495
522
  case "definitionMarker": {
496
- const nextNode = nodes[index + 1] ?? nextUpperNode;
497
- const currentContent = currentNode.content.endsWith("\n") &&
498
- nextNode &&
499
- /^[^\n]*?\S+?/.test(syntaxNodeToString(nextNode))
500
- ? currentNode.content + " "
501
- : currentNode.content;
502
523
  return [
503
524
  ...accNodes,
504
- { ...currentNode, content: currentContent.replace(/\n([^\n]*?\S+?)/g, "\n $1") },
525
+ {
526
+ ...currentNode,
527
+ content: currentNode.content.replace(/\n(?!\n)/g, "\n" + " ".repeat(indentation)),
528
+ },
505
529
  ];
506
530
  }
507
531
  case "footnoteRef":
@@ -509,18 +533,18 @@ const addIndentationToSyntax = (nodes, nextUpperNode) => nodes.reduce((accNodes,
509
533
  default:
510
534
  return assertExhaustive(currentNode);
511
535
  }
512
- }, []);
536
+ }, excludeFirstLine ? [] : [textNode(" ".repeat(indentation))]);
513
537
  const footnoteRule = {
514
538
  pattern: /^\[\^([a-zA-Z0-9]+?)\]: (.+?(?:\n(?: {2}.+)?)*)(\n{2,}|\s*$)/,
515
539
  map: ([_match, label = "", content = "", _trailingWhitespace]) => ({
516
540
  kind: "footnote",
517
541
  label: label,
518
- content: parseBlockMarkdown(removeIndentation(content)),
542
+ content: parseBlockMarkdown(removeIndentation(content, true)),
519
543
  }),
520
544
  mapHighlighting: ([_match, label = "", content = "", trailingWhitespace,]) => [
521
545
  { kind: "footnoteMarker", content: `[^${label}]:` },
522
546
  textNode(" "),
523
- ...addIndentationToSyntax(parseBlockMarkdownForSyntaxHighlighting(removeIndentation(content))),
547
+ ...addIndentationToSyntax(parseBlockMarkdownForSyntaxHighlighting(removeIndentation(content, true)), detectIndentation(content, true), true),
524
548
  ...nodesForTrailingWhitespace(trailingWhitespace),
525
549
  ],
526
550
  };
@@ -537,7 +561,7 @@ const definitionListRule = {
537
561
  const definitions = definitionsText
538
562
  .split("\n:")
539
563
  .slice(1)
540
- .map(definition => parseBlockMarkdown(removeIndentation(definition.trim())));
564
+ .map(definition => parseBlockMarkdown(removeIndentation(definition.trim(), true)));
541
565
  return {
542
566
  kind: "definitionListItem",
543
567
  terms,
@@ -562,7 +586,7 @@ const definitionListRule = {
562
586
  .slice(1)
563
587
  .flatMap((definition, defIndex, defArray) => [
564
588
  { kind: "definitionMarker", content: ":" },
565
- ...addIndentationToSyntax(parseBlockMarkdownForSyntaxHighlighting(removeIndentation(definition))),
589
+ ...addIndentationToSyntax(parseBlockMarkdownForSyntaxHighlighting(removeIndentation(definition, true)), detectIndentation(definition, true), true),
566
590
  ...(defIndex < defArray.length - 1 ? [textNode("\n")] : []),
567
591
  ]);
568
592
  return [...terms, textNode("\n"), ...definitions];
@@ -11,13 +11,12 @@ export const BlockMarkdown = ({ node, outerHeadingLevel = 0, insertBefore, footn
11
11
  case "heading":
12
12
  const Tag = `h${(node.level + outerHeadingLevel).toString()}`;
13
13
  return (_jsxs(Tag, { children: [insertBefore, node.content.map((inline, ii) => (_jsx(InlineMarkdown, { node: inline }, ii)))] }));
14
- case "list":
15
- if (node.ordered) {
16
- return (_jsxs(_Fragment, { children: [insertBefore, _jsx("ol", { children: node.content.map((item, ii) => (_jsx("li", { children: item.content.map((inline, iii) => (_jsx(InlineMarkdown, { node: inline }, iii))) }, ii))) })] }));
17
- }
18
- else {
19
- return (_jsxs(_Fragment, { children: [insertBefore, _jsx("ul", { children: node.content.map((item, ii) => (_jsx("li", { children: item.content.map((inline, iii) => (_jsx(InlineMarkdown, { node: inline }, iii))) }, ii))) })] }));
20
- }
14
+ case "list": {
15
+ const Tag = node.ordered ? "ol" : "ul";
16
+ return (_jsxs(_Fragment, { children: [insertBefore, _jsx(Tag, { children: node.content.map((item, ii) => (_jsxs("li", { children: [item.inlineLabel && item.inlineLabel.length > 0
17
+ ? item.inlineLabel.map((inline, iii) => (_jsx(InlineMarkdown, { node: inline }, iii)))
18
+ : null, item.content.map((content, iii) => (_jsx(BlockMarkdown, { node: content }, iii)))] }, ii))) })] }));
19
+ }
21
20
  case "table":
22
21
  return (_jsxs(_Fragment, { children: [insertBefore, _jsxs("table", { children: [node.caption !== undefined && (_jsx("caption", { children: node.caption.map((inline, ci) => (_jsx(InlineMarkdown, { node: inline }, ci))) })), _jsx("thead", { children: _jsx(TableRow, { columns: node.columns, cells: node.header, cellType: "th" }) }), checkTableRowsAreSections(node.rows) ? (node.rows.map((section, si) => (_jsxs("tbody", { children: [section.header && (_jsx(TableRow, { columns: node.columns, cells: section.header, cellType: "th" })), section.rows.map((row, ri) => (_jsx(TableRow, { columns: node.columns, cells: row.cells }, ri)))] }, si)))) : (_jsx("tbody", { children: node.rows.map((row, ri) => (_jsx(TableRow, { columns: node.columns, cells: row.cells }, ri))) }))] })] }));
23
22
  case "container":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsondb",
3
- "version": "0.11.1",
3
+ "version": "0.11.3",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "Lukas Obermann",