diff --git a/typescript/README.md b/typescript/README.md index ce636dd..8990c24 100644 --- a/typescript/README.md +++ b/typescript/README.md @@ -274,11 +274,12 @@ b7b30c1 : Make more typesafe You can choose a different version from the list or create new one. But bumpp is smart enough to use appropriate next version. 3. Verify and confirm -4. Push commit and tag +4. Push commit and tag ``` git push --follow-tags ``` + 5. The new tag will trigger a release on github actions. 6. Go to github and create release using the new tag. Make sure you set the correct previous tag prefixed with `typescript-v` @@ -317,6 +318,7 @@ git push --follow-tags - [ ] validate page prop somehow. not clear how to do yet. we can't use the /schema because it's HUGE and also because it's outside of /typescript. Will need to think about this. maybe do something like this? + ``` import type { Page } from "../models/generated/page/page"; import { isPage } from "../models/generated/essential-types"; @@ -353,4 +355,4 @@ export function validatePageWithError(obj: unknown): { will require us to write a validator and we won't benefit from the defined schema jsons. -- [ ] make error boundary catch errors in JsonDocRenderer.tsx body \ No newline at end of file +- [ ] make error boundary catch errors in JsonDocRenderer.tsx body diff --git a/typescript/eslint.config.js b/typescript/eslint.config.js index a313898..a958d87 100644 --- a/typescript/eslint.config.js +++ b/typescript/eslint.config.js @@ -48,7 +48,11 @@ module.exports = [ // "@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/no-unused-vars": [ "warn", - { argsIgnorePattern: "^_" }, + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_", + caughtErrorsIgnorePattern: "^_", + }, ], // React rules @@ -97,9 +101,7 @@ module.exports = [ "coverage/**", ".jest/**", "scripts/**", - "tests/**", "**/generated/**", - "src/serialization/**", ], }, ]; diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 9e6113a..784bab3 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -46,6 +46,7 @@ "json-schema-to-typescript": "^15.0.4", "json5": "^2.2.3", "lint-staged": "^15.5.2", + "nodemon": "^3.1.10", "prettier": "3.5.3", "puppeteer": "^24.9.0", "size-limit": "^11.2.0", @@ -2949,6 +2950,20 @@ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", "dev": true }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -3295,6 +3310,19 @@ "node": ">=10.0.0" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -5784,6 +5812,13 @@ "node": ">= 4" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -5924,6 +5959,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", @@ -7373,6 +7421,132 @@ "dev": true, "license": "MIT" }, + "node_modules/nodemon": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", + "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/nodemon/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/nwsapi": { "version": "2.2.20", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", @@ -7989,6 +8163,13 @@ "dev": true, "license": "MIT" }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, "node_modules/pump": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", @@ -8660,6 +8841,32 @@ "dev": true, "license": "ISC" }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/sirv": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.1.tgz", @@ -9362,6 +9569,16 @@ "node": ">=6" } }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, "node_modules/tough-cookie": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", @@ -9690,6 +9907,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", diff --git a/typescript/package.json b/typescript/package.json index 190db47..d4d014d 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -9,9 +9,9 @@ "clean": "rm -rf dist", "build": "tsup", "build:watch": "tsup --watch", - "dev": "concurrently \"npm run build:watch\" \"npm run lint:watch\" \"npm run type-check:watch\"", - "type-check:watch": "tsc --noEmit --watch --pretty", - "lint:watch": "eslint src --ext .ts,.tsx --cache", + "dev": "concurrently \"npm run build:watch\" \"npm run lint:watch\" \"npm run check:watch\"", + "check:watch": "tsc --noEmit --watch --pretty", + "lint:watch": "nodemon --watch src --ext ts,tsx --exec \"eslint src --ext .ts,.tsx\"", "generate-types": "ts-node scripts/generate-types.ts", "test": "vitest", "test:run": "vitest run", @@ -62,6 +62,7 @@ "json-schema-to-typescript": "^15.0.4", "json5": "^2.2.3", "lint-staged": "^15.5.2", + "nodemon": "^3.1.10", "prettier": "3.5.3", "puppeteer": "^24.9.0", "size-limit": "^11.2.0", diff --git a/typescript/src/models/generated/block/types/equation/equation.ts b/typescript/src/models/generated/block/types/equation/equation.ts index 1c232c0..b4c6942 100644 --- a/typescript/src/models/generated/block/types/equation/equation.ts +++ b/typescript/src/models/generated/block/types/equation/equation.ts @@ -1,6 +1,6 @@ -import type { Block } from "../../block"; +import type { BlockBase } from "../../base"; -export type EquationBlock = Block & { +export type EquationBlock = BlockBase & { type: "equation"; equation: { expression: string; diff --git a/typescript/src/renderer/JsonDocRenderer.tsx b/typescript/src/renderer/JsonDocRenderer.tsx index 338e830..c9da51b 100644 --- a/typescript/src/renderer/JsonDocRenderer.tsx +++ b/typescript/src/renderer/JsonDocRenderer.tsx @@ -1,8 +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 { loadPage } from "@/serialization/loader"; import { BlockRenderer } from "./components/BlockRenderer"; import { PageDelimiter } from "./components/PageDelimiter"; @@ -46,6 +46,15 @@ export const JsonDocRenderer = ({ backrefs, }); + useEffect(() => { + try { + //TODO: this is not throwing for invalid page object (one that doesn't follow schema) + loadPage(page); + } catch (_) { + // console.log("error ", error); + } + }, [page]); + // return null; const renderedContent = (
({ describe("JsonDocRenderer - All Block Types", () => { it("renders page title correctly", () => { render(); + expect( screen.getByText("Test Page with All Block Types") ).toBeInTheDocument(); @@ -49,6 +50,8 @@ describe("JsonDocRenderer - All Block Types", () => { const page = createPageWithBlocks([mockBlocks.heading_1]); render( ); + screen.debug(); + expect(screen.getByText("Main Heading")).toBeInTheDocument(); }); diff --git a/typescript/tests/ThemeSwitching.test.tsx b/typescript/tests/ThemeSwitching.test.tsx new file mode 100644 index 0000000..f2f63da --- /dev/null +++ b/typescript/tests/ThemeSwitching.test.tsx @@ -0,0 +1,87 @@ +import "@testing-library/jest-dom"; + +import React from "react"; +import { render, screen } from "@testing-library/react"; +import { describe, it, expect } from "vitest"; +import { JsonDocRenderer } from "../src/renderer/JsonDocRenderer"; +import { mockBlocks, mockPageWithAllBlocks } from "./fixtures/test-blocks"; + +// Helper to create a simple page for theme testing +const createSimplePage = () => ({ + object: "page", + id: "theme-test-page", + properties: { + title: { + type: "title", + title: [ + { + href: null, + type: "text", + text: { link: null, content: "Theme Test Page" }, + annotations: {}, + plain_text: "Theme Test Page", + }, + ], + }, + }, + children: [mockBlocks.paragraph], +}); + +const JSON_DOC_ROOT_TEST_ID = "jsondoc-renderer-root"; + +describe("JsonDocRenderer - Theme Switching", () => { + const simplePage = createSimplePage(); + + it("renders with light theme by default", () => { + const { container } = render( ); + + const rendererDiv = screen.getByTestId(JSON_DOC_ROOT_TEST_ID); + expect(rendererDiv).toHaveClass("jsondoc-theme-light"); + expect(rendererDiv).not.toHaveClass("jsondoc-theme-dark"); + }); + + it("renders with light theme when explicitly set", () => { + const { container } = render( + + ); + + const rendererDiv = screen.getByTestId(JSON_DOC_ROOT_TEST_ID); + expect(rendererDiv).toHaveClass("jsondoc-theme-light"); + expect(rendererDiv).not.toHaveClass("jsondoc-theme-dark"); + }); + + it("renders with dark theme when theme prop is set to dark", () => { + const { container } = render( + + ); + + const rendererDiv = screen.getByTestId(JSON_DOC_ROOT_TEST_ID); + expect(rendererDiv).toHaveClass("jsondoc-theme-dark"); + expect(rendererDiv).not.toHaveClass("jsondoc-theme-light"); + }); + + it("handles undefined theme prop gracefully", () => { + const { container } = render( + + ); + + const rendererDiv = screen.getByTestId(JSON_DOC_ROOT_TEST_ID); + expect(rendererDiv).toHaveClass("jsondoc-theme-light"); + }); + + it("theme persists across different block types", () => { + const { container } = render( + + ); + + const rendererDiv = screen.getByTestId(JSON_DOC_ROOT_TEST_ID); + expect(rendererDiv).toHaveClass("jsondoc-theme-dark"); + + // Verify various block types are still rendered + expect(screen.getByText("This is a paragraph with")).toBeInTheDocument(); + expect(screen.getByText("First bullet point")).toBeInTheDocument(); + expect( + screen.getByText('console.log("Hello, World!");') + ).toBeInTheDocument(); + }); +}); diff --git a/typescript/tests/UnsupportedBlockHandling.test.tsx b/typescript/tests/UnsupportedBlockHandling.test.tsx new file mode 100644 index 0000000..160a78d --- /dev/null +++ b/typescript/tests/UnsupportedBlockHandling.test.tsx @@ -0,0 +1,105 @@ +import React from "react"; +import { render, screen } from "@testing-library/react"; +import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; +import { JsonDocRenderer } from "../src/renderer/JsonDocRenderer"; +import { mockBlocks } from "./fixtures/test-blocks"; + +// Helper to create a page with specific blocks +const createPageWithBlocks = (blocks: any[]) => ({ + object: "page", + id: "test-page", + properties: { + title: { + type: "title", + title: [ + { + href: null, + type: "text", + text: { link: null, content: "Test Page" }, + annotations: {}, + plain_text: "Test Page", + }, + ], + }, + }, + children: blocks, +}); + +describe("Unsupported Block Handling", () => { + // Mock console.warn to test logging behavior + const originalConsoleWarn = console.warn; + beforeEach(() => { + console.warn = vi.fn(); + }); + afterEach(() => { + console.warn = originalConsoleWarn; + }); + + const warningMsg = expect.stringMatching(/Unsupported block type:/); + + it("renders fallback UI for unsupported block types", () => { + const page = createPageWithBlocks([mockBlocks.unsupported_with_content]); + const { container } = render( ); + + // Should still render fallback UI regardless of block content + expect( + screen.getByText(/Unsupported block type: ai_block/) + ).toBeInTheDocument(); + + expect(screen.getByRole("alert")).toBeInTheDocument(); + }); + + it("renders unsupported blocks with children gracefully", () => { + const page = createPageWithBlocks([mockBlocks.unsupported_with_children]); + const { container } = render( ); + + // Should show fallback for the unsupported parent block + expect( + screen.getByText(/Unsupported block type: template_block/) + ).toBeInTheDocument(); + + expect( + container.querySelector('[data-block-type="template_block"]') + ).toBeInTheDocument(); + + // Children should not be rendered within unsupported block fallback + expect( + screen.queryByText(/Content inside unsupported block/) + ).not.toBeInTheDocument(); + }); + + it("handles multiple unsupported blocks without breaking renderer", () => { + const page = createPageWithBlocks([ + mockBlocks.unsupported_single, + mockBlocks.paragraph, // Mix with supported block + mockBlocks.unsupported_with_content, + mockBlocks.heading_1, // Another supported block + mockBlocks.unsupported_with_children, + ]); + const { container } = render( ); + + // All unsupported blocks should have fallback UI + expect( + screen.getByText(/Unsupported block type: custom_widget/) + ).toBeInTheDocument(); + expect( + screen.getByText(/Unsupported block type: ai_block/) + ).toBeInTheDocument(); + expect( + screen.getByText(/Unsupported block type: template_block/) + ).toBeInTheDocument(); + + // Supported blocks should still render normally + expect(screen.getByText(/This is a paragraph with/)).toBeInTheDocument(); + expect(screen.getByText(/Main Heading/)).toBeInTheDocument(); + + // Check all unsupported blocks have correct CSS class + expect(screen.getAllByRole("alert")).toHaveLength(3); + + // Verify all warnings were logged + expect(console.warn).toHaveBeenCalledTimes(3); + expect(console.warn).toHaveBeenCalledWith(warningMsg, "custom_widget"); + expect(console.warn).toHaveBeenCalledWith(warningMsg, "ai_block"); + expect(console.warn).toHaveBeenCalledWith(warningMsg, "template_block"); + }); +}); diff --git a/typescript/tests/fixtures/test-blocks.ts b/typescript/tests/fixtures/test-blocks.ts index 4c3b97b..8293a72 100644 --- a/typescript/tests/fixtures/test-blocks.ts +++ b/typescript/tests/fixtures/test-blocks.ts @@ -454,6 +454,59 @@ export const mockBlocks: Record< expression: "E = mc^2", }, }, + + // Mock unsupported block types for testing fallback behavior + unsupported_single: { + object: "block", + id: "unsupported-1", + type: "custom_widget" as any, + created_time: "2025-06-24T09:44:12.014249Z", + has_children: false, + }, + + unsupported_with_content: { + object: "block", + id: "unsupported-2", + type: "ai_block" as any, + created_time: "2025-06-24T09:44:12.014249Z", + has_children: false, + // @ts-expect-error + ai_block: { + prompt: "Generate something amazing", + }, + }, + + unsupported_with_children: { + object: "block", + id: "unsupported-3", + type: "template_block" as any, + created_time: "2025-06-24T09:44:12.014249Z", + has_children: true, + template_block: { + template_id: "template-123", + }, + children: [ + { + object: "block", + id: "h1-1", + // @ts-ignore + type: "paragraph", + created_time: "2025-06-24T09:44:12.014249Z", + has_children: false, + // @ts-ignore + heading_1: { + rich_text: [ + { + type: "text", + text: { content: "Main Heading" }, + annotations: {}, + plain_text: "Main Heading", + }, + ], + }, + }, + ], + }, }; // Complete page with all block types for comprehensive testing diff --git a/typescript/tests/test-cases.md b/typescript/tests/test-cases.md index 8b87f91..b980a0c 100644 --- a/typescript/tests/test-cases.md +++ b/typescript/tests/test-cases.md @@ -5,4 +5,4 @@ - make sure all blocks are rendered - make sure numbered lists are correctly labeled - make sure bad page is gracefully handled -- invalid block type should show error block UI \ No newline at end of file +- invalid block type should show error block UI diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json index c62ecad..287d36d 100644 --- a/typescript/tsconfig.json +++ b/typescript/tsconfig.json @@ -1,4 +1,6 @@ { + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { "target": "es2022", "module": "NodeNext", @@ -16,6 +18,8 @@ "resolveJsonModule": true, "sourceMap": true, "allowJs": true, + "noUnusedLocals": true, + "noUnusedParameters": true, // "noUncheckedIndexedAccess": true, "baseUrl": ".", "paths": {