agent-canvas 0.1.36 → 0.1.37

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.
@@ -3,6 +3,27 @@ import { marked } from "marked";
3
3
 
4
4
  marked.setOptions({ gfm: true, breaks: false });
5
5
 
6
+ /** Host tags that flow inline and must not break a prose run into separate blocks. */
7
+ const INLINE_TAGS = new Set([
8
+ "a", "abbr", "b", "br", "code", "del", "em", "i", "kbd", "mark",
9
+ "q", "s", "small", "span", "strong", "sub", "sup", "time", "u",
10
+ ]);
11
+
12
+ /** Custom components that render inline (e.g. <Priority>). */
13
+ const INLINE_COMPONENTS = new Set(["Priority"]);
14
+
15
+ function isInlineNode(node: React.ReactNode): boolean {
16
+ if (typeof node === "string" || typeof node === "number") return true;
17
+ if (!React.isValidElement(node)) return false;
18
+ const type = node.type;
19
+ if (typeof type === "string") return INLINE_TAGS.has(type);
20
+ if (typeof type === "function") {
21
+ const name = (type as { displayName?: string; name?: string }).displayName ?? (type as { name?: string }).name;
22
+ return name ? INLINE_COMPONENTS.has(name) : false;
23
+ }
24
+ return false;
25
+ }
26
+
6
27
  function renderTextAsMarkdown(text: string, key: string): React.ReactNode {
7
28
  const trimmed = text.trim();
8
29
  if (!trimmed) return null;
@@ -18,30 +39,54 @@ function renderTextAsMarkdown(text: string, key: string): React.ReactNode {
18
39
  );
19
40
  }
20
41
 
42
+ /**
43
+ * Render a run of inline content (text + inline JSX like <code>/<strong>) as a single
44
+ * flowing paragraph. Text segments are parsed as inline markdown; JSX passes through.
45
+ * No `data-md` attribute so the markdown exporter treats it as an inline container.
46
+ */
47
+ function renderInlineRun(run: React.ReactNode[], key: string): React.ReactNode {
48
+ return (
49
+ <div key={key} className="prose-canvas">
50
+ {run.map((node, i) => {
51
+ if (typeof node === "string" || typeof node === "number") {
52
+ const html = marked.parseInline(String(node), { async: false }) as string;
53
+ return <span key={i} dangerouslySetInnerHTML={{ __html: html }} />;
54
+ }
55
+ return node;
56
+ })}
57
+ </div>
58
+ );
59
+ }
60
+
21
61
  /**
22
62
  * Auto-render markdown for string children, passing JSX children through.
23
- * Consecutive string runs are grouped into a single markdown block so multi-paragraph
24
- * prose between JSX elements renders correctly.
63
+ * Block-level JSX (Callout, Diff, etc.) breaks the prose into separate markdown blocks,
64
+ * while inline JSX (code, strong, links) stays within the surrounding paragraph so text
65
+ * keeps flowing instead of stacking one fragment per line.
25
66
  */
26
67
  export function renderMarkdownChildren(children: React.ReactNode): React.ReactNode {
27
68
  const kids = React.Children.toArray(children);
28
69
  if (kids.length === 0) return null;
29
70
 
30
71
  const result: React.ReactNode[] = [];
31
- let buffer = "";
32
- let bufferIdx = 0;
72
+ let segment: React.ReactNode[] = [];
73
+ let segIdx = 0;
33
74
 
34
75
  const flush = () => {
35
- if (buffer) {
36
- const node = renderTextAsMarkdown(buffer, `md-${bufferIdx++}`);
76
+ if (segment.length === 0) return;
77
+ const hasInlineJsx = segment.some((n) => typeof n !== "string" && typeof n !== "number");
78
+ if (hasInlineJsx) {
79
+ result.push(renderInlineRun(segment, `md-${segIdx++}`));
80
+ } else {
81
+ const node = renderTextAsMarkdown(segment.join(""), `md-${segIdx++}`);
37
82
  if (node) result.push(node);
38
- buffer = "";
39
83
  }
84
+ segment = [];
40
85
  };
41
86
 
42
87
  for (const child of kids) {
43
- if (typeof child === "string" || typeof child === "number") {
44
- buffer += String(child);
88
+ if (isInlineNode(child)) {
89
+ segment.push(child);
45
90
  } else {
46
91
  flush();
47
92
  result.push(child);