Monaco-based code editor with syntax highlighting, multi-tab editing, command palette, JSON schema validation, and full programmatic control.
<iframe id="ce-demo" src="/online/webapp/code-editor" width="100%" height="450" frameborder="0" style="border:1px solid #ccc; border-radius:4px;"></iframe>
<script>window._wsConnect('ce-demo', 'ceSocket');</script>
<iframe src="https://sgapps.io/online/webapp/code-editor"
width="100%" height="600" frameborder="0" allow="clipboard-write"></iframe>active-file:codeEditor:value -- Get or Set Editor ContentThe most commonly used event. When called with a string, it sets the editor text. When called with only a callback, it returns the current text.
| Arg | Type | Description |
|---|---|---|
value | string (optional) | New content to set |
callback | function | (err, value: string) when getting, (err) when setting |
// Set content
socket.fire("webapp::instance::request",
"active-file:codeEditor:value",
"function hello() {\n return 'world';\n}",
function (err) { console.log(err || "Content set"); }
);
// Get content
socket.fire("webapp::instance::request",
"active-file:codeEditor:value",
function (err, value) {
if (err) return console.error(err);
console.log("Content:", value);
}
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file:codeEditor:value','// Hello from the docs page!\nfunction greet(name) {\n return 'Hello, ' + name + '!';\n}\n\nconsole.log(greet('World'));',function(err){if(err)alert('Set error: '+err.message)})">Try: Set JS Code</button><button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file:codeEditor:value',function(err,v){if(err)return alert('Get error: '+err.message);alert('Length: '+v.length+' chars\n\nFirst 200 chars:\n'+v.substring(0,200))})">Try: Get Code</button>
active-file:codeEditor:syntax -- Get or Set Language ModeChanges the syntax highlighting language. Uses Monaco's language identifiers: javascript, typescript, html, css, json, python, markdown, xml, sql, yaml, go, rust, cpp, etc.
| Arg | Type | Description |
|---|---|---|
syntax | string (optional) | Language ID to set |
callback | function | (err, currentLanguage: string) |
// Set to Python
socket.fire("webapp::instance::request", "active-file:codeEditor:syntax", "python");
// Get current language
socket.fire("webapp::instance::request", "active-file:codeEditor:syntax",
function (err, lang) { console.log("Language:", lang); }
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file:codeEditor:syntax','javascript')">Try: JavaScript</button><button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file:codeEditor:syntax','python')">Try: Python</button><button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file:codeEditor:syntax','html')">Try: HTML</button>
active-file:codeEditor:options -- Set Monaco Editor OptionsConfigures the Monaco editor instance. Any Monaco IEditorOptions can be passed.
| Arg | Type | Description |
|---|---|---|
options | object | Monaco editor options |
callback | function | (err) |
// Make read-only with large font
socket.fire("webapp::instance::request", "active-file:codeEditor:options", {
readOnly: true,
fontSize: 18,
wordWrap: "on",
minimap: { enabled: false }
});
// Restore editable
socket.fire("webapp::instance::request", "active-file:codeEditor:options", {
readOnly: false,
fontSize: 14
});<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file:codeEditor:options',{readOnly:true,fontSize:18})">Try: Read-Only + Large Font</button><button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file:codeEditor:options',{readOnly:false,fontSize:14})">Try: Restore Editable</button>
active-file:codeEditor:selection -- Get Selected TextReturns the current text selection with line/column positions.
socket.fire("webapp::instance::request", "active-file:codeEditor:selection",
function (err, sel) {
console.log("Selected:", sel);
// { startLine: 3, startCol: 5, endLine: 3, endCol: 20, text: "selected text" }
}
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file:codeEditor:selection',function(e,s){alert(s.text?('Selected: "'+s.text+'" at line '+s.startLine):'No selection')})">Try: Get Selection</button>
active-file:codeEditor:insertText -- Insert TextInserts text at a specific position or at the current cursor position. If a position object is provided, text is inserted at that line/column. Otherwise, it replaces the current selection.
| Arg | Type | Description |
|---|---|---|
text | string | Text to insert |
position | object (optional) | { line: number, col: number } |
callback | function | (err) |
// Insert at line 1, column 1
socket.fire("webapp::instance::request", "active-file:codeEditor:insertText",
"// Auto-generated header\n",
{ line: 1, col: 1 }
);
// Insert at current cursor position
socket.fire("webapp::instance::request", "active-file:codeEditor:insertText",
"console.log('inserted');"
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file:codeEditor:insertText','// Inserted from docs!\n',{line:1,col:1})">Try: Insert at Top</button>
active-file:codeEditor:revealLine -- Scroll to LineScrolls the editor to center a specific line number in the viewport. Useful when navigating to errors or search results.
| Arg | Type | Description |
|---|---|---|
lineNumber | number | Line to reveal |
callback | function | (err) |
socket.fire("webapp::instance::request", "active-file:codeEditor:revealLine", 42);active-file:codeEditor:json:schema -- JSON Schema ValidationSets a JSON Schema for real-time validation of the active editor content. Monaco will show errors/warnings inline when the content doesn't match the schema.
| Arg | Type | Description |
|---|---|---|
schema | object | JSON Schema object |
callback | function | (err) |
socket.fire("webapp::instance::request", "active-file:codeEditor:json:schema", {
type: "object",
properties: {
name: { type: "string" },
version: { type: "string", pattern: "^\\d+\\.\\d+\\.\\d+$" }
},
required: ["name", "version"]
});active-file:save -- Save Active FileTriggers the save action on the currently active file tab. The file is written back to its original path in the file system.
socket.fire("webapp::instance::request", "active-file:save", function (err) {
console.log(err || "File saved");
});active-file:markers -- Set Error/Warning MarkersProgrammatically set diagnostic markers (errors, warnings, info) on the editor. This is useful for showing linting results, build errors, or custom validation from your application.
| Arg | Type | Description |
|---|---|---|
markers | Array | Array of marker objects |
callback | function | (err) |
{ startLine, startCol, endLine, endCol, message, severity }1 = Hint, 2 = Info, 4 = Warning, 8 = Errorsocket.fire("webapp::instance::request", "active-file:markers", [
{ startLine: 3, startCol: 1, endLine: 3, endCol: 30,
message: "Unused variable 'x'", severity: 4 },
{ startLine: 7, startCol: 5, endLine: 7, endCol: 15,
message: "Syntax error: unexpected token", severity: 8 }
]);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file:markers',[{startLine:1,startCol:1,endLine:1,endCol:50,message:'This is a warning from the docs page',severity:4},{startLine:3,startCol:1,endLine:3,endCol:30,message:'This is an error marker',severity:8}])">Try: Set Markers</button><button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file:markers',[])">Try: Clear Markers</button>
files:open -- Open a File in a New TabOpens a file in a new editor tab. The type field determines the renderer: "file" for text editor, "markdown" for rendered markdown, "file-image" for image viewer.
| Arg | Type | Description |
|---|---|---|
fileConfig | object | { path, type?, title? } |
callback | function | (err) |
socket.fire("webapp::instance::request", "files:open", {
path: "web:///api/applications.json",
type: "file",
title: "applications.json"
});files:list -- List Open TabsReturns an array of all currently open tabs with their index, name, path, type, and title.
socket.fire("webapp::instance::request", "files:list", function (err, tabs) {
console.log(tabs);
// [{ index: 0, name: "index.js", path: "/home/user/index.js", type: "file", title: "index.js" }]
});<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','files:list',function(e,t){alert('Open tabs: '+t.length+'\n'+t.map(function(x){return x.index+': '+x.title}).join('\n'))})">Try: List Tabs</button>
files:active:set -- Activate a TabSwitches to a specific tab by its index (as returned by files:list).
| Arg | Type | Description |
|---|---|---|
tabIndex | number | Zero-based tab index |
callback | function | (err) |
socket.fire("webapp::instance::request", "files:active:set", 0);files:close:all -- Close All TabsCloses all open editor tabs.
socket.fire("webapp::instance::request", "files:close:all");gui:sidebar:toggle -- Show/Hide SidebarToggle the file tree sidebar visibility.
| Arg | Type | Description |
|---|---|---|
visible | boolean | true to show, false to hide |
socket.fire("webapp::instance::request", "gui:sidebar:toggle", false); // hide
socket.fire("webapp::instance::request", "gui:sidebar:toggle", true); // show<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','gui:sidebar:toggle',false)">Try: Hide Sidebar</button><button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','gui:sidebar:toggle',true)">Try: Show Sidebar</button>
active-file -- Introspect the Active TabReturns a snapshot of the currently focused tab plus a live reference to its editor wrapper. Useful for introspection and as the entry point for building higher-level helpers (active-file:codeEditor:* handlers all go through this internally).
| Arg | Type | Description |
|---|---|---|
callback | function | (err, info) -- see shape below |
| Field | Type | Description | |
|---|---|---|---|
activeTab | object | {id, name, path, type, title, statuses} snapshot | |
codeEditor | object \ | null | Monaco wrapper (.editor(), .value(), .syntax(), .isLoading(), .config()); null when no file tab is active |
codeEditorConfig | object \ | null | Convenience alias for codeEditor.config() |
tab | object \ | null | Internal Tab wrapper (full API) |
socket.fire("webapp::instance::request", "active-file", function (err, info) {
if (err) return console.error(err);
console.log("tab id:", info.activeTab.id);
console.log("tab path:", info.activeTab.path);
console.log("editor ready:", info.codeEditor !== null);
});<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file',function(e,i){if(e)return alert(e.message);alert('Tab: '+(i.activeTab.title||i.activeTab.name||'(none)')+'\nPath: '+(i.activeTab.path||'(none)')+'\nType: '+i.activeTab.type+'\nEditor: '+(i.codeEditor?'ready':'none'))})">Try: Introspect Active Tab</button>
active-file:codeEditor:isLoading -- Loading FlagReturns true while the active editor is still fetching / parsing its initial content (and briefly during subsequent reloads).
| Arg | Type | Description |
|---|---|---|
activeTabId | string (optional) | When provided, errors out if the active tab's id does not match (prevents racing with a tab switch) |
callback | function | (err, isLoading: boolean) |
socket.fire("webapp::instance::request", "active-file:codeEditor:isLoading",
function (err, loading) {
if (err) return console.error(err);
console.log(loading ? "still loading" : "ready");
}
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','active-file:codeEditor:isLoading',function(e,l){if(e)return alert(e.message);alert('isLoading: '+l)})">Try: Check Loading State</button>
The fs:* events expose the same virtual filesystem that the file-manager webapp uses, bound to the editor's own fs decorator so writes also trigger the universal fs-event bridge (afterWrite, afterRemove, afterCwd -- see File Manager docs for subscription). Within an unauthenticated embedding context, operations are sandboxed to the input:// scheme (browser-memory, isolated per tab, destroyed on refresh).
A common pattern: write a markdown file via fs:write, open it as a markdown tab via files:open -- the tab subscribes to afterWrite and auto-refreshes on every subsequent write, giving a live preview without re-opening.
fs:write -- Write a FileWrites content to path. Creates the file (and intermediate directories under input://) if missing.
| Arg | Type | Description | ||
|---|---|---|---|---|
path | string | Target path (e.g. input://notes.md) | ||
content | string \ | Blob \ | ArrayBuffer | File body |
callback | function | (err) |
socket.fire("webapp::instance::request", "fs:write",
"input://hello.txt", "Hello, world!",
function (err) { console.log(err || "written"); }
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','fs:write','input://hello.txt','Hello from code-editor docs @ '+new Date().toISOString(),function(e){if(e)alert('Error: '+e.message);else alert('Wrote input://hello.txt')})">Try: Write hello.txt</button>
fs:read -- Read a FileReads path as UTF-8 text.
| Arg | Type | Description |
|---|---|---|
path | string | Source path |
callback | function | (err, content: string) |
socket.fire("webapp::instance::request", "fs:read", "input://hello.txt",
function (err, content) {
if (err) return console.error(err);
console.log("content:", content);
}
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','fs:read','input://hello.txt',function(e,c){if(e)alert('Error: '+e.message);else alert('Content:\n'+c)})">Try: Read hello.txt</button>
fs:exists -- Check Existence| Arg | Type | Description |
|---|---|---|
path | string | Path to check |
callback | function | (err, exists: boolean) |
socket.fire("webapp::instance::request", "fs:exists", "input://hello.txt",
function (err, exists) { console.log(exists ? "yes" : "no"); }
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','fs:exists','input://hello.txt',function(e,x){if(e)alert('Error: '+e.message);else alert('exists: '+x)})">Try: Check hello.txt</button>
fs:stats -- File Metadata| Arg | Type | Description |
|---|---|---|
path | string | Target path |
callback | function | (err, info) with {length, mtime, type, ...} fields depending on backend |
socket.fire("webapp::instance::request", "fs:stats", "input://hello.txt",
function (err, info) { console.log(info); }
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','fs:stats','input://hello.txt',function(e,i){if(e)alert('Error: '+e.message);else alert('Stats:\n'+JSON.stringify(i,null,2))})">Try: Stat hello.txt</button>
fs:mkdir -- Create a Directory (non-recursive)Fails when the parent directory does not exist. Use fs:mkdirp to create intermediate levels.
| Arg | Type | Description |
|---|---|---|
path | string | Directory path (trailing / optional) |
callback | function | (err) |
socket.fire("webapp::instance::request", "fs:mkdir", "input://data/",
function (err) { console.log(err || "created"); }
);fs:mkdirp -- Create a Directory (recursive)Like mkdir -p: creates every missing level in the path.
| Arg | Type | Description |
|---|---|---|
path | string | Directory path |
callback | function | (err) |
socket.fire("webapp::instance::request", "fs:mkdirp",
"input://proj/src/components/",
function (err) { console.log(err || "created"); }
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','fs:mkdirp','input://proj/src/components/',function(e){if(e)alert('Error: '+e.message);else alert('Created input://proj/src/components/')})">Try: Create proj/src/components/</button>
fs:remove -- Delete a File or Directory| Arg | Type | Description |
|---|---|---|
path | string | File or directory to remove |
callback | function | (err) |
socket.fire("webapp::instance::request", "fs:remove", "input://hello.txt",
function (err) { console.log(err || "removed"); }
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','fs:remove','input://hello.txt',function(e){if(e)alert('Error: '+e.message);else alert('Removed input://hello.txt')})">Try: Remove hello.txt</button>
fs:mv -- Move or Rename| Arg | Type | Description |
|---|---|---|
src | string | Source path |
dst | string | Destination path |
callback | function | (err) |
socket.fire("webapp::instance::request", "fs:mv",
"input://notes.md", "input://archive/notes.md",
function (err) { console.log(err || "moved"); }
);fs:ls -- List DirectoryReturns an array of entry descriptors for the given directory.
| Arg | Type | Description |
|---|---|---|
path | string | Directory to list |
callback | function | (err, entries: Array) -- each entry has {name, type, ...} fields |
socket.fire("webapp::instance::request", "fs:ls", "input://",
function (err, list) { console.log(list); }
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','fs:ls','input://',function(e,l){if(e)alert('Error: '+e.message);else alert('Entries at input://\n'+(l&&l.length?l.map(function(x){return (x.type||'?')+' '+(x.name||x.path||JSON.stringify(x))}).join('\n'):'(empty)'))})">Try: List input://</button>
fs:cwd -- Get or Set Current Working DirectoryWhen called with a string, changes the sidebar's current working directory (and emits afterCwd). When called with only a callback, returns the current path.
| Arg | Type | Description |
|---|---|---|
path | string (optional) | New cwd |
callback | function | (err, cwd: string) |
// Get
socket.fire("webapp::instance::request", "fs:cwd",
function (err, cwd) { console.log("cwd:", cwd); }
);
// Set
socket.fire("webapp::instance::request", "fs:cwd", "input://proj/",
function (err, cwd) { console.log("now at:", cwd); }
);<button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','fs:cwd',function(e,c){if(e)alert('Error: '+e.message);else alert('cwd: '+c)})">Try: Get cwd</button><button onclick="window._ws('ceSocket')&&window.ceSocket.fire('webapp::instance::request','fs:mkdirp','input://proj/',function(){window.ceSocket.fire('webapp::instance::request','fs:cwd','input://proj/',function(e,c){if(e)alert('Error: '+e.message);else alert('cwd: '+c)})})">Try: Set cwd -> input://proj/</button>
<!DOCTYPE html>
<html>
<head><title>Embedded Code Editor</title></head>
<body>
<div style="display:flex;gap:8px;padding:10px;flex-wrap:wrap;">
<button id="set-code">Load Sample</button>
<button id="get-code">Read Code</button>
<button id="set-python">Python Mode</button>
<button id="readonly">Read-Only</button>
<button id="add-markers">Show Errors</button>
</div>
<iframe id="editor" src="https://sgapps.io/online/webapp/code-editor"
width="100%" height="500" frameborder="0" allow="clipboard-write"></iframe>
<pre id="output" style="background:#f6f8fa;padding:10px;max-height:200px;overflow:auto;"></pre>
<script src="https://sgapps.io/components/window-socket/index.js"></script>
<script>
var socket = new WindowSocket(document.getElementById('editor').contentWindow);
socket.start();
socket.on("webapp::connection::ping", function () {
socket.fire("webapp::instance::embed-mode", true);
});
document.getElementById('set-code').onclick = function () {
socket.fire("webapp::instance::request", "active-file:codeEditor:value",
"def fibonacci(n):\n a, b = 0, 1\n for _ in range(n):\n a, b = b, a + b\n return a\n\nprint(fibonacci(10))");
socket.fire("webapp::instance::request", "active-file:codeEditor:syntax", "python");
};
document.getElementById('get-code').onclick = function () {
socket.fire("webapp::instance::request", "active-file:codeEditor:value",
function (err, v) {
if (err) return console.error(err);
document.getElementById('output').textContent = v;
});
};
document.getElementById('set-python').onclick = function () {
socket.fire("webapp::instance::request", "active-file:codeEditor:syntax", "python");
};
document.getElementById('readonly').onclick = function () {
socket.fire("webapp::instance::request", "active-file:codeEditor:options", { readOnly: true });
};
document.getElementById('add-markers').onclick = function () {
socket.fire("webapp::instance::request", "active-file:markers", [
{ startLine: 2, startCol: 1, endLine: 2, endCol: 20, message: "Consider using a list comprehension", severity: 4 }
]);
};
</script>
</body>
</html>