generated from coulomb/repo-seed
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>
This commit is contained in:
709
JS_FIRST_REFACTORING.md
Normal file
709
JS_FIRST_REFACTORING.md
Normal file
@@ -0,0 +1,709 @@
|
||||
# JavaScript-First Refactoring Plan
|
||||
|
||||
**Goal**: Transform testdrive-jsui from a Python package with JS assets into a **pure JavaScript library** with optional backend adapters.
|
||||
|
||||
**Date**: 2025-12-16
|
||||
**Status**: Planning
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Vision
|
||||
|
||||
### Before (Current - Hybrid)
|
||||
```
|
||||
Python (TestDriveJSUIEngine)
|
||||
↓ generates HTML template
|
||||
↓ does fallback markdown rendering
|
||||
↓ injects configuration
|
||||
Browser receives: HTML with embedded JS config
|
||||
JavaScript: Enhances the pre-rendered HTML
|
||||
```
|
||||
|
||||
### After (Target - JS-First)
|
||||
```
|
||||
JavaScript Library (testdrive-jsui.js)
|
||||
↓ Standalone, works in any browser
|
||||
↓ Renders markdown using marked.js
|
||||
↓ Creates full UI
|
||||
↓ Handles all interactions
|
||||
|
||||
Optional: Python/Ruby/Java Adapter
|
||||
↓ Just serves JS/CSS files
|
||||
↓ Passes config as JSON
|
||||
↓ Provides testing helpers
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Phase 1: Create Standalone JavaScript Bundle
|
||||
|
||||
### Goal
|
||||
Create a single `testdrive-jsui.js` file that works completely standalone in a browser.
|
||||
|
||||
### Tasks
|
||||
|
||||
#### 1.1: Create Main Library Entry Point
|
||||
|
||||
**Create**: `js/testdrive-jsui.js`
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* TestDrive-JSUI - Standalone JavaScript Markdown Editor
|
||||
*
|
||||
* A complete markdown editing and viewing UI that runs entirely in the browser.
|
||||
* No backend required!
|
||||
*
|
||||
* @version 1.0.0
|
||||
* @requires marked.js (for markdown parsing)
|
||||
*/
|
||||
|
||||
class TestDriveJSUI {
|
||||
/**
|
||||
* Initialize TestDrive-JSUI
|
||||
*
|
||||
* @param {Object} config - Configuration options
|
||||
* @param {string|HTMLElement} config.container - Container element or selector
|
||||
* @param {string} config.mode - 'edit' or 'view'
|
||||
* @param {string} config.markdown - Initial markdown content
|
||||
* @param {string} config.theme - Theme name (default: 'github')
|
||||
* @param {boolean} config.autosave - Enable autosave (default: false)
|
||||
* @param {Object} config.callbacks - Event callbacks
|
||||
*/
|
||||
constructor(config) {
|
||||
this.config = this._validateConfig(config);
|
||||
this.container = this._resolveContainer(config.container);
|
||||
|
||||
// Initialize core systems
|
||||
this.debugSystem = new MarkitectDebugSystem();
|
||||
this.sectionManager = new SectionManager();
|
||||
this.domRenderer = new DOMRenderer(this.sectionManager, this.container);
|
||||
|
||||
// Initialize controls based on mode
|
||||
this._initializeControls();
|
||||
|
||||
// Load initial content
|
||||
if (config.markdown) {
|
||||
this.setContent(config.markdown);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set markdown content
|
||||
* @param {string} markdown - Markdown text
|
||||
*/
|
||||
setContent(markdown) {
|
||||
// Parse markdown to sections
|
||||
const sections = this.sectionManager.createSectionsFromMarkdown(markdown);
|
||||
|
||||
// Render to DOM
|
||||
this.domRenderer.renderAllSections(sections);
|
||||
|
||||
// Emit event
|
||||
this._emit('contentLoaded', { markdown, sections });
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current markdown content
|
||||
* @returns {string} Current markdown
|
||||
*/
|
||||
getContent() {
|
||||
return this.sectionManager.getAllSectionsAsMarkdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch between edit and view modes
|
||||
* @param {string} mode - 'edit' or 'view'
|
||||
*/
|
||||
setMode(mode) {
|
||||
if (!['edit', 'view'].includes(mode)) {
|
||||
throw new Error(`Invalid mode: ${mode}`);
|
||||
}
|
||||
|
||||
this.config.mode = mode;
|
||||
this._reinitializeControls();
|
||||
this._emit('modeChanged', { mode });
|
||||
}
|
||||
|
||||
/**
|
||||
* Save current content (triggers callback)
|
||||
*/
|
||||
save() {
|
||||
const markdown = this.getContent();
|
||||
|
||||
if (this.config.callbacks?.onSave) {
|
||||
this.config.callbacks.onSave(markdown);
|
||||
} else if (this.config.autosave) {
|
||||
// Default: save to localStorage
|
||||
localStorage.setItem('testdrive-jsui-content', markdown);
|
||||
}
|
||||
|
||||
this._emit('saved', { markdown });
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the editor and clean up
|
||||
*/
|
||||
destroy() {
|
||||
// Clean up controls
|
||||
this.controls?.forEach(control => control?.destroy?.());
|
||||
|
||||
// Clear container
|
||||
this.container.innerHTML = '';
|
||||
|
||||
this._emit('destroyed');
|
||||
}
|
||||
|
||||
// Internal methods
|
||||
_validateConfig(config) {
|
||||
const defaults = {
|
||||
mode: 'edit',
|
||||
theme: 'github',
|
||||
autosave: false,
|
||||
shortcuts: true,
|
||||
sections: true,
|
||||
debug: false,
|
||||
callbacks: {}
|
||||
};
|
||||
|
||||
return { ...defaults, ...config };
|
||||
}
|
||||
|
||||
_resolveContainer(selector) {
|
||||
if (typeof selector === 'string') {
|
||||
const element = document.querySelector(selector);
|
||||
if (!element) {
|
||||
throw new Error(`Container not found: ${selector}`);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
return selector;
|
||||
}
|
||||
|
||||
_initializeControls() {
|
||||
this.controls = [];
|
||||
|
||||
if (this.config.mode === 'edit') {
|
||||
this.controls.push(
|
||||
new EditControl(this),
|
||||
new StatusControl(this),
|
||||
new ContentsControl(this)
|
||||
);
|
||||
}
|
||||
|
||||
if (this.config.debug) {
|
||||
this.controls.push(new DebugControl(this));
|
||||
}
|
||||
|
||||
// Initialize all controls
|
||||
this.controls.forEach(control => control.initialize());
|
||||
}
|
||||
|
||||
_reinitializeControls() {
|
||||
// Destroy old controls
|
||||
this.controls?.forEach(control => control?.destroy?.());
|
||||
|
||||
// Create new controls for current mode
|
||||
this._initializeControls();
|
||||
}
|
||||
|
||||
_emit(event, data) {
|
||||
const callback = this.config.callbacks?.[`on${event.charAt(0).toUpperCase()}${event.slice(1)}`];
|
||||
if (callback) {
|
||||
callback(data);
|
||||
}
|
||||
|
||||
// Also emit as custom event
|
||||
this.container.dispatchEvent(new CustomEvent(`testdrive:${event}`, { detail: data }));
|
||||
}
|
||||
}
|
||||
|
||||
// Expose globally
|
||||
if (typeof window !== 'undefined') {
|
||||
window.TestDriveJSUI = TestDriveJSUI;
|
||||
}
|
||||
|
||||
// ES module export
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = TestDriveJSUI;
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.2: Create Standalone HTML Example
|
||||
|
||||
**Create**: `examples/standalone.html`
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>TestDrive-JSUI Standalone Demo</title>
|
||||
|
||||
<!-- TestDrive-JSUI Styles -->
|
||||
<link rel="stylesheet" href="../static/css/editor.css">
|
||||
<link rel="stylesheet" href="../static/css/controls.css">
|
||||
<link rel="stylesheet" href="../static/css/themes/github.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="editor-container"></div>
|
||||
|
||||
<!-- Dependencies -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||
|
||||
<!-- TestDrive-JSUI Core Components -->
|
||||
<script src="../js/core/debug-system.js"></script>
|
||||
<script src="../js/core/section-manager.js"></script>
|
||||
<script src="../js/components/dom-renderer.js"></script>
|
||||
<script src="../js/components/debug-panel.js"></script>
|
||||
<script src="../js/controls/control-base.js"></script>
|
||||
<script src="../js/controls/edit-control.js"></script>
|
||||
<script src="../js/controls/debug-control.js"></script>
|
||||
<script src="../js/controls/status-control.js"></script>
|
||||
<script src="../js/controls/contents-control.js"></script>
|
||||
|
||||
<!-- Main library -->
|
||||
<script src="../js/testdrive-jsui.js"></script>
|
||||
|
||||
<!-- Initialize -->
|
||||
<script>
|
||||
// Example markdown content
|
||||
const sampleMarkdown = `# TestDrive-JSUI Standalone Demo
|
||||
|
||||
## Welcome!
|
||||
|
||||
This is a **completely standalone** markdown editor running entirely in your browser. No backend required!
|
||||
|
||||
### Features
|
||||
|
||||
- ✅ Real-time markdown rendering
|
||||
- ✅ Section-based editing
|
||||
- ✅ Interactive controls
|
||||
- ✅ Keyboard shortcuts
|
||||
- ✅ Debug mode
|
||||
|
||||
### Try It Out
|
||||
|
||||
1. Click the edit button on any section
|
||||
2. Modify the markdown
|
||||
3. Save your changes
|
||||
|
||||
## Code Example
|
||||
|
||||
\`\`\`javascript
|
||||
const editor = new TestDriveJSUI({
|
||||
container: '#editor-container',
|
||||
mode: 'edit',
|
||||
markdown: '# Hello World'
|
||||
});
|
||||
\`\`\`
|
||||
|
||||
That's it! No backend needed.`;
|
||||
|
||||
// Initialize TestDrive-JSUI
|
||||
const editor = new TestDriveJSUI({
|
||||
container: '#editor-container',
|
||||
mode: 'edit',
|
||||
markdown: sampleMarkdown,
|
||||
theme: 'github',
|
||||
autosave: true,
|
||||
debug: true,
|
||||
callbacks: {
|
||||
onSave: (markdown) => {
|
||||
console.log('Content saved:', markdown);
|
||||
alert('Content saved to localStorage!');
|
||||
},
|
||||
onContentLoaded: (data) => {
|
||||
console.log('Content loaded:', data);
|
||||
},
|
||||
onModeChanged: (data) => {
|
||||
console.log('Mode changed to:', data.mode);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Expose for debugging
|
||||
window.editor = editor;
|
||||
|
||||
console.log('✅ TestDrive-JSUI initialized!');
|
||||
console.log('Try: editor.getContent(), editor.setMode("view"), editor.save()');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
#### 1.3: Update Components to Work Standalone
|
||||
|
||||
**Tasks**:
|
||||
- Ensure all JS components work without Python-generated HTML
|
||||
- Remove any assumptions about server-side rendering
|
||||
- Make all components initialize from JavaScript
|
||||
|
||||
#### 1.4: Add Markdown Rendering Helper
|
||||
|
||||
**Update**: `js/utils/markdown-helper.js` (create if needed)
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* Markdown rendering utilities
|
||||
* Uses marked.js for parsing
|
||||
*/
|
||||
const MarkdownHelper = {
|
||||
/**
|
||||
* Render markdown to HTML
|
||||
* @param {string} markdown - Markdown text
|
||||
* @returns {string} HTML string
|
||||
*/
|
||||
render(markdown) {
|
||||
if (!window.marked) {
|
||||
throw new Error('marked.js is required but not loaded');
|
||||
}
|
||||
|
||||
// Configure marked
|
||||
marked.setOptions({
|
||||
gfm: true,
|
||||
breaks: true,
|
||||
headerIds: true,
|
||||
mangle: false
|
||||
});
|
||||
|
||||
return marked.parse(markdown);
|
||||
},
|
||||
|
||||
/**
|
||||
* Extract sections from markdown
|
||||
* @param {string} markdown - Markdown text
|
||||
* @returns {Array} Array of section objects
|
||||
*/
|
||||
extractSections(markdown) {
|
||||
// Split on headers
|
||||
const sections = [];
|
||||
const lines = markdown.split('\n');
|
||||
let currentSection = { level: 0, title: '', content: '' };
|
||||
|
||||
for (const line of lines) {
|
||||
const headerMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
||||
|
||||
if (headerMatch) {
|
||||
// Save previous section
|
||||
if (currentSection.content) {
|
||||
sections.push(currentSection);
|
||||
}
|
||||
|
||||
// Start new section
|
||||
currentSection = {
|
||||
level: headerMatch[1].length,
|
||||
title: headerMatch[2],
|
||||
content: line + '\n'
|
||||
};
|
||||
} else {
|
||||
currentSection.content += line + '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// Add final section
|
||||
if (currentSection.content) {
|
||||
sections.push(currentSection);
|
||||
}
|
||||
|
||||
return sections;
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.MarkdownHelper = MarkdownHelper;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Phase 2: Refactor Python as Thin Adapter
|
||||
|
||||
### Goal
|
||||
Transform Python code from "rendering engine" to "integration adapter".
|
||||
|
||||
### Tasks
|
||||
|
||||
#### 2.1: Rename Python Package Structure
|
||||
|
||||
```
|
||||
src/testdrive_jsui/ # OLD NAME
|
||||
↓
|
||||
src/testdrive_jsui_python/ # NEW NAME (makes it clear it's an adapter)
|
||||
```
|
||||
|
||||
Or keep name but rename classes to show they're adapters:
|
||||
|
||||
```python
|
||||
# Old (implies it does rendering)
|
||||
class TestDriveJSUIEngine
|
||||
|
||||
# New (clear it's just an adapter)
|
||||
class TestDriveJSUIAdapter
|
||||
class PythonIntegrationAdapter
|
||||
```
|
||||
|
||||
#### 2.2: Simplify Python Adapter
|
||||
|
||||
**New**: `src/testdrive_jsui/adapter.py`
|
||||
|
||||
```python
|
||||
"""
|
||||
Python Integration Adapter for TestDrive-JSUI
|
||||
|
||||
This is NOT the rendering engine - it's a helper for Python projects.
|
||||
The JavaScript library does all the actual work.
|
||||
"""
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional
|
||||
import json
|
||||
|
||||
class TestDriveJSUIAdapter:
|
||||
"""
|
||||
Python integration adapter for TestDrive-JSUI JavaScript library.
|
||||
|
||||
Purpose:
|
||||
- Serve JS/CSS assets
|
||||
- Generate HTML templates with config
|
||||
- Provide testing helpers
|
||||
|
||||
Does NOT:
|
||||
- Render markdown (JS does this)
|
||||
- Implement UI (JS does this)
|
||||
- Transform content (JS does this)
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.js_library_path = self._find_js_library()
|
||||
|
||||
def _find_js_library(self) -> Path:
|
||||
"""Locate the JavaScript library files."""
|
||||
# Look in capability directory
|
||||
current = Path(__file__).parent
|
||||
while current.parent != current:
|
||||
js_dir = current / "js"
|
||||
if js_dir.exists() and (js_dir / "testdrive-jsui.js").exists():
|
||||
return js_dir
|
||||
current = current.parent
|
||||
raise FileNotFoundError("testdrive-jsui.js not found")
|
||||
|
||||
def get_asset_urls(self, base_url: str = "/static") -> Dict[str, list]:
|
||||
"""
|
||||
Get URLs for JS/CSS assets.
|
||||
|
||||
Helper for web frameworks to include assets in templates.
|
||||
"""
|
||||
return {
|
||||
"css": [
|
||||
f"{base_url}/testdrive-jsui/css/editor.css",
|
||||
f"{base_url}/testdrive-jsui/css/controls.css",
|
||||
f"{base_url}/testdrive-jsui/css/themes/github.css",
|
||||
],
|
||||
"js": [
|
||||
"https://cdn.jsdelivr.net/npm/marked/marked.min.js",
|
||||
f"{base_url}/testdrive-jsui/js/testdrive-jsui.js",
|
||||
]
|
||||
}
|
||||
|
||||
def generate_html(self,
|
||||
markdown: str,
|
||||
mode: str = "edit",
|
||||
config: Optional[Dict] = None) -> str:
|
||||
"""
|
||||
Generate HTML that loads and initializes the JS library.
|
||||
|
||||
This is just a convenience helper - you can write your own template!
|
||||
"""
|
||||
config = config or {}
|
||||
config.update({
|
||||
"markdown": markdown,
|
||||
"mode": mode
|
||||
})
|
||||
|
||||
assets = self.get_asset_urls()
|
||||
|
||||
return f"""<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>TestDrive-JSUI</title>
|
||||
{''.join(f'<link rel="stylesheet" href="{url}">' for url in assets['css'])}
|
||||
</head>
|
||||
<body>
|
||||
<div id="editor"></div>
|
||||
|
||||
{''.join(f'<script src="{url}"></script>' for url in assets['js'])}
|
||||
|
||||
<script>
|
||||
const editor = new TestDriveJSUI({json.dumps(config, indent=2)});
|
||||
</script>
|
||||
</body>
|
||||
</html>"""
|
||||
|
||||
def run_js_tests(self):
|
||||
"""Run JavaScript tests (existing functionality - keep this!)."""
|
||||
from .testing import JavaScriptTestRunner
|
||||
runner = JavaScriptTestRunner(self.js_library_path.parent)
|
||||
return runner.run_js_tests()
|
||||
```
|
||||
|
||||
#### 2.3: Update Documentation
|
||||
|
||||
**Update**: README.md to show Python as optional
|
||||
|
||||
```markdown
|
||||
## Installation
|
||||
|
||||
### Option 1: Use JavaScript Directly (No Backend)
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/testdrive-jsui@1.0.0"></script>
|
||||
<script>
|
||||
const editor = new TestDriveJSUI({ ... });
|
||||
</script>
|
||||
```
|
||||
|
||||
### Option 2: With Python Adapter (for Django/Flask)
|
||||
|
||||
```bash
|
||||
pip install testdrive-jsui-python
|
||||
```
|
||||
|
||||
```python
|
||||
from testdrive_jsui import TestDriveJSUIAdapter
|
||||
adapter = TestDriveJSUIAdapter()
|
||||
html = adapter.generate_html(markdown="# Hello")
|
||||
```
|
||||
|
||||
### Option 3: With Ruby Adapter (for Rails) - Coming Soon
|
||||
|
||||
### Option 4: With Java Adapter (for Spring) - Coming Soon
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Phase 3: Build and Distribution
|
||||
|
||||
### Goal
|
||||
Package JavaScript library for easy distribution.
|
||||
|
||||
### Tasks
|
||||
|
||||
#### 3.1: Create Build Script
|
||||
|
||||
**Create**: `js/build.js`
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* Build script for testdrive-jsui
|
||||
* Combines all modules into single distributable file
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Files to concatenate in order
|
||||
const files = [
|
||||
'utils/markdown-helper.js',
|
||||
'core/debug-system.js',
|
||||
'core/section-manager.js',
|
||||
'components/dom-renderer.js',
|
||||
'components/debug-panel.js',
|
||||
'controls/control-base.js',
|
||||
'controls/edit-control.js',
|
||||
'controls/debug-control.js',
|
||||
'controls/status-control.js',
|
||||
'controls/contents-control.js',
|
||||
'testdrive-jsui.js' // Main class last
|
||||
];
|
||||
|
||||
// Read and concatenate
|
||||
let bundle = '// TestDrive-JSUI v1.0.0 - MIT License\n';
|
||||
bundle += '(function() {\n';
|
||||
|
||||
for (const file of files) {
|
||||
const content = fs.readFileSync(path.join(__dirname, file), 'utf8');
|
||||
bundle += '\n// === ' + file + ' ===\n';
|
||||
bundle += content + '\n';
|
||||
}
|
||||
|
||||
bundle += '})();\n';
|
||||
|
||||
// Write bundle
|
||||
fs.writeFileSync(path.join(__dirname, 'dist', 'testdrive-jsui.js'), bundle);
|
||||
|
||||
console.log('✅ Built: dist/testdrive-jsui.js');
|
||||
```
|
||||
|
||||
#### 3.2: Create package.json for npm
|
||||
|
||||
**Update**: `package.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "testdrive-jsui",
|
||||
"version": "1.0.0",
|
||||
"description": "Standalone JavaScript markdown editor with interactive UI",
|
||||
"main": "js/dist/testdrive-jsui.js",
|
||||
"types": "js/testdrive-jsui.d.ts",
|
||||
"files": [
|
||||
"js/dist/",
|
||||
"static/css/",
|
||||
"README.md"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "node js/build.js",
|
||||
"test": "jest",
|
||||
"prepublish": "npm run build"
|
||||
},
|
||||
"keywords": [
|
||||
"markdown", "editor", "javascript", "standalone", "ui"
|
||||
],
|
||||
"dependencies": {
|
||||
"marked": "^4.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Success Criteria
|
||||
|
||||
### Phase 1 Complete When:
|
||||
- [ ] Can open `standalone.html` in browser (no server needed)
|
||||
- [ ] Can edit markdown completely in JavaScript
|
||||
- [ ] All UI controls work without Python
|
||||
- [ ] marked.js renders markdown in browser
|
||||
|
||||
### Phase 2 Complete When:
|
||||
- [ ] Python adapter is < 200 lines of code
|
||||
- [ ] Python doesn't render markdown
|
||||
- [ ] Python doesn't generate HTML structure
|
||||
- [ ] Can use testdrive-jsui with Flask/Django via adapter
|
||||
|
||||
### Phase 3 Complete When:
|
||||
- [ ] Single `testdrive-jsui.js` file works everywhere
|
||||
- [ ] Published to npm
|
||||
- [ ] Available via CDN
|
||||
- [ ] < 100KB minified + gzipped
|
||||
|
||||
---
|
||||
|
||||
## 📅 Timeline Estimate
|
||||
|
||||
- **Phase 1**: 1-2 days (core JavaScript refactoring)
|
||||
- **Phase 2**: 1 day (simplify Python adapter)
|
||||
- **Phase 3**: 0.5 day (build and distribution)
|
||||
|
||||
**Total**: 2-4 days of focused work
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Priority Order
|
||||
|
||||
1. **Phase 1.2**: Create standalone.html example (proves concept)
|
||||
2. **Phase 1.4**: Markdown rendering in JS
|
||||
3. **Phase 1.1**: Main library class
|
||||
4. **Phase 2.2**: Simplify Python adapter
|
||||
5. **Phase 3**: Build and distribution
|
||||
|
||||
Start with #1 to validate the approach!
|
||||
Reference in New Issue
Block a user