A modern, web-based AsciiDoc editor designed to deliver a smooth writing experience with powerful real-time preview capabilities. Built with React 19 and Vite, it integrates the Asciidoctor.js core and supports bidirectional synchronized scrolling, diagram rendering, math formulas, and local file system access.
-
Real-time Preview & Rendering:
- Standard AsciiDoc syntax parsing powered by
Asciidoctor.js. - Bidirectional Synchronized Scrolling: Precise line-level synchronization between the source view and the preview (based on AST line number mapping).
- Advanced Diagram Support: Built-in
Mermaidrendering engine for flowcharts, sequence diagrams, and more. - Math Formula Support: Integrated
KaTeXfor rendering LaTeX math formulas (STEM blocks). - Syntax Highlighting: Code block beautification using
highlight.js.
- Standard AsciiDoc syntax parsing powered by
-
Modern Editing Experience:
- Dual-Mode Editing:
- Source Mode: A high-performance code editor based on
CodeMirror 6with AsciiDoc syntax highlighting and autocompletion. - WYSIWYG Mode: Integrated
Tiptapeditor providing rich-text editing capabilities.
- Source Mode: A high-performance code editor based on
- Multiple View Layouts: Switch between editor-only, preview-only, or side-by-side split-screen modes.
- Dual-Mode Editing:
-
File System & Management:
- Local File System Access: Uses the File System Access API to directly read and save
.adocfiles on the local disk — no upload/download required. - Virtual File Management: Built-in state management powered by
Zustand, supporting multi-file tabs, folder structures, file renaming, and moving. - Browser Storage Persistence: Automatic workspace state saving via IndexedDB/LocalStorage.
- Local File System Access: Uses the File System Access API to directly read and save
-
Additional Features:
- Dark Mode support.
- Image Manager.
- Export options (HTML, PDF, ZIP).
- Core Framework: React 19, Vite
- Language: TypeScript
- State Management: Zustand
- Editor Engines:
- @codemirror/* (Source code editing)
- @tiptap/* (Rich-text editing)
- Rendering Engines:
- UI Components & Styling: Lucide React (Icons)
- Testing: Vitest, React Testing Library
Asciidoc WYSIWYG Editor
├── App.tsx # [Core] Main app entry — global layout, Toast notifications, keyboard shortcuts, and Provider wrapper
├── components # [UI Components] View and interaction components
│ ├── AttributesPanel.tsx # AsciiDoc document attributes panel (e.g., :toc:, :sectnums:)
│ ├── Autocomplete.tsx # Editor autocompletion component (IntelliSense)
│ ├── BlockMenu.tsx # Block-level element action menu (floating/context menu)
│ ├── BlockWrapper.tsx # React wrapper for Tiptap nodes, for custom rendering
│ ├── ContextMenu.tsx # Right-click context menu implementation
│ ├── ErrorBoundary.tsx # React error boundary — prevents editor crashes from causing blank screens
│ ├── ImageManager.tsx # Image resource manager — handles upload, insertion, and IndexedDB storage
│ ├── MobileHeader.tsx # Mobile-adapted top navigation bar
│ ├── OutlineNavigator.tsx # Document outline navigation (TOC)
│ ├── SearchReplaceDialog.tsx # Search and replace dialog
│ ├── Sidebar.tsx # Left-side file explorer / sidebar
│ ├── SourceEditor.tsx # [Core] Source mode editor (based on CodeMirror 6)
│ ├── TableEditor.tsx # Visual table editing tool
│ ├── TiptapEditor.tsx # [Core] WYSIWYG editor (based on Tiptap), integrated with real-time preview logic
│ ├── Toolbar.tsx # Top rich-text toolbar
│ └── ui # Common base UI component library
│ └── Button.tsx
├── extensions # [Tiptap Extensions] Custom ProseMirror nodes for AsciiDoc syntax support
│ ├── BlockNodeView.tsx # Generic block-level node view
│ ├── LintingExtension.ts # Linting extension (interfaces with the Linter)
│ ├── RawBlock.ts # Raw block node (stores unparseable AsciiDoc fragments)
│ ├── TableCaption.ts # Table caption extension
│ ├── UniqueId.ts # Unique ID generation extension (for synchronized scroll positioning)
│ ├── admonition-node.tsx # Admonition block (NOTE, TIP, WARNING, etc.) React rendering node
│ ├── include-node.tsx # Visual node for the Include directive
│ └── slash-commands.tsx # Slash commands (Notion-style "/" menu)
├── hooks # [React Hooks] Custom logic reuse
│ ├── useAsyncRender.ts # Async rendering hook — optimizes performance for large documents
│ └── useTransientUpdates.ts # Performance optimization hook for high-frequency updates (e.g., scroll sync)
├── index.css # Global styles, Tailwind CSS entry point
├── index.html # HTML template
├── index.tsx # Application mount point
├── lib # [Core Logic Library] Business logic and utility functions
│ ├── LanguageClient.ts # Language Server Client (LSP) simulation layer
│ ├── asciidoc.ts # AsciiDoc base processing logic
│ ├── asciidoctor-renderer.ts # [Core] Asciidoctor.js rendering engine wrapper (with Mermaid/KaTeX support)
│ ├── ast-error-collector.ts # AST error collector (for Lint)
│ ├── ast-visitor.ts # AST visitor pattern implementation
│ ├── codemirror-editor.ts # CodeMirror editor configuration and extensions
│ ├── file-system-access.ts # File System Access API wrapper (local file read/write)
│ ├── html-sanitizer.ts # HTML sanitizer (DOMPurify) — prevents XSS
│ ├── image-service.ts # Image processing service
│ ├── include-preprocessor.ts # Include directive preprocessor (resolves file references)
│ ├── indexed-db-storage.ts # [Storage] IndexedDB wrapper (using idb-keyval) — large file persistence
│ ├── intellisense.ts # IntelliSense and autocompletion logic
│ ├── kroki-renderer.ts # Kroki diagram service integration (supports multiple diagram DSLs)
│ ├── lazy-loader.ts # Resource lazy-loading utility
│ ├── log-collector.ts # Log collection
│ ├── markdown-converter.ts # Markdown to AsciiDoc converter
│ ├── paste-converter.ts # Paste handler (smart detection and conversion of HTML/Markdown)
│ ├── pdf-export.ts # PDF export (client-side generation)
│ ├── strict-schema.ts # Data validation schema definitions
│ ├── sync-utils.ts # [Core] Bidirectional scroll synchronization algorithm (Editor <-> Preview)
│ ├── theme-system.ts # Theme switching logic (Dark/Light Mode)
│ ├── transformer # [Transform Engine]
│ │ └── prosemirror-to-asciidoc.ts # [Key] Serializes Tiptap JSON state to AsciiDoc source (with SourceMap)
│ ├── validator # Data validators
│ │ └── save-validator.ts # Pre-save data integrity validation
│ ├── worker-manager.ts # Web Worker manager (handles communication with Workers)
│ ├── xref-manager.ts # Cross-reference (xref) manager
│ └── zip-export.ts # Project export as ZIP archive
├── metadata.json # Project metadata
├── package.json # Dependency management (React 19, Vite, Tiptap, Asciidoctor)
├── store # [State Management]
│ └── useEditorStore.ts # [Core] Zustand Store — manages file tree, editor state, and persistence
├── tests # Unit tests
│ ├── ast-visitor.test.ts # AST visitor tests
│ └── setup.ts # Vitest test environment configuration
├── tsconfig.json # TypeScript compiler configuration
├── types # Type definitions
│ └── lsp.ts # LSP protocol-related types (Diagnostic, Position, etc.)
├── types.ts # Global shared type definitions (FileItem, ViewMode, etc.)
├── vite.config.ts # Vite build configuration (includes path aliases and plugin configs)
├── vitest.config.ts # Vitest test configuration
└── workers # [Web Workers] Background thread scripts
└── asciidoctor.worker.ts # [Performance] Runs Asciidoctor compilation and lint checks in a separate thread
- Node.js (v18+ recommended)
- npm or yarn/pnpm
npm install
Start the local development server:
npm run dev
Visit http://localhost:3000 to view the editor.
npm run build
npm test # Run tests
npm run test:cov # View coverage
Scripts defined in package.json:
dev: Start the Vite development server.build: Run the Vite production build.preview: Preview the production build locally.test: Run unit tests with Vitest.test:watch: Run tests in watch mode.deploy: Deploy build artifacts to GitHub Pages.
This module wraps the Asciidoctor instance and is responsible for converting AsciiDoc text into HTML. It customizes the processing pipeline to support:
- Mermaid: Intercepts code blocks, generates placeholders, and renders diagrams asynchronously on the client side.
- KaTeX: Parses
stemblocks and inline formulas. - Source Map: Generates
data-lineattributes to establish mappings between source line numbers and DOM nodes, enabling synchronized scrolling.
Wraps the browser's native FileSystemFileHandle interface.
showOpenFilePicker: Opens the file picker dialog.showSaveFilePicker: Save As functionality.- Provides a fallback mechanism for browsers that do not support the native API, using traditional
<input type="file">and Blob downloads.
Manages the global editor state, including:
- File tree structure (Files, Folders).
- Currently active file and view mode.
- UI state (sidebar visibility, dialog visibility).
- Synchronized scroll position information (
highlightLine,syncToLine).