@surrealdb/ui 1.2.12 → 1.2.14

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.
Files changed (99) hide show
  1. package/.claude/launch.json +17 -0
  2. package/.oxfmtrc.json +27 -0
  3. package/.oxlintrc.json +23 -0
  4. package/.zed/settings.json +34 -34
  5. package/AGENTS.md +25 -19
  6. package/CLAUDE.md +111 -0
  7. package/README.md +15 -10
  8. package/dist/icons.d.ts +4 -0
  9. package/dist/icons.js +91 -89
  10. package/dist/icons.js.map +1 -1
  11. package/dist/ui.css +1 -1
  12. package/dist/ui.d.ts +259 -1
  13. package/dist/ui.js +9807 -12265
  14. package/dist/ui.js.map +1 -1
  15. package/doc/code-style.md +264 -0
  16. package/doc/release.md +102 -0
  17. package/doc/stacker-plan.md +219 -0
  18. package/package.json +120 -116
  19. package/release-notes.md +0 -0
  20. package/res/_mixins.scss +15 -11
  21. package/tests/_setup/e2e-helpers.tsx +85 -85
  22. package/tests/_setup/portable-stories.ts +11 -10
  23. package/tests/e2e/MarkdownEditor/content-blocks.test.tsx +140 -139
  24. package/tests/e2e/MarkdownEditor/edits.test.tsx +101 -100
  25. package/tests/e2e/MarkdownEditor/heading-fold.test.tsx +35 -34
  26. package/tests/e2e/MarkdownEditor/hybrid-widgets.test.tsx +178 -177
  27. package/tests/e2e/MarkdownEditor/image-on-image.test.tsx +50 -49
  28. package/tests/e2e/MarkdownEditor/jsx-block-content.test.tsx +195 -194
  29. package/tests/e2e/MarkdownEditor/jsx-highlight.test.tsx +47 -46
  30. package/tests/e2e/MarkdownEditor/jsx-inline-badges.test.tsx +35 -34
  31. package/tests/e2e/MarkdownEditor/jsx-inline-click.test.tsx +39 -38
  32. package/tests/e2e/MarkdownEditor/jsx-selection.test.tsx +28 -27
  33. package/tests/e2e/MarkdownEditor/link-placeholder.test.tsx +49 -48
  34. package/tests/e2e/MarkdownEditor/media-align.test.tsx +40 -39
  35. package/tests/e2e/MarkdownEditor/media-edit.test.tsx +49 -48
  36. package/tests/e2e/MarkdownEditor/media-sizing.test.tsx +108 -107
  37. package/tests/e2e/MarkdownEditor/modes.test.tsx +79 -78
  38. package/tests/e2e/MarkdownEditor/onimage-parity.test.tsx +29 -28
  39. package/tests/e2e/MarkdownEditor/regressions.test.tsx +194 -193
  40. package/tests/e2e/MarkdownEditor/slash-commands.test.tsx +81 -80
  41. package/tests/e2e/MarkdownEditor/table-click.test.tsx +36 -35
  42. package/tests/e2e/MarkdownEditor/table-controls.test.tsx +44 -43
  43. package/tests/e2e/MarkdownEditor/table-format.test.tsx +28 -27
  44. package/tests/e2e/MarkdownEditor/undo-redo.test.tsx +22 -21
  45. package/tests/e2e/MarkdownViewer/parity.test.tsx +144 -143
  46. package/tests/e2e/MarkdownViewer/render.test.tsx +20 -19
  47. package/tests/e2e/Stacker/stacker.test.tsx +304 -0
  48. package/tests/unit/Editor/helpers.test.ts +26 -26
  49. package/tests/unit/MarkdownConformance/error-isolation.test.tsx +26 -25
  50. package/tests/unit/MarkdownConformance/indentation.test.tsx +20 -19
  51. package/tests/unit/MarkdownConformance/inline-code-fuzz.test.tsx +255 -0
  52. package/tests/unit/MarkdownConformance/jsx-attributes.test.tsx +39 -38
  53. package/tests/unit/MarkdownConformance/jsx-fuzz.test.tsx +122 -122
  54. package/tests/unit/MarkdownConformance/links.test.tsx +78 -54
  55. package/tests/unit/MarkdownConformance/render-helpers.tsx +60 -60
  56. package/tests/unit/MarkdownEditor/code-info.test.ts +58 -58
  57. package/tests/unit/MarkdownEditor/decorations.test.ts +423 -421
  58. package/tests/unit/MarkdownEditor/editor-ready.test.ts +22 -22
  59. package/tests/unit/MarkdownEditor/html-descriptors.test.ts +70 -70
  60. package/tests/unit/MarkdownEditor/indented-fence.test.ts +80 -80
  61. package/tests/unit/MarkdownEditor/jsx-attr-scan.test.ts +87 -87
  62. package/tests/unit/MarkdownEditor/jsx-block-widget.test.ts +51 -51
  63. package/tests/unit/MarkdownEditor/jsx-tag-grammar.test.ts +63 -63
  64. package/tests/unit/MarkdownEditor/list-indent.test.ts +67 -67
  65. package/tests/unit/MarkdownEditor/slash-commands.test.ts +150 -150
  66. package/tests/unit/MarkdownEditor/table-format.test.ts +67 -67
  67. package/tests/unit/MarkdownEditor/table.test.ts +96 -96
  68. package/tests/unit/MarkdownEditor/triggers.test.ts +167 -167
  69. package/tests/unit/MarkdownEditor/widget-store.test.ts +90 -90
  70. package/tests/unit/MarkdownViewer/callout.test.tsx +42 -42
  71. package/tests/unit/MarkdownViewer/code-highlight.test.tsx +41 -41
  72. package/tests/unit/MarkdownViewer/code-title.test.tsx +45 -45
  73. package/tests/unit/MarkdownViewer/features.test.tsx +129 -129
  74. package/tests/unit/MarkdownViewer/headings.test.tsx +28 -28
  75. package/tests/unit/MarkdownViewer/indented-jsx-children.test.tsx +53 -53
  76. package/tests/unit/MarkdownViewer/jsx-block-nesting.test.tsx +137 -137
  77. package/tests/unit/MarkdownViewer/jsx.test.tsx +188 -188
  78. package/tests/unit/MarkdownViewer/list-bullets.test.tsx +31 -31
  79. package/tests/unit/MarkdownViewer/list-code.test.tsx +45 -45
  80. package/tests/unit/MarkdownViewer/preserve-newlines.test.tsx +109 -109
  81. package/tests/unit/MarkdownViewer/read-time.test.ts +13 -13
  82. package/tests/unit/MarkdownViewer/renderers.test.tsx +75 -75
  83. package/tests/unit/MarkdownViewer/runnable.test.tsx +51 -51
  84. package/tests/unit/MarkdownViewer/ssr.test.tsx +56 -55
  85. package/tests/unit/MarkdownViewer/syntax-highlighting.test.tsx +43 -42
  86. package/tests/unit/MarkdownViewer/tabs-fenced-code.test.tsx +120 -120
  87. package/tests/unit/MarkdownViewer/tabs.test.tsx +83 -82
  88. package/tests/unit/Stacker/drag.test.ts +21 -0
  89. package/tests/unit/Stacker/helpers.test.ts +105 -0
  90. package/tests/unit/Stacker/reducer.test.ts +107 -0
  91. package/tools/duplicate-vector-mappings.json +141 -141
  92. package/tools/glass-export-overrides.json +6 -6
  93. package/tools/icon-parser.ts +41 -40
  94. package/tools/integration-gradient-exports.json +55 -55
  95. package/tools/picto-compare.ts +32 -32
  96. package/tools/picto-merge-urls.ts +19 -19
  97. package/tools/picto-sync.ts +543 -543
  98. package/tools/picto-verify-gradients.ts +50 -50
  99. package/tools/vector-export-nodes.json +975 -975
@@ -7,41 +7,41 @@ import { renderToString } from "react-dom/server";
7
7
  import { beforeAll, describe, expect, it } from "vitest";
8
8
 
9
9
  beforeAll(() => {
10
- if (typeof window !== "undefined" && typeof window.matchMedia !== "function") {
11
- Object.defineProperty(window, "matchMedia", {
12
- writable: true,
13
- value: (query: string) => ({
14
- matches: false,
15
- media: query,
16
- onchange: null,
17
- addListener: () => {},
18
- removeListener: () => {},
19
- addEventListener: () => {},
20
- removeEventListener: () => {},
21
- dispatchEvent: () => false,
22
- }),
23
- });
24
- }
10
+ if (typeof window !== "undefined" && typeof window.matchMedia !== "function") {
11
+ Object.defineProperty(window, "matchMedia", {
12
+ writable: true,
13
+ value: (query: string) => ({
14
+ matches: false,
15
+ media: query,
16
+ onchange: null,
17
+ addListener: () => {},
18
+ removeListener: () => {},
19
+ addEventListener: () => {},
20
+ removeEventListener: () => {},
21
+ dispatchEvent: () => false,
22
+ }),
23
+ });
24
+ }
25
25
  });
26
26
 
27
27
  function shell(node: ReactElement): string {
28
- return renderToString(
29
- <MantineProvider
30
- theme={MANTINE_THEME}
31
- cssVariablesResolver={v8CssVariablesResolver}
32
- forceColorScheme="dark"
33
- >
34
- {node}
35
- </MantineProvider>,
36
- );
28
+ return renderToString(
29
+ <MantineProvider
30
+ theme={MANTINE_THEME}
31
+ cssVariablesResolver={v8CssVariablesResolver}
32
+ forceColorScheme="dark"
33
+ >
34
+ {node}
35
+ </MantineProvider>,
36
+ );
37
37
  }
38
38
 
39
39
  function TwoColumn({ children }: { children?: ReactNode }): ReactElement {
40
- return <div data-testid="two-column">{children}</div>;
40
+ return <div data-testid="two-column">{children}</div>;
41
41
  }
42
42
 
43
43
  function ColBox({ children }: { children?: ReactNode }): ReactElement {
44
- return <div data-testid="col-box">{children}</div>;
44
+ return <div data-testid="col-box">{children}</div>;
45
45
  }
46
46
 
47
47
  const LAYOUT = `<TwoColumn>
@@ -51,93 +51,93 @@ const LAYOUT = `<TwoColumn>
51
51
  </TwoColumn>`;
52
52
 
53
53
  describe("MarkdownViewer / custom component preserveNewlines", () => {
54
- it("does not inject <br /> between block children (they render as blocks)", () => {
55
- const components: MarkdownComponents = {
56
- TwoColumn: { component: TwoColumn, block: true },
57
- ColBox: { component: ColBox, block: true },
58
- };
59
- const html = shell(
60
- <MarkdownViewer
61
- content={LAYOUT}
62
- components={components}
63
- />,
64
- );
54
+ it("does not inject <br /> between block children (they render as blocks)", () => {
55
+ const components: MarkdownComponents = {
56
+ TwoColumn: { component: TwoColumn, block: true },
57
+ ColBox: { component: ColBox, block: true },
58
+ };
59
+ const html = shell(
60
+ <MarkdownViewer
61
+ content={LAYOUT}
62
+ components={components}
63
+ />,
64
+ );
65
65
 
66
- // Three boxes still render, in order.
67
- expect(html.match(/data-testid="col-box"/g)?.length).toBe(3);
68
- // Block-level children are carved out and rendered as their own blocks:
69
- // the newlines that merely separate them must NOT become <br /> elements.
70
- // A stray <br /> here would also be counted as an extra child by
71
- // introspecting parents (e.g. <Tabs> reading each <TabItem>), so the two
72
- // behaviours are unified — `preserveNewlines` governs prose line breaks
73
- // (see the prose test below), not gaps between block children.
74
- const inner = html.slice(
75
- html.indexOf('data-testid="two-column"'),
76
- html.lastIndexOf("</div>"),
77
- );
78
- expect(inner).not.toMatch(/<br\s*\/?>/);
79
- });
66
+ // Three boxes still render, in order.
67
+ expect(html.match(/data-testid="col-box"/g)?.length).toBe(3);
68
+ // Block-level children are carved out and rendered as their own blocks:
69
+ // the newlines that merely separate them must NOT become <br /> elements.
70
+ // A stray <br /> here would also be counted as an extra child by
71
+ // introspecting parents (e.g. <Tabs> reading each <TabItem>), so the two
72
+ // behaviours are unified — `preserveNewlines` governs prose line breaks
73
+ // (see the prose test below), not gaps between block children.
74
+ const inner = html.slice(
75
+ html.indexOf('data-testid="two-column"'),
76
+ html.lastIndexOf("</div>"),
77
+ );
78
+ expect(inner).not.toMatch(/<br\s*\/?>/);
79
+ });
80
80
 
81
- it("omits <br /> between block children when preserveNewlines is false", () => {
82
- const components: MarkdownComponents = {
83
- TwoColumn: { component: TwoColumn, block: true, preserveNewlines: false },
84
- ColBox: { component: ColBox, block: true },
85
- };
86
- const html = shell(
87
- <MarkdownViewer
88
- content={LAYOUT}
89
- components={components}
90
- />,
91
- );
81
+ it("omits <br /> between block children when preserveNewlines is false", () => {
82
+ const components: MarkdownComponents = {
83
+ TwoColumn: { component: TwoColumn, block: true, preserveNewlines: false },
84
+ ColBox: { component: ColBox, block: true },
85
+ };
86
+ const html = shell(
87
+ <MarkdownViewer
88
+ content={LAYOUT}
89
+ components={components}
90
+ />,
91
+ );
92
92
 
93
- // All three boxes still render.
94
- expect(html.match(/data-testid="col-box"/g)?.length).toBe(3);
95
- // The TwoColumn wrapper is present.
96
- expect(html).toContain('data-testid="two-column"');
93
+ // All three boxes still render.
94
+ expect(html.match(/data-testid="col-box"/g)?.length).toBe(3);
95
+ // The TwoColumn wrapper is present.
96
+ expect(html).toContain('data-testid="two-column"');
97
97
 
98
- // No stray line breaks injected between the child blocks.
99
- const inner = html.slice(
100
- html.indexOf('data-testid="two-column"'),
101
- html.lastIndexOf("</div>"),
102
- );
103
- expect(inner).not.toMatch(/<br\s*\/?>/);
104
- });
98
+ // No stray line breaks injected between the child blocks.
99
+ const inner = html.slice(
100
+ html.indexOf('data-testid="two-column"'),
101
+ html.lastIndexOf("</div>"),
102
+ );
103
+ expect(inner).not.toMatch(/<br\s*\/?>/);
104
+ });
105
105
 
106
- it("still preserves newlines for prose components by default", () => {
107
- function Prose({ children }: { children?: ReactNode }): ReactElement {
108
- return <section data-testid="prose">{children}</section>;
109
- }
110
- const components: MarkdownComponents = {
111
- Prose: { component: Prose, block: true },
112
- };
113
- const html = shell(
114
- <MarkdownViewer
115
- content={"<Prose>\nLine one\nLine two\n</Prose>"}
116
- components={components}
117
- />,
118
- );
119
- expect(html).toContain("Line one");
120
- expect(html).toContain("Line two");
121
- // Multi-line prose keeps its line break.
122
- expect(html).toMatch(/<br\s*\/?>/);
123
- });
106
+ it("still preserves newlines for prose components by default", () => {
107
+ function Prose({ children }: { children?: ReactNode }): ReactElement {
108
+ return <section data-testid="prose">{children}</section>;
109
+ }
110
+ const components: MarkdownComponents = {
111
+ Prose: { component: Prose, block: true },
112
+ };
113
+ const html = shell(
114
+ <MarkdownViewer
115
+ content={"<Prose>\nLine one\nLine two\n</Prose>"}
116
+ components={components}
117
+ />,
118
+ );
119
+ expect(html).toContain("Line one");
120
+ expect(html).toContain("Line two");
121
+ // Multi-line prose keeps its line break.
122
+ expect(html).toMatch(/<br\s*\/?>/);
123
+ });
124
124
 
125
- it("disabling preserveNewlines collapses multi-line text to a single run", () => {
126
- function Prose({ children }: { children?: ReactNode }): ReactElement {
127
- return <section data-testid="prose">{children}</section>;
128
- }
129
- const components: MarkdownComponents = {
130
- Prose: { component: Prose, block: true, preserveNewlines: false },
131
- };
132
- const html = shell(
133
- <MarkdownViewer
134
- content={"<Prose>\nLine one\nLine two\n</Prose>"}
135
- components={components}
136
- />,
137
- );
138
- expect(html).toContain("Line one");
139
- expect(html).toContain("Line two");
140
- const inner = html.slice(html.indexOf('data-testid="prose"'));
141
- expect(inner).not.toMatch(/<br\s*\/?>/);
142
- });
125
+ it("disabling preserveNewlines collapses multi-line text to a single run", () => {
126
+ function Prose({ children }: { children?: ReactNode }): ReactElement {
127
+ return <section data-testid="prose">{children}</section>;
128
+ }
129
+ const components: MarkdownComponents = {
130
+ Prose: { component: Prose, block: true, preserveNewlines: false },
131
+ };
132
+ const html = shell(
133
+ <MarkdownViewer
134
+ content={"<Prose>\nLine one\nLine two\n</Prose>"}
135
+ components={components}
136
+ />,
137
+ );
138
+ expect(html).toContain("Line one");
139
+ expect(html).toContain("Line two");
140
+ const inner = html.slice(html.indexOf('data-testid="prose"'));
141
+ expect(inner).not.toMatch(/<br\s*\/?>/);
142
+ });
143
143
  });
@@ -1,21 +1,21 @@
1
1
  import {
2
- estimateMarkdownReadTimeMinutes,
3
- formatMarkdownReadTime,
4
- markdownToPlainText,
2
+ estimateMarkdownReadTimeMinutes,
3
+ formatMarkdownReadTime,
4
+ markdownToPlainText,
5
5
  } from "@src/lib/markdown/read-time";
6
6
  import { describe, expect, it } from "vitest";
7
7
 
8
8
  describe("markdown read time", () => {
9
- it("strips markdown syntax for word counting", () => {
10
- expect(markdownToPlainText("# Title\n\n[link](https://example.com)")).toBe("Title link");
11
- });
9
+ it("strips markdown syntax for word counting", () => {
10
+ expect(markdownToPlainText("# Title\n\n[link](https://example.com)")).toBe("Title link");
11
+ });
12
12
 
13
- it("estimates at least one minute", () => {
14
- expect(estimateMarkdownReadTimeMinutes("")).toBe(1);
15
- });
13
+ it("estimates at least one minute", () => {
14
+ expect(estimateMarkdownReadTimeMinutes("")).toBe(1);
15
+ });
16
16
 
17
- it("formats a read-time label", () => {
18
- const words = Array.from({ length: 400 }, () => "word").join(" ");
19
- expect(formatMarkdownReadTime(words)).toBe("2 min read");
20
- });
17
+ it("formats a read-time label", () => {
18
+ const words = Array.from({ length: 400 }, () => "word").join(" ");
19
+ expect(formatMarkdownReadTime(words)).toBe("2 min read");
20
+ });
21
21
  });
@@ -6,90 +6,90 @@ import { renderToString } from "react-dom/server";
6
6
  import { beforeAll, describe, expect, it } from "vitest";
7
7
 
8
8
  beforeAll(() => {
9
- if (typeof window !== "undefined" && typeof window.matchMedia !== "function") {
10
- Object.defineProperty(window, "matchMedia", {
11
- writable: true,
12
- value: (query: string) => ({
13
- matches: false,
14
- media: query,
15
- onchange: null,
16
- addListener: () => {},
17
- removeListener: () => {},
18
- addEventListener: () => {},
19
- removeEventListener: () => {},
20
- dispatchEvent: () => false,
21
- }),
22
- });
23
- }
9
+ if (typeof window !== "undefined" && typeof window.matchMedia !== "function") {
10
+ Object.defineProperty(window, "matchMedia", {
11
+ writable: true,
12
+ value: (query: string) => ({
13
+ matches: false,
14
+ media: query,
15
+ onchange: null,
16
+ addListener: () => {},
17
+ removeListener: () => {},
18
+ addEventListener: () => {},
19
+ removeEventListener: () => {},
20
+ dispatchEvent: () => false,
21
+ }),
22
+ });
23
+ }
24
24
  });
25
25
 
26
26
  function shell(node: ReactElement): string {
27
- return renderToString(
28
- <MantineProvider
29
- theme={MANTINE_THEME}
30
- cssVariablesResolver={v8CssVariablesResolver}
31
- forceColorScheme="dark"
32
- >
33
- {node}
34
- </MantineProvider>,
35
- );
27
+ return renderToString(
28
+ <MantineProvider
29
+ theme={MANTINE_THEME}
30
+ cssVariablesResolver={v8CssVariablesResolver}
31
+ forceColorScheme="dark"
32
+ >
33
+ {node}
34
+ </MantineProvider>,
35
+ );
36
36
  }
37
37
 
38
38
  describe("MarkdownViewer / MarkdownViewerRenderers", () => {
39
- it("uses heading renderer override", () => {
40
- const html = shell(
41
- <MarkdownViewer
42
- content="## Section title"
43
- renderers={{
44
- heading: () => <span data-custom-heading>HEADING_MARKER</span>,
45
- }}
46
- />,
47
- );
48
- expect(html).toContain("HEADING_MARKER");
49
- expect(html).not.toContain("Section title");
50
- });
39
+ it("uses heading renderer override", () => {
40
+ const html = shell(
41
+ <MarkdownViewer
42
+ content="## Section title"
43
+ renderers={{
44
+ heading: () => <span data-custom-heading>HEADING_MARKER</span>,
45
+ }}
46
+ />,
47
+ );
48
+ expect(html).toContain("HEADING_MARKER");
49
+ expect(html).not.toContain("Section title");
50
+ });
51
51
 
52
- it("uses link renderer override", () => {
53
- const html = shell(
54
- <MarkdownViewer
55
- content="[Example](https://example.com)"
56
- renderers={{
57
- link: () => <span data-custom-link>LINK_MARKER</span>,
58
- }}
59
- />,
60
- );
61
- expect(html).toContain("LINK_MARKER");
62
- expect(html).not.toContain("Example");
63
- expect(html).not.toContain("https://example.com");
64
- });
52
+ it("uses link renderer override", () => {
53
+ const html = shell(
54
+ <MarkdownViewer
55
+ content="[Example](https://example.com)"
56
+ renderers={{
57
+ link: () => <span data-custom-link>LINK_MARKER</span>,
58
+ }}
59
+ />,
60
+ );
61
+ expect(html).toContain("LINK_MARKER");
62
+ expect(html).not.toContain("Example");
63
+ expect(html).not.toContain("https://example.com");
64
+ });
65
65
 
66
- it("uses table renderer override without the scroll wrapper", () => {
67
- const html = shell(
68
- <MarkdownViewer
69
- content={`| A | B |
66
+ it("uses table renderer override without the scroll wrapper", () => {
67
+ const html = shell(
68
+ <MarkdownViewer
69
+ content={`| A | B |
70
70
  | - | - |
71
71
  | 1 | 2 |`}
72
- renderers={{
73
- table: () => <span data-custom-table>TABLE_MARKER</span>,
74
- }}
75
- />,
76
- );
77
- expect(html).toContain("TABLE_MARKER");
78
- expect(html).not.toContain("<table");
79
- expect(html).not.toContain("mantine-TableScrollContainer-scrollContainer");
80
- });
72
+ renderers={{
73
+ table: () => <span data-custom-table>TABLE_MARKER</span>,
74
+ }}
75
+ />,
76
+ );
77
+ expect(html).toContain("TABLE_MARKER");
78
+ expect(html).not.toContain("<table");
79
+ expect(html).not.toContain("mantine-TableScrollContainer-scrollContainer");
80
+ });
81
81
 
82
- it("uses image renderer override", () => {
83
- const html = shell(
84
- <MarkdownViewer
85
- content='![Alt text](https://example.com/image.png "Title")'
86
- renderers={{
87
- image: () => <span data-custom-image>IMAGE_MARKER</span>,
88
- }}
89
- />,
90
- );
91
- expect(html).toContain("IMAGE_MARKER");
92
- expect(html).not.toContain("Alt text");
93
- expect(html).not.toContain("https://example.com/image.png");
94
- });
82
+ it("uses image renderer override", () => {
83
+ const html = shell(
84
+ <MarkdownViewer
85
+ content='![Alt text](https://example.com/image.png "Title")'
86
+ renderers={{
87
+ image: () => <span data-custom-image>IMAGE_MARKER</span>,
88
+ }}
89
+ />,
90
+ );
91
+ expect(html).toContain("IMAGE_MARKER");
92
+ expect(html).not.toContain("Alt text");
93
+ expect(html).not.toContain("https://example.com/image.png");
94
+ });
95
95
  });
@@ -6,64 +6,64 @@ import { renderToString } from "react-dom/server";
6
6
  import { beforeAll, describe, expect, it } from "vitest";
7
7
 
8
8
  beforeAll(() => {
9
- if (typeof window !== "undefined" && typeof window.matchMedia !== "function") {
10
- Object.defineProperty(window, "matchMedia", {
11
- writable: true,
12
- value: (query: string) => ({
13
- matches: false,
14
- media: query,
15
- onchange: null,
16
- addListener: () => {},
17
- removeListener: () => {},
18
- addEventListener: () => {},
19
- removeEventListener: () => {},
20
- dispatchEvent: () => false,
21
- }),
22
- });
23
- }
9
+ if (typeof window !== "undefined" && typeof window.matchMedia !== "function") {
10
+ Object.defineProperty(window, "matchMedia", {
11
+ writable: true,
12
+ value: (query: string) => ({
13
+ matches: false,
14
+ media: query,
15
+ onchange: null,
16
+ addListener: () => {},
17
+ removeListener: () => {},
18
+ addEventListener: () => {},
19
+ removeEventListener: () => {},
20
+ dispatchEvent: () => false,
21
+ }),
22
+ });
23
+ }
24
24
  });
25
25
 
26
26
  function shell(node: ReactElement): string {
27
- return renderToString(
28
- <MantineProvider
29
- theme={MANTINE_THEME}
30
- cssVariablesResolver={v8CssVariablesResolver}
31
- forceColorScheme="dark"
32
- >
33
- {node}
34
- </MantineProvider>,
35
- );
27
+ return renderToString(
28
+ <MantineProvider
29
+ theme={MANTINE_THEME}
30
+ cssVariablesResolver={v8CssVariablesResolver}
31
+ forceColorScheme="dark"
32
+ >
33
+ {node}
34
+ </MantineProvider>,
35
+ );
36
36
  }
37
37
 
38
38
  describe("MarkdownViewer / runnable code", () => {
39
- it("renders RunnableCodeBlock when fenced info includes runnable", () => {
40
- const html = shell(
41
- <MarkdownViewer content={'```surql runnable="SELECT 1"\nRETURN 1;\n```'} />,
42
- );
43
- expect(html).toContain("Run Query");
44
- });
39
+ it("renders RunnableCodeBlock when fenced info includes runnable", () => {
40
+ const html = shell(
41
+ <MarkdownViewer content={'```surql runnable="SELECT 1"\nRETURN 1;\n```'} />,
42
+ );
43
+ expect(html).toContain("Run Query");
44
+ });
45
45
 
46
- it("renders RunnableCodeBlock for a loose runnable flag with no value", () => {
47
- const html = shell(<MarkdownViewer content={"```surql runnable\nRETURN 1;\n```"} />);
48
- expect(html).toContain("Run Query");
49
- });
46
+ it("renders RunnableCodeBlock for a loose runnable flag with no value", () => {
47
+ const html = shell(<MarkdownViewer content={"```surql runnable\nRETURN 1;\n```"} />);
48
+ expect(html).toContain("Run Query");
49
+ });
50
50
 
51
- it("does not render RunnableCodeBlock for plain fenced code", () => {
52
- const html = shell(<MarkdownViewer content={"```surql\nRETURN 1;\n```"} />);
53
- expect(html).not.toContain("Run Query");
54
- });
51
+ it("does not render RunnableCodeBlock for plain fenced code", () => {
52
+ const html = shell(<MarkdownViewer content={"```surql\nRETURN 1;\n```"} />);
53
+ expect(html).not.toContain("Run Query");
54
+ });
55
55
 
56
- it("preserves runnable attribute casing through the render pipeline", () => {
57
- const html = shell(
58
- <MarkdownViewer
59
- content={'```surql runnable="SELECT 1"\nRETURN 1;\n```'}
60
- codeRenderers={{}}
61
- renderers={{
62
- code: ({ runnable }) => <span data-runnable={runnable}>{runnable}</span>,
63
- }}
64
- />,
65
- );
66
- expect(html).toContain("SELECT 1");
67
- expect(html).not.toContain("select 1");
68
- });
56
+ it("preserves runnable attribute casing through the render pipeline", () => {
57
+ const html = shell(
58
+ <MarkdownViewer
59
+ content={'```surql runnable="SELECT 1"\nRETURN 1;\n```'}
60
+ codeRenderers={{}}
61
+ renderers={{
62
+ code: ({ runnable }) => <span data-runnable={runnable}>{runnable}</span>,
63
+ }}
64
+ />,
65
+ );
66
+ expect(html).toContain("SELECT 1");
67
+ expect(html).not.toContain("select 1");
68
+ });
69
69
  });