Skip to content

Commit 7eb9d44

Browse files
add json viewer
1 parent f7df2ae commit 7eb9d44

File tree

2 files changed

+84
-44
lines changed

2 files changed

+84
-44
lines changed

typescript/src/renderer/JsonDocRenderer.tsx

Lines changed: 60 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React from "react";
33

44
import { BlockRenderer } from "./components/BlockRenderer";
55
import { PageDelimiter } from "./components/PageDelimiter";
6+
import { JsonViewPanel } from "./components/dev/JsonViewPanel";
67
import { RendererProvider } from "./context/RendererContext";
78

89
interface JsonDocRendererProps {
@@ -12,6 +13,7 @@ interface JsonDocRendererProps {
1213
theme?: "light" | "dark";
1314
resolveImageUrl?: (url: string) => Promise<string>;
1415
devMode?: boolean;
16+
viewJson?: boolean;
1517
}
1618

1719
export const JsonDocRenderer = ({
@@ -21,56 +23,70 @@ export const JsonDocRenderer = ({
2123
theme = "light",
2224
resolveImageUrl,
2325
devMode = false,
26+
viewJson = false,
2427
}: JsonDocRendererProps) => {
25-
return (
26-
<RendererProvider value={{ devMode, resolveImageUrl }}>
27-
<div className={`json-doc-renderer jsondoc-theme-${theme} ${className}`}>
28-
<div className="json-doc-page">
29-
{/* Page icon */}
30-
{page.icon && (
31-
<div className="json-doc-page-icon">
32-
{page.icon.type === "emoji" && page.icon.emoji}
33-
</div>
34-
)}
28+
const renderedContent = (
29+
<div className="json-doc-page">
30+
{/* Page icon */}
31+
{page.icon && (
32+
<div className="json-doc-page-icon">
33+
{page.icon.type === "emoji" && page.icon.emoji}
34+
</div>
35+
)}
3536

36-
{/* Page title */}
37-
{page.properties?.title && (
38-
<h1 className="json-doc-page-title">
39-
{page.properties.title.title?.[0]?.plain_text || "Untitled"}
40-
</h1>
41-
)}
37+
{/* Page title */}
38+
{page.properties?.title && (
39+
<h1 className="json-doc-page-title">
40+
{page.properties.title.title?.[0]?.plain_text || "Untitled"}
41+
</h1>
42+
)}
4243

43-
{/* Page children blocks */}
44-
{page.children && page.children.length > 0 && (
45-
<div className="json-doc-page-content">
46-
{page.children.map((block: any, index: number) => {
47-
const currentPageNum = block.metadata?.origin?.page_num;
48-
const nextPageNum =
49-
index < page.children.length - 1
50-
? page.children[index + 1]?.metadata?.origin?.page_num
51-
: null;
44+
{/* Page children blocks */}
45+
{page.children && page.children.length > 0 && (
46+
<div className="json-doc-page-content">
47+
{page.children.map((block: any, index: number) => {
48+
const currentPageNum = block.metadata?.origin?.page_num;
49+
const nextPageNum =
50+
index < page.children.length - 1
51+
? page.children[index + 1]?.metadata?.origin?.page_num
52+
: null;
5253

53-
// Show delimiter after the last block of each page
54-
const showPageDelimiter =
55-
currentPageNum &&
56-
(nextPageNum !== currentPageNum || index === page.children.length - 1);
54+
// Show delimiter after the last block of each page
55+
const showPageDelimiter =
56+
currentPageNum &&
57+
(nextPageNum !== currentPageNum || index === page.children.length - 1);
5758

58-
return (
59-
<React.Fragment key={block.id || index}>
60-
<BlockRenderer
61-
block={block}
62-
depth={0}
63-
components={components}
64-
/>
65-
{showPageDelimiter && (
66-
<PageDelimiter pageNumber={currentPageNum} />
67-
)}
68-
</React.Fragment>
69-
);
70-
})}
71-
</div>
72-
)}
59+
return (
60+
<React.Fragment key={block.id || index}>
61+
<BlockRenderer
62+
block={block}
63+
depth={0}
64+
components={components}
65+
/>
66+
{showPageDelimiter && (
67+
<PageDelimiter pageNumber={currentPageNum} />
68+
)}
69+
</React.Fragment>
70+
);
71+
})}
7372
</div>
73+
)}
74+
</div>
75+
);
76+
77+
return (
78+
<RendererProvider value={{ devMode, resolveImageUrl }}>
79+
<div className={`json-doc-renderer jsondoc-theme-${theme} ${className}`}>
80+
{viewJson ? (
81+
<div className="flex h-screen">
82+
<div className="w-1/2 overflow-y-auto">
83+
{renderedContent}
84+
</div>
85+
<JsonViewPanel data={page} />
86+
</div>
87+
) : (
88+
renderedContent
89+
)}
7490
</div>
7591
</RendererProvider>
7692
);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from "react";
2+
3+
interface JsonViewPanelProps {
4+
data: any;
5+
title?: string;
6+
}
7+
8+
export const JsonViewPanel: React.FC<JsonViewPanelProps> = ({
9+
data,
10+
title = "Raw JSON Data"
11+
}) => {
12+
return (
13+
<div className="w-1/2 overflow-y-auto bg-gray-50 dark:bg-gray-900">
14+
<div className="p-4">
15+
<h4 className="text-sm font-medium text-gray-900 dark:text-gray-100 mb-3 sticky top-0 bg-gray-50 dark:bg-gray-900 pb-2">
16+
{title}
17+
</h4>
18+
<pre className="text-xs text-gray-700 dark:text-gray-300 whitespace-pre-wrap break-words bg-white dark:bg-gray-800 p-4 rounded-md border border-gray-200 dark:border-gray-700 overflow-x-auto">
19+
{data ? JSON.stringify(data, null, 2) : 'No data available'}
20+
</pre>
21+
</div>
22+
</div>
23+
);
24+
};

0 commit comments

Comments
 (0)