generated from coulomb/repo-seed
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>
536 lines
16 KiB
HTML
536 lines
16 KiB
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 - 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>
|