feat: implement JavaScript-first TestDriveJSUI library (v1.0.0)

Completed Phase 1 refactoring to JavaScript-first architecture:

Core Library Implementation:
- Created js/testdrive-jsui.js main library class
- Integrated all existing components (SectionManager, DOMRenderer, DocumentControls)
- Added marked.js integration for markdown rendering
- Implemented event-driven API (on/off/emit)
- Support for edit/view modes and themes
- LocalStorage save/load functionality
- Download as markdown file
- Keyboard shortcuts (Ctrl+S, Escape)
- Auto-save capability (optional)

Examples:
- examples/full-editor.html - Complete demo with all features
- Updated examples/README.md with full documentation

Documentation:
- Updated README.md with JavaScript-first architecture section
- Added complete API reference (constructor, methods, events)
- Updated CLAUDE.md with library quick start and API
- Emphasized JavaScript-first design principles

Architecture:
- JavaScript provides ALL functionality
- Language adapters are optional integration helpers
- Works standalone in browser (no backend required)
- Clean separation: JS (functionality) vs Adapters (integration)

This completes the architectural shift documented in ARCHITECTURE.md
and JS_FIRST_REFACTORING.md Phase 1.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-16 12:14:58 +01:00
parent b84770e2d3
commit 796c04709a
5 changed files with 1424 additions and 58 deletions

535
examples/full-editor.html Normal file
View File

@@ -0,0 +1,535 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TestDrive-JSUI - Full Editor Demo</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
line-height: 1.6;
color: #24292e;
background: #f6f8fa;
padding: 20px;
}
.header {
background: white;
padding: 20px;
margin-bottom: 20px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.header h1 {
color: #0366d6;
margin-bottom: 10px;
}
.header p {
color: #586069;
}
.info-box {
background: #e8f5e9;
border: 1px solid #a5d6a7;
border-radius: 6px;
padding: 15px;
margin-bottom: 20px;
}
.info-box strong {
color: #2e7d32;
}
.toolbar {
background: white;
padding: 15px;
margin-bottom: 20px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.toolbar button {
background: #0366d6;
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: background 0.2s;
}
.toolbar button:hover {
background: #0256c7;
}
.toolbar button.secondary {
background: #6a737d;
}
.toolbar button.secondary:hover {
background: #586069;
}
.toolbar button.success {
background: #28a745;
}
.toolbar button.success:hover {
background: #218838;
}
#editor-container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
min-height: 500px;
}
/* GitHub theme styles for rendered markdown */
#editor-container h1,
#editor-container h2,
#editor-container h3 {
margin-top: 24px;
margin-bottom: 16px;
font-weight: 600;
line-height: 1.25;
}
#editor-container h1 {
font-size: 2em;
border-bottom: 1px solid #eaecef;
padding-bottom: 0.3em;
}
#editor-container h2 {
font-size: 1.5em;
border-bottom: 1px solid #eaecef;
padding-bottom: 0.3em;
}
#editor-container p {
margin-bottom: 16px;
}
#editor-container ul,
#editor-container ol {
margin-bottom: 16px;
padding-left: 2em;
}
#editor-container code {
background-color: rgba(27,31,35,0.05);
border-radius: 3px;
font-size: 85%;
padding: 0.2em 0.4em;
}
#editor-container pre {
background-color: #f6f8fa;
border-radius: 6px;
font-size: 85%;
overflow: auto;
padding: 16px;
margin-bottom: 16px;
}
#editor-container blockquote {
border-left: 4px solid #dfe2e5;
color: #6a737d;
padding-left: 1em;
margin-bottom: 16px;
}
.footer {
text-align: center;
margin-top: 40px;
color: #586069;
font-size: 14px;
}
.status-bar {
background: white;
padding: 12px 20px;
margin-top: 20px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
display: flex;
justify-content: space-between;
align-items: center;
font-size: 13px;
color: #586069;
}
.status-bar .stat {
display: flex;
align-items: center;
gap: 8px;
}
.status-bar .label {
font-weight: 600;
color: #24292e;
}
</style>
</head>
<body>
<div class="header">
<h1>📝 TestDrive-JSUI Full Editor</h1>
<p>
Complete interactive markdown editor demonstrating the full TestDrive-JSUI library.
Click any section to edit, use the toolbar for document operations.
</p>
</div>
<div class="info-box">
<strong>✨ Full Library Integration:</strong> This demo uses the complete TestDriveJSUI class
with all components (SectionManager, DOMRenderer, DocumentControls) working together.
</div>
<div class="toolbar">
<button onclick="saveDocument()" class="success">💾 Save Document</button>
<button onclick="loadDocument()">📂 Load Saved</button>
<button onclick="downloadDocument()">⬇️ Download .md</button>
<button onclick="showStatus()">📊 Show Status</button>
<button onclick="resetDocument()" class="secondary">🔄 Reset All</button>
<button onclick="switchToViewMode()" class="secondary">👁️ View Mode</button>
<button onclick="switchToEditMode()" class="secondary">✏️ Edit Mode</button>
</div>
<div id="editor-container">
<!-- Editor will be initialized here -->
</div>
<div class="status-bar" id="status-bar">
<div class="stat">
<span class="label">Mode:</span>
<span id="status-mode">edit</span>
</div>
<div class="stat">
<span class="label">Sections:</span>
<span id="status-sections">0</span>
</div>
<div class="stat">
<span class="label">Words:</span>
<span id="status-words">0</span>
</div>
<div class="stat">
<span class="label">Characters:</span>
<span id="status-chars">0</span>
</div>
</div>
<div class="footer">
<p>TestDrive-JSUI • JavaScript-First Architecture • Full Featured Editor</p>
<p><small>Uses: marked.js (markdown) + TestDriveJSUI library</small></p>
</div>
<!-- External 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/document-controls.js"></script>
<!-- TestDrive-JSUI Main Library -->
<script src="../js/testdrive-jsui.js"></script>
<!-- Application Script -->
<script>
// Sample document content
const defaultMarkdown = `# TestDrive-JSUI Full Editor
## What is This?
This is the **complete TestDrive-JSUI library** in action. Unlike the standalone proof of concept, this demo uses the full \`TestDriveJSUI\` class that wraps all components together.
### Key Features
- ✅ **Section-Based Editing**: Click any section to edit it independently
- ✅ **Interactive Controls**: Floating control panel for document operations
- ✅ **Event System**: Listen to editor events for integration
- ✅ **Multiple Modes**: Switch between edit and view modes
- ✅ **Auto-save**: Optional automatic saving to localStorage
- ✅ **Keyboard Shortcuts**: Ctrl+S to save, Escape to close editor
## Architecture
### JavaScript-First Design
TestDrive-JSUI is built with a JavaScript-first architecture:
1. **Core Library**: Pure JavaScript, works standalone
2. **Components**: Modular design (SectionManager, DOMRenderer, DocumentControls)
3. **Language Adapters**: Python, Ruby, Java adapters are optional helpers
### How It Works
\`\`\`javascript
// Initialize the editor
const editor = new TestDriveJSUI({
container: '#editor-container',
markdown: '# Hello World',
mode: 'edit',
theme: 'github',
autosave: false
});
// Listen to events
editor.on('save', (data) => {
console.log('Document saved:', data.markdown);
});
// Get current content
const markdown = editor.getMarkdown();
\`\`\`
## Try It Out!
### Editing Sections
Click any section above or below to start editing. You'll see:
- **Textarea**: Edit the markdown content
- **Accept Button (✓)**: Save your changes
- **Cancel Button (✗)**: Discard changes
- **Reset Button (↺)**: Restore original content
### Document Operations
Use the toolbar buttons:
- **Save**: Saves to browser localStorage
- **Load**: Loads previously saved document
- **Download**: Downloads as .md file
- **Status**: Shows document statistics
- **Reset All**: Restores all sections to original content
- **View/Edit Mode**: Toggle between modes
## Code Example
Here's how easy it is to integrate TestDrive-JSUI:
\`\`\`html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="testdrive-jsui.min.js"></script>
</head>
<body>
<div id="editor"></div>
<script>
const editor = new TestDriveJSUI({
container: '#editor',
markdown: '# Start writing...',
mode: 'edit'
});
</script>
</body>
</html>
\`\`\`
## API Reference
### Constructor Options
- \`container\` (required): CSS selector or DOM element
- \`markdown\` (optional): Initial markdown content
- \`mode\` (optional): 'edit' or 'view' (default: 'edit')
- \`theme\` (optional): Theme name (default: 'github')
- \`autosave\` (optional): Enable auto-save (default: false)
- \`shortcuts\` (optional): Enable keyboard shortcuts (default: true)
- \`sections\` (optional): Enable section-based editing (default: true)
- \`debug\` (optional): Enable debug mode (default: false)
### Methods
- \`getMarkdown()\`: Get current document content
- \`setMarkdown(markdown)\`: Set document content
- \`getStatus()\`: Get editor status (sections, words, etc.)
- \`save()\`: Trigger save event
- \`download(filename)\`: Download as markdown file
- \`resetAll()\`: Reset all sections to original content
- \`destroy()\`: Clean up and destroy editor
### Events
- \`initialized\`: Editor finished initializing
- \`save\`: Document save triggered
- \`content-changed\`: Content was modified
- \`autosave\`: Auto-save occurred
- \`download\`: Document downloaded
- \`reset\`: Document reset
- \`destroyed\`: Editor destroyed
## Benefits
### For Users
- **Intuitive**: Click to edit, visual feedback
- **Fast**: No page reloads, instant updates
- **Reliable**: Undo/reset functionality
- **Flexible**: Works in any browser, no installation
### For Developers
- **Easy Integration**: Simple API, minimal setup
- **Customizable**: Event system for custom behavior
- **Extensible**: Plugin architecture (coming soon)
- **Language Agnostic**: Use with any backend
---
**Ready to build?** Check out the [documentation](../README.md) or browse the [source code](../js/) to learn more!
`;
// Global editor instance
let editor;
// Initialize editor on page load
window.addEventListener('DOMContentLoaded', function() {
// Create editor instance
editor = new TestDriveJSUI({
container: '#editor-container',
markdown: defaultMarkdown,
mode: 'edit',
theme: 'github',
autosave: false,
shortcuts: true,
sections: true,
debug: false
});
// Set up event listeners
editor.on('initialized', (data) => {
console.log('✅ Editor initialized:', data);
updateStatusBar();
});
editor.on('save', (data) => {
console.log('💾 Document saved:', data.markdown.length, 'characters');
updateStatusBar();
});
editor.on('content-changed', (data) => {
console.log('📝 Content changed');
updateStatusBar();
});
editor.on('reset', () => {
console.log('🔄 Document reset');
updateStatusBar();
});
// Update status bar initially
updateStatusBar();
// Update status bar periodically
setInterval(updateStatusBar, 2000);
console.log('✅ TestDrive-JSUI Full Editor initialized!');
console.log('📝 Global editor instance available as window.editor');
});
// Toolbar functions
function saveDocument() {
editor.save();
alert('✅ Document saved to browser localStorage!');
}
function loadDocument() {
const loaded = editor.loadFromLocalStorage();
if (loaded) {
alert('📂 Document loaded from localStorage!');
} else {
alert(' No saved document found.');
}
}
function downloadDocument() {
const filename = prompt('Enter filename:', 'document.md');
if (filename) {
editor.download(filename);
}
}
function showStatus() {
const status = editor.getStatus();
const message = [
`📊 Document Status`,
``,
`Mode: ${status.mode}`,
`Total Sections: ${status.totalSections || 0}`,
`Currently Editing: ${status.editingSections || 0}`,
`Modified Sections: ${status.modifiedSections || 0}`,
`Word Count: ${status.wordCount}`,
`Character Count: ${status.characterCount}`
].join('\n');
alert(message);
}
function resetDocument() {
if (confirm('Reset all sections to original content?\n\nThis cannot be undone.')) {
editor.resetAll();
alert('🔄 Document reset to original content!');
}
}
function switchToViewMode() {
const markdown = editor.getMarkdown();
editor.destroy();
editor = new TestDriveJSUI({
container: '#editor-container',
markdown: markdown,
mode: 'view',
theme: 'github'
});
updateStatusBar();
alert('👁️ Switched to view mode. Click "Edit Mode" to return.');
}
function switchToEditMode() {
const markdown = editor.getMarkdown();
editor.destroy();
editor = new TestDriveJSUI({
container: '#editor-container',
markdown: markdown,
mode: 'edit',
theme: 'github',
autosave: false,
shortcuts: true
});
updateStatusBar();
alert('✏️ Switched to edit mode. Click sections to edit them.');
}
function updateStatusBar() {
const status = editor.getStatus();
document.getElementById('status-mode').textContent = status.mode;
document.getElementById('status-sections').textContent = status.totalSections || 0;
document.getElementById('status-words').textContent = status.wordCount || 0;
document.getElementById('status-chars').textContent = status.characterCount || 0;
}
// Expose editor for debugging
window.editor = editor;
</script>
</body>
</html>