@surrealdb/ui 1.2.11 → 1.2.13

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 (101) 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 +21 -19
  6. package/README.md +15 -10
  7. package/dist/assets/245b1ccaa4927818.svg +3 -0
  8. package/dist/assets/333e1fe6e67ca4a2.svg +10 -0
  9. package/dist/assets/4b0e10c655814886.svg +21 -0
  10. package/dist/assets/9932da008ea5dd32.svg +3 -0
  11. package/dist/assets/a372168d5789daa2.svg +4 -0
  12. package/dist/assets/b140e44ee4ae7e35.svg +5 -0
  13. package/dist/assets/e028075817d928e4.svg +3 -0
  14. package/dist/assets/ee1065ad5a8f7f14.svg +6 -0
  15. package/dist/ui.css +1 -1
  16. package/dist/ui.d.ts +579 -1
  17. package/dist/ui.js +11553 -8988
  18. package/dist/ui.js.map +1 -1
  19. package/doc/code-style.md +264 -0
  20. package/doc/stacker-plan.md +219 -0
  21. package/package.json +119 -115
  22. package/res/_mixins.scss +15 -11
  23. package/tests/_setup/e2e-helpers.tsx +85 -85
  24. package/tests/_setup/portable-stories.ts +11 -10
  25. package/tests/e2e/MarkdownEditor/content-blocks.test.tsx +140 -139
  26. package/tests/e2e/MarkdownEditor/edits.test.tsx +101 -100
  27. package/tests/e2e/MarkdownEditor/heading-fold.test.tsx +35 -34
  28. package/tests/e2e/MarkdownEditor/hybrid-widgets.test.tsx +178 -177
  29. package/tests/e2e/MarkdownEditor/image-on-image.test.tsx +50 -49
  30. package/tests/e2e/MarkdownEditor/jsx-block-content.test.tsx +195 -194
  31. package/tests/e2e/MarkdownEditor/jsx-highlight.test.tsx +47 -46
  32. package/tests/e2e/MarkdownEditor/jsx-inline-badges.test.tsx +35 -34
  33. package/tests/e2e/MarkdownEditor/jsx-inline-click.test.tsx +39 -38
  34. package/tests/e2e/MarkdownEditor/jsx-selection.test.tsx +28 -27
  35. package/tests/e2e/MarkdownEditor/link-placeholder.test.tsx +49 -48
  36. package/tests/e2e/MarkdownEditor/media-align.test.tsx +40 -39
  37. package/tests/e2e/MarkdownEditor/media-edit.test.tsx +49 -48
  38. package/tests/e2e/MarkdownEditor/media-sizing.test.tsx +108 -107
  39. package/tests/e2e/MarkdownEditor/modes.test.tsx +79 -78
  40. package/tests/e2e/MarkdownEditor/onimage-parity.test.tsx +29 -28
  41. package/tests/e2e/MarkdownEditor/regressions.test.tsx +194 -193
  42. package/tests/e2e/MarkdownEditor/slash-commands.test.tsx +81 -80
  43. package/tests/e2e/MarkdownEditor/table-click.test.tsx +36 -35
  44. package/tests/e2e/MarkdownEditor/table-controls.test.tsx +44 -43
  45. package/tests/e2e/MarkdownEditor/table-format.test.tsx +28 -27
  46. package/tests/e2e/MarkdownEditor/undo-redo.test.tsx +22 -21
  47. package/tests/e2e/MarkdownViewer/parity.test.tsx +144 -143
  48. package/tests/e2e/MarkdownViewer/render.test.tsx +20 -19
  49. package/tests/e2e/Stacker/stacker.test.tsx +304 -0
  50. package/tests/unit/Editor/helpers.test.ts +26 -26
  51. package/tests/unit/MarkdownConformance/error-isolation.test.tsx +26 -25
  52. package/tests/unit/MarkdownConformance/indentation.test.tsx +20 -19
  53. package/tests/unit/MarkdownConformance/inline-code-fuzz.test.tsx +255 -0
  54. package/tests/unit/MarkdownConformance/jsx-attributes.test.tsx +39 -38
  55. package/tests/unit/MarkdownConformance/jsx-fuzz.test.tsx +122 -122
  56. package/tests/unit/MarkdownConformance/links.test.tsx +78 -54
  57. package/tests/unit/MarkdownConformance/render-helpers.tsx +60 -60
  58. package/tests/unit/MarkdownEditor/code-info.test.ts +58 -58
  59. package/tests/unit/MarkdownEditor/decorations.test.ts +423 -421
  60. package/tests/unit/MarkdownEditor/editor-ready.test.ts +22 -22
  61. package/tests/unit/MarkdownEditor/html-descriptors.test.ts +70 -70
  62. package/tests/unit/MarkdownEditor/indented-fence.test.ts +80 -80
  63. package/tests/unit/MarkdownEditor/jsx-attr-scan.test.ts +87 -87
  64. package/tests/unit/MarkdownEditor/jsx-block-widget.test.ts +51 -51
  65. package/tests/unit/MarkdownEditor/jsx-tag-grammar.test.ts +63 -63
  66. package/tests/unit/MarkdownEditor/list-indent.test.ts +67 -67
  67. package/tests/unit/MarkdownEditor/slash-commands.test.ts +150 -150
  68. package/tests/unit/MarkdownEditor/table-format.test.ts +67 -67
  69. package/tests/unit/MarkdownEditor/table.test.ts +96 -96
  70. package/tests/unit/MarkdownEditor/triggers.test.ts +167 -167
  71. package/tests/unit/MarkdownEditor/widget-store.test.ts +90 -90
  72. package/tests/unit/MarkdownViewer/callout.test.tsx +42 -42
  73. package/tests/unit/MarkdownViewer/code-highlight.test.tsx +41 -41
  74. package/tests/unit/MarkdownViewer/code-title.test.tsx +45 -45
  75. package/tests/unit/MarkdownViewer/features.test.tsx +129 -129
  76. package/tests/unit/MarkdownViewer/headings.test.tsx +28 -28
  77. package/tests/unit/MarkdownViewer/indented-jsx-children.test.tsx +53 -53
  78. package/tests/unit/MarkdownViewer/jsx-block-nesting.test.tsx +137 -137
  79. package/tests/unit/MarkdownViewer/jsx.test.tsx +188 -188
  80. package/tests/unit/MarkdownViewer/list-bullets.test.tsx +31 -31
  81. package/tests/unit/MarkdownViewer/list-code.test.tsx +45 -45
  82. package/tests/unit/MarkdownViewer/preserve-newlines.test.tsx +109 -109
  83. package/tests/unit/MarkdownViewer/read-time.test.ts +13 -13
  84. package/tests/unit/MarkdownViewer/renderers.test.tsx +75 -75
  85. package/tests/unit/MarkdownViewer/runnable.test.tsx +51 -51
  86. package/tests/unit/MarkdownViewer/ssr.test.tsx +56 -55
  87. package/tests/unit/MarkdownViewer/syntax-highlighting.test.tsx +43 -42
  88. package/tests/unit/MarkdownViewer/tabs-fenced-code.test.tsx +120 -120
  89. package/tests/unit/MarkdownViewer/tabs.test.tsx +83 -82
  90. package/tests/unit/Stacker/drag.test.ts +21 -0
  91. package/tests/unit/Stacker/helpers.test.ts +105 -0
  92. package/tests/unit/Stacker/reducer.test.ts +107 -0
  93. package/tools/duplicate-vector-mappings.json +141 -141
  94. package/tools/glass-export-overrides.json +6 -6
  95. package/tools/icon-parser.ts +41 -40
  96. package/tools/integration-gradient-exports.json +55 -55
  97. package/tools/picto-compare.ts +32 -32
  98. package/tools/picto-merge-urls.ts +19 -19
  99. package/tools/picto-sync.ts +543 -543
  100. package/tools/picto-verify-gradients.ts +50 -50
  101. 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
  });