diff --git a/typescript/README.md b/typescript/README.md index 6595a1a..6f4baa0 100644 --- a/typescript/README.md +++ b/typescript/README.md @@ -256,13 +256,15 @@ MIT - [x] equation - [x] image - [x] blockquote -- [] fix ts and eslint errors in these dirs and remove from ignore list of ts and eslint +- [x] fix ts and eslint errors in these dirs and remove from ignore list of ts and eslint ``` "**/generated/**", "src/serialization/**", ``` + - [x] add counter for numbered lists - [x] setup up bumpp: https://www.npmjs.com/package/bumpp - [] migrate test runner to vitest - [x] move vite app to typescript root examples dir - [] setup monorepo tooling +- [] fix model generation for Image and RichText, then type renderers diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 243525c..79cda98 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -1,12 +1,12 @@ { "name": "@textcortex/jsondoc", - "version": "0.2.0-alpha.2", + "version": "0.2.0-alpha.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@textcortex/jsondoc", - "version": "0.2.0-alpha.2", + "version": "0.2.0-alpha.3", "license": "MIT", "dependencies": { "ajv": "^8.17.1", diff --git a/typescript/package.json b/typescript/package.json index 3171ac8..55cb972 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "@textcortex/jsondoc", - "version": "0.2.0-alpha.2", + "version": "0.2.0-alpha.3", "description": "JSON-DOC TypeScript implementation", "main": "dist/index.js", "module": "dist/index.mjs", diff --git a/typescript/scripts/generate-types.ts b/typescript/scripts/generate-types.ts index fe52291..aa70518 100644 --- a/typescript/scripts/generate-types.ts +++ b/typescript/scripts/generate-types.ts @@ -128,17 +128,19 @@ async function resolveRefs(obj: any, sourceDir: string): Promise { customTypePath = [...refTokens, title].join("."); } - // Create a simplified reference object - return { - type: "object", - title, - properties: {}, - additionalProperties: false, - // Add metadata for TypeScript generator - // These will be processed by json-schema-to-typescript - description: `Reference to ${customTypePath}`, - tsType: customTypePath.split(".").pop(), - }; + // For external references, just return a simple type reference + // This prevents inlining the entire interface definition + if (title) { + return { + type: "object", + title: title, + // Mark as external reference to prevent inlining + "x-external-ref": true, + }; + } + + // Fallback: return the resolved object if no title + return refObj || {}; } catch (error) { console.error(`Error resolving reference ${ref}:`, error); return {}; @@ -198,8 +200,14 @@ async function convertSchemaToTypeScript( const outputDir = path.dirname(outputPath); await mkdir(outputDir, { recursive: true }); + // Post-process to fix external references + const processedTypeScript = await postProcessTypeScript( + typeScript, + outputPath + ); + // Write the TypeScript interface to file - await writeFile(outputPath, typeScript); + await writeFile(outputPath, processedTypeScript); console.log(`Generated: ${outputPath}`); } catch (error) { console.error(`Error converting schema ${schemaPath}:`, error); @@ -274,6 +282,76 @@ function createBarrelFiles(dir: string): void { } } +/** + * Post-process generated TypeScript to fix external references + */ +async function postProcessTypeScript( + typeScript: string, + outputPath: string +): Promise { + let processed = typeScript; + + // Calculate the correct import path for each interface based on current output path + const getImportPath = (interfaceName: string): string => { + const outputDir = path.dirname(outputPath); + const modelsGenerated = path.resolve(__dirname, "../src/models/generated"); + + // Define the actual locations of each interface + const interfaceLocations: Record = { + BlockBase: path.join(modelsGenerated, "block/base"), + Block: path.join(modelsGenerated, "block"), + RichText: path.join(modelsGenerated, "block/types/rich_text"), + File: path.join(modelsGenerated, "file"), + ColumnBlock: path.join(modelsGenerated, "block/types/column"), + TableRowBlock: path.join(modelsGenerated, "block/types/table_row"), + FileExternal: path.join(modelsGenerated, "file/external"), + RichTextText: path.join(modelsGenerated, "block/types/rich_text/text"), + }; + + const targetPath = interfaceLocations[interfaceName]; + if (!targetPath) return ""; + + const relativePath = path.relative(outputDir, targetPath); + return relativePath.startsWith(".") + ? relativePath.replace(/\\/g, "/") + : `./${relativePath.replace(/\\/g, "/")}`; + }; + + // Find empty interface definitions and replace with imports + const emptyInterfaceRegex = /export interface (\w+) \{\}\s*/g; + const imports: string[] = []; + + processed = processed.replace(emptyInterfaceRegex, (match, interfaceName) => { + const importPath = getImportPath(interfaceName); + if (importPath) { + imports.push(`import type { ${interfaceName} } from '${importPath}';`); + return ""; // Remove the empty interface + } + return match; // Keep if not in our external interfaces map + }); + + // Add imports at the top if any were found + if (imports.length > 0) { + processed = imports.join("\n") + "\n\n" + processed; + } + + // Fix Block type to extend BlockBase if this is the block.ts file + if (outputPath.endsWith("block/block.ts")) { + // Add import for BlockBase if not already present + if (!processed.includes("import type { BlockBase }")) { + processed = `import type { BlockBase } from './base';\n\n` + processed; + } + + // Replace the Block type definition to extend BlockBase + processed = processed.replace( + /export type Block = \{[^}]*\} & \{/, + "export type Block = BlockBase & {" + ); + } + + return processed; +} + /** * Extract enum values from a JSON schema file */ diff --git a/typescript/scripts/viewer.js b/typescript/scripts/viewer.js deleted file mode 100644 index 0291719..0000000 --- a/typescript/scripts/viewer.js +++ /dev/null @@ -1,248 +0,0 @@ -#!/usr/bin/env node - -const fs = require("fs"); -const path = require("path"); -const http = require("http"); -const JSON5 = require("json5"); - -const PORT = 3000; - -// Get file path from command line argument -const filePath = process.argv[2]; - -if (!filePath) { - console.error("Usage: npm run view "); - process.exit(1); -} - -if (!fs.existsSync(filePath)) { - console.error(`File not found: ${filePath}`); - process.exit(1); -} - -// Load the JSON-DOC file -let pageData; -try { - const fileContent = fs.readFileSync(filePath, "utf-8"); - pageData = JSON5.parse(fileContent); - console.log(`Loaded JSON-DOC file: ${filePath}`); - console.log( - `Page title: ${pageData.properties?.title?.title?.[0]?.plain_text || "Untitled"}` - ); - console.log(`Blocks: ${pageData.children?.length || 0}`); -} catch (error) { - console.error(`Error reading file: ${error.message}`); - process.exit(1); -} - -// Read the CSS file -const cssPath = path.join(__dirname, "../src/renderer/styles.css"); -const cssContent = fs.existsSync(cssPath) - ? fs.readFileSync(cssPath, "utf-8") - : ""; - -// Read utility files -const blockMappingPath = path.join( - __dirname, - "../src/renderer/utils/blockMapping.js" -); -const listCounterPath = path.join( - __dirname, - "../src/renderer/utils/listCounter.js" -); -const richTextRendererPath = path.join( - __dirname, - "../src/renderer/utils/richTextRenderer.js" -); -const blockRendererFactoryPath = path.join( - __dirname, - "../src/renderer/blockRendererFactory.js" -); - -let blockMappingCode = ""; -let listCounterCode = ""; -let richTextRendererCode = ""; -let blockRendererFactoryCode = ""; - -try { - blockMappingCode = fs - .readFileSync(blockMappingPath, "utf-8") - .replace(/export /g, "") - .replace(/import [^;]+;/g, ""); - listCounterCode = fs - .readFileSync(listCounterPath, "utf-8") - .replace(/export /g, "") - .replace(/import [^;]+;/g, ""); - richTextRendererCode = fs - .readFileSync(richTextRendererPath, "utf-8") - .replace(/export /g, "") - .replace(/import [^;]+;/g, ""); - blockRendererFactoryCode = fs - .readFileSync(blockRendererFactoryPath, "utf-8") - .replace(/export /g, "") - .replace(/import [^;]+;/g, ""); -} catch (error) { - console.error("Error reading utility files:", error.message); - process.exit(1); -} - -// Create HTML template -const htmlTemplate = ` - - - - - - JSON-DOC Viewer - ${pageData.properties?.title?.title?.[0]?.plain_text || "Untitled"} - - - - -
-

JSON-DOC Viewer

-

File: ${path.basename(filePath)} • Blocks: ${pageData.children?.length || 0}

-
- -
- - - - - - - -`; - -// Create HTTP server -const server = http.createServer((req, res) => { - res.setHeader("Access-Control-Allow-Origin", "*"); - res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); - res.setHeader("Access-Control-Allow-Headers", "Content-Type"); - - if (req.url === "/") { - res.writeHead(200, { "Content-Type": "text/html" }); - res.end(htmlTemplate); - } else { - res.writeHead(404, { "Content-Type": "text/plain" }); - res.end("Not Found"); - } -}); - -// Start server -server.listen(PORT, () => { - const url = `http://localhost:${PORT}`; - console.log(`\nJSON-DOC Viewer started at ${url}`); - console.log("Press Ctrl+C to stop the server\n"); - - // Try to open browser automatically - const open = (url) => { - const { exec } = require("child_process"); - const start = - process.platform === "darwin" - ? "open" - : process.platform === "win32" - ? "start" - : "xdg-open"; - exec(`${start} ${url}`); - }; - - try { - open(url); - } catch (err) { - console.log( - "Could not automatically open browser. Please visit the URL manually." - ); - } -}); - -// Handle Ctrl+C -process.on("SIGINT", () => { - console.log("\nShutting down JSON-DOC Viewer..."); - server.close(() => { - console.log("Server stopped."); - process.exit(0); - }); -}); diff --git a/typescript/src/models/generated/block/block.ts b/typescript/src/models/generated/block/block.ts index c7c4b71..6ce722b 100644 --- a/typescript/src/models/generated/block/block.ts +++ b/typescript/src/models/generated/block/block.ts @@ -1,6 +1,6 @@ -export type Block = { - [k: string]: unknown; -} & { +import type { BlockBase } from "./base"; + +export type Block = BlockBase & { type: | "paragraph" | "to_do" diff --git a/typescript/src/models/generated/block/types/bulleted_list_item/bulleted_list_item.ts b/typescript/src/models/generated/block/types/bulleted_list_item/bulleted_list_item.ts index 75cbdcf..54b79cc 100644 --- a/typescript/src/models/generated/block/types/bulleted_list_item/bulleted_list_item.ts +++ b/typescript/src/models/generated/block/types/bulleted_list_item/bulleted_list_item.ts @@ -1,3 +1,6 @@ +import type { BlockBase } from "../../base"; +import type { Block } from "../.."; + export type BulletedListItemBlock = BlockBase & { type: "bulleted_list_item"; bulleted_list_item: { @@ -27,11 +30,3 @@ export type BulletedListItemBlock = BlockBase & { }; children?: Block[]; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; -/** - * Reference to jsondoc.models.block.base.BlockBase - */ -export type Block = BlockBase; diff --git a/typescript/src/models/generated/block/types/code/code.ts b/typescript/src/models/generated/block/types/code/code.ts index c916fa7..5b13d9a 100644 --- a/typescript/src/models/generated/block/types/code/code.ts +++ b/typescript/src/models/generated/block/types/code/code.ts @@ -1,3 +1,5 @@ +import type { BlockBase } from "../../base"; + export type CodeBlock = BlockBase & { type: "code"; code: { @@ -82,7 +84,3 @@ export type CodeBlock = BlockBase & { | "java/c/c++/c#"; }; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; diff --git a/typescript/src/models/generated/block/types/column/column.ts b/typescript/src/models/generated/block/types/column/column.ts index 217f411..6618c4e 100644 --- a/typescript/src/models/generated/block/types/column/column.ts +++ b/typescript/src/models/generated/block/types/column/column.ts @@ -1,13 +1,8 @@ +import type { BlockBase } from "../../base"; +import type { Block } from "../.."; + export type ColumnBlock = BlockBase & { type: "column"; column: {}; children?: Block[]; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; -/** - * Reference to jsondoc.models.block.base.BlockBase - */ -export type Block = BlockBase; diff --git a/typescript/src/models/generated/block/types/column_list/column_list.ts b/typescript/src/models/generated/block/types/column_list/column_list.ts index 63b8fdd..9edfb99 100644 --- a/typescript/src/models/generated/block/types/column_list/column_list.ts +++ b/typescript/src/models/generated/block/types/column_list/column_list.ts @@ -1,13 +1,8 @@ +import type { BlockBase } from "../../base"; +import type { ColumnBlock } from "../column"; + export type ColumnListBlock = BlockBase & { type: "column_list"; column_list: {}; children?: ColumnBlock[]; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; -/** - * Reference to block.types.column.ColumnBlock - */ -export type ColumnBlock = ColumnBlock; diff --git a/typescript/src/models/generated/block/types/divider/divider.ts b/typescript/src/models/generated/block/types/divider/divider.ts index dae6059..5d22661 100644 --- a/typescript/src/models/generated/block/types/divider/divider.ts +++ b/typescript/src/models/generated/block/types/divider/divider.ts @@ -1,8 +1,6 @@ +import type { BlockBase } from "../../base"; + export type DividerBlock = BlockBase & { type: "divider"; divider: {}; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; diff --git a/typescript/src/models/generated/block/types/equation/equation.ts b/typescript/src/models/generated/block/types/equation/equation.ts index e2fe111..1c232c0 100644 --- a/typescript/src/models/generated/block/types/equation/equation.ts +++ b/typescript/src/models/generated/block/types/equation/equation.ts @@ -1,10 +1,8 @@ -export type EquationBlock = BlockBase & { +import type { Block } from "../../block"; + +export type EquationBlock = Block & { type: "equation"; equation: { expression: string; }; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; diff --git a/typescript/src/models/generated/block/types/heading_1/heading_1.ts b/typescript/src/models/generated/block/types/heading_1/heading_1.ts index 916348d..7e1fecc 100644 --- a/typescript/src/models/generated/block/types/heading_1/heading_1.ts +++ b/typescript/src/models/generated/block/types/heading_1/heading_1.ts @@ -1,3 +1,5 @@ +import type { BlockBase } from "../../base"; + export type Heading1Block = BlockBase & { type: "heading_1"; heading_1: { @@ -27,7 +29,3 @@ export type Heading1Block = BlockBase & { is_toggleable?: boolean; }; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; diff --git a/typescript/src/models/generated/block/types/heading_2/heading_2.ts b/typescript/src/models/generated/block/types/heading_2/heading_2.ts index a83fa6c..7ff659b 100644 --- a/typescript/src/models/generated/block/types/heading_2/heading_2.ts +++ b/typescript/src/models/generated/block/types/heading_2/heading_2.ts @@ -1,3 +1,5 @@ +import type { BlockBase } from "../../base"; + export type Heading2Block = BlockBase & { type: "heading_2"; heading_2: { @@ -27,7 +29,3 @@ export type Heading2Block = BlockBase & { is_toggleable?: boolean; }; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; diff --git a/typescript/src/models/generated/block/types/heading_3/heading_3.ts b/typescript/src/models/generated/block/types/heading_3/heading_3.ts index d1b6b49..4c454fc 100644 --- a/typescript/src/models/generated/block/types/heading_3/heading_3.ts +++ b/typescript/src/models/generated/block/types/heading_3/heading_3.ts @@ -1,3 +1,5 @@ +import type { BlockBase } from "../../base"; + export type Heading3Block = BlockBase & { type: "heading_3"; heading_3: { @@ -27,7 +29,3 @@ export type Heading3Block = BlockBase & { is_toggleable?: boolean; }; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; diff --git a/typescript/src/models/generated/block/types/image/external_image/external_image.ts b/typescript/src/models/generated/block/types/image/external_image/external_image.ts index 4d17974..e728b48 100644 --- a/typescript/src/models/generated/block/types/image/external_image/external_image.ts +++ b/typescript/src/models/generated/block/types/image/external_image/external_image.ts @@ -1,9 +1,7 @@ +import type { FileExternal } from "../../../../file/external"; + export type ExternalImage = FileExternal & { caption?: { [k: string]: unknown; }[]; }; -/** - * Reference to file.external.FileExternal - */ -export type FileExternal = FileExternal; diff --git a/typescript/src/models/generated/block/types/image/file_image/file_image.ts b/typescript/src/models/generated/block/types/image/file_image/file_image.ts index ffc445a..5a12a06 100644 --- a/typescript/src/models/generated/block/types/image/file_image/file_image.ts +++ b/typescript/src/models/generated/block/types/image/file_image/file_image.ts @@ -3,7 +3,5 @@ export type FileImage = FileFile & { [k: string]: unknown; }[]; }; -/** - * Reference to file.file.FileFile - */ -export type FileFile = FileFile; + +export interface FileFile {} diff --git a/typescript/src/models/generated/block/types/image/image.ts b/typescript/src/models/generated/block/types/image/image.ts index e04e98b..64bda48 100644 --- a/typescript/src/models/generated/block/types/image/image.ts +++ b/typescript/src/models/generated/block/types/image/image.ts @@ -1,10 +1,8 @@ +import type { BlockBase } from "../../base"; + export type ImageBlock = BlockBase & { type: "image"; image: { [k: string]: unknown; }; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; diff --git a/typescript/src/models/generated/block/types/numbered_list_item/numbered_list_item.ts b/typescript/src/models/generated/block/types/numbered_list_item/numbered_list_item.ts index 9c581c1..5010429 100644 --- a/typescript/src/models/generated/block/types/numbered_list_item/numbered_list_item.ts +++ b/typescript/src/models/generated/block/types/numbered_list_item/numbered_list_item.ts @@ -1,3 +1,6 @@ +import type { BlockBase } from "../../base"; +import type { Block } from "../.."; + export type NumberedListItemBlock = BlockBase & { type: "numbered_list_item"; numbered_list_item: { @@ -27,11 +30,3 @@ export type NumberedListItemBlock = BlockBase & { }; children?: Block[]; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; -/** - * Reference to jsondoc.models.block.base.BlockBase - */ -export type Block = BlockBase; diff --git a/typescript/src/models/generated/block/types/paragraph/paragraph.ts b/typescript/src/models/generated/block/types/paragraph/paragraph.ts index 18888b3..aae4749 100644 --- a/typescript/src/models/generated/block/types/paragraph/paragraph.ts +++ b/typescript/src/models/generated/block/types/paragraph/paragraph.ts @@ -1,3 +1,6 @@ +import type { BlockBase } from "../../base"; +import type { Block } from "../.."; + export type ParagraphBlock = BlockBase & { type: "paragraph"; paragraph: { @@ -27,11 +30,3 @@ export type ParagraphBlock = BlockBase & { }; children?: Block[]; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; -/** - * Reference to jsondoc.models.block.base.BlockBase - */ -export type Block = BlockBase; diff --git a/typescript/src/models/generated/block/types/quote/quote.ts b/typescript/src/models/generated/block/types/quote/quote.ts index 23f481d..15d3856 100644 --- a/typescript/src/models/generated/block/types/quote/quote.ts +++ b/typescript/src/models/generated/block/types/quote/quote.ts @@ -1,3 +1,6 @@ +import type { BlockBase } from "../../base"; +import type { Block } from "../.."; + export type QuoteBlock = BlockBase & { type: "quote"; quote: { @@ -27,11 +30,3 @@ export type QuoteBlock = BlockBase & { }; children?: Block[]; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; -/** - * Reference to jsondoc.models.block.base.BlockBase - */ -export type Block = BlockBase; diff --git a/typescript/src/models/generated/block/types/table/table.ts b/typescript/src/models/generated/block/types/table/table.ts index 35181ad..7c7b0a2 100644 --- a/typescript/src/models/generated/block/types/table/table.ts +++ b/typescript/src/models/generated/block/types/table/table.ts @@ -1,3 +1,6 @@ +import type { BlockBase } from "../../base"; +import type { TableRowBlock } from "../table_row"; + export type TableBlock = BlockBase & { type: "table"; table: { @@ -7,11 +10,3 @@ export type TableBlock = BlockBase & { }; children?: TableRowBlock[]; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; -/** - * Reference to block.types.table_row.TableRowBlock - */ -export type TableRowBlock = TableRowBlock; diff --git a/typescript/src/models/generated/block/types/table_row/table_row.ts b/typescript/src/models/generated/block/types/table_row/table_row.ts index c6e7cce..f60511a 100644 --- a/typescript/src/models/generated/block/types/table_row/table_row.ts +++ b/typescript/src/models/generated/block/types/table_row/table_row.ts @@ -1,3 +1,5 @@ +import type { BlockBase } from "../../base"; + export type TableRowBlock = BlockBase & { type: "table_row"; table_row: { @@ -6,7 +8,3 @@ export type TableRowBlock = BlockBase & { }[][]; }; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; diff --git a/typescript/src/models/generated/block/types/to_do/to_do.ts b/typescript/src/models/generated/block/types/to_do/to_do.ts index 651c7c5..3bcdfdd 100644 --- a/typescript/src/models/generated/block/types/to_do/to_do.ts +++ b/typescript/src/models/generated/block/types/to_do/to_do.ts @@ -1,3 +1,6 @@ +import type { BlockBase } from "../../base"; +import type { Block } from "../.."; + export type ToDoBlock = BlockBase & { type: "to_do"; to_do: { @@ -28,11 +31,3 @@ export type ToDoBlock = BlockBase & { }; children?: Block[]; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; -/** - * Reference to jsondoc.models.block.base.BlockBase - */ -export type Block = BlockBase; diff --git a/typescript/src/models/generated/block/types/toggle/toggle.ts b/typescript/src/models/generated/block/types/toggle/toggle.ts index fbc9dbe..bfdb774 100644 --- a/typescript/src/models/generated/block/types/toggle/toggle.ts +++ b/typescript/src/models/generated/block/types/toggle/toggle.ts @@ -1,3 +1,6 @@ +import type { BlockBase } from "../../base"; +import type { Block } from "../.."; + export type ToggleBlock = BlockBase & { type: "toggle"; toggle: { @@ -27,11 +30,3 @@ export type ToggleBlock = BlockBase & { }; children?: Block[]; }; -/** - * Reference to block.base.BlockBase - */ -export type BlockBase = BlockBase; -/** - * Reference to jsondoc.models.block.base.BlockBase - */ -export type Block = BlockBase; diff --git a/typescript/src/models/generated/page/page.ts b/typescript/src/models/generated/page/page.ts index 496fd58..51b8695 100644 --- a/typescript/src/models/generated/page/page.ts +++ b/typescript/src/models/generated/page/page.ts @@ -1,11 +1,5 @@ -/** - * Reference to block.types.rich_text.text.RichTextText - */ -export type RichTextText = RichTextText; -/** - * Reference to jsondoc.models.block.base.BlockBase - */ -export type Block = BlockBase; +import type { RichTextText } from "../block/types/rich_text/text"; +import type { Block } from "../block"; export interface Page { object: "page"; diff --git a/typescript/src/renderer/JsonDocRenderer.tsx b/typescript/src/renderer/JsonDocRenderer.tsx index 8cafdde..c35a7db 100644 --- a/typescript/src/renderer/JsonDocRenderer.tsx +++ b/typescript/src/renderer/JsonDocRenderer.tsx @@ -1,5 +1,8 @@ import "./styles/index.css"; -import React from "react"; +import React, { useEffect } from "react"; + +import { Page } from "@/models/generated"; +// import { validateAgainstSchema } from "@/validation/validator"; import { BlockRenderer } from "./components/BlockRenderer"; import { PageDelimiter } from "./components/PageDelimiter"; @@ -7,7 +10,7 @@ import { JsonViewPanel } from "./components/dev/JsonViewPanel"; import { RendererProvider } from "./context/RendererContext"; interface JsonDocRendererProps { - page: any; + page: Page; className?: string; components?: React.ComponentProps["components"]; theme?: "light" | "dark"; @@ -25,22 +28,38 @@ export const JsonDocRenderer = ({ devMode = false, viewJson = false, }: 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(); + }, []); + + // return null; const renderedContent = (
+ hello {/* Page icon */} {page.icon && (
{page.icon.type === "emoji" && page.icon.emoji}
)} - {/* Page title */} {page.properties?.title && (

{page.properties.title.title?.[0]?.plain_text || "Untitled"}

)} - {/* Page children blocks */} {page.children && page.children.length > 0 && (
@@ -48,7 +67,7 @@ export const JsonDocRenderer = ({ const currentPageNum = block.metadata?.origin?.page_num; const nextPageNum = index < page.children.length - 1 - ? page.children[index + 1]?.metadata?.origin?.page_num + ? (page.children[index + 1]?.metadata as any)?.origin?.page_num : null; // Show delimiter after the last block of each page @@ -77,6 +96,7 @@ export const JsonDocRenderer = ({ return ( + hello and hello
{viewJson ? (
diff --git a/typescript/src/renderer/components/BlockRenderer.tsx b/typescript/src/renderer/components/BlockRenderer.tsx index a4d0113..bc3b130 100644 --- a/typescript/src/renderer/components/BlockRenderer.tsx +++ b/typescript/src/renderer/components/BlockRenderer.tsx @@ -1,5 +1,25 @@ import React from "react"; +import { + Block, + BlockBase, + Heading1Block, + Heading2Block, + Heading3Block, + ParagraphBlock, + BulletedListItemBlock, + NumberedListItemBlock, + CodeBlock, + ImageBlock, + TableBlock, + QuoteBlock, + DividerBlock, + ToDoBlock, + ToggleBlock, + ColumnListBlock, + EquationBlock, +} from "@/models/generated"; + import { useRenderer } from "../context/RendererContext"; import { DevWrapper } from "./dev/DevWrapper"; @@ -56,7 +76,7 @@ export type BlockComponents = { }; interface BlockRendererProps { - block: any; + block: Block; depth?: number; components?: BlockComponents; } @@ -80,92 +100,127 @@ export const BlockRenderer: React.FC = ({ // Paragraph block if (block?.type === "paragraph") { const ParagraphComponent = components?.paragraph || ParagraphBlockRenderer; - return wrapWithDev(); + return wrapWithDev( + + ); } // Heading blocks - if (block?.type === "heading_1") { + if ( + block?.type === "heading_1" || + block?.type === "heading_2" || + block?.type === "heading_3" + ) { const HeadingComponent = components?.heading_1 || HeadingBlockRenderer; - return wrapWithDev(); - } - if (block?.type === "heading_2") { - const HeadingComponent = components?.heading_2 || HeadingBlockRenderer; - return wrapWithDev(); - } - if (block?.type === "heading_3") { - const HeadingComponent = components?.heading_3 || HeadingBlockRenderer; - return wrapWithDev(); + return wrapWithDev( + + ); } + // if (block?.type === "heading_2") { + // const HeadingComponent = components?.heading_2 || HeadingBlockRenderer; + // return wrapWithDev(); + // } + // if (block?.type === "heading_3") { + // const HeadingComponent = components?.heading_3 || HeadingBlockRenderer; + // return wrapWithDev(); + // } // List item blocks if (block?.type === "bulleted_list_item") { const BulletedListItemComponent = components?.bulleted_list_item || ListItemBlockRenderer; return wrapWithDev( - + ); } if (block?.type === "numbered_list_item") { const NumberedListItemComponent = components?.numbered_list_item || ListItemBlockRenderer; return wrapWithDev( - + ); } // Code block if (block?.type === "code") { const CodeComponent = components?.code || CodeBlockRenderer; - return wrapWithDev(); + return wrapWithDev( + + ); } // Image block if (block?.type === "image") { const ImageComponent = components?.image || ImageBlockRenderer; - return wrapWithDev(); + return wrapWithDev( + + ); } // Table blocks if (block?.type === "table") { const TableComponent = components?.table || TableBlockRenderer; - return wrapWithDev(); + return wrapWithDev( + + ); } // Quote block if (block?.type === "quote") { const QuoteComponent = components?.quote || QuoteBlockRenderer; - return wrapWithDev(); + return wrapWithDev( + + ); } // Divider block if (block?.type === "divider") { const DividerComponent = components?.divider || DividerBlockRenderer; - return wrapWithDev(); + return wrapWithDev( + + ); } // To-do block if (block?.type === "to_do") { const ToDoComponent = components?.to_do || ToDoBlockRenderer; - return wrapWithDev(); + return wrapWithDev( + + ); } // Toggle block if (block?.type === "toggle") { const ToggleComponent = components?.toggle || ToggleBlockRenderer; - return wrapWithDev(); + return wrapWithDev( + + ); } // Column list and column blocks if (block?.type === "column_list") { const ColumnListComponent = components?.column_list || ColumnListBlockRenderer; - return wrapWithDev(); + return wrapWithDev( + + ); } // Equation block if (block?.type === "equation") { const EquationComponent = components?.equation || EquationBlockRenderer; - return wrapWithDev(); + return wrapWithDev( + + ); } // Fallback for unsupported block types diff --git a/typescript/src/renderer/components/RichTextRenderer.tsx b/typescript/src/renderer/components/RichTextRenderer.tsx index 8971bd6..614a484 100644 --- a/typescript/src/renderer/components/RichTextRenderer.tsx +++ b/typescript/src/renderer/components/RichTextRenderer.tsx @@ -1,5 +1,7 @@ import React from "react"; +// import { RichText } from "@/models/generated"; + interface RichTextRendererProps { richText: any[]; } @@ -13,7 +15,7 @@ export const RichTextRenderer: React.FC = ({ return ( <> - {richText.map((item: any, index: number) => { + {richText.map((item, index: number) => { const key = `rich-text-${index}`; if (item?.type === "text") { diff --git a/typescript/src/renderer/components/blocks/CodeBlockRenderer.tsx b/typescript/src/renderer/components/blocks/CodeBlockRenderer.tsx index 3abcf01..2e3b9c0 100644 --- a/typescript/src/renderer/components/blocks/CodeBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/CodeBlockRenderer.tsx @@ -1,19 +1,16 @@ import React from "react"; +import { CodeBlock } from "@/models/generated"; + import { RichTextRenderer } from "../RichTextRenderer"; -import { BlockRenderer } from "../BlockRenderer"; interface CodeBlockRendererProps extends React.HTMLAttributes { - block: any; - depth?: number; - components?: React.ComponentProps["components"]; + block: CodeBlock; } export const CodeBlockRenderer: React.FC = ({ block, - depth = 0, className, - components, ...props }) => { const codeData = block.code; @@ -39,22 +36,7 @@ export const CodeBlockRenderer: React.FC = ({
- {/* Render children blocks recursively */} - {block.children && block.children.length > 0 && ( -
- {block.children.map((child: any, index: number) => ( - - ))} -
- )} + {/* code block can't have children */}
); }; diff --git a/typescript/src/renderer/components/blocks/ColumnListBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ColumnListBlockRenderer.tsx index 9373d19..80be805 100644 --- a/typescript/src/renderer/components/blocks/ColumnListBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ColumnListBlockRenderer.tsx @@ -1,10 +1,12 @@ import React from "react"; +import { ColumnListBlock } from "@/models/generated"; + import { BlockRenderer } from "../BlockRenderer"; interface ColumnListBlockRendererProps extends React.HTMLAttributes { - block: any; + block: ColumnListBlock; depth?: number; components?: React.ComponentProps["components"]; } @@ -22,7 +24,7 @@ export const ColumnListBlockRenderer: React.FC< className="notion-column-list" style={{ display: "flex", gap: "16px" }} > - {block.children?.map((child: any, index: number) => { + {block.children?.map((child, index: number) => { if (child?.type === "column") { return (
{ - block: any; + block: DividerBlock; depth?: number; components?: React.ComponentProps["components"]; } export const DividerBlockRenderer: React.FC = ({ block, - depth = 0, className, - components, ...props }) => { return ( @@ -25,23 +25,6 @@ export const DividerBlockRenderer: React.FC = ({
- - {/* Render children blocks recursively */} - {block.children && block.children.length > 0 && ( -
- {block.children.map((child: any, index: number) => ( - - ))} -
- )}
); }; diff --git a/typescript/src/renderer/components/blocks/EquationBlockRenderer.tsx b/typescript/src/renderer/components/blocks/EquationBlockRenderer.tsx index 8ad2c0a..7f26509 100644 --- a/typescript/src/renderer/components/blocks/EquationBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/EquationBlockRenderer.tsx @@ -1,19 +1,16 @@ import React from "react"; -import { BlockRenderer } from "../BlockRenderer"; +import { EquationBlock } from "@/models/generated"; interface EquationBlockRendererProps extends React.HTMLAttributes { - block: any; + block: EquationBlock; depth?: number; - components?: React.ComponentProps["components"]; } export const EquationBlockRenderer: React.FC = ({ block, - depth = 0, className, - components, ...props }) => { const equationData = block.equation; @@ -31,23 +28,6 @@ export const EquationBlockRenderer: React.FC = ({
- - {/* Render children blocks recursively */} - {block.children && block.children.length > 0 && ( -
- {block.children.map((child: any, index: number) => ( - - ))} -
- )} ); }; diff --git a/typescript/src/renderer/components/blocks/HeadingBlockRenderer.tsx b/typescript/src/renderer/components/blocks/HeadingBlockRenderer.tsx index 68da465..fabb751 100644 --- a/typescript/src/renderer/components/blocks/HeadingBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/HeadingBlockRenderer.tsx @@ -1,31 +1,30 @@ import React from "react"; +import { + Heading1Block, + Heading2Block, + Heading3Block, +} from "@/models/generated"; + import { RichTextRenderer } from "../RichTextRenderer"; -import { BlockRenderer } from "../BlockRenderer"; interface HeadingBlockRendererProps extends React.HTMLAttributes { - block: any; - level: 1 | 2 | 3; - depth?: number; - components?: React.ComponentProps["components"]; + block: Heading1Block | Heading2Block | Heading3Block; } export const HeadingBlockRenderer: React.FC = ({ block, - level, - depth = 0, className, - components, ...props }) => { const getHeadingData = () => { - switch (level) { - case 1: + switch (block.type) { + case "heading_1": return block.heading_1; - case 2: + case "heading_2": return block.heading_2; - case 3: + case "heading_3": return block.heading_3; default: return null; @@ -34,18 +33,20 @@ export const HeadingBlockRenderer: React.FC = ({ const headingData = getHeadingData(); const blockClassName = - level === 1 ? "notion-header-block" : "notion-sub_header-block"; + block.type === "heading_1" + ? "notion-header-block" + : "notion-sub_header-block"; const renderHeading = () => { const content = ( ); - switch (level) { - case 1: + switch (block.type) { + case "heading_1": return

{content}

; - case 2: + case "heading_2": return

{content}

; - case 3: + case "heading_3": return

{content}

; default: return

{content}

; @@ -59,23 +60,6 @@ export const HeadingBlockRenderer: React.FC = ({ data-block-id={block.id} >
{renderHeading()}
- - {/* Render children blocks recursively */} - {block.children && block.children.length > 0 && ( -
- {block.children.map((child: any, index: number) => ( - - ))} -
- )} ); }; diff --git a/typescript/src/renderer/components/blocks/ImageBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ImageBlockRenderer.tsx index 62350c1..0f1991a 100644 --- a/typescript/src/renderer/components/blocks/ImageBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ImageBlockRenderer.tsx @@ -122,7 +122,6 @@ export const ImageBlockRenderer: React.FC = ({ )} - {/* Caption */} {imageData?.caption && imageData.caption.length > 0 && (
@@ -135,7 +134,7 @@ export const ImageBlockRenderer: React.FC = ({ className="caption-toggle-btn" onClick={() => setShowFullCaption(!showFullCaption)} > - {showFullCaption ? "Show less" : "Show more"} + {showFullCaption ? "Show less" : "Show more"}
diff --git a/typescript/src/renderer/components/blocks/ListItemBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ListItemBlockRenderer.tsx index 5c01ba7..adc8483 100644 --- a/typescript/src/renderer/components/blocks/ListItemBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ListItemBlockRenderer.tsx @@ -2,28 +2,30 @@ import React from "react"; import { RichTextRenderer } from "../RichTextRenderer"; import { BlockRenderer } from "../BlockRenderer"; +import { BulletedListItemBlock } from "../../../models/generated/block/types/bulleted_list_item"; +import { NumberedListItemBlock } from "../../../models/generated/block/types/numbered_list_item"; interface ListItemBlockRendererProps extends React.HTMLAttributes { - block: any; - type: "bulleted" | "numbered"; + block: BulletedListItemBlock | NumberedListItemBlock; depth?: number; components?: React.ComponentProps["components"]; } export const ListItemBlockRenderer: React.FC = ({ block, - type, depth = 0, className, components, ...props }) => { const listData = - type === "bulleted" ? block.bulleted_list_item : block.numbered_list_item; + block.type === "bulleted_list_item" + ? (block as BulletedListItemBlock).bulleted_list_item + : (block as NumberedListItemBlock).numbered_list_item; const blockClassName = - type === "bulleted" + block.type === "bulleted_list_item" ? "notion-bulleted_list-block" : "notion-numbered_list-block"; @@ -34,7 +36,9 @@ export const ListItemBlockRenderer: React.FC = ({ data-block-id={block.id} > {/*
*/} - {type === "bulleted" &&
} + {block.type === "bulleted_list_item" && ( +
+ )}
@@ -45,9 +49,9 @@ export const ListItemBlockRenderer: React.FC = ({ className="notion-block-children" style={{ marginLeft: `${depth * 24}px` }} > - {block.children.map((child: any, index: number) => ( + {block.children.map((child, index: number) => ( { - block: any; + block: ParagraphBlock; depth?: number; components?: React.ComponentProps["components"]; } diff --git a/typescript/src/renderer/components/blocks/QuoteBlockRenderer.tsx b/typescript/src/renderer/components/blocks/QuoteBlockRenderer.tsx index 5a8cf2e..ba0647b 100644 --- a/typescript/src/renderer/components/blocks/QuoteBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/QuoteBlockRenderer.tsx @@ -1,10 +1,12 @@ import React from "react"; +import { QuoteBlock } from "@/models/generated"; + import { RichTextRenderer } from "../RichTextRenderer"; import { BlockRenderer } from "../BlockRenderer"; interface QuoteBlockRendererProps extends React.HTMLAttributes { - block: any; + block: QuoteBlock; depth?: number; components?: React.ComponentProps["components"]; } diff --git a/typescript/src/renderer/components/blocks/TableBlockRenderer.tsx b/typescript/src/renderer/components/blocks/TableBlockRenderer.tsx index 14d85fc..c4949a2 100644 --- a/typescript/src/renderer/components/blocks/TableBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/TableBlockRenderer.tsx @@ -1,10 +1,12 @@ import React from "react"; +import { TableBlock } from "@/models/generated"; + import { RichTextRenderer } from "../RichTextRenderer"; import { BlockRenderer } from "../BlockRenderer"; interface TableBlockRendererProps extends React.HTMLAttributes { - block: any; + block: TableBlock; depth?: number; components?: React.ComponentProps["components"]; } diff --git a/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx index dfcb356..4f0b7f8 100644 --- a/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx @@ -1,10 +1,12 @@ import React from "react"; +import { ToDoBlock } from "@/models/generated"; + import { RichTextRenderer } from "../RichTextRenderer"; import { BlockRenderer } from "../BlockRenderer"; interface ToDoBlockRendererProps extends React.HTMLAttributes { - block: any; + block: ToDoBlock; depth?: number; components?: React.ComponentProps["components"]; } diff --git a/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx index 6721f16..6d1c277 100644 --- a/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx @@ -1,11 +1,13 @@ import React, { useState } from "react"; +import { ToggleBlock } from "@/models/generated"; + import { RichTextRenderer } from "../RichTextRenderer"; import { BlockRenderer } from "../BlockRenderer"; interface ToggleBlockRendererProps extends React.HTMLAttributes { - block: any; + block: ToggleBlock; depth?: number; components?: React.ComponentProps["components"]; } diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json index 814fe73..58c6756 100644 --- a/typescript/tsconfig.json +++ b/typescript/tsconfig.json @@ -31,11 +31,5 @@ "tests/**/*.ts", "scripts/**/*.ts" ], - "exclude": [ - "node_modules", - "dist", - "**/generated/**/*", - "src/serialization/**", - "src/models/generated/**/*" - ] + "exclude": ["node_modules", "dist", "src/serialization/**"] }