Fix syntax coloring, modernize toolbar UI, and clean up CSS
- Fix Monarch tokenizer loading: await initLinter() before editor creation so loadScript() doesn't clobber window.define during lazy tokenizer init - Fix JSX/TSX coloring: use file URIs with proper extensions (.jsx/.tsx) so Monaco enables JSX tokenization via the TypeScript language service - Modernize toolbar: move settings to gear popover, replace text buttons with SVG icons, consolidate toggle checkboxes into compact group - Clean up CSS: remove duplicate toggle classes, dead selectors, orphaned rules
This commit is contained in:
@@ -147,9 +147,6 @@ body.resizing iframe { pointer-events: none; }
|
||||
.tab-lang-javascript .tab-color-dot { background: #F7DF1E; }
|
||||
.tab-lang-typescript .tab-color-dot { background: #3178C6; }
|
||||
.tab-lang-markdown .tab-color-dot { background: #83B; }
|
||||
.tab-lang-html .tab-btn-label, .tab-lang-css .tab-btn-label,
|
||||
.tab-lang-javascript .tab-btn-label, .tab-lang-typescript .tab-btn-label,
|
||||
.tab-lang-markdown .tab-btn-label { /* no extra style needed, just grouping */ }
|
||||
|
||||
/* Active tab border matches language color */
|
||||
.tab-lang-html.active { border-bottom-color: #E44D26; }
|
||||
@@ -219,51 +216,39 @@ body.resizing iframe { pointer-events: none; }
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Auto-run toggle */
|
||||
.auto-run-toggle {
|
||||
/* Toolbar toggles (shared) */
|
||||
.toolbar-toggles {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
gap: 2px;
|
||||
}
|
||||
.toolbar-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
font-size: 11px;
|
||||
color: var(--text-dim);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: 3px 6px;
|
||||
border-radius: 4px;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
.auto-run-toggle input { cursor: pointer; }
|
||||
|
||||
/* Tailwind toggle */
|
||||
.tailwind-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--text-dim);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
.toolbar-toggle:hover { background: rgba(255,255,255,0.06); color: var(--text); }
|
||||
.toolbar-toggle:has(input:checked) { color: var(--accent); }
|
||||
.toolbar-toggle input { display: none; }
|
||||
.toolbar-toggle span { pointer-events: none; }
|
||||
.toolbar-divider {
|
||||
width: 1px;
|
||||
height: 20px;
|
||||
background: var(--border);
|
||||
margin: 0 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.tailwind-toggle input { cursor: pointer; }
|
||||
|
||||
/* Dividers */
|
||||
.divider { background: var(--border); transition: background 0.15s; z-index: 2; }
|
||||
|
||||
/* Layout/keybinding/preview-theme selects — match framework select */
|
||||
#layout-mode, #keybinding-mode, #preview-theme, #editor-theme {
|
||||
background: var(--bg); color: var(--text); border: 1px solid var(--border);
|
||||
padding: 4px 6px; border-radius: 4px; font-size: 12px; cursor: pointer;
|
||||
}
|
||||
|
||||
/* Listed toggle */
|
||||
.listed-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--text-dim);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.listed-toggle input { cursor: pointer; }
|
||||
|
||||
/* Tags input */
|
||||
.tags-input-wrap {
|
||||
display: flex;
|
||||
@@ -294,6 +279,58 @@ body.resizing iframe { pointer-events: none; }
|
||||
}
|
||||
.btn-secondary:hover { color: var(--text); background: var(--border); }
|
||||
|
||||
/* Icon buttons */
|
||||
.btn-icon {
|
||||
background: transparent;
|
||||
color: var(--text-dim);
|
||||
border: none;
|
||||
padding: 5px 6px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
.btn-icon:hover { color: var(--text); background: rgba(255,255,255,0.08); }
|
||||
.btn-icon svg { display: block; }
|
||||
|
||||
/* Settings popover */
|
||||
.settings-popover-wrap { position: relative; }
|
||||
.settings-popover {
|
||||
position: absolute;
|
||||
top: calc(100% + 6px);
|
||||
right: 0;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 12px 14px;
|
||||
min-width: 220px;
|
||||
z-index: 100;
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.4);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
.settings-popover.hidden { display: none; }
|
||||
.settings-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
}
|
||||
.settings-label {
|
||||
font-size: 12px;
|
||||
color: var(--text-dim);
|
||||
white-space: nowrap;
|
||||
font-weight: 500;
|
||||
}
|
||||
.settings-popover select {
|
||||
background: var(--bg); color: var(--text); border: 1px solid var(--border);
|
||||
padding: 3px 6px; border-radius: 4px; font-size: 11px; cursor: pointer;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
/* QR Modal */
|
||||
.modal-overlay {
|
||||
position: fixed; inset: 0; background: rgba(0,0,0,0.7);
|
||||
@@ -617,24 +654,6 @@ body.resizing iframe { pointer-events: none; }
|
||||
.templates-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
/* ===================== Format Save Toggle ===================== */
|
||||
.format-save-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--text-dim);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.format-save-toggle input { cursor: pointer; }
|
||||
|
||||
/* ===================== Editor Font Select ===================== */
|
||||
#editor-font {
|
||||
background: var(--bg); color: var(--text); border: 1px solid var(--border);
|
||||
padding: 4px 6px; border-radius: 4px; font-size: 12px; cursor: pointer;
|
||||
}
|
||||
|
||||
/* ===================== Version History Modal ===================== */
|
||||
.history-modal-content { min-width: 500px; max-width: 700px; text-align: left; }
|
||||
.history-list {
|
||||
|
||||
@@ -21,71 +21,115 @@
|
||||
<option value="wasm">WASM</option>
|
||||
</select>
|
||||
<input type="text" id="title-input" placeholder="Untitled" spellcheck="false">
|
||||
<select id="layout-mode">
|
||||
<option value="default">Default</option>
|
||||
<option value="top-bottom">Top / Bottom</option>
|
||||
<option value="editor-only">Editor Only</option>
|
||||
<option value="preview-only">Preview Only</option>
|
||||
</select>
|
||||
<select id="keybinding-mode">
|
||||
<option value="default">Default</option>
|
||||
<option value="vim">Vim</option>
|
||||
<option value="emacs">Emacs</option>
|
||||
</select>
|
||||
<select id="editor-theme">
|
||||
<option value="vs-dark">VS Dark</option>
|
||||
<option value="vs">VS Light</option>
|
||||
<option value="hc-black">High Contrast</option>
|
||||
<option value="monokai">Monokai</option>
|
||||
<option value="dracula">Dracula</option>
|
||||
<option value="github-dark">GitHub Dark</option>
|
||||
</select>
|
||||
<select id="editor-font" title="Editor font">
|
||||
<option value="default">Default Font</option>
|
||||
<option value="Fira Code">Fira Code</option>
|
||||
<option value="JetBrains Mono">JetBrains Mono</option>
|
||||
<option value="Source Code Pro">Source Code Pro</option>
|
||||
<option value="IBM Plex Mono">IBM Plex Mono</option>
|
||||
<option value="Cascadia Code">Cascadia Code</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="toolbar-right">
|
||||
<div class="tags-input-wrap">
|
||||
<input type="text" id="tags-input" placeholder="Add tags..." list="tags-datalist" spellcheck="false">
|
||||
<input type="text" id="tags-input" placeholder="Tags..." list="tags-datalist" spellcheck="false">
|
||||
<datalist id="tags-datalist"></datalist>
|
||||
<div id="tags-display" class="tags-display"></div>
|
||||
</div>
|
||||
<select id="preview-theme" title="Preview background theme">
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
<button id="btn-templates" class="btn-secondary" title="Starter templates gallery">Templates</button>
|
||||
<button id="btn-resources" class="btn-secondary" title="External CSS/JS resources">Resources</button>
|
||||
<button id="btn-shortcuts" class="btn-secondary" title="Keyboard shortcuts (?)" aria-label="Keyboard shortcuts">?</button>
|
||||
<label class="tailwind-toggle" title="Enable Tailwind CSS">
|
||||
<input type="checkbox" id="tailwind-checkbox">
|
||||
Tailwind
|
||||
</label>
|
||||
<label class="listed-toggle" title="Show in browse page">
|
||||
<input type="checkbox" id="listed-checkbox" checked>
|
||||
Listed
|
||||
</label>
|
||||
<label class="format-save-toggle" title="Auto-format code on save">
|
||||
<input type="checkbox" id="format-save-checkbox">
|
||||
Fmt
|
||||
</label>
|
||||
<label class="auto-run-toggle" title="Auto-run on change">
|
||||
<input type="checkbox" id="auto-run-checkbox" checked>
|
||||
Auto
|
||||
</label>
|
||||
</div>
|
||||
<div class="toolbar-right">
|
||||
<div class="toolbar-toggles">
|
||||
<label class="toolbar-toggle" title="Enable Tailwind CSS">
|
||||
<input type="checkbox" id="tailwind-checkbox">
|
||||
<span>TW</span>
|
||||
</label>
|
||||
<label class="toolbar-toggle" title="Auto-run on change">
|
||||
<input type="checkbox" id="auto-run-checkbox" checked>
|
||||
<span>Auto</span>
|
||||
</label>
|
||||
<label class="toolbar-toggle" title="Auto-format on save">
|
||||
<input type="checkbox" id="format-save-checkbox">
|
||||
<span>Fmt</span>
|
||||
</label>
|
||||
<label class="toolbar-toggle" title="Show in browse page">
|
||||
<input type="checkbox" id="listed-checkbox" checked>
|
||||
<span>Listed</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="toolbar-divider"></div>
|
||||
<button id="btn-run" title="Run (Ctrl+Enter)">Run</button>
|
||||
<button id="btn-save" title="Save (Ctrl+S)">Save</button>
|
||||
<button id="btn-fork" title="Fork">Fork</button>
|
||||
<button id="btn-history" title="Version history" class="btn-secondary">History</button>
|
||||
<button id="btn-embed" title="Embed code generator" class="btn-secondary">Embed</button>
|
||||
<button id="btn-collection" title="Add to collection" class="btn-secondary">Collection</button>
|
||||
<button id="btn-export" title="Export standalone HTML" class="btn-secondary">Export</button>
|
||||
<button id="btn-qr" title="QR code" class="btn-secondary">QR</button>
|
||||
<button id="btn-fork" class="btn-secondary" title="Fork">Fork</button>
|
||||
<div class="toolbar-divider"></div>
|
||||
<button id="btn-templates" class="btn-icon" title="Starter templates">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg>
|
||||
</button>
|
||||
<button id="btn-resources" class="btn-icon" title="External resources">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>
|
||||
</button>
|
||||
<button id="btn-history" class="btn-icon" title="Version history">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
||||
</button>
|
||||
<button id="btn-embed" class="btn-icon" title="Embed code">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
|
||||
</button>
|
||||
<button id="btn-export" class="btn-icon" title="Export HTML">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
||||
</button>
|
||||
<button id="btn-collection" class="btn-icon" title="Collections">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
|
||||
</button>
|
||||
<button id="btn-qr" class="btn-icon" title="QR code">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="2" width="8" height="8" rx="1"/><rect x="14" y="2" width="8" height="8" rx="1"/><rect x="2" y="14" width="8" height="8" rx="1"/><rect x="14" y="14" width="4" height="4"/><line x1="22" y1="14" x2="22" y2="22"/><line x1="14" y1="22" x2="22" y2="22"/></svg>
|
||||
</button>
|
||||
<div class="toolbar-divider"></div>
|
||||
<div class="settings-popover-wrap">
|
||||
<button id="btn-settings" class="btn-icon" title="Settings">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
|
||||
</button>
|
||||
<div id="settings-popover" class="settings-popover hidden">
|
||||
<div class="settings-group">
|
||||
<label class="settings-label">Layout</label>
|
||||
<select id="layout-mode">
|
||||
<option value="default">Default</option>
|
||||
<option value="top-bottom">Top / Bottom</option>
|
||||
<option value="editor-only">Editor Only</option>
|
||||
<option value="preview-only">Preview Only</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="settings-group">
|
||||
<label class="settings-label">Theme</label>
|
||||
<select id="editor-theme">
|
||||
<option value="vs-dark">VS Dark</option>
|
||||
<option value="vs">VS Light</option>
|
||||
<option value="hc-black">High Contrast</option>
|
||||
<option value="monokai">Monokai</option>
|
||||
<option value="dracula">Dracula</option>
|
||||
<option value="github-dark">GitHub Dark</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="settings-group">
|
||||
<label class="settings-label">Font</label>
|
||||
<select id="editor-font" title="Editor font">
|
||||
<option value="default">Default Font</option>
|
||||
<option value="Fira Code">Fira Code</option>
|
||||
<option value="JetBrains Mono">JetBrains Mono</option>
|
||||
<option value="Source Code Pro">Source Code Pro</option>
|
||||
<option value="IBM Plex Mono">IBM Plex Mono</option>
|
||||
<option value="Cascadia Code">Cascadia Code</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="settings-group">
|
||||
<label class="settings-label">Keybindings</label>
|
||||
<select id="keybinding-mode">
|
||||
<option value="default">Default</option>
|
||||
<option value="vim">Vim</option>
|
||||
<option value="emacs">Emacs</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="settings-group">
|
||||
<label class="settings-label">Preview</label>
|
||||
<select id="preview-theme" title="Preview background">
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="settings-group">
|
||||
<label class="settings-label">Shortcuts</label>
|
||||
<button id="btn-shortcuts" class="btn-small">View all</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -290,8 +290,10 @@ function applyLayout(layout) {
|
||||
}
|
||||
|
||||
async function init() {
|
||||
// Load Emmet before editors so completion providers are registered
|
||||
// Load ALL CDN scripts before editor creation so window.define
|
||||
// (Monaco's RequireJS) is never clobbered during Monarch tokenizer init
|
||||
await initEmmet();
|
||||
await initLinter();
|
||||
|
||||
// Register custom Monaco themes before creating editors
|
||||
registerCustomThemes();
|
||||
@@ -312,7 +314,6 @@ async function init() {
|
||||
initPerformance();
|
||||
initResizer();
|
||||
initKeybindings();
|
||||
initLinter();
|
||||
|
||||
// Auto-run checkbox
|
||||
const autoRunCb = $('#auto-run-checkbox');
|
||||
@@ -571,6 +572,18 @@ async function init() {
|
||||
$('#shortcuts-modal-close').addEventListener('click', () => scModal.classList.add('hidden'));
|
||||
scModal.addEventListener('click', (e) => { if (e.target === scModal) scModal.classList.add('hidden'); });
|
||||
|
||||
// Settings popover toggle
|
||||
const settingsPopover = $('#settings-popover');
|
||||
$('#btn-settings').addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
settingsPopover.classList.toggle('hidden');
|
||||
});
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!settingsPopover.classList.contains('hidden') && !e.target.closest('.settings-popover-wrap')) {
|
||||
settingsPopover.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
// Load fiddle from URL if present
|
||||
loadFromUrl();
|
||||
|
||||
|
||||
@@ -37,41 +37,41 @@ const editorOpts = {
|
||||
|
||||
export const MODE_TABS = {
|
||||
'html-css-js': [
|
||||
{ id: 'html', label: 'HTML', lang: 'html' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css' },
|
||||
{ id: 'js', label: 'JavaScript', lang: 'javascript' },
|
||||
{ id: 'html', label: 'HTML', lang: 'html', ext: 'html' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css', ext: 'css' },
|
||||
{ id: 'js', label: 'JavaScript', lang: 'javascript', ext: 'js' },
|
||||
],
|
||||
'typescript': [
|
||||
{ id: 'html', label: 'HTML', lang: 'html' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css' },
|
||||
{ id: 'js', label: 'TypeScript', lang: 'typescript' },
|
||||
{ id: 'html', label: 'HTML', lang: 'html', ext: 'html' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css', ext: 'css' },
|
||||
{ id: 'js', label: 'TypeScript', lang: 'typescript', ext: 'ts' },
|
||||
],
|
||||
'react': [
|
||||
{ id: 'js', label: 'JSX', lang: 'javascript' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css' },
|
||||
{ id: 'html', label: 'HTML', lang: 'html' },
|
||||
{ id: 'js', label: 'JSX', lang: 'javascript', ext: 'jsx' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css', ext: 'css' },
|
||||
{ id: 'html', label: 'HTML', lang: 'html', ext: 'html' },
|
||||
],
|
||||
'react-ts': [
|
||||
{ id: 'js', label: 'TSX', lang: 'typescript' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css' },
|
||||
{ id: 'html', label: 'HTML', lang: 'html' },
|
||||
{ id: 'js', label: 'TSX', lang: 'typescript', ext: 'tsx' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css', ext: 'css' },
|
||||
{ id: 'html', label: 'HTML', lang: 'html', ext: 'html' },
|
||||
],
|
||||
'vue': [
|
||||
{ id: 'js', label: 'Vue SFC', lang: 'html' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css' },
|
||||
{ id: 'js', label: 'Vue SFC', lang: 'html', ext: 'vue' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css', ext: 'css' },
|
||||
],
|
||||
'svelte': [
|
||||
{ id: 'js', label: 'Svelte', lang: 'html' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css' },
|
||||
{ id: 'js', label: 'Svelte', lang: 'html', ext: 'svelte' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css', ext: 'css' },
|
||||
],
|
||||
'markdown': [
|
||||
{ id: 'js', label: 'Markdown', lang: 'markdown' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css' },
|
||||
{ id: 'js', label: 'Markdown', lang: 'markdown', ext: 'md' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css', ext: 'css' },
|
||||
],
|
||||
'wasm': [
|
||||
{ id: 'html', label: 'HTML', lang: 'html' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css' },
|
||||
{ id: 'js', label: 'JavaScript', lang: 'javascript' },
|
||||
{ id: 'html', label: 'HTML', lang: 'html', ext: 'html' },
|
||||
{ id: 'css', label: 'CSS', lang: 'css', ext: 'css' },
|
||||
{ id: 'js', label: 'JavaScript', lang: 'javascript', ext: 'js' },
|
||||
],
|
||||
};
|
||||
|
||||
@@ -179,16 +179,20 @@ function configureJsxSupport(mode) {
|
||||
}
|
||||
}
|
||||
|
||||
let modelCounter = 0;
|
||||
|
||||
function createEditor(tabDef) {
|
||||
const container = document.createElement('div');
|
||||
container.className = 'editor-container';
|
||||
container.id = `editor-${tabDef.id}`;
|
||||
editorArea().appendChild(container);
|
||||
|
||||
const uri = monaco.Uri.parse(`file:///fiddle-${++modelCounter}.${tabDef.ext}`);
|
||||
const model = monaco.editor.createModel('', tabDef.lang, uri);
|
||||
|
||||
const editor = monaco.editor.create(container, {
|
||||
...editorOpts,
|
||||
language: tabDef.lang,
|
||||
value: '',
|
||||
model,
|
||||
});
|
||||
|
||||
if (onChangeCallback) {
|
||||
@@ -289,11 +293,13 @@ export function initEditors(mode = 'html-css-js') {
|
||||
export function switchMode(mode) {
|
||||
if (mode === currentMode) return;
|
||||
|
||||
// Dispose existing editors
|
||||
// Dispose existing editors and their models
|
||||
const oldTabs = MODE_TABS[currentMode];
|
||||
oldTabs.forEach((tab) => {
|
||||
if (editors[tab.id]) {
|
||||
const model = editors[tab.id].getModel();
|
||||
editors[tab.id].dispose();
|
||||
if (model) model.dispose();
|
||||
}
|
||||
const container = editors[`_container_${tab.id}`];
|
||||
if (container && container.parentNode) {
|
||||
|
||||
Reference in New Issue
Block a user