Skip to content

Commit 7c46c54

Browse files
Page title highlighting and error boundry (#29)
* make page title highlighting work * error boundry * fix test import
1 parent 3fdb6d5 commit 7c46c54

File tree

13 files changed

+299
-141
lines changed

13 files changed

+299
-141
lines changed

examples/vite_basic/src/App.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,16 @@ import DevPanel from "./components/DevPanel";
66
// Test backrefs for highlighting
77
const testBackrefs: Array<{
88
end_idx: number;
9-
block_id: string;
109
start_idx: number;
10+
block_id?: string;
11+
page_id?: string;
1112
}> = [
13+
// Test page title highlighting
14+
{
15+
end_idx: 15,
16+
page_id: "pg_01jxm798ddfdvt60gy8nqh0xm7",
17+
start_idx: 0,
18+
},
1219
// {
1320
// end_idx: 50,
1421
// block_id: "blk_table_row_5",

typescript/README.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,4 +307,44 @@ You can choose a different version from the list or create new one. But bumpp is
307307
- [x] move vite app to typescript root examples dir
308308
- [ ] setup monorepo tooling
309309
- [ ] fix model generation for Image and RichText, then type renderers
310-
- [ ] use katex or similar package for equations
310+
- [x] use katex or similar package for equations
311+
- [x] add error boundry
312+
- [x] add page title highlighting
313+
- [ ] validate page prop somehow. not clear how to do yet. we can't use the /schema because it's HUGE and also because it's outside of /typescript. Will need to think about this.
314+
315+
maybe do something like this?
316+
```
317+
import type { Page } from "../models/generated/page/page";
318+
import { isPage } from "../models/generated/essential-types";
319+
320+
export function validatePage(obj: unknown): obj is Page {
321+
console.log("isPage(obj) ", isPage(obj));
322+
return (
323+
isPage(obj) &&
324+
typeof (obj as any).id === "string" &&
325+
Array.isArray((obj as any).children)
326+
);
327+
}
328+
329+
export function validatePageWithError(obj: unknown): {
330+
valid: boolean;
331+
error?: string;
332+
} {
333+
if (!isPage(obj)) {
334+
return { valid: false, error: "Not a valid page object" };
335+
}
336+
337+
if (typeof (obj as any).id !== "string") {
338+
return { valid: false, error: "Page id must be a string" };
339+
}
340+
341+
if (!Array.isArray((obj as any).children)) {
342+
return { valid: false, error: "Page children must be an array" };
343+
}
344+
345+
return { valid: true };
346+
}
347+
348+
```
349+
350+
will require us to write a validator and we won't benefit from the defined schema jsons.

typescript/package-lock.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

typescript/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"ajv": "^8.17.1",
7171
"ajv-formats": "^3.0.1",
7272
"katex": "^0.16.22",
73+
"react-error-boundary": "^6.0.0",
7374
"react-intersection-observer": "^9.13.0"
7475
},
7576
"peerDependencies": {

typescript/src/renderer/JsonDocRenderer.tsx

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { RendererProvider } from "./context/RendererContext";
1111
import { HighlightNavigation } from "./components/HighlightNavigation";
1212
import { useHighlights } from "./hooks/useHighlights";
1313
import { Backref } from "./utils/highlightUtils";
14+
import { GlobalErrorBoundary } from "./components/ErrorBoundary";
1415

1516
interface JsonDocRendererProps {
1617
page: Page;
@@ -25,6 +26,7 @@ interface JsonDocRendererProps {
2526
devMode?: boolean;
2627
viewJson?: boolean;
2728
backrefs?: Backref[];
29+
onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
2830
}
2931

3032
export const JsonDocRenderer = ({
@@ -36,6 +38,7 @@ export const JsonDocRenderer = ({
3638
devMode = false,
3739
viewJson = false,
3840
backrefs = [],
41+
onError,
3942
}: JsonDocRendererProps) => {
4043
// Use the modular hooks for highlight management
4144
const { highlightCount, currentActiveIndex, navigateToHighlight } =
@@ -97,25 +100,29 @@ export const JsonDocRenderer = ({
97100
);
98101

99102
return (
100-
<RendererProvider value={{ devMode, resolveImageUrl }}>
101-
<div className={`json-doc-renderer jsondoc-theme-${theme} ${className}`}>
102-
{viewJson ? (
103-
<div className="flex h-screen">
104-
<div className="w-1/2 overflow-y-auto">{renderedContent}</div>
105-
<JsonViewPanel data={page} />
103+
<div className={`jsondoc-theme-${theme}`}>
104+
<GlobalErrorBoundary onError={onError}>
105+
<RendererProvider value={{ devMode, resolveImageUrl }}>
106+
<div className={`json-doc-renderer ${className}`}>
107+
{viewJson ? (
108+
<div className="flex h-screen">
109+
<div className="w-1/2 overflow-y-auto">{renderedContent}</div>
110+
<JsonViewPanel data={page} />
111+
</div>
112+
) : (
113+
renderedContent
114+
)}
115+
{/* Show highlight navigation when there are highlights */}
116+
{highlightCount > 0 && (
117+
<HighlightNavigation
118+
highlightCount={highlightCount}
119+
onNavigate={navigateToHighlight}
120+
currentIndex={currentActiveIndex}
121+
/>
122+
)}
106123
</div>
107-
) : (
108-
renderedContent
109-
)}
110-
{/* Show highlight navigation when there are highlights */}
111-
{highlightCount > 0 && (
112-
<HighlightNavigation
113-
highlightCount={highlightCount}
114-
onNavigate={navigateToHighlight}
115-
currentIndex={currentActiveIndex}
116-
/>
117-
)}
118-
</div>
119-
</RendererProvider>
124+
</RendererProvider>
125+
</GlobalErrorBoundary>
126+
</div>
120127
);
121128
};
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React from "react";
2+
import { ErrorBoundary, FallbackProps } from "react-error-boundary";
3+
4+
interface GlobalErrorBoundaryProps {
5+
children: React.ReactNode;
6+
onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
7+
}
8+
9+
function GlobalErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
10+
console.log("error ", error);
11+
return (
12+
<div className="json-doc-error-boundary">
13+
<div className="json-doc-error-content">
14+
<h2>Document Failed to Load</h2>
15+
<p>Something went wrong while rendering this document.</p>
16+
<pre>
17+
<strong>Message:</strong> {error.message}
18+
{error.stack && (
19+
<div>
20+
<strong>Stack Trace:</strong>
21+
{error.stack}
22+
</div>
23+
)}
24+
</pre>
25+
26+
<button
27+
onClick={resetErrorBoundary}
28+
className="json-doc-error-retry-button"
29+
>
30+
Try Again
31+
</button>
32+
</div>
33+
</div>
34+
);
35+
}
36+
37+
export function GlobalErrorBoundary({
38+
children,
39+
onError,
40+
}: GlobalErrorBoundaryProps) {
41+
return (
42+
<ErrorBoundary
43+
FallbackComponent={GlobalErrorFallback}
44+
onError={onError}
45+
onReset={() => {
46+
// Optional: Add any cleanup logic here
47+
window.location.reload();
48+
}}
49+
>
50+
{children}
51+
</ErrorBoundary>
52+
);
53+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/* Error Boundary Styles */
2+
.json-doc-error-boundary {
3+
display: flex;
4+
align-items: center;
5+
justify-content: center;
6+
min-height: 400px;
7+
width: 100%;
8+
/* max-width: 600px; */
9+
padding: var(--jsondoc-spacing-xl);
10+
background: var(--jsondoc-bg-primary);
11+
border: 1px solid var(--jsondoc-border-light);
12+
border-radius: var(--jsondoc-radius-md);
13+
margin: var(--jsondoc-spacing-lg);
14+
}
15+
16+
.json-doc-error-content {
17+
text-align: center;
18+
max-width: 500px;
19+
}
20+
21+
.json-doc-error-content h2 {
22+
color: var(--jsondoc-text-primary);
23+
font-size: var(--jsondoc-font-size-xl);
24+
font-weight: var(--jsondoc-font-weight-bold);
25+
margin: 0 0 var(--jsondoc-spacing-md) 0;
26+
}
27+
28+
.json-doc-error-content p {
29+
color: var(--jsondoc-text-secondary);
30+
font-size: var(--jsondoc-font-size-base);
31+
margin: 0 0 var(--jsondoc-spacing-lg) 0;
32+
line-height: var(--jsondoc-line-height-normal);
33+
}
34+
35+
.json-doc-error-details {
36+
margin: var(--jsondoc-spacing-lg) 0;
37+
text-align: left;
38+
}
39+
40+
.json-doc-error-details summary {
41+
color: var(--jsondoc-text-secondary);
42+
font-size: var(--jsondoc-font-size-sm);
43+
cursor: pointer;
44+
margin-bottom: var(--jsondoc-spacing-sm);
45+
}
46+
47+
.json-doc-error-boundary pre {
48+
background: var(--jsondoc-bg-code);
49+
color: var(--jsondoc-text-primary);
50+
padding: var(--jsondoc-spacing-md);
51+
border-radius: var(--jsondoc-radius-sm);
52+
font-family: var(--jsondoc-font-family-mono);
53+
font-size: var(--jsondoc-font-size-sm);
54+
overflow-x: auto;
55+
white-space: pre-wrap;
56+
word-break: break-word;
57+
max-height: 400px;
58+
}
59+
60+
.json-doc-error-retry-button {
61+
background: var(--jsondoc-color-primary);
62+
color: var(--jsondoc-text-primary);
63+
border: none;
64+
padding: var(--jsondoc-spacing-sm) var(--jsondoc-spacing-lg);
65+
border-radius: var(--jsondoc-radius-sm);
66+
font-size: var(--jsondoc-font-size-base);
67+
font-weight: var(--jsondoc-font-weight-medium);
68+
cursor: pointer;
69+
transition: all var(--jsondoc-transition-fast);
70+
}
71+
72+
.json-doc-error-retry-button:hover {
73+
background: var(--jsondoc-color-primary-hover);
74+
transform: translateY(-1px);
75+
}
76+
77+
.json-doc-error-retry-button:active {
78+
transform: translateY(0);
79+
}

typescript/src/renderer/styles/index.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* JSON-DOC Renderer Styles */
22

33
/* Import KaTeX styles for equations */
4-
@import "katex/dist/katex.min.css";
4+
/* @import "katex/dist/katex.min.css"; */
55

66
/* Import design tokens first */
77
@import "./variables.css";
@@ -16,6 +16,6 @@
1616
@import "./table.css";
1717
@import "./media.css";
1818
@import "./layout.css";
19-
19+
@import "./error-boundry.css";
2020
/* Import responsive styles last */
2121
@import "./responsive.css";

typescript/src/renderer/utils/blockMapping.js

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)