diff --git a/znai-reactjs/src/layout/TopHeader.tsx b/znai-reactjs/src/layout/TopHeader.tsx
index d9649fac8..9898e50c3 100644
--- a/znai-reactjs/src/layout/TopHeader.tsx
+++ b/znai-reactjs/src/layout/TopHeader.tsx
@@ -15,12 +15,12 @@
*/
import React from "react";
-import { DocMeta } from "../structure/docMeta";
+import type { DocMeta } from "../structure/docMeta";
import TocPanelSearch from "./TocPanelSearch";
import { DarkLightThemeSwitcher } from "./DarkLightThemeSwitcher";
import "./TopHeader.css";
-import { TocItem } from "../structure/TocItem";
+import type { TocItem } from "../structure/TocItem";
interface Props {
docMeta: DocMeta;
diff --git a/znai-reactjs/src/layout/mobile/TocMobileHeader.demo.tsx b/znai-reactjs/src/layout/mobile/TocMobileHeader.demo.tsx
index 26cdde272..4ebfda5c2 100644
--- a/znai-reactjs/src/layout/mobile/TocMobileHeader.demo.tsx
+++ b/znai-reactjs/src/layout/mobile/TocMobileHeader.demo.tsx
@@ -16,9 +16,10 @@
import React from 'react';
-import { Registry, simpleAction } from 'react-component-viewer';
+import type { Registry} from 'react-component-viewer';
+import { simpleAction } from 'react-component-viewer';
import { TocMobileHeader } from './TocMobileHeader';
-import { DocMeta } from '../../structure/docMeta';
+import type { DocMeta } from '../../structure/docMeta';
const headerClick = simpleAction('header clicked');
const menuClick = simpleAction('menu clicked');
diff --git a/znai-reactjs/src/layout/mobile/TocMobileHeader.tsx b/znai-reactjs/src/layout/mobile/TocMobileHeader.tsx
index 2d871f75d..d72332d2a 100644
--- a/znai-reactjs/src/layout/mobile/TocMobileHeader.tsx
+++ b/znai-reactjs/src/layout/mobile/TocMobileHeader.tsx
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { DocMeta } from '../../structure/docMeta';
+import type { DocMeta } from '../../structure/docMeta';
import React from 'react';
import { Icon } from '../../doc-elements/icons/Icon';
diff --git a/znai-reactjs/src/layout/mobile/TocMobilePanel.tsx b/znai-reactjs/src/layout/mobile/TocMobilePanel.tsx
index 347600db3..e43dad527 100644
--- a/znai-reactjs/src/layout/mobile/TocMobilePanel.tsx
+++ b/znai-reactjs/src/layout/mobile/TocMobilePanel.tsx
@@ -16,7 +16,7 @@
import TocMenu from '../TocMenu';
import React from 'react';
-import { TocItem } from '../../structure/TocItem';
+import type { TocItem } from '../../structure/TocItem';
import { DarkLightThemeSwitcher } from '../DarkLightThemeSwitcher';
diff --git a/znai-reactjs/src/screens/landing/Landing.demo.tsx b/znai-reactjs/src/screens/landing/Landing.demo.tsx
index 5d85a4c7e..476e184f1 100644
--- a/znai-reactjs/src/screens/landing/Landing.demo.tsx
+++ b/znai-reactjs/src/screens/landing/Landing.demo.tsx
@@ -16,8 +16,9 @@
*/
import React from "react";
-import { Landing, LandingDocumentation } from "./Landing";
-import { Registry } from "react-component-viewer";
+import type { LandingDocumentation } from "./Landing";
+import { Landing } from "./Landing";
+import type { Registry } from "react-component-viewer";
const documentations: LandingDocumentation[] = [
{
diff --git a/znai-reactjs/src/screens/not-authorized/NotAuthorizedScreen.demo.tsx b/znai-reactjs/src/screens/not-authorized/NotAuthorizedScreen.demo.tsx
index 0edd333a9..450cb605b 100644
--- a/znai-reactjs/src/screens/not-authorized/NotAuthorizedScreen.demo.tsx
+++ b/znai-reactjs/src/screens/not-authorized/NotAuthorizedScreen.demo.tsx
@@ -15,7 +15,7 @@
*/
import React from 'react'
-import { Registry } from 'react-component-viewer';
+import type { Registry } from 'react-component-viewer';
import { NotAuthorizedScreen } from './NotAuthorizedScreen';
export function notAuthorizedDemo(registry: Registry) {
diff --git a/znai-reactjs/src/screens/preview-change-path/PreviewChangeScreen.tsx b/znai-reactjs/src/screens/preview-change-path/PreviewChangeScreen.tsx
index f23502ef1..7abeb47b5 100644
--- a/znai-reactjs/src/screens/preview-change-path/PreviewChangeScreen.tsx
+++ b/znai-reactjs/src/screens/preview-change-path/PreviewChangeScreen.tsx
@@ -17,7 +17,8 @@
import * as React from "react";
import { useEffect, useState } from "react";
import { socketUrl } from "../../utils/socket";
-import { Line, PreviewConsoleOutput } from "./PreviewConsoleOutput";
+import type { Line} from "./PreviewConsoleOutput";
+import { PreviewConsoleOutput } from "./PreviewConsoleOutput";
interface Props {
srcRoot: string;
diff --git a/znai-reactjs/src/screens/preview-change-path/PreviewConsoleOutput.demo.tsx b/znai-reactjs/src/screens/preview-change-path/PreviewConsoleOutput.demo.tsx
index 9a1daba26..f5efa05f3 100644
--- a/znai-reactjs/src/screens/preview-change-path/PreviewConsoleOutput.demo.tsx
+++ b/znai-reactjs/src/screens/preview-change-path/PreviewConsoleOutput.demo.tsx
@@ -15,8 +15,9 @@
*/
import React from "react";
-import { Registry } from "react-component-viewer";
-import { PreviewConsoleOutput, Line } from "./PreviewConsoleOutput";
+import type { Registry } from "react-component-viewer";
+import type { Line } from "./PreviewConsoleOutput";
+import { PreviewConsoleOutput } from "./PreviewConsoleOutput";
export function previewConsoleOutputDemo(registry: Registry) {
const lines: Line[] = [
diff --git a/znai-reactjs/src/screens/preview-change-path/PreviewConsoleOutput.tsx b/znai-reactjs/src/screens/preview-change-path/PreviewConsoleOutput.tsx
index bd09f9579..e349b4ee3 100644
--- a/znai-reactjs/src/screens/preview-change-path/PreviewConsoleOutput.tsx
+++ b/znai-reactjs/src/screens/preview-change-path/PreviewConsoleOutput.tsx
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+import React from "react";
import { useEffect, useRef } from "react";
import "./PreviewChangeScreen.css";
diff --git a/znai-reactjs/src/structure/toc/TableOfContents.ts b/znai-reactjs/src/structure/toc/TableOfContents.ts
index 0bb2edb7f..55852a0ac 100644
--- a/znai-reactjs/src/structure/toc/TableOfContents.ts
+++ b/znai-reactjs/src/structure/toc/TableOfContents.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-import { TocItem } from "../TocItem";
+import type { TocItem } from "../TocItem";
/**
diff --git a/znai-reactjs/src/structure/toc/toc.test.data.ts b/znai-reactjs/src/structure/toc/toc.test.data.ts
index 202f646a1..64dbdd56d 100644
--- a/znai-reactjs/src/structure/toc/toc.test.data.ts
+++ b/znai-reactjs/src/structure/toc/toc.test.data.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { TocItem } from "../TocItem";
+import type { TocItem } from "../TocItem";
export function testLongToc(): TocItem[] {
return [
diff --git a/znai-reactjs/src/test/setup.ts b/znai-reactjs/src/test/setup.ts
new file mode 100644
index 000000000..a4e7e5f61
--- /dev/null
+++ b/znai-reactjs/src/test/setup.ts
@@ -0,0 +1,17 @@
+import '@testing-library/jest-dom'
+import { vi } from 'vitest'
+
+// Setup DOM environment
+global.DOMParser = window.DOMParser
+global.document = window.document
+
+
+// Add any other global mocks or setup needed
+
+beforeAll(() => {
+ // Add any setup that should run before all tests
+})
+
+afterAll(() => {
+ // Add any cleanup that should run after all tests
+})
\ No newline at end of file
diff --git a/znai-reactjs/src/types/ansi_up.d.ts b/znai-reactjs/src/types/ansi_up.d.ts
new file mode 100644
index 000000000..840668c82
--- /dev/null
+++ b/znai-reactjs/src/types/ansi_up.d.ts
@@ -0,0 +1,82 @@
+// ansi_up.d.ts
+
+declare module 'ansi_up' {
+ /**
+ * Options for configuring AnsiUp behavior
+ */
+ export interface AnsiUpOptions {
+ /**
+ * Enable parsing of 256-color ANSI codes
+ * @default true
+ */
+ use_classes?: boolean;
+
+ /**
+ * Escape HTML characters in the input text
+ * @default false
+ */
+ escape_for_html?: boolean;
+ }
+
+ /**
+ * Packet containing text and foreground/background colors
+ */
+ export interface TextPacket {
+ text: string;
+ fg?: string;
+ bg?: string;
+ bold?: boolean;
+ italic?: boolean;
+ underline?: boolean;
+ strikethrough?: boolean;
+ }
+
+ /**
+ * AnsiUp - Convert ANSI escape codes to HTML or text
+ */
+ export class AnsiUp {
+ constructor();
+
+ /**
+ * Convert ANSI escape codes to HTML
+ * @param text - Input text containing ANSI codes
+ * @returns HTML string with ANSI codes converted to span elements
+ */
+ ansi_to_html(text: string): string;
+
+ /**
+ * Convert ANSI escape codes to text (strips ANSI codes)
+ * @param text - Input text containing ANSI codes
+ * @returns Plain text with ANSI codes removed
+ */
+ ansi_to_text(text: string): string;
+
+ /**
+ * Convert ANSI escape codes to an array of text packets
+ * @param text - Input text containing ANSI codes
+ * @returns Array of text packets with styling information
+ */
+ ansi_to_json(text: string): TextPacket[];
+
+ /**
+ * Use classes instead of inline styles for colors
+ */
+ use_classes: boolean;
+
+ /**
+ * Escape HTML in the input text
+ */
+ escape_for_html: boolean;
+
+ /**
+ * Set the palette for 256-color mode
+ * @param palette - Array of 256 color strings (hex format)
+ */
+ setupPalette(palette?: string[]): void;
+
+ /**
+ * URL pattern for linkifying URLs in the text
+ */
+ url_whitelist: { [scheme: string]: boolean };
+ }
+}
\ No newline at end of file
diff --git a/znai-reactjs/tsconfig.app.json b/znai-reactjs/tsconfig.app.json
new file mode 100644
index 000000000..e0c793789
--- /dev/null
+++ b/znai-reactjs/tsconfig.app.json
@@ -0,0 +1,34 @@
+{
+ "compilerOptions": {
+ "jsx": "react",
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2022",
+ "useDefineForClassFields": true,
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "types": ["vite/client"],
+ "skipLibCheck": true,
+ "allowJs": true,
+ "checkJs": true,
+ "typeRoots": ["./node_modules/@types", "./src/types"],
+ // or use:
+ "baseUrl": ".",
+ "paths": {
+ "*": ["src/types/*"]
+ },
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["src"]
+}
diff --git a/znai-reactjs/tsconfig.json b/znai-reactjs/tsconfig.json
index 8db13217f..1ffef600d 100644
--- a/znai-reactjs/tsconfig.json
+++ b/znai-reactjs/tsconfig.json
@@ -1,25 +1,7 @@
{
- "compilerOptions": {
- "target": "es5",
- "lib": [
- "dom",
- "dom.iterable",
- "esnext"
- ],
- "allowJs": true,
- "skipLibCheck": true,
- "esModuleInterop": true,
- "allowSyntheticDefaultImports": true,
- "strict": true,
- "forceConsistentCasingInFileNames": true,
- "module": "esnext",
- "moduleResolution": "node",
- "resolveJsonModule": true,
- "isolatedModules": true,
- "noEmit": true,
- "jsx": "react-jsx"
- },
- "include": [
- "src"
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
]
}
diff --git a/znai-reactjs/tsconfig.node.json b/znai-reactjs/tsconfig.node.json
new file mode 100644
index 000000000..43b6e4c3d
--- /dev/null
+++ b/znai-reactjs/tsconfig.node.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2023",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "types": ["node"],
+ "skipLibCheck": true,
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/znai-reactjs/vite.config.ts b/znai-reactjs/vite.config.ts
index 4a6ed7f58..04cbcca15 100644
--- a/znai-reactjs/vite.config.ts
+++ b/znai-reactjs/vite.config.ts
@@ -1,6 +1,7 @@
-import { defineConfig } from "vite";
-import react from "@vitejs/plugin-react-swc";
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
server: {
@@ -17,14 +18,22 @@ export default defineConfig({
},
},
build: {
- rollupOptions: {
- output: {
- manualChunks: undefined, // Prevent splitting chunks
+ target: ['es2020', 'chrome87', 'firefox78', 'safari14'],
+ rolldownOptions: {
+ jsx: {
+ mode: 'automatic'
},
- },
- },
- test: {
- globals: true,
- environment: "jsdom",
- },
-});
+ logLevel: 'debug',
+ output: {
+ advancedChunks: {
+ groups: [
+ {
+ name: 'mermaid',
+ test: /node_modules[\\/]mermaid/,
+ priority: 20,
+ }]
+ }
+ }
+ }
+ }
+})
diff --git a/znai-reactjs/vitest.config.ts b/znai-reactjs/vitest.config.ts
new file mode 100644
index 000000000..688b175d8
--- /dev/null
+++ b/znai-reactjs/vitest.config.ts
@@ -0,0 +1,17 @@
+import { defineConfig } from 'vitest/config'
+import react from '@vitejs/plugin-react-swc'
+
+export default defineConfig({
+ plugins: [react()],
+ test: {
+ environment: 'jsdom',
+ globals: true,
+ setupFiles: ['./src/test/setup.ts'],
+ include: ['src/**/*.{test,spec}.{js,jsx,ts,tsx}'],
+ includeSource: ['src/**/*.{js,ts}'],
+ css: true
+ },
+ resolve: {
+ extensions: ['.js', '.jsx', '.ts', '.tsx']
+ }
+})
\ No newline at end of file
diff --git a/znai-tests/pom.xml b/znai-tests/pom.xml
index e0d6845a7..1c5f9fcd8 100644
--- a/znai-tests/pom.xml
+++ b/znai-tests/pom.xml
@@ -55,6 +55,7 @@
test
+ webtau-test
run
diff --git a/znai-website-gen/src/main/java/org/testingisdocumenting/znai/html/reactjs/HtmlReactJsPage.java b/znai-website-gen/src/main/java/org/testingisdocumenting/znai/html/reactjs/HtmlReactJsPage.java
index ead90e97c..f169ee6ba 100644
--- a/znai-website-gen/src/main/java/org/testingisdocumenting/znai/html/reactjs/HtmlReactJsPage.java
+++ b/znai-website-gen/src/main/java/org/testingisdocumenting/znai/html/reactjs/HtmlReactJsPage.java
@@ -1,4 +1,5 @@
/*
+ * Copyright 2025 znai maintainers
* Copyright 2019 TWO SIGMA OPEN SOURCE, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,6 +22,7 @@
import org.testingisdocumenting.znai.utils.JsonUtils;
import org.testingisdocumenting.znai.website.WebResource;
import org.testingisdocumenting.znai.website.WebSiteResourcesProviders;
+import org.testingisdocumenting.znai.utils.ResourceUtils;
import java.util.Map;
@@ -52,6 +54,7 @@ public HtmlPage create(String title,
// because it is embedded into html page