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>
|