diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml
index 02a80f8..c84258b 100644
--- a/.github/workflows/preview.yml
+++ b/.github/workflows/preview.yml
@@ -40,8 +40,6 @@ jobs:
run: |
npm pack
-
-
- name: List files in typescript dir
working-directory: ./typescript
run: |
diff --git a/typescript/examples/vite_basic/public/spacing_test.json b/typescript/examples/vite_basic/public/spacing_test.json
new file mode 100644
index 0000000..9f3247c
--- /dev/null
+++ b/typescript/examples/vite_basic/public/spacing_test.json
@@ -0,0 +1,1056 @@
+{
+ "object": "page",
+ "id": "pg_spacing_test_document",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "properties": {
+ "title": {
+ "type": "title",
+ "title": [
+ {
+ "type": "text",
+ "text": {
+ "content": "JSON-DOC Block Spacing Test"
+ },
+ "annotations": {},
+ "plain_text": "JSON-DOC Block Spacing Test"
+ }
+ ]
+ }
+ },
+ "children": [
+ {
+ "object": "block",
+ "id": "blk_heading1_top",
+ "type": "heading_1",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "heading_1": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Heading 1"
+ },
+ "annotations": {},
+ "plain_text": "Heading 1"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_heading2_top",
+ "type": "heading_2",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "heading_2": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Heading 2"
+ },
+ "annotations": {},
+ "plain_text": "Heading 2"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_heading3_top",
+ "type": "heading_3",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "heading_3": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Heading 3"
+ },
+ "annotations": {},
+ "plain_text": "Heading 3"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_heading1_1",
+ "type": "heading_1",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "heading_1": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Heading 1 - Main Title"
+ },
+ "annotations": {},
+ "plain_text": "Heading 1 - Main Title"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_paragraph_1",
+ "type": "paragraph",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "paragraph": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "This is a paragraph that comes after Heading 1. It should have proper spacing above and below. The text can be "
+ },
+ "annotations": {},
+ "plain_text": "This is a paragraph that comes after Heading 1. It should have proper spacing above and below. The text can be "
+ },
+ {
+ "type": "text",
+ "text": {
+ "content": "bold"
+ },
+ "annotations": {
+ "bold": true
+ },
+ "plain_text": "bold"
+ },
+ {
+ "type": "text",
+ "text": {
+ "content": ", "
+ },
+ "annotations": {},
+ "plain_text": ", "
+ },
+ {
+ "type": "text",
+ "text": {
+ "content": "italic"
+ },
+ "annotations": {
+ "italic": true
+ },
+ "plain_text": "italic"
+ },
+ {
+ "type": "text",
+ "text": {
+ "content": ", or "
+ },
+ "annotations": {},
+ "plain_text": ", or "
+ },
+ {
+ "type": "text",
+ "text": {
+ "content": "both bold and italic"
+ },
+ "annotations": {
+ "bold": true,
+ "italic": true
+ },
+ "plain_text": "both bold and italic"
+ },
+ {
+ "type": "text",
+ "text": {
+ "content": "."
+ },
+ "annotations": {},
+ "plain_text": "."
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_heading2_1",
+ "type": "heading_2",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "heading_2": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Heading 2 - Secondary Title"
+ },
+ "annotations": {},
+ "plain_text": "Heading 2 - Secondary Title"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_paragraph_2",
+ "type": "paragraph",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "paragraph": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Another paragraph after Heading 2. Notice the spacing relationship between headings and paragraphs."
+ },
+ "annotations": {},
+ "plain_text": "Another paragraph after Heading 2. Notice the spacing relationship between headings and paragraphs."
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_heading3_1",
+ "type": "heading_3",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "heading_3": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Heading 3 - Tertiary Title"
+ },
+ "annotations": {},
+ "plain_text": "Heading 3 - Tertiary Title"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_bulleted_list_1",
+ "type": "bulleted_list_item",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "bulleted_list_item": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "First bulleted list item"
+ },
+ "annotations": {},
+ "plain_text": "First bulleted list item"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_bulleted_list_2",
+ "type": "bulleted_list_item",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "bulleted_list_item": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Second bulleted list item with "
+ },
+ "annotations": {},
+ "plain_text": "Second bulleted list item with "
+ },
+ {
+ "type": "text",
+ "text": {
+ "content": "bold text"
+ },
+ "annotations": {
+ "bold": true
+ },
+ "plain_text": "bold text"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_bulleted_list_3",
+ "type": "bulleted_list_item",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "bulleted_list_item": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Third bulleted list item"
+ },
+ "annotations": {},
+ "plain_text": "Third bulleted list item"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_numbered_list_1",
+ "type": "numbered_list_item",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "numbered_list_item": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "First numbered list item"
+ },
+ "annotations": {},
+ "plain_text": "First numbered list item"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_numbered_list_2",
+ "type": "numbered_list_item",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "numbered_list_item": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Second numbered list item"
+ },
+ "annotations": {},
+ "plain_text": "Second numbered list item"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_numbered_list_3",
+ "type": "numbered_list_item",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "numbered_list_item": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Third numbered list item"
+ },
+ "annotations": {},
+ "plain_text": "Third numbered list item"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_quote_1",
+ "type": "quote",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "quote": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "This is a quote block. It should be visually distinct from paragraphs with proper indentation and styling. Quote blocks are often used for citations or emphasized text."
+ },
+ "annotations": {},
+ "plain_text": "This is a quote block. It should be visually distinct from paragraphs with proper indentation and styling. Quote blocks are often used for citations or emphasized text."
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_code_1",
+ "type": "code",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "code": {
+ "language": "javascript",
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "// This is a code block\nfunction helloWorld() {\n console.log('Hello, World!');\n return 'Perfect spacing test';\n}\n\n// Multiple lines to test spacing\nconst result = helloWorld();"
+ },
+ "annotations": {},
+ "plain_text": "// This is a code block\nfunction helloWorld() {\n console.log('Hello, World!');\n return 'Perfect spacing test';\n}\n\n// Multiple lines to test spacing\nconst result = helloWorld();"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_to_do_1",
+ "type": "to_do",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "to_do": {
+ "checked": false,
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Unchecked to-do item"
+ },
+ "annotations": {},
+ "plain_text": "Unchecked to-do item"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_to_do_2",
+ "type": "to_do",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "to_do": {
+ "checked": true,
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Checked to-do item"
+ },
+ "annotations": {},
+ "plain_text": "Checked to-do item"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_to_do_3",
+ "type": "to_do",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "to_do": {
+ "checked": false,
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Another to-do with "
+ },
+ "annotations": {},
+ "plain_text": "Another to-do with "
+ },
+ {
+ "type": "text",
+ "text": {
+ "content": "formatted text"
+ },
+ "annotations": {
+ "bold": true,
+ "italic": true
+ },
+ "plain_text": "formatted text"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_divider_1",
+ "type": "divider",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "divider": {}
+ },
+ {
+ "object": "block",
+ "id": "blk_paragraph_3",
+ "type": "paragraph",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "paragraph": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "This paragraph comes after a divider. The divider should have proper spacing above and below to separate content sections."
+ },
+ "annotations": {},
+ "plain_text": "This paragraph comes after a divider. The divider should have proper spacing above and below to separate content sections."
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_equation_1",
+ "type": "equation",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "equation": {
+ "expression": "E = mc^2"
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_table_1",
+ "type": "table",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "table": {
+ "table_width": 3,
+ "has_column_header": true,
+ "has_row_header": false
+ },
+ "children": [
+ {
+ "object": "block",
+ "id": "blk_table_row_1",
+ "type": "table_row",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "table_row": {
+ "cells": [
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Header 1"
+ },
+ "annotations": {
+ "bold": true
+ },
+ "plain_text": "Header 1"
+ }
+ ],
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Header 2"
+ },
+ "annotations": {
+ "bold": true
+ },
+ "plain_text": "Header 2"
+ }
+ ],
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Header 3"
+ },
+ "annotations": {
+ "bold": true
+ },
+ "plain_text": "Header 3"
+ }
+ ]
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_table_row_2",
+ "type": "table_row",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "table_row": {
+ "cells": [
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Row 1, Col 1"
+ },
+ "annotations": {},
+ "plain_text": "Row 1, Col 1"
+ }
+ ],
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Row 1, Col 2"
+ },
+ "annotations": {},
+ "plain_text": "Row 1, Col 2"
+ }
+ ],
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Row 1, Col 3"
+ },
+ "annotations": {},
+ "plain_text": "Row 1, Col 3"
+ }
+ ]
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_table_row_3",
+ "type": "table_row",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "table_row": {
+ "cells": [
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Row 2, Col 1"
+ },
+ "annotations": {},
+ "plain_text": "Row 2, Col 1"
+ }
+ ],
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Row 2, Col 2"
+ },
+ "annotations": {},
+ "plain_text": "Row 2, Col 2"
+ }
+ ],
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Row 2, Col 3"
+ },
+ "annotations": {},
+ "plain_text": "Row 2, Col 3"
+ }
+ ]
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_table_row_4",
+ "type": "table_row",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "table_row": {
+ "cells": [
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "This is a very long cell content that should wrap properly within the table cell boundaries and test the word wrapping functionality"
+ },
+ "annotations": {},
+ "plain_text": "This is a very long cell content that should wrap properly within the table cell boundaries and test the word wrapping functionality"
+ }
+ ],
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Short"
+ },
+ "annotations": {},
+ "plain_text": "Short"
+ }
+ ],
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Medium length content here"
+ },
+ "annotations": {},
+ "plain_text": "Medium length content here"
+ }
+ ]
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_table_row_5",
+ "type": "table_row",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "table_row": {
+ "cells": [
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Normal text"
+ },
+ "annotations": {},
+ "plain_text": "Normal text"
+ }
+ ],
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "This column has super long content that would normally cause horizontal overflow in a constrained container but should now wrap properly"
+ },
+ "annotations": {},
+ "plain_text": "This column has super long content that would normally cause horizontal overflow in a constrained container but should now wrap properly"
+ }
+ ],
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Another cell"
+ },
+ "annotations": {},
+ "plain_text": "Another cell"
+ }
+ ]
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_table_row_6",
+ "type": "table_row",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "table_row": {
+ "cells": [
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "URL Test"
+ },
+ "annotations": {},
+ "plain_text": "URL Test"
+ }
+ ],
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "https://example.com/very-long-url-path/that-might-cause-overflow/if-not-handled-properly"
+ },
+ "annotations": {},
+ "plain_text": "https://example.com/very-long-url-path/that-might-cause-overflow/if-not-handled-properly"
+ }
+ ],
+ [
+ {
+ "type": "text",
+ "text": {
+ "content": "Final column content that has moderate length"
+ },
+ "annotations": {},
+ "plain_text": "Final column content that has moderate length"
+ }
+ ]
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "object": "block",
+ "id": "blk_toggle_1",
+ "type": "toggle",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "toggle": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Toggle Block - Click to expand"
+ },
+ "annotations": {},
+ "plain_text": "Toggle Block - Click to expand"
+ }
+ ]
+ },
+ "children": [
+ {
+ "object": "block",
+ "id": "blk_toggle_child_1",
+ "type": "paragraph",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "paragraph": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "This is hidden content inside the toggle block. It should have proper indentation and spacing."
+ },
+ "annotations": {},
+ "plain_text": "This is hidden content inside the toggle block. It should have proper indentation and spacing."
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_toggle_child_2",
+ "type": "bulleted_list_item",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "bulleted_list_item": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "Nested list item in toggle"
+ },
+ "annotations": {},
+ "plain_text": "Nested list item in toggle"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "object": "block",
+ "id": "blk_column_list_1",
+ "type": "column_list",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "column_list": {},
+ "children": [
+ {
+ "object": "block",
+ "id": "blk_column_1",
+ "type": "column",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "column": {},
+ "children": [
+ {
+ "object": "block",
+ "id": "blk_column_1_paragraph_1",
+ "type": "paragraph",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "paragraph": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "This is the first column. Columns should be displayed side by side with proper spacing and alignment."
+ },
+ "annotations": {},
+ "plain_text": "This is the first column. Columns should be displayed side by side with proper spacing and alignment."
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "object": "block",
+ "id": "blk_column_2",
+ "type": "column",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "column": {},
+ "children": [
+ {
+ "object": "block",
+ "id": "blk_column_2_paragraph_1",
+ "type": "paragraph",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "paragraph": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "This is the second column. The spacing between columns should be consistent and visually appealing."
+ },
+ "annotations": {},
+ "plain_text": "This is the second column. The spacing between columns should be consistent and visually appealing."
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "object": "block",
+ "id": "blk_image_1",
+ "type": "image",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "image": {
+ "type": "external",
+ "external": {
+ "url": "https://images.unsplash.com/photo-1503327431567-3ab5e6e79140?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&w=4800"
+ },
+ "caption": [
+ {
+ "type": "text",
+ "text": {
+ "content": "This is a sample image with a caption. Image blocks should thiyyy This is a sample image with a caption. Image blocks should thiyyy"
+ },
+ "annotations": {},
+ "plain_text": "This is a sample image with a caption. Image blocks should"
+ }
+ ]
+ }
+ },
+ {
+ "object": "block",
+ "id": "blk_paragraph_final",
+ "type": "paragraph",
+ "created_time": "2025-06-19T14:04:08.260514Z",
+ "created_by": {
+ "object": "user",
+ "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b"
+ },
+ "paragraph": {
+ "rich_text": [
+ {
+ "type": "text",
+ "text": {
+ "content": "This is the final paragraph in our spacing test document. It demonstrates how all block types work together with consistent spacing throughout the document."
+ },
+ "annotations": {},
+ "plain_text": "This is the final paragraph in our spacing test document. It demonstrates how all block types work together with consistent spacing throughout the document."
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/typescript/examples/vite_basic/src/App.tsx b/typescript/examples/vite_basic/src/App.tsx
index 2851e7e..9c994d6 100644
--- a/typescript/examples/vite_basic/src/App.tsx
+++ b/typescript/examples/vite_basic/src/App.tsx
@@ -1,15 +1,50 @@
import { JsonDocRenderer, PageDelimiter } from "@textcortex/jsondoc";
import "@textcortex/jsondoc/dist/index.css";
import { useState, useEffect } from "react";
+import DevPanel from "./components/DevPanel";
+
+// Test backrefs for highlighting
+const testBackrefs: Array<{
+ end_idx: number;
+ block_id: string;
+ start_idx: number;
+}> = [
+ // {
+ // end_idx: 50,
+ // block_id: "blk_table_row_5",
+ // start_idx: 0,
+ // },
+ // {
+ // end_idx: 40,
+ // block_id: "blk_toggle_1",
+ // start_idx: 12,
+ // },
+ // {
+ // 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,
+ // },
+];
const App = () => {
const [testPage, setTestPage] = useState(null);
const [devMode, setDevMode] = useState(false);
+ const [theme, setTheme] = useState<"light" | "dark">("dark");
useEffect(() => {
const loadData = async () => {
try {
- const response = await fetch("/test_document.json");
+ const response = await fetch("/spacing_test.json");
const data = await response.json();
setTestPage(data);
} catch (error) {
@@ -23,70 +58,34 @@ const App = () => {
return
Loading...
;
}
- // 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 (
-
-
JSON-DOC Renderer Development
-
-
-
-
+
+
void;
+ theme: "light" | "dark";
+ setTheme: (theme: "light" | "dark") => void;
+}
+
+const DevPanel: React.FC = ({
+ devMode,
+ setDevMode,
+ theme,
+ setTheme,
+}) => {
+ return (
+ <>
+ {/* Floating Dev Mode Button */}
+ setDevMode(!devMode)}
+ backgroundColor={devMode ? "oklch(60% 0.2 250)" : "oklch(40% 0.2 250)"}
+ offset={{ x: 20, y: 20 }}
+ >
+ {devMode ? "Disable" : "Enable"} Dev Mode
+
+
+ {/* Floating Theme Toggle Button */}
+ setTheme(theme === "dark" ? "light" : "dark")}
+ backgroundColor={
+ theme === "dark" ? "oklch(60% 0.2 50)" : "oklch(40% 0.2 50)"
+ }
+ offset={{ x: 200, y: 20 }}
+ >
+ {theme === "dark" ? "☀️ Light" : "🌙 Dark"} Mode
+
+ >
+ );
+};
+
+export default DevPanel;
diff --git a/typescript/examples/vite_basic/src/components/FloatingButton.tsx b/typescript/examples/vite_basic/src/components/FloatingButton.tsx
new file mode 100644
index 0000000..1b8fe95
--- /dev/null
+++ b/typescript/examples/vite_basic/src/components/FloatingButton.tsx
@@ -0,0 +1,63 @@
+import React from "react";
+
+interface FloatingButtonProps {
+ onClick: () => void;
+ children: React.ReactNode;
+ position?: "top-right" | "top-left" | "bottom-right" | "bottom-left";
+ offset?: { x: number; y: number };
+ backgroundColor?: string;
+ color?: string;
+ zIndex?: number;
+}
+
+const FloatingButton: React.FC = ({
+ onClick,
+ children,
+ position = "top-right",
+ offset = { x: 20, y: 20 },
+ backgroundColor = "oklch(40% 0.2 250)",
+ color = "white",
+ zIndex = 1000,
+}) => {
+ const getPositionStyles = () => {
+ switch (position) {
+ case "top-left":
+ return { top: offset.y, left: offset.x };
+ case "bottom-right":
+ return { bottom: offset.y, right: offset.x };
+ case "bottom-left":
+ return { bottom: offset.y, left: offset.x };
+ default:
+ return { top: offset.y, right: offset.x };
+ }
+ };
+
+ return (
+
+ );
+};
+
+export default FloatingButton;
diff --git a/typescript/package-lock.json b/typescript/package-lock.json
index 3f0742e..04b271b 100644
--- a/typescript/package-lock.json
+++ b/typescript/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.2.0-alpha.4",
"license": "MIT",
"dependencies": {
+ "@types/katex": "^0.16.7",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"katex": "^0.16.22",
@@ -16,6 +17,7 @@
},
"devDependencies": {
"@eslint/js": "^9.28.0",
+ "@size-limit/preset-small-lib": "^11.2.0",
"@types/jest": "^29.5.14",
"@types/node": "^22.15.27",
"@types/react": "^19.1.5",
@@ -40,6 +42,7 @@
"lint-staged": "^15.5.2",
"prettier": "3.5.3",
"puppeteer": "^24.9.0",
+ "size-limit": "^11.2.0",
"strip-json-comments": "^5.0.2",
"ts-jest": "^29.3.4",
"ts-node": "^10.9.2",
@@ -2160,6 +2163,66 @@
"@sinonjs/commons": "^3.0.0"
}
},
+ "node_modules/@size-limit/esbuild": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/@size-limit/esbuild/-/esbuild-11.2.0.tgz",
+ "integrity": "sha512-vSg9H0WxGQPRzDnBzeDyD9XT0Zdq0L+AI3+77/JhxznbSCMJMMr8ndaWVQRhOsixl97N0oD4pRFw2+R1Lcvi6A==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "^0.25.0",
+ "nanoid": "^5.1.0"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "size-limit": "11.2.0"
+ }
+ },
+ "node_modules/@size-limit/esbuild/node_modules/nanoid": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz",
+ "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.js"
+ },
+ "engines": {
+ "node": "^18 || >=20"
+ }
+ },
+ "node_modules/@size-limit/file": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/@size-limit/file/-/file-11.2.0.tgz",
+ "integrity": "sha512-OZHE3putEkQ/fgzz3Tp/0hSmfVo3wyTpOJSRNm6AmcwX4Nm9YtTfbQQ/hZRwbBFR23S7x2Sd9EbqYzngKwbRoA==",
+ "dev": true,
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "size-limit": "11.2.0"
+ }
+ },
+ "node_modules/@size-limit/preset-small-lib": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/@size-limit/preset-small-lib/-/preset-small-lib-11.2.0.tgz",
+ "integrity": "sha512-RFbbIVfv8/QDgTPyXzjo5NKO6CYyK5Uq5xtNLHLbw5RgSKrgo8WpiB/fNivZuNd/5Wk0s91PtaJ9ThNcnFuI3g==",
+ "dev": true,
+ "dependencies": {
+ "@size-limit/esbuild": "11.2.0",
+ "@size-limit/file": "11.2.0",
+ "size-limit": "11.2.0"
+ },
+ "peerDependencies": {
+ "size-limit": "11.2.0"
+ }
+ },
"node_modules/@tootallnate/quickjs-emscripten": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
@@ -2316,6 +2379,11 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true
},
+ "node_modules/@types/katex": {
+ "version": "0.16.7",
+ "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz",
+ "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ=="
+ },
"node_modules/@types/lodash": {
"version": "4.17.17",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz",
@@ -3645,6 +3713,15 @@
"esbuild": ">=0.18"
}
},
+ "node_modules/bytes-iec": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/bytes-iec/-/bytes-iec-3.1.1.tgz",
+ "integrity": "sha512-fey6+4jDK7TFtFg/klGSvNKJctyU7n2aQdnM+CO0ruLPbqqMOM8Tio0Pc+deqUeVKX1tL5DQep1zQ7+37aTAsA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/c12": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/c12/-/c12-3.0.4.tgz",
@@ -7611,7 +7688,6 @@
"https://opencollective.com/katex",
"https://github.com/sponsors/katex"
],
- "license": "MIT",
"dependencies": {
"commander": "^8.3.0"
},
@@ -8425,6 +8501,15 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/nanospinner": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/nanospinner/-/nanospinner-1.2.2.tgz",
+ "integrity": "sha512-Zt/AmG6qRU3e+WnzGGLuMCEAO/dAu45stNbHY223tUxldaDAeE+FxSPsd9Q+j+paejmm0ZbrNVs5Sraqy3dRxA==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^1.1.1"
+ }
+ },
"node_modules/napi-postinstall": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.4.tgz",
@@ -9870,6 +9955,27 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/size-limit": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/size-limit/-/size-limit-11.2.0.tgz",
+ "integrity": "sha512-2kpQq2DD/pRpx3Tal/qRW1SYwcIeQ0iq8li5CJHQgOC+FtPn2BVmuDtzUCgNnpCrbgtfEHqh+iWzxK+Tq6C+RQ==",
+ "dev": true,
+ "dependencies": {
+ "bytes-iec": "^3.1.1",
+ "chokidar": "^4.0.3",
+ "jiti": "^2.4.2",
+ "lilconfig": "^3.1.3",
+ "nanospinner": "^1.2.2",
+ "picocolors": "^1.1.1",
+ "tinyglobby": "^0.2.11"
+ },
+ "bin": {
+ "size-limit": "bin.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ }
+ },
"node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
diff --git a/typescript/package.json b/typescript/package.json
index 0f0cc66..f156384 100644
--- a/typescript/package.json
+++ b/typescript/package.json
@@ -20,7 +20,8 @@
"check": "tsc --noEmit",
"lint": "eslint src --ext .ts,.tsx",
"lint:fix": "eslint src --ext .ts,.tsx --fix",
- "prepare": "husky"
+ "prepare": "husky",
+ "size": "npm run build && size-limit"
},
"keywords": [
"json",
@@ -32,6 +33,7 @@
"license": "MIT",
"devDependencies": {
"@eslint/js": "^9.28.0",
+ "@size-limit/preset-small-lib": "^11.2.0",
"@types/jest": "^29.5.14",
"@types/node": "^22.15.27",
"@types/react": "^19.1.5",
@@ -52,17 +54,19 @@
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"json-schema-to-typescript": "^15.0.4",
+ "json5": "^2.2.3",
"lint-staged": "^15.5.2",
"prettier": "3.5.3",
+ "puppeteer": "^24.9.0",
+ "size-limit": "^11.2.0",
+ "strip-json-comments": "^5.0.2",
"ts-jest": "^29.3.4",
"ts-node": "^10.9.2",
"tsup": "^8.5.0",
- "typescript": "^5.8.3",
- "puppeteer": "^24.9.0",
- "strip-json-comments": "^5.0.2",
- "json5": "^2.2.3"
+ "typescript": "^5.8.3"
},
"dependencies": {
+ "@types/katex": "^0.16.7",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"katex": "^0.16.22",
@@ -96,5 +100,19 @@
"*.{ts,tsx}": [
"eslint --fix"
]
- }
+ },
+ "size-limit": [
+ {
+ "path": "dist/index.js",
+ "limit": "20 KB"
+ },
+ {
+ "path": "dist/index.mjs",
+ "limit": "20 KB"
+ },
+ {
+ "path": "dist/index.css",
+ "limit": "20 KB"
+ }
+ ]
}
diff --git a/typescript/src/index.ts b/typescript/src/index.ts
index 3d13119..8b3c805 100644
--- a/typescript/src/index.ts
+++ b/typescript/src/index.ts
@@ -3,12 +3,7 @@
*/
// Export utility functions
-export {
- loadJson,
- getNestedValue,
- setNestedValue,
- deepClone,
-} from "./utils/json";
+export { loadJson, deepClone } from "./utils/json";
// Export React renderer components
export {
diff --git a/typescript/src/renderer/JsonDocRenderer.tsx b/typescript/src/renderer/JsonDocRenderer.tsx
index cc72773..e207a07 100644
--- a/typescript/src/renderer/JsonDocRenderer.tsx
+++ b/typescript/src/renderer/JsonDocRenderer.tsx
@@ -37,8 +37,6 @@ export const JsonDocRenderer = ({
viewJson = false,
backrefs = [],
}: JsonDocRendererProps) => {
- console.log("page: ", page);
-
// Use the modular hooks for highlight management
const { highlightCount, currentActiveIndex, navigateToHighlight } =
useHighlights({
diff --git a/typescript/src/renderer/components/PageDelimiter.tsx b/typescript/src/renderer/components/PageDelimiter.tsx
index 8a606c6..b583856 100644
--- a/typescript/src/renderer/components/PageDelimiter.tsx
+++ b/typescript/src/renderer/components/PageDelimiter.tsx
@@ -11,9 +11,8 @@ export const PageDelimiter: React.FC = ({
}) => {
return (
-
- Page {pageNumber}
-
+
+
Page {pageNumber}
);
};
diff --git a/typescript/src/renderer/components/blocks/ColumnListBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ColumnListBlockRenderer.tsx
index 80be805..72a5b41 100644
--- a/typescript/src/renderer/components/blocks/ColumnListBlockRenderer.tsx
+++ b/typescript/src/renderer/components/blocks/ColumnListBlockRenderer.tsx
@@ -22,7 +22,7 @@ export const ColumnListBlockRenderer: React.FC<
>
{block.children?.map((child, index: number) => {
if (child?.type === "column") {
diff --git a/typescript/src/renderer/components/blocks/EquationBlockRenderer.tsx b/typescript/src/renderer/components/blocks/EquationBlockRenderer.tsx
index 7f26509..d798ba6 100644
--- a/typescript/src/renderer/components/blocks/EquationBlockRenderer.tsx
+++ b/typescript/src/renderer/components/blocks/EquationBlockRenderer.tsx
@@ -1,4 +1,5 @@
-import React from "react";
+import React, { useEffect, useRef } from "react";
+import katex from "katex";
import { EquationBlock } from "@/models/generated";
@@ -14,6 +15,25 @@ export const EquationBlockRenderer: React.FC
= ({
...props
}) => {
const equationData = block.equation;
+ const containerRef = useRef(null);
+
+ useEffect(() => {
+ if (containerRef.current && equationData?.expression) {
+ try {
+ katex.render(equationData.expression, containerRef.current, {
+ displayMode: true,
+ throwOnError: false,
+ errorColor: '#cc0000',
+ strict: 'warn'
+ });
+ } catch (error) {
+ console.warn('KaTeX render error:', error);
+ if (containerRef.current) {
+ containerRef.current.textContent = equationData.expression;
+ }
+ }
+ }
+ }, [equationData?.expression]);
return (
= ({
>
-
- {equationData?.expression || ""}
-
+
diff --git a/typescript/src/renderer/components/blocks/ImageBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ImageBlockRenderer.tsx
index 0f1991a..b26f70a 100644
--- a/typescript/src/renderer/components/blocks/ImageBlockRenderer.tsx
+++ b/typescript/src/renderer/components/blocks/ImageBlockRenderer.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from "react";
+import React, { useEffect, useState, useRef } from "react";
import { useInView } from "react-intersection-observer";
import { useRenderer } from "../../context/RendererContext";
@@ -41,7 +41,9 @@ export const ImageBlockRenderer: React.FC = ({
const [isLoading, setIsLoading] = useState(false);
const [hasError, setHasError] = useState(false);
const [showFullCaption, setShowFullCaption] = useState(false);
+ const [needsTruncation, setNeedsTruncation] = useState(false);
const { ref, inView } = useInView({ threshold: 0.1, triggerOnce: true });
+ const captionRef = useRef(null);
const getImageUrl = () => {
if (imageData?.type === "external") {
@@ -86,6 +88,14 @@ export const ImageBlockRenderer: React.FC = ({
};
}, [inView, imageUrl, resolveImageUrl]);
+ useEffect(() => {
+ if (captionRef.current && imageData?.caption && imageData.caption.length > 0) {
+ const element = captionRef.current;
+ const isOverflowing = element.scrollHeight > element.clientHeight;
+ setNeedsTruncation(isOverflowing);
+ }
+ }, [imageData?.caption]);
+
return (
= ({
-
+ {needsTruncation && (
+
+ )}
)}
diff --git a/typescript/src/renderer/components/blocks/ListItemBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ListItemBlockRenderer.tsx
index adc8483..3b9b4be 100644
--- a/typescript/src/renderer/components/blocks/ListItemBlockRenderer.tsx
+++ b/typescript/src/renderer/components/blocks/ListItemBlockRenderer.tsx
@@ -39,7 +39,7 @@ export const ListItemBlockRenderer: React.FC
= ({
{block.type === "bulleted_list_item" && (
)}
-
+
diff --git a/typescript/src/renderer/components/blocks/QuoteBlockRenderer.tsx b/typescript/src/renderer/components/blocks/QuoteBlockRenderer.tsx
index ba0647b..8868671 100644
--- a/typescript/src/renderer/components/blocks/QuoteBlockRenderer.tsx
+++ b/typescript/src/renderer/components/blocks/QuoteBlockRenderer.tsx
@@ -27,10 +27,8 @@ export const QuoteBlockRenderer: React.FC
= ({
data-block-id={block.id}
>
-
-
-
-
+
+
diff --git a/typescript/src/renderer/components/blocks/TableBlockRenderer.tsx b/typescript/src/renderer/components/blocks/TableBlockRenderer.tsx
index 97cb673..e82f094 100644
--- a/typescript/src/renderer/components/blocks/TableBlockRenderer.tsx
+++ b/typescript/src/renderer/components/blocks/TableBlockRenderer.tsx
@@ -26,71 +26,45 @@ export const TableBlockRenderer: React.FC
= ({
className={`notion-selectable notion-table-block${className ? ` ${className}` : ""}`}
data-block-id={block.id}
>
-
-
-
-
-
-
- {block.children?.map((child: any, index: number) => {
- if (child?.type === "table_row") {
- const rowData = child.table_row;
- const isHeader =
- index === 0 && tableData?.has_column_header;
+
+
+
+
+ {block.children?.map((child: any, index: number) => {
+ if (child?.type === "table_row") {
+ const rowData = child.table_row;
+ const isHeader = index === 0 && tableData?.has_column_header;
- return (
-
- {rowData?.cells?.map(
- (cell: any, cellIndex: number) => {
- const CellTag = isHeader ? "th" : "td";
- return (
-
-
-
- );
- }
- )}
-
- );
- }
- return null;
- })}
-
-
-
-
+ return (
+
+ {rowData?.cells?.map((cell: any, cellIndex: number) => {
+ const CellTag = isHeader ? "th" : "td";
+ return (
+
+
+
+ );
+ })}
+
+ );
+ }
+ return null;
+ })}
+
+
-
- {/* Render other children blocks recursively (non-table-row blocks) */}
- {block.children && block.children.length > 0 && (
-
- {block.children
- .filter((child: any) => child?.type !== "table_row")
- .map((child: any, index: number) => (
-
- ))}
-
- )}
);
};
diff --git a/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx
index 4f0b7f8..efffbd0 100644
--- a/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx
+++ b/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx
@@ -27,54 +27,11 @@ export const ToDoBlockRenderer: React.FC
= ({
className={`notion-selectable notion-to_do-block ${className || ""}`.trim()}
data-block-id={block.id}
>
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
{/* Render children blocks recursively */}
diff --git a/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx
index 6d1c277..9b99c07 100644
--- a/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx
+++ b/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx
@@ -32,61 +32,68 @@ export const ToggleBlockRenderer: React.FC
= ({
className={`notion-selectable notion-toggle-block${className ? ` ${className}` : ""}`}
data-block-id={block.id}
>
-
-
-
{
- if (e.key === "Enter" || e.key === " ") {
- e.preventDefault();
- handleToggle();
- }
+
{
+ if (e.key === "Enter" || e.key === " ") {
+ e.preventDefault();
+ handleToggle();
+ }
+ }}
+ style={{
+ display: "flex",
+ alignItems: "center",
+ gap: 4,
+ cursor: "pointer",
+ }}
+ >
+
+
+
-
{/* Render children blocks recursively when toggle is open */}
{isOpen && block.children && block.children.length > 0 && (
- {block.children.map((child: any, index: number) => (
-
- ))}
+
+ {block.children.map((child: any, index: number) => (
+
+ ))}
+
)}
diff --git a/typescript/src/renderer/styles/base.css b/typescript/src/renderer/styles/base.css
index 1a5c991..9d642dd 100644
--- a/typescript/src/renderer/styles/base.css
+++ b/typescript/src/renderer/styles/base.css
@@ -1,10 +1,12 @@
/* Base Layout and Page Styles */
+.json-doc-renderer {
+ max-width: inherit;
+}
.json-doc-page {
max-width: var(--jsondoc-page-max-width);
+ max-width: inherit;
margin: 0 auto;
- /* padding: var(--jsondoc-page-padding-desktop)
- var(--jsondoc-page-padding-desktop) var(--jsondoc-page-bottom-padding); */
color: var(--jsondoc-text-primary);
font-family: var(--jsondoc-font-family-sans);
}
@@ -19,17 +21,13 @@
font-size: var(--jsondoc-font-size-page-title);
line-height: var(--jsondoc-line-height-normal);
font-weight: var(--jsondoc-font-weight-bold);
- margin: 0 0 var(--jsondoc-spacing-xs);
+ margin: 0px 0px var(--jsondoc-spacing-lg) 0px;
padding: var(--jsondoc-spacing-sm) 0px;
}
-.json-doc-page-content {
- margin-top: var(--jsondoc-spacing-lg);
-}
-
/* Base Block Styles */
.notion-selectable {
- position: relative;
+ /* position: relative; */
margin: 0;
padding: var(--jsondoc-spacing-sm) 0px;
}
diff --git a/typescript/src/renderer/styles/blocks.css b/typescript/src/renderer/styles/blocks.css
index a90da43..c19baf7 100644
--- a/typescript/src/renderer/styles/blocks.css
+++ b/typescript/src/renderer/styles/blocks.css
@@ -36,7 +36,7 @@
/* Quote Block */
.notion-quote-block {
- padding: var(--jsondoc-spacing-sm) var(--jsondoc-spacing-xs);
+ padding: var(--jsondoc-spacing-md) var(--jsondoc-spacing-xs);
}
.notion-quote-block blockquote {
@@ -60,9 +60,10 @@
/* To-do Block */
.notion-to_do-block {
display: flex;
- align-items: flex-start;
- padding: 1px var(--jsondoc-spacing-xs);
+ align-items: center;
+ padding: 3px var(--jsondoc-spacing-xs);
margin: 0;
+ gap: 8px;
}
.notion-to_do-block .checkboxSquare,
@@ -76,6 +77,10 @@
color: var(--jsondoc-accent-checkbox);
}
+.notion-to_do-block .checked {
+ text-decoration: line-through;
+}
+
.pseudoHover.pseudoActive {
position: relative;
display: flex;
@@ -85,15 +90,13 @@
/* Toggle Block */
.notion-toggle-block {
- display: flex;
- align-items: flex-start;
padding: var(--jsondoc-spacing-sm) var(--jsondoc-spacing-xs);
}
-.notion-toggle-block .arrowCaretDownFillSmall {
+.notion-toggle-block svg.arrowCaretDownFillSmall {
width: var(--jsondoc-icon-size);
height: var(--jsondoc-icon-size);
- color: var(--jsondoc-text-muted);
+ fill: var(--jsondoc-text-muted);
}
.notion-toggle-content {
@@ -112,6 +115,15 @@
flex: 1;
}
+.notion-toggle-block div[role="button"] {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 4px;
+}
+.notion-toggle-block div[role="button"]:hover {
+ background-color: var(--jsondoc-bg);
+}
/* Equation Block */
.notion-equation-block {
padding: var(--jsondoc-spacing-sm) var(--jsondoc-spacing-xs);
@@ -121,7 +133,6 @@
.notion-equation-display {
text-align: center;
padding: var(--jsondoc-spacing-lg);
- background: var(--jsondoc-bg-code);
border-radius: var(--jsondoc-radius-sm);
}
diff --git a/typescript/src/renderer/styles/index.css b/typescript/src/renderer/styles/index.css
index a3aa8d0..8772d4e 100644
--- a/typescript/src/renderer/styles/index.css
+++ b/typescript/src/renderer/styles/index.css
@@ -1,5 +1,8 @@
/* JSON-DOC Renderer Styles */
+/* Import KaTeX styles for equations */
+@import "katex/dist/katex.min.css";
+
/* Import design tokens first */
@import "./variables.css";
diff --git a/typescript/src/renderer/styles/layout.css b/typescript/src/renderer/styles/layout.css
index 6d391ba..d0575bd 100644
--- a/typescript/src/renderer/styles/layout.css
+++ b/typescript/src/renderer/styles/layout.css
@@ -3,21 +3,15 @@
/* Page Delimiter */
.jsondoc-page-delimiter {
margin: var(--jsondoc-spacing-xl) 0;
- margin-bottom: var(--jsondoc-spacing-3xl);
- position: relative;
+ margin-bottom: var(--jsondoc-spacing-xl);
display: flex;
- align-items: center;
- justify-content: center;
+ flex-direction: column;
}
.jsondoc-page-delimiter-line {
- position: absolute;
- top: 50%;
- left: 0;
- right: 0;
+ width: 100%;
height: 1px;
background: var(--jsondoc-border-light);
- z-index: var(--jsondoc-z-base);
}
.jsondoc-page-number {
@@ -27,9 +21,7 @@
font-size: var(--jsondoc-font-size-caption);
font-weight: var(--jsondoc-font-weight-normal);
border-radius: var(--jsondoc-radius-sm);
- position: relative;
- z-index: var(--jsondoc-z-elevated);
- display: inline-block;
+ width: fit-content;
}
/* Dark theme support for page delimiter */
diff --git a/typescript/src/renderer/styles/lists.css b/typescript/src/renderer/styles/lists.css
index e4797e9..e1ca4b7 100644
--- a/typescript/src/renderer/styles/lists.css
+++ b/typescript/src/renderer/styles/lists.css
@@ -6,6 +6,7 @@
line-height: var(--jsondoc-line-height-very-loose);
list-style-type: none;
display: flex;
+ margin-bottom: 2px;
}
/*
@@ -85,9 +86,10 @@
padding: 0px;
text-indent: 0px;
font-size: var(--jsondoc-font-size-h2);
- margin-right: var(--jsondoc-spacing-sm);
line-height: var(--jsondoc-line-height-tight);
- margin-left: 1em;
+ margin-left: 8px;
+ margin-right: 10px;
+ margin-bottom: 4px;
}
/*
@@ -103,8 +105,9 @@
content: counter(list-number) ". ";
font-size: var(--jsondoc-font-size-body);
margin-right: var(--jsondoc-spacing-sm);
- min-width: 2em;
text-align: right;
+ margin-left: 8px;
+ margin-right: 10px;
}
.notion-checkbox {
diff --git a/typescript/src/renderer/styles/media.css b/typescript/src/renderer/styles/media.css
index e4c5a6a..387311f 100644
--- a/typescript/src/renderer/styles/media.css
+++ b/typescript/src/renderer/styles/media.css
@@ -161,18 +161,45 @@
}
button.caption-toggle-btn {
- background: none;
- border: none;
- color: var(--jsondoc-text-muted);
+ background: rgba(55, 53, 47, 0.08);
+ border: 1px solid rgba(55, 53, 47, 0.16);
+ border-radius: 6px;
+ color: var(--jsondoc-text-secondary);
cursor: pointer;
- font-size: 0.875rem;
- margin-top: 4px;
- padding: 2px 4px;
- text-decoration: underline;
- transition: color 0.2s ease;
+ font-size: 0.75rem;
+ font-weight: 500;
+ margin-top: 8px;
+ padding: 6px 10px;
+ transition: all 0.15s ease;
margin-left: auto;
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ text-decoration: none;
+ outline: none;
}
.caption-toggle-btn:hover {
- color: var(--jsondoc-text-muted);
+ background: rgba(55, 53, 47, 0.12);
+ border-color: rgba(55, 53, 47, 0.24);
+ color: var(--jsondoc-text-primary);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.caption-toggle-btn:active {
+ transform: translateY(0);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+
+.caption-toggle-btn .btn-text {
+ line-height: 1;
+}
+
+.caption-toggle-btn .btn-icon {
+ /* transition: transform 0.4s ease; */
+ flex-shrink: 0;
+}
+
+.caption-toggle-btn .btn-icon.rotated {
+ transform: rotate(180deg);
}
diff --git a/typescript/src/renderer/styles/table.css b/typescript/src/renderer/styles/table.css
index 099512a..3c56b6c 100644
--- a/typescript/src/renderer/styles/table.css
+++ b/typescript/src/renderer/styles/table.css
@@ -7,7 +7,6 @@
.notion-scroller.horizontal {
overflow-x: auto;
- overflow-y: hidden;
width: 100%;
}
@@ -21,25 +20,28 @@
border-collapse: collapse;
border-spacing: 0;
table-layout: auto;
- min-width: 600px;
+ min-width: max-content;
}
.notion-table-row th,
.notion-table-row td {
- border: 1px solid var(--jsondoc-border-medium);
+ border: 1px solid var(--jsondoc-border-light);
padding: 8px 12px;
vertical-align: top;
- white-space: nowrap;
- min-width: 120px;
+ white-space: normal;
+ min-width: 80px;
+ max-width: 200px;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
}
.notion-table-row th {
- background-color: var(--jsondoc-bg-code);
font-weight: var(--jsondoc-font-weight-semibold);
+ text-align: left;
}
.notion-table-cell-text {
- overflow: hidden;
- text-overflow: ellipsis;
- max-width: 300px;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ white-space: normal;
}
diff --git a/typescript/src/renderer/styles/typography.css b/typescript/src/renderer/styles/typography.css
index 9622f00..4eddb25 100644
--- a/typescript/src/renderer/styles/typography.css
+++ b/typescript/src/renderer/styles/typography.css
@@ -1,3 +1,8 @@
+.notion-list-content {
+ display: flex;
+ align-items: center;
+}
+
/* Heading Blocks */
.notion-header-block,
.notion-sub_header-block {
@@ -14,6 +19,7 @@
margin: 0;
font-weight: var(--jsondoc-font-weight-semibold);
line-height: var(--jsondoc-line-height-relaxed);
+ margin-top: 32px;
}
.notion-sub_header-block h3 {
@@ -21,6 +27,7 @@
margin: 0;
font-weight: var(--jsondoc-font-weight-semibold);
line-height: var(--jsondoc-line-height-relaxed);
+ margin-top: 22px;
}
.notion-sub_header-block h4 {
@@ -28,6 +35,7 @@
margin: 0;
font-weight: var(--jsondoc-font-weight-semibold);
line-height: var(--jsondoc-line-height-relaxed);
+ margin-top: 16px;
}
.notion-link a {
@@ -39,8 +47,9 @@
transition: text-decoration-color var(--jsondoc-transition-fast);
}
-.notion-text-block div {
+.notion-text-block {
color: var(--jsondoc-text-primary);
+ line-height: var(--jsondoc-line-height-very-loose);
}
.notion-link:hover {
@@ -50,8 +59,6 @@
.notion-equation {
background: var(--jsondoc-bg-inline-code);
border-radius: var(--jsondoc-radius-sm);
- padding: 0.2em 0.4em;
- font-family: var(--jsondoc-font-family-serif);
}
/* Text Colors */
diff --git a/typescript/src/renderer/styles/variables.css b/typescript/src/renderer/styles/variables.css
index 1fecad8..33137d9 100644
--- a/typescript/src/renderer/styles/variables.css
+++ b/typescript/src/renderer/styles/variables.css
@@ -11,9 +11,9 @@
--jsondoc-bg-code: rgb(247, 246, 243);
--jsondoc-bg-inline-code: rgba(135, 131, 120, 0.15);
--jsondoc-bg-unsupported: rgba(255, 0, 0, 0.1);
-
- /* Text Colors */
- --jsondoc-color-gray: rgba(120, 119, 116, 1);
+ --jsondoc-bg: rgba(55, 53, 47, 0.45);
+ --jsondoc-foreground: #37352f /* Text Colors */
+ --jsondoc-color-gray: rgba(120, 119, 116, 1);
--jsondoc-color-brown: rgba(159, 107, 83, 1);
--jsondoc-color-orange: rgba(217, 115, 13, 1);
--jsondoc-color-yellow: rgba(203, 145, 47, 1);
@@ -109,14 +109,18 @@
--jsondoc-border-medium: rgb(233, 233, 231);
--jsondoc-bg-code: rgb(247, 246, 243);
--jsondoc-bg-inline-code: rgba(135, 131, 120, 0.15);
+ --jsondoc-bg: rgba(255, 255, 255, 0.8);
+ --jsondoc-foreground: #37352f;
}
.jsondoc-theme-dark {
- --jsondoc-text-primary: #ffffff;
+ --jsondoc-text-primary: rgba(255, 255, 255, 0.81);
--jsondoc-text-secondary: rgba(255, 255, 255, 0.65);
--jsondoc-text-muted: rgba(255, 255, 255, 0.45);
--jsondoc-border-light: rgba(255, 255, 255, 0.16);
--jsondoc-border-medium: rgba(255, 255, 255, 0.2);
--jsondoc-bg-code: rgba(255, 255, 255, 0.05);
--jsondoc-bg-inline-code: rgba(255, 255, 255, 0.1);
+ --jsondoc-bg: rgba(55, 53, 47, 0.45);
+ --jsondoc-foreground: #37352f;
}
diff --git a/typescript/tsup.config.ts b/typescript/tsup.config.ts
index 5788121..13b40b6 100644
--- a/typescript/tsup.config.ts
+++ b/typescript/tsup.config.ts
@@ -5,7 +5,7 @@ export default defineConfig({
format: ["cjs", "esm"],
dts: true,
splitting: false,
- sourcemap: true,
+ // sourcemap: true,
clean: true,
external: ["react", "react-dom"],
esbuildOptions(options) {