Files
testdrive-jsui/ARCHITECTURE.md
tegwick ab4679126e docs: establish JavaScript-first architecture and refactoring plan
Clarified that testdrive-jsui is a JavaScript library with optional
backend adapters, not a Python package with JavaScript assets.

Added ARCHITECTURE.md:
- Core principle: JavaScript provides all functionality
- Python/Ruby/Java are integration adapters only
- Clear layer separation: JS library vs language adapters
- Distribution models: CDN, npm, with adapters
- Anti-patterns to avoid
- Success metrics

Added JS_FIRST_REFACTORING.md:
- Phase 1: Create standalone JavaScript bundle
- Phase 2: Refactor Python as thin adapter
- Phase 3: Build and distribution
- Concrete implementation steps with code examples
- Timeline: 2-4 days of focused work

Key Changes in Approach:
- JavaScript does ALL rendering (using marked.js)
- Backend adapters only serve assets and pass config
- No HTML generation in Python/Ruby/Java
- Library works completely standalone in browser

This establishes foundation for true language-agnostic design.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-16 12:04:12 +01:00

11 KiB

TestDrive-JSUI Architecture

Last Updated: 2025-12-16 Status: Refactoring to JavaScript-first architecture


🎯 Core Principle

TestDrive-JSUI is a JavaScript library, not a Python package.

The JavaScript code provides all functionality. Python, Ruby, Java, or other language bindings are integration adapters that help serve, configure, and test the JavaScript library - they do not provide core functionality.


📐 Architectural Layers

Layer 1: Core JavaScript Library (Functionality)

Location: /js/ Purpose: Complete standalone JavaScript UI framework Dependencies: Only marked.js (markdown parsing) Language: Pure JavaScript (ES6+)

js/
├── testdrive-jsui.js         # Main library bundle (future)
├── core/                     # Core systems
│   ├── debug-system.js       # Debug infrastructure
│   └── section-manager.js    # Document section management
├── components/               # UI components
│   ├── dom-renderer.js       # DOM rendering engine
│   ├── debug-panel.js        # Debug UI
│   └── document-controls.js  # Document control UI
├── controls/                 # Interactive control panels
│   ├── control-base.js       # Base control class
│   ├── edit-control.js       # Edit mode controls
│   ├── debug-control.js      # Debug controls
│   ├── status-control.js     # Status indicator
│   └── contents-control.js   # Table of contents
├── widgets/                  # Reusable UI widgets
├── plugins/                  # Extension system
└── utils/                    # Shared utilities

Key Characteristics:

  • Works standalone in any browser
  • No backend required (can load from file://)
  • Self-contained markdown rendering
  • All UI logic in JavaScript
  • Configuration via JSON

Standalone Usage:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="testdrive-jsui.css">
</head>
<body>
    <div id="content"></div>

    <!-- Dependencies -->
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>

    <!-- TestDrive-JSUI -->
    <script src="testdrive-jsui.js"></script>

    <script>
        // Initialize with configuration
        const ui = new TestDriveJSUI({
            container: '#content',
            mode: 'edit',
            markdown: '# Hello World\n\nEdit me!',
            theme: 'github'
        });
    </script>
</body>
</html>

Layer 2: Language Adapters (Integration)

Purpose: Integration helpers for different backend languages Function: Serve assets, provide testing, backend integration NOT: Core functionality implementation

Python Adapter

Location: /src/testdrive_jsui/ (optional, for Python projects) Purpose: Python project integration

# Python is just a helper to serve/test the JS library
from testdrive_jsui import TestDriveJSUIAdapter

adapter = TestDriveJSUIAdapter()

# Adapter helps with:
# 1. Asset serving
assets = adapter.get_asset_urls()

# 2. HTML template generation
html = adapter.generate_html(
    markdown="# Content",
    mode="edit",
    config={...}
)

# 3. Testing JavaScript
test_result = adapter.run_js_tests()

Python Adapter Responsibilities:

  • Asset path resolution
  • HTML template generation
  • Configuration serialization (Python dict → JSON)
  • JavaScript test runner integration (pytest ↔ Jest)
  • Development server (optional)
  • NOT markdown rendering (JS does this)
  • NOT UI logic (JS does this)
  • NOT content transformation (JS does this)

Ruby Adapter (Future)

# Similar concept for Ruby/Rails projects
adapter = TestDriveJSUI::Adapter.new

# Generate view helper
<%= testdrive_jsui_editor(
  markdown: @document.content,
  mode: :edit
) %>

Java Adapter (Future)

// Similar concept for Java/Spring projects
TestDriveJSUIAdapter adapter = new TestDriveJSUIAdapter();
String html = adapter.generateHtml(markdown, "edit", config);

🔄 Data Flow

Standalone Mode (No Backend)

1. Browser loads HTML
2. HTML includes testdrive-jsui.js
3. JS initializes with config
4. JS fetches/parses markdown → marked.js
5. JS renders UI → DOM
6. User interacts → JS handles everything
7. Save via JS (localStorage, download, etc.)

With Backend Adapter (Python/Ruby/Java)

1. Backend serves HTML template
2. Backend injects config JSON
3. Backend includes JS/CSS assets
4. Browser runs JavaScript (same as standalone)
5. JS may call backend APIs for save/load

Key Point: Backend is optional and only for convenience!


🎨 Current vs Target Architecture

Current (Hybrid - Needs Refactoring)

❌ Python generates HTML structure
❌ Python does markdown fallback rendering
❌ JavaScript enhances the Python-generated HTML
❌ Tight coupling between Python and JavaScript

Target (Clean Separation)

✅ JavaScript is the complete UI library
✅ JavaScript handles all rendering (markdown → HTML → DOM)
✅ Python/Ruby/Java are thin adapters
✅ Zero coupling - JS works without any backend

📦 Distribution Models

Model 1: CDN (Simplest)

<!-- Use directly from CDN -->
<script src="https://cdn.jsdelivr.net/npm/testdrive-jsui@1.0.0/dist/testdrive-jsui.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/testdrive-jsui@1.0.0/dist/testdrive-jsui.min.css">

Model 2: npm Package

npm install testdrive-jsui
import TestDriveJSUI from 'testdrive-jsui';

Model 3: With Language Adapter

# Python projects
pip install testdrive-jsui-python

# Ruby projects
gem install testdrive-jsui

# Java projects
maven: com.testdrive:testdrive-jsui-java

Important: Language adapters are separate packages that bundle/reference the core JS library.


🧪 Testing Architecture

JavaScript Tests (Core)

Framework: Jest with jsdom Location: /js/tests/ What: Tests the JavaScript library itself

describe('TestDriveJSUI', () => {
  test('renders markdown to HTML', () => {
    const ui = new TestDriveJSUI({...});
    expect(ui.render('# Hello')).toContain('<h1>');
  });
});

Python Integration Tests (Adapter)

Framework: pytest Location: /tests/ (in Python adapter) What: Tests Python ↔ JavaScript integration

def test_python_adapter_runs_js_tests():
    adapter = TestDriveJSUIAdapter()
    result = adapter.run_js_tests()
    assert result.success

Key: Python tests verify the adapter works, not the JS functionality!


🔧 Configuration System

JavaScript Configuration (Core)

{
  // Core JS library config
  "mode": "edit",              // 'edit' | 'view'
  "theme": "github",           // CSS theme
  "markdown": "# Content",     // Initial content
  "autosave": false,           // Auto-save behavior
  "shortcuts": true,           // Keyboard shortcuts
  "sections": true,            // Section management
  "debug": false               // Debug mode
}

Adapter Configuration (Language-specific)

# Python adapter config (separate from JS)
{
  "asset_base_url": "/static",     # Where to serve JS/CSS
  "development_mode": True,        # Dev vs production
  "template_path": "...",          # HTML template location
}

Separation: JS config controls the library, adapter config controls integration.


🎯 Migration Path

Phase 1: Improve Current Structure (Starting)

  1. Document architecture (this file)
  2. ⏸️ Rename Python code to clearly show it's an adapter
  3. ⏸️ Ensure JS can work standalone
  4. ⏸️ Separate JS config from adapter config

Phase 2: Pure JavaScript Rendering

  1. ⏸️ Move all markdown rendering to JavaScript (use marked.js)
  2. ⏸️ Remove Python HTML generation
  3. ⏸️ Make Python adapter purely serve assets + config
  4. ⏸️ Create standalone HTML example

Phase 3: Proper Distribution

  1. ⏸️ Bundle JavaScript library (testdrive-jsui.js)
  2. ⏸️ Publish to npm
  3. ⏸️ Publish to CDN
  4. ⏸️ Separate Python adapter package

Phase 4: Additional Adapters

  1. ⏸️ Ruby adapter
  2. ⏸️ Java adapter
  3. ⏸️ PHP adapter (if needed)

📚 Documentation Structure

docs/
├── javascript/                    # Core JS library docs
│   ├── getting-started.md         # Standalone usage
│   ├── api-reference.md           # JavaScript API
│   ├── configuration.md           # JS config options
│   └── examples/                  # Pure JS examples
├── adapters/                      # Language adapter docs
│   ├── python/
│   │   ├── installation.md
│   │   ├── django-integration.md
│   │   └── flask-integration.md
│   ├── ruby/
│   │   └── rails-integration.md
│   └── java/
│       └── spring-integration.md
└── architecture/
    └── ARCHITECTURE.md            # This file

🔑 Key Principles

  1. JavaScript First: All functionality in JavaScript
  2. Backend Optional: Works without any backend
  3. Adapters Not Implementations: Language bindings help integrate, don't implement
  4. Clear Boundaries: JS does UI, backend does serving/storage
  5. Language Agnostic: Core library works with any backend
  6. Zero Lock-in: Use testdrive-jsui without any specific backend framework

🚫 Anti-Patterns to Avoid

Don't: Implement UI logic in Python/Ruby/Java Do: Implement UI logic in JavaScript

Don't: Render markdown in backend Do: Render markdown in JavaScript (marked.js)

Don't: Generate HTML structure in backend Do: Generate HTML structure in JavaScript

Don't: Make JavaScript depend on backend APIs Do: Make JavaScript work standalone, optionally call APIs

Don't: Create language-specific forks Do: Create thin adapters around single JS library


📈 Success Metrics

  • Can use testdrive-jsui with pure HTML file (no backend)
  • Can use testdrive-jsui with Python/Flask
  • Can use testdrive-jsui with Ruby/Rails
  • Can use testdrive-jsui with Java/Spring
  • JavaScript library < 100KB minified
  • Zero runtime dependencies except marked.js
  • Works in all modern browsers
  • Published to npm and CDN

🤝 Contributing

When contributing:

  • Core functionality → JavaScript
  • Integration helpers → Language adapters
  • Keep adapters thin and similar across languages
  • Test JavaScript with Jest
  • Test adapters with language-native tools (pytest, rspec, junit)

Remember: TestDrive-JSUI is a JavaScript library with optional backend adapters, not a backend framework with JavaScript assets!