tsondb 0.7.11 → 0.8.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.
@@ -24,45 +24,83 @@ type AttributedStringMarkdownNode = {
24
24
  attributes: Record<string, string | number | boolean>;
25
25
  content: InlineMarkdownNode[];
26
26
  };
27
- export type InlineMarkdownNode = BoldMarkdownNode | ItalicMarkdownNode | CodeMarkdownNode | LinkMarkdownNode | AttributedStringMarkdownNode | TextNode;
28
- type ParagraphBlockNode = {
27
+ type FootnoteRefInlineNode = {
28
+ kind: "footnoteRef";
29
+ label: string;
30
+ };
31
+ export type InlineMarkdownNode = BoldMarkdownNode | ItalicMarkdownNode | CodeMarkdownNode | LinkMarkdownNode | AttributedStringMarkdownNode | TextNode | FootnoteRefInlineNode;
32
+ export declare const checkTableRowsAreSections: (rows: TableRowBlockNode[] | TableSectionBlockNode[]) => rows is TableSectionBlockNode[];
33
+ export declare const syntaxNodeToString: (node: BlockSyntaxMarkdownNode) => string;
34
+ export type ParagraphBlockNode = {
29
35
  kind: "paragraph";
30
36
  content: InlineMarkdownNode[];
31
37
  };
32
- type HeadingBlockNode = {
38
+ export type HeadingBlockNode = {
33
39
  kind: "heading";
34
40
  level: number;
35
41
  content: InlineMarkdownNode[];
36
42
  };
37
- type ListBlockNode = {
43
+ export type ListBlockNode = {
38
44
  kind: "list";
39
45
  ordered: boolean;
40
46
  content: ListItemNode[];
41
47
  };
42
- type ListItemNode = {
43
- kind: "listitem";
48
+ export type ListItemNode = {
49
+ kind: "listItem";
44
50
  content: InlineMarkdownNode[];
45
51
  };
46
- type TableBlockNode = {
52
+ export type TableBlockNode = {
47
53
  kind: "table";
48
54
  caption?: InlineMarkdownNode[];
49
- header: InlineMarkdownNode[][];
50
- rows: InlineMarkdownNode[][][];
55
+ header: TableCellBlockNode[];
56
+ rows: TableRowBlockNode[] | TableSectionBlockNode[];
57
+ };
58
+ export type TableSectionBlockNode = {
59
+ kind: "tableSection";
60
+ header?: TableCellBlockNode[];
61
+ rows: TableRowBlockNode[];
62
+ };
63
+ export type TableRowBlockNode = {
64
+ kind: "tableRow";
65
+ cells: TableCellBlockNode[];
66
+ };
67
+ export type TableCellBlockNode = {
68
+ kind: "tableCell";
69
+ colSpan?: number;
70
+ content: InlineMarkdownNode[];
71
+ };
72
+ export type SectionBlockNode = {
73
+ kind: "section";
74
+ name?: string;
75
+ content: BlockMarkdownNode[];
51
76
  };
52
- export type BlockMarkdownNode = ParagraphBlockNode | HeadingBlockNode | ListBlockNode | TableBlockNode;
77
+ export type FootnoteBlockNode = {
78
+ kind: "footnote";
79
+ label: string;
80
+ content: BlockMarkdownNode[];
81
+ };
82
+ export type BlockMarkdownNode = ParagraphBlockNode | HeadingBlockNode | ListBlockNode | TableBlockNode | SectionBlockNode | FootnoteBlockNode;
53
83
  type ListItemMarkerSyntaxNode = {
54
- kind: "listitemmarker";
84
+ kind: "listItemMarker";
55
85
  content: string;
56
86
  };
57
87
  type TableMarkerSyntaxNode = {
58
- kind: "tablemarker";
88
+ kind: "tableMarker";
59
89
  content: string;
60
90
  };
61
91
  type HeadingMarkerSyntaxNode = {
62
- kind: "headingmarker";
92
+ kind: "headingMarker";
93
+ content: string;
94
+ };
95
+ type SectionMarkerSyntaxNode = {
96
+ kind: "sectionMarker";
97
+ content: string;
98
+ };
99
+ type FootnoteMarkerSyntaxNode = {
100
+ kind: "footnoteMarker";
63
101
  content: string;
64
102
  };
65
- type SyntaxNode = ListItemMarkerSyntaxNode | TableMarkerSyntaxNode | HeadingMarkerSyntaxNode;
103
+ type SyntaxNode = ListItemMarkerSyntaxNode | TableMarkerSyntaxNode | HeadingMarkerSyntaxNode | SectionMarkerSyntaxNode | FootnoteMarkerSyntaxNode;
66
104
  export type BlockSyntaxMarkdownNode = InlineMarkdownNode | SyntaxNode;
67
105
  export declare const parseBlockMarkdown: (text: string) => BlockMarkdownNode[];
68
106
  export declare const parseBlockMarkdownForSyntaxHighlighting: (text: string) => BlockSyntaxMarkdownNode[];
@@ -149,6 +149,17 @@ const attributedRule = {
149
149
  };
150
150
  },
151
151
  };
152
+ const footnoteRefRule = {
153
+ pattern: /(?<!\\)\[\^([a-zA-Z0-9*]+?)\]/,
154
+ map: ([_match, label = ""]) => ({
155
+ kind: "footnoteRef",
156
+ label,
157
+ }),
158
+ mapHighlighting: ([match]) => ({
159
+ kind: "footnoteRef",
160
+ label: match,
161
+ }),
162
+ };
152
163
  const textNode = (content) => ({
153
164
  kind: "text",
154
165
  content: content,
@@ -173,6 +184,7 @@ const inlineRules = [
173
184
  italicWithBoldRule,
174
185
  boldRule,
175
186
  italicRule,
187
+ footnoteRefRule,
176
188
  textRule,
177
189
  ];
178
190
  const parseForInlineRules = (rules, text, forSyntaxHighlighting) => {
@@ -203,19 +215,19 @@ const nodesForTrailingWhitespace = (text) => {
203
215
  return trailingWhitespace.length === 0 ? [] : [textNode(trailingWhitespace)];
204
216
  };
205
217
  const listRule = {
206
- pattern: /^((?:(?:\d+\.|[-*]) [^\n]+?)(?:\n(?:\d+\.|[-*]) [^\n]+?)*)(\n{2,}|$)/,
218
+ pattern: /^((?:(?:\d+\.|[-*]) [^\n]+?)(?:\n(?:\d+\.|[-*]) [^\n]+?)*)(\n{2,}|\s*$)/,
207
219
  map: result => ({
208
220
  kind: "list",
209
221
  ordered: /^\d+\. /.test(result[0]),
210
222
  content: (result[1] ?? "").split("\n").map(item => ({
211
- kind: "listitem",
223
+ kind: "listItem",
212
224
  content: parseInlineMarkdown(item.replace(/^\d+\. |[-*] /, ""), false),
213
225
  })),
214
226
  }),
215
227
  mapHighlighting: result => [
216
228
  ...(result[1] ?? "").split("\n").flatMap((item, index, array) => [
217
229
  {
218
- kind: "listitemmarker",
230
+ kind: "listItemMarker",
219
231
  content: /^(\d+\. |[-*] )/.exec(item)?.[1] ?? "",
220
232
  },
221
233
  ...parseInlineMarkdown(item.replace(/^\d+\. |[-*] /, ""), true),
@@ -243,28 +255,111 @@ const headingRule = {
243
255
  content: parseInlineMarkdown(result[3] ?? "", false),
244
256
  }),
245
257
  mapHighlighting: result => [
246
- { kind: "headingmarker", content: (result[1] ?? "") + (result[2] ?? "") },
258
+ { kind: "headingMarker", content: (result[1] ?? "") + (result[2] ?? "") },
247
259
  ...parseInlineMarkdown(result[3] ?? "", true),
248
260
  ...nodesForTrailingWhitespace(result[4]),
249
261
  ],
250
262
  };
251
- const removeSurroundingPipes = (text) => text.replace(/^\|/, "").replace(/\|$/, "");
252
263
  const tableMarker = (text) => ({
253
- kind: "tablemarker",
264
+ kind: "tableMarker",
254
265
  content: text,
255
266
  });
267
+ const sectionSeparatorPattern = /^\|? *-{3,} *(?:\| *-{3,} *)+\|?$|^\|? *={3,} *(?:\| *={3,} *)+\|?$/;
268
+ const sectionWithHeaderSeparatorPattern = /^\|? *={3,} *(?:\| *={3,} *)+\|?$/;
269
+ export const checkTableRowsAreSections = (rows) => rows.every(row => row.kind === "tableSection");
270
+ const parseContentRow = (row) => row
271
+ .replace(/^\|/, "")
272
+ .split(/(\|+)/)
273
+ .reduce((acc, segment, index, arr) => {
274
+ if (index % 2 === 0 && segment.trim() !== "") {
275
+ const colSpan = arr[index + 1]?.length;
276
+ return [
277
+ ...acc,
278
+ omitUndefinedKeys({
279
+ kind: "tableCell",
280
+ colSpan: colSpan !== undefined && colSpan > 1 ? colSpan : undefined,
281
+ content: parseInlineMarkdown(segment.trim(), false),
282
+ }),
283
+ ];
284
+ }
285
+ return acc;
286
+ }, []);
287
+ const parseContentRowForSyntaxHighlighting = (row) => row.split(/(\|+)/).reduce((acc, segment, index) => {
288
+ if (index % 2 === 0) {
289
+ return [...acc, ...parseInlineMarkdown(segment, true)];
290
+ }
291
+ else {
292
+ return [...acc, tableMarker(segment)];
293
+ }
294
+ }, []);
256
295
  const tableRule = {
257
- pattern: /^(?:(\|#)(.+?)(#\|)\n)?(\|)?(.+?(?:(?<!\\)\|.+?)+)((?<!\\)\|)?\n((?:\| *)?(?:-{3,}|:-{2,}|-{2,}:|:-+:)(?: *\| *(?:-{3,}|:-{2,}|-{2,}:|:-+:))*(?: *\|)?)((?:\n\|?.+?(?:(?<!\\)\|.+?)*(?<!\\)\|?)+)(\n{2,}|$)/,
296
+ pattern: /^(?:(\|#)(.+?)(#\|)\n)?(\|)?(.+?(?:(?<!\\)\|.+?)+)((?<!\\)\|)?\n((?:\| *)?(?:-{3,}|:-{2,}|-{2,}:|:-+:)(?: *\| *(?:-{3,}|:-{2,}|-{2,}:|:-+:))*(?: *\|)?)((?:\n\|?.+?(?:(?<!\\)\|+.+?)*(?:(?<!\\)\|+)?)+)(\n{2,}|$)/,
258
297
  map: ([_res, _captionMarkerStart, caption, _captionMarkerEnd, _headerMarkerStart, headers, _headerMarkerEnd, _bodySeparators, body, _trailingWhitespace,]) => omitUndefinedKeys({
259
298
  kind: "table",
260
299
  caption: caption !== undefined ? parseInlineMarkdown(caption.trim(), false) : undefined,
261
- header: headers?.split("|").map(th => parseInlineMarkdown(th.trim(), false)) ?? [],
300
+ header: headers ? parseContentRow(headers) : [],
262
301
  rows: body
263
302
  ?.split("\n")
264
- .slice(1)
265
- .map(tr => removeSurroundingPipes(tr)
266
- .split("|")
267
- .map(tc => parseInlineMarkdown(tc.trim(), false))) ?? [],
303
+ .slice(1) // leading newline due to regex
304
+ .reduce((accRows, row) => {
305
+ if (sectionSeparatorPattern.test(row)) {
306
+ const hasHeader = sectionWithHeaderSeparatorPattern.test(row);
307
+ const newSection = omitUndefinedKeys({
308
+ kind: "tableSection",
309
+ header: hasHeader ? [] : undefined,
310
+ rows: [],
311
+ });
312
+ if (accRows[0] === undefined) {
313
+ return [newSection];
314
+ }
315
+ if (checkTableRowsAreSections(accRows)) {
316
+ return [...accRows, newSection];
317
+ }
318
+ return [{ kind: "tableSection", rows: accRows }, newSection];
319
+ }
320
+ const lastRow = accRows[accRows.length - 1];
321
+ const rowContent = parseContentRow(row);
322
+ if (lastRow === undefined) {
323
+ return [
324
+ {
325
+ kind: "tableRow",
326
+ cells: rowContent,
327
+ },
328
+ ];
329
+ }
330
+ if (checkTableRowsAreSections(accRows)) {
331
+ const lastSection = lastRow;
332
+ if (lastSection.header !== undefined && lastSection.header.length === 0) {
333
+ return [
334
+ ...accRows.slice(0, -1),
335
+ {
336
+ ...lastSection,
337
+ header: rowContent,
338
+ },
339
+ ];
340
+ }
341
+ return [
342
+ ...accRows.slice(0, -1),
343
+ {
344
+ ...lastSection,
345
+ rows: [
346
+ ...lastSection.rows,
347
+ {
348
+ kind: "tableRow",
349
+ cells: rowContent,
350
+ },
351
+ ],
352
+ },
353
+ ];
354
+ }
355
+ return [
356
+ ...accRows,
357
+ {
358
+ kind: "tableRow",
359
+ cells: rowContent,
360
+ },
361
+ ];
362
+ }, []) ?? [],
268
363
  }),
269
364
  mapHighlighting: ([_res, captionMarkerStart, caption, captionMarkerEnd, headerMarkerStart, headers, headerMarkerEnd, bodySeparators, body, trailingWhitespace,]) => [
270
365
  ...(caption !== undefined
@@ -281,22 +376,121 @@ const tableRule = {
281
376
  .flatMap((th, i) => i === 0
282
377
  ? parseInlineMarkdown(th, true)
283
378
  : [tableMarker("|"), ...parseInlineMarkdown(th, true)]) ?? []),
284
- tableMarker((headerMarkerEnd ?? "") + "\n" + (bodySeparators ?? "")),
379
+ tableMarker(headerMarkerEnd ?? ""),
380
+ textNode("\n"),
381
+ tableMarker(bodySeparators ?? ""),
285
382
  ...(body
286
383
  ?.split("\n")
287
384
  .slice(1)
288
385
  .flatMap((tr) => [
289
386
  textNode("\n"),
290
- ...tr
291
- .split("|")
292
- .flatMap((tc, i) => i === 0
293
- ? parseInlineMarkdown(tc, true)
294
- : [tableMarker("|"), ...parseInlineMarkdown(tc, true)]),
387
+ ...(sectionSeparatorPattern.test(tr)
388
+ ? [tableMarker(tr)]
389
+ : parseContentRowForSyntaxHighlighting(tr)),
295
390
  ]) ?? []),
296
391
  ...nodesForTrailingWhitespace(trailingWhitespace),
297
392
  ],
298
393
  };
299
- const blockRules = [headingRule, tableRule, listRule, paragraphRule];
394
+ const sectionRule = {
395
+ pattern: /^::: (\w+)?(\n+)(.+?)\n:::(\n{2,}|\s*$)/s,
396
+ map: ([_match, name, _leadingContentWhitespace, content, _trailingWhitespace,]) => ({
397
+ kind: "section",
398
+ name: name ?? undefined,
399
+ content: parseBlockMarkdown(content ?? ""),
400
+ }),
401
+ mapHighlighting: ([_match, name, leadingContentWhitespace = "", content, trailingWhitespace,]) => [
402
+ { kind: "sectionMarker", content: `::: ${name ?? ""}` },
403
+ textNode(leadingContentWhitespace),
404
+ ...parseBlockMarkdownForSyntaxHighlighting(content ?? ""),
405
+ textNode("\n"),
406
+ { kind: "sectionMarker", content: ":::" },
407
+ ...nodesForTrailingWhitespace(trailingWhitespace),
408
+ ],
409
+ };
410
+ const removeIndentation = (text) => text
411
+ .split("\n")
412
+ .map(line => line.replace(/^ {2}/, ""))
413
+ .join("\n");
414
+ export const syntaxNodeToString = (node) => {
415
+ switch (node.kind) {
416
+ case "bold":
417
+ case "italic":
418
+ case "link":
419
+ case "attributed":
420
+ return node.content.map(syntaxNodeToString).join("");
421
+ case "text":
422
+ case "code":
423
+ case "listItemMarker":
424
+ case "tableMarker":
425
+ case "headingMarker":
426
+ case "sectionMarker":
427
+ case "footnoteMarker":
428
+ return node.content;
429
+ case "footnoteRef":
430
+ return node.label;
431
+ default:
432
+ return assertExhaustive(node);
433
+ }
434
+ };
435
+ const addIndentationToSyntax = (nodes, nextUpperNode) => nodes.reduce((accNodes, currentNode, index) => {
436
+ switch (currentNode.kind) {
437
+ case "bold":
438
+ case "italic":
439
+ case "link":
440
+ case "attributed":
441
+ return [
442
+ ...accNodes,
443
+ {
444
+ ...currentNode,
445
+ content: addIndentationToSyntax(currentNode.content, nodes[index + 1] ?? nextUpperNode),
446
+ },
447
+ ];
448
+ case "text":
449
+ case "code":
450
+ case "listItemMarker":
451
+ case "tableMarker":
452
+ case "headingMarker":
453
+ case "sectionMarker":
454
+ case "footnoteMarker": {
455
+ const nextNode = nodes[index + 1] ?? nextUpperNode;
456
+ const currentContent = currentNode.content.endsWith("\n") &&
457
+ nextNode &&
458
+ /^[^\n]*?\S+?/.test(syntaxNodeToString(nextNode))
459
+ ? currentNode.content + " "
460
+ : currentNode.content;
461
+ return [
462
+ ...accNodes,
463
+ { ...currentNode, content: currentContent.replace(/\n([^\n]*?\S+?)/g, "\n $1") },
464
+ ];
465
+ }
466
+ case "footnoteRef":
467
+ return [...accNodes, currentNode];
468
+ default:
469
+ return assertExhaustive(currentNode);
470
+ }
471
+ }, []);
472
+ const footnoteRule = {
473
+ pattern: /^\[\^([a-zA-Z0-9*]+?)\]: (.+?(?:\n(?: {2}.+)?)*)(\n{2,}|\s*$)/,
474
+ map: ([_match, label = "", content = "", _trailingWhitespace]) => ({
475
+ kind: "footnote",
476
+ label: label,
477
+ content: parseBlockMarkdown(removeIndentation(content)),
478
+ }),
479
+ mapHighlighting: ([_match, label = "", content = "", trailingWhitespace,]) => [
480
+ { kind: "footnoteMarker", content: `[^${label}]:` },
481
+ textNode(" "),
482
+ ...addIndentationToSyntax(parseBlockMarkdownForSyntaxHighlighting(removeIndentation(content))),
483
+ ...nodesForTrailingWhitespace(trailingWhitespace),
484
+ ],
485
+ };
486
+ const blockRules = [
487
+ sectionRule,
488
+ headingRule,
489
+ footnoteRule,
490
+ tableRule,
491
+ listRule,
492
+ paragraphRule,
493
+ ];
300
494
  const parseActiveBlockRule = (rule, res) => [
301
495
  rule.map(res),
302
496
  ];
@@ -341,9 +535,12 @@ const reduceSyntaxNode = (node) => {
341
535
  case "link":
342
536
  case "attributed":
343
537
  case "text":
344
- case "listitemmarker":
345
- case "tablemarker":
346
- case "headingmarker":
538
+ case "listItemMarker":
539
+ case "tableMarker":
540
+ case "headingMarker":
541
+ case "sectionMarker":
542
+ case "footnoteMarker":
543
+ case "footnoteRef":
347
544
  return node;
348
545
  default:
349
546
  return assertExhaustive(node);
@@ -354,9 +551,12 @@ const syntaxNodeMergeRules = {
354
551
  italic: (a, b) => ({ ...a, content: [...a.content, ...b.content] }),
355
552
  code: (a, b) => ({ ...a, content: a.content + b.content }),
356
553
  text: (a, b) => ({ ...a, content: a.content + b.content }),
357
- listitemmarker: (a, b) => ({ ...a, content: a.content + b.content }),
358
- tablemarker: (a, b) => ({ ...a, content: a.content + b.content }),
359
- headingmarker: (a, b) => ({ ...a, content: a.content + b.content }),
554
+ listItemMarker: (a, b) => ({ ...a, content: a.content + b.content }),
555
+ tableMarker: (a, b) => ({ ...a, content: a.content + b.content }),
556
+ headingMarker: (a, b) => ({ ...a, content: a.content + b.content }),
557
+ sectionMarker: (a, b) => ({ ...a, content: a.content + b.content }),
558
+ footnoteMarker: (a, b) => ({ ...a, content: a.content + b.content }),
559
+ footnoteRef: null,
360
560
  link: null,
361
561
  attributed: null,
362
562
  };
@@ -14,7 +14,7 @@ export const Git = () => {
14
14
  if (!client || !client.isRepo) {
15
15
  return null;
16
16
  }
17
- return (_jsxs(_Fragment, { children: [_jsxs(ModalDialog, { open: isOpen, class: "git", closedBy: "any", onClose: () => {
17
+ return (_jsxs(_Fragment, { children: [_jsxs(ModalDialog, { open: isOpen, class: "git" + (!isGitAlwaysOpen ? " git--no-sidebar" : ""), closedBy: "any", onClose: () => {
18
18
  setIsOpen(false);
19
19
  }, children: [_jsxs("header", { children: [_jsx("h2", { children: (() => {
20
20
  switch (mode) {
@@ -1,8 +1,9 @@
1
1
  import type { FunctionalComponent } from "preact";
2
- import type { BlockMarkdownNode } from "../../shared/utils/markdown.ts";
2
+ import { type BlockMarkdownNode } from "../../shared/utils/markdown.ts";
3
3
  type Props = {
4
4
  node: BlockMarkdownNode;
5
5
  outerHeadingLevel?: number;
6
+ insertBefore?: preact.ComponentChildren;
6
7
  };
7
8
  export declare const BlockMarkdown: FunctionalComponent<Props>;
8
9
  export {};
@@ -1,22 +1,34 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "preact/jsx-runtime";
2
+ import { checkTableRowsAreSections, } from "../../shared/utils/markdown.js";
3
+ import { assertExhaustive } from "../../shared/utils/typeSafety.js";
2
4
  import { InlineMarkdown } from "./InlineMarkdown.js";
3
- export const BlockMarkdown = ({ node, outerHeadingLevel = 0 }) => {
5
+ export const BlockMarkdown = ({ node, outerHeadingLevel = 0, insertBefore, }) => {
4
6
  switch (node.kind) {
5
7
  case "paragraph":
6
- return (_jsx("p", { children: node.content.map((inline, ii) => (_jsx(InlineMarkdown, { node: inline }, ii))) }));
8
+ return (_jsxs("p", { children: [insertBefore, node.content.map((inline, ii) => (_jsx(InlineMarkdown, { node: inline }, ii)))] }));
7
9
  case "heading":
8
10
  const Tag = `h${(node.level + outerHeadingLevel).toString()}`;
9
- return (_jsx(Tag, { children: node.content.map((inline, ii) => (_jsx(InlineMarkdown, { node: inline }, ii))) }));
11
+ return (_jsxs(Tag, { children: [insertBefore, node.content.map((inline, ii) => (_jsx(InlineMarkdown, { node: inline }, ii)))] }));
10
12
  case "list":
11
13
  if (node.ordered) {
12
- return (_jsx("ol", { children: node.content.map((item, ii) => (_jsx("li", { children: item.content.map((inline, iii) => (_jsx(InlineMarkdown, { node: inline }, iii))) }, ii))) }));
14
+ 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))) })] }));
13
15
  }
14
16
  else {
15
- return (_jsx("ul", { children: node.content.map((item, ii) => (_jsx("li", { children: item.content.map((inline, iii) => (_jsx(InlineMarkdown, { node: inline }, iii))) }, ii))) }));
17
+ 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))) })] }));
16
18
  }
17
19
  case "table":
18
- return (_jsxs("table", { children: [node.caption !== undefined && (_jsx("caption", { children: node.caption.map((inline, ci) => (_jsx(InlineMarkdown, { node: inline }, ci))) })), _jsx("thead", { children: _jsx("tr", { children: node.header.map((th, hi) => (_jsx("th", { children: th.map((inline, hii) => (_jsx(InlineMarkdown, { node: inline }, hii))) }, hi))) }) }), _jsx("tbody", { children: node.rows.map((tr, ri) => (_jsx("tr", { children: tr.map((tc, ci) => (_jsx("td", { children: tc.map((inline, cii) => (_jsx(InlineMarkdown, { node: inline }, cii))) }, ci))) }, ri))) })] }));
20
+ 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, { cells: node.header, cellType: "th" }) }), checkTableRowsAreSections(node.rows) ? (node.rows.map((section, si) => (_jsxs("tbody", { children: [section.header && _jsx(TableRow, { cells: section.header, cellType: "th" }), section.rows.map((row, ri) => (_jsx(TableRow, { cells: row.cells }, ri)))] }, si)))) : (_jsx("tbody", { children: node.rows.map((row, ri) => (_jsx(TableRow, { cells: row.cells }, ri))) }))] })] }));
21
+ case "section":
22
+ return (_jsxs("div", { class: node.name, children: [insertBefore, node.content.map((childNode, i) => (_jsx(BlockMarkdown, { node: childNode }, i)))] }));
23
+ case "footnote": {
24
+ const label = (_jsxs(_Fragment, { children: [_jsxs("span", { class: "footnote-label", children: [node.label, /^\*+$/.test(node.label) ? ")" : ":"] }), " "] }));
25
+ return (_jsxs("div", { role: "note", children: [insertBefore, node.content.map((n, i) => (_jsx(BlockMarkdown, { node: n, insertBefore: label }, i)))] }));
26
+ }
19
27
  default:
20
- return null;
28
+ return assertExhaustive(node);
21
29
  }
22
30
  };
31
+ const TableRow = ({ cells, cellType = "td", }) => {
32
+ const CellTag = cellType;
33
+ return (_jsx("tr", { children: cells.map((tc, ci) => (_jsx(CellTag, { scope: cellType === "th" && cells.length === 1 ? "colgroup" : undefined, colSpan: tc.colSpan, children: tc.content.map((inline, cii) => (_jsx(InlineMarkdown, { node: inline }, cii))) }, ci))) }));
34
+ };
@@ -2,12 +2,18 @@ import { jsx as _jsx } from "preact/jsx-runtime";
2
2
  import { InlineMarkdown } from "./InlineMarkdown.js";
3
3
  export const BlockMarkdownHighlighting = ({ node }) => {
4
4
  switch (node.kind) {
5
- case "listitemmarker":
5
+ case "listItemMarker":
6
6
  return _jsx("span", { class: "list-item-marker", children: node.content });
7
- case "tablemarker":
7
+ case "tableMarker":
8
8
  return _jsx("span", { class: "table-marker", children: node.content });
9
- case "headingmarker":
9
+ case "headingMarker":
10
10
  return _jsx("span", { class: "heading-marker", children: node.content });
11
+ case "sectionMarker":
12
+ return _jsx("span", { class: "section-marker", children: node.content });
13
+ case "footnoteMarker":
14
+ return _jsx("span", { class: "footnote-marker", children: node.content });
15
+ case "footnoteRef":
16
+ return _jsx("span", { class: "footnote-marker", children: node.label });
11
17
  default:
12
18
  return _jsx(InlineMarkdown, { node: node });
13
19
  }
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { Fragment } from "preact";
3
+ import { assertExhaustive } from "../../shared/utils/typeSafety.js";
3
4
  const emptyNode = { kind: "text", content: "" };
4
5
  export const InlineMarkdown = ({ node }) => {
5
6
  switch (node.kind) {
@@ -21,7 +22,11 @@ export const InlineMarkdown = ({ node }) => {
21
22
  const trailingNodes = node.content.slice(attributesEnd);
22
23
  return (_jsxs("span", { class: "attributed", ...Object.fromEntries(Object.entries(node.attributes).map(([k, v]) => [`data-${k}`, v.toString()])), children: [leadingNodes.map((inline, i) => (_jsx(InlineMarkdown, { node: inline }, i))), Array.from({ length: count }, (_, i) => (_jsxs(Fragment, { children: [_jsx("span", { class: "attributed__name", children: _jsx(InlineMarkdown, { node: attributes[i * 4] ?? emptyNode }) }), _jsx("span", { class: "attributed__separator", children: _jsx(InlineMarkdown, { node: attributes[i * 4 + 1] ?? emptyNode }) }), _jsx("span", { class: "attributed__value", children: _jsx(InlineMarkdown, { node: attributes[i * 4 + 2] ?? emptyNode }) }), i < count - 1 && (_jsx("span", { class: "attributed__separator", children: _jsx(InlineMarkdown, { node: attributes[i * 4 + 3] ?? emptyNode }) }))] }, `attr-${(i + 1).toString()}`))), trailingNodes.map((inline, i) => (_jsx(InlineMarkdown, { node: inline }, i)))] }));
23
24
  }
25
+ case "footnoteRef":
26
+ return /^\*+$/.test(node.label) ? (_jsx("span", { class: "footnote-ref", children: node.label })) : (_jsx("sup", { class: "footnote-ref", children: node.label }));
24
27
  case "text":
25
28
  return node.content;
29
+ default:
30
+ return assertExhaustive(node);
26
31
  }
27
32
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsondb",
3
- "version": "0.7.11",
3
+ "version": "0.8.0",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "Lukas Obermann",
@@ -63,6 +63,8 @@
63
63
  --color-syntax-table-marker: rgb(237, 58, 118);
64
64
  --color-syntax-attributed: rgb(48, 81, 228);
65
65
  --color-syntax-heading-marker: rgb(62, 189, 191);
66
+ --color-syntax-footnote: rgb(48, 126, 228);
67
+ --color-syntax-section: rgb(172, 147, 3);
66
68
  }
67
69
 
68
70
  @media (prefers-color-scheme: dark) {
@@ -105,6 +107,8 @@
105
107
  --color-syntax-table-marker: rgb(244, 135, 171);
106
108
  --color-syntax-attributed: rgb(137, 157, 244);
107
109
  --color-syntax-heading-marker: rgb(140, 229, 231);
110
+ --color-syntax-footnote: rgb(157, 199, 255);
111
+ --color-syntax-section: rgb(247, 231, 135);
108
112
  }
109
113
  }
110
114
 
@@ -704,6 +708,7 @@ form > .field--container {
704
708
  .editor--markdown input,
705
709
  .editor--markdown .textarea-grow-wrap__mirror {
706
710
  font-family: var(--font-mono);
711
+ line-height: 1.5;
707
712
  }
708
713
 
709
714
  .editor--markdown textarea {
@@ -732,6 +737,14 @@ form > .field--container {
732
737
  color: var(--color-syntax-heading-marker);
733
738
  }
734
739
 
740
+ .editor-highlighting .footnote-marker {
741
+ color: var(--color-syntax-footnote);
742
+ }
743
+
744
+ .editor-highlighting .section-marker {
745
+ color: var(--color-syntax-section);
746
+ }
747
+
735
748
  .preview .attributed {
736
749
  text-decoration-line: underline;
737
750
  text-decoration-style: dashed;
@@ -1081,7 +1094,7 @@ dialog.git {
1081
1094
  }
1082
1095
 
1083
1096
  @media (min-width: 80rem) {
1084
- dialog.git header .git__tab--files {
1097
+ dialog.git:not(.git--no-sidebar) header .git__tab--files {
1085
1098
  display: none;
1086
1099
  }
1087
1100
  }