Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,16 +239,18 @@ MIT

- followed this for ts config setup: https://www.totaltypescript.com/tsconfig-cheat-sheet


## Release workflow

We using bumpp to bump package.json and lock, create git tag and commit
1. Run:
We using bumpp to bump package.json and lock, create git tag and commit

1. Run:

```
npx bumpp
```

2. You should see:

```

4 Commits since the last version:
Expand All @@ -268,16 +270,14 @@ b7b30c1 : Make more typesafe
from 0.2.0-alpha.3
to 0.2.0-alpha.4
```

You can choose a different version from the list or create new one. But bumpp is smart enough to use appropriate next version.

3. Verify and confirm
4. Push commit and tag
5. The new tag will trigger a release on github actions.
5. The new tag will trigger a release on github actions.
6. Go to github and create release using the new tag. Make sure you set the correct previous tag prefixed with `typescript-v`




## Todos

- [x] setup eslint
Expand All @@ -295,6 +295,7 @@ You can choose a different version from the list or create new one. But bumpp is
- [x] image
- [x] blockquote
- [x] fix ts and eslint errors in these dirs and remove from ignore list of ts and eslint

```
"**/generated/**",
"src/serialization/**",
Expand All @@ -306,4 +307,4 @@ You can choose a different version from the list or create new one. But bumpp is
- [x] move vite app to typescript root examples dir
- [] setup monorepo tooling
- [] fix model generation for Image and RichText, then type renderers
- [] use katex or similar package for equations
- [] use katex or similar package for equations
118 changes: 118 additions & 0 deletions typescript/examples/vite_basic/public/test_document.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,124 @@
}
},
"children": [
{
"object": "block",
"id": "bk_01jxj01879f8cvyq2hqc6p37z2",
"type": "numbered_list_item",
"created_time": "2025-06-12T11:57:32.236290Z",
"created_by": {
"object": "user",
"id": "bcf6c03e-51a1-4f05-97d8-d616405b42a2"
},
"has_children": false,
"metadata": {
"origin": {
"file_id": "file_01jxwgtg7qfr79j59j7xe777ek",
"page_num": 1
}
},
"numbered_list_item": {
"rich_text": [
{
"type": "text",
"text": {
"content": "Volume and premium OEMs, Tier-1 and Tier-n companies trying to \"shape the market\""
},
"annotations": {},
"plain_text": "Volume and premium OEMs, Tier-1 and Tier-n companies trying to \"shape the market\""
}
]
}
},

{
"object": "block",
"id": "bk_01jxj01879f8cvyq2hqc6p37z2",
"type": "numbered_list_item",
"created_time": "2025-06-12T11:57:32.236290Z",
"created_by": {
"object": "user",
"id": "bcf6c03e-51a1-4f05-97d8-d616405b42a2"
},
"has_children": false,
"metadata": {
"origin": {
"file_id": "file_01jxhzyhk6f2bvjjabjx4dxqje",
"page_num": 1
}
},
"numbered_list_item": {
"rich_text": [
{
"type": "text",
"text": {
"content": "Volume and premium OEMs, Tier-1 and Tier-n companies trying to \"shape the market\""
},
"annotations": {},
"plain_text": "Volume and premium OEMs, Tier-1 and Tier-n companies trying to \"shape the market\""
}
]
}
},
{
"object": "block",
"id": "bk_01jxj01879f8cvyq2hqc6p37z2",
"type": "numbered_list_item",
"created_time": "2025-06-12T11:57:32.236290Z",
"created_by": {
"object": "user",
"id": "bcf6c03e-51a1-4f05-97d8-d616405b42a2"
},
"has_children": false,
"metadata": {
"origin": {
"file_id": "file_01jxhzyhk6f2bvjjabjx4dxqje",
"page_num": 1
}
},
"numbered_list_item": {
"rich_text": [
{
"type": "text",
"text": {
"content": "Volume and premium OEMs, Tier-1 and Tier-n companies trying to \"shape the market\""
},
"annotations": {},
"plain_text": "Volume and premium OEMs, Tier-1 and Tier-n companies trying to \"shape the market\""
}
]
}
},
{
"object": "block",
"id": "bk_01jxj01879f8cvyq2hqc6p37z2",
"type": "numbered_list_item",
"created_time": "2025-06-12T11:57:32.236290Z",
"created_by": {
"object": "user",
"id": "bcf6c03e-51a1-4f05-97d8-d616405b42a2"
},
"has_children": false,
"metadata": {
"origin": {
"file_id": "file_01jxhzyhk6f2bvjjabjx4dxqje",
"page_num": 1
}
},
"numbered_list_item": {
"rich_text": [
{
"type": "text",
"text": {
"content": "Volume and premium OEMs, Tier-1 and Tier-n companies trying to \"shape the market\""
},
"annotations": {},
"plain_text": "Volume and premium OEMs, Tier-1 and Tier-n companies trying to \"shape the market\""
}
]
}
},

{
"object": "block",
"id": "bk_01jxwgvydvf8zts3qzst8nbkcq",
Expand Down
Empty file.
50 changes: 49 additions & 1 deletion typescript/examples/vite_basic/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useState, useEffect } from "react";

const App = () => {
const [testPage, setTestPage] = useState(null);
const [devMode, setDevMode] = useState(false);

useEffect(() => {
const loadData = async () => {
Expand All @@ -22,6 +23,35 @@ const App = () => {
return <div>Loading...</div>;
}

// Test backrefs for highlighting
const testBackrefs = [
{
end_idx: 50,
block_id: "bk_01jxwgvye6er08spmyxj99f6cp",
start_idx: 0,
},
{
end_idx: 100,
block_id: "bk_01jxwgvydyfj6rhm125q1rd4h8",
start_idx: 70,
},
{
end_idx: 80,
block_id: "bk_01jxwgvydze3bsy2p19cfteqge",
start_idx: 20,
},
// {
// block_id: "bk_01jxwgvyehecbb2bv3jtnm9bzx",
// start_idx: 0,
// end_idx: 70,
// },
// {
// block_id: "bk_01jxj01879f8cvyq2hqc6p37z2",
// start_idx: 0,
// end_idx: 170,
// },
];

return (
<div
style={{
Expand All @@ -37,10 +67,28 @@ const App = () => {
>
<div>
<h1>JSON-DOC Renderer Development</h1>

<div style={{ marginBottom: "20px" }}>
<button
onClick={() => setDevMode(!devMode)}
style={{
padding: "8px 16px",
background: devMode ? "oklch(60% 0.2 250)" : "oklch(40% 0.2 250)",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer",
}}
>
{devMode ? "Disable" : "Enable"} Dev Mode
</button>
</div>

<JsonDocRenderer
page={testPage}
theme="dark"
devMode={true}
devMode={devMode}
backrefs={testBackrefs}
components={{
page_delimiter: (props) => {
return <PageDelimiter {...props} />;
Expand Down
34 changes: 19 additions & 15 deletions typescript/src/renderer/JsonDocRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import "./styles/index.css";
import React, { useEffect } from "react";
import React from "react";

import { Page } from "@/models/generated";
// import { validateAgainstSchema } from "@/validation/validator";
Expand All @@ -8,6 +8,9 @@ import { BlockRenderer } from "./components/BlockRenderer";
import { PageDelimiter } from "./components/PageDelimiter";
import { JsonViewPanel } from "./components/dev/JsonViewPanel";
import { RendererProvider } from "./context/RendererContext";
import { HighlightNavigation } from "./components/HighlightNavigation";
import { useHighlights } from "./hooks/useHighlights";
import { Backref } from "./utils/highlightUtils";

interface JsonDocRendererProps {
page: Page;
Expand All @@ -21,6 +24,7 @@ interface JsonDocRendererProps {
resolveImageUrl?: (url: string) => Promise<string>;
devMode?: boolean;
viewJson?: boolean;
backrefs?: Backref[];
}

export const JsonDocRenderer = ({
Expand All @@ -31,23 +35,15 @@ export const JsonDocRenderer = ({
resolveImageUrl,
devMode = false,
viewJson = false,
// PageDelimiterComponent = PageDelimiter,
backrefs = [],
}: JsonDocRendererProps) => {
console.log("page: ", page);

const loadAndValidate = async () => {
// const response = await fetch("/schema/page/page_schema.json"); // Updated path
// const data = await response.json();
// console.log("schema: ", data);
// validateAgainstSchema(
// page,
// )
};

useEffect(() => {
console.log("in jsondocrendererrrr");
loadAndValidate();
}, []);
// Use the modular hooks for highlight management
const { highlightCount, currentActiveIndex, navigateToHighlight } =
useHighlights({
backrefs,
});

// return null;
const renderedContent = (
Expand Down Expand Up @@ -113,6 +109,14 @@ export const JsonDocRenderer = ({
) : (
renderedContent
)}
{/* Show highlight navigation when there are highlights */}
{highlightCount > 0 && (
<HighlightNavigation
highlightCount={highlightCount}
onNavigate={navigateToHighlight}
currentIndex={currentActiveIndex}
/>
)}
</div>
</RendererProvider>
);
Expand Down
53 changes: 53 additions & 0 deletions typescript/src/renderer/components/HighlightNavigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from "react";

Check warning on line 1 in typescript/src/renderer/components/HighlightNavigation.tsx

View workflow job for this annotation

GitHub Actions / build-typescript

There should be at least one empty line between import groups
import { useHighlightNavigation } from "../hooks/useHighlightNavigation";

interface HighlightNavigationProps {
highlightCount: number;
onNavigate: (index: number) => void;
currentIndex?: number;
}

export const HighlightNavigation: React.FC<HighlightNavigationProps> = ({
highlightCount,
onNavigate,
currentIndex: externalCurrentIndex,
}) => {
const { currentIndex, navigatePrevious, navigateNext, hasHighlights } =
useHighlightNavigation({
highlightCount,
onNavigate,
externalCurrentIndex,
});

if (!hasHighlights) {
return null;
}

return (
<div className="json-doc-highlight-navigation">
<div className="highlight-nav-content">
<button
className="highlight-nav-button"
onClick={navigatePrevious}
aria-label="Previous highlight"
title="Previous highlight (↑/k)"
>
up
</button>

<span className="highlight-nav-counter">
{currentIndex >= 0 ? currentIndex + 1 : "-"} of {highlightCount}
</span>

<button
className="highlight-nav-button"
onClick={navigateNext}
aria-label="Next highlight"
title="Next highlight (↓/j)"
>
down
</button>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const TableBlockRenderer: React.FC<TableBlockRendererProps> = ({
<tr
key={child.id || index}
className="notion-table-row"
data-block-id={child.id}
>
{rowData?.cells?.map(
(cell: any, cellIndex: number) => {
Expand Down
Loading
Loading