Embed the Monaco editor in the cell
Community Note
- Please use a 👍 reaction to provide a +1/vote. This helps the community and maintainers prioritize this request.
- If you are interested in working on this issue or have submitted a pull request, please leave a comment.
Graph Notebook Version (and Graph Database and Version used if applicable)
Is your feature request related to a problem? Please describe. Magics and graph languages keywords are challenging to remember.
Describe the solution you'd like Embed the Monaco editor in a cell. It provides Magic keywords autocomplete, language keyword coloring, language keyword auto-complete, node labels autocomplete, edge types autocomplete, and properties auto-complete.
Additional context Add any other context or screenshots about the feature request here. Describe any alternatives you've considered.
There are several ways to embed the Monaco editor in a Jupyter Lab cell. Here are the most effective approaches:
Method 1: Direct HTML/JavaScript Implementation
from IPython.display import HTML, display
import json
def create_monaco_editor(initial_code="", language="python", height="400px"):
editor_id = "monaco-editor-" + str(id(initial_code))
html_content = f'''
<div id="{editor_id}" style="width: 100%; height: {height}; border: 1px solid #ccc;"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.44.0/min/vs/loader.min.js"></script>
<script>
require.config({{ paths: {{ vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.44.0/min/vs' }} }});
require(['vs/editor/editor.main'], function() {{
const editor = monaco.editor.create(document.getElementById('{editor_id}'), {{
value: {json.dumps(initial_code)},
language: '{language}',
theme: 'vs-dark',
automaticLayout: true,
minimap: {{ enabled: false }},
scrollBeyondLastLine: false
}});
// Store editor reference globally for access
window.{editor_id.replace('-', '_')} = editor;
// Optional: Add button to get editor content
const button = document.createElement('button');
button.innerText = 'Get Code';
button.onclick = function() {{
const code = editor.getValue();
console.log(code);
// You can also store it in a Python variable or execute it
}};
document.getElementById('{editor_id}').parentNode.insertBefore(button, document.getElementById('{editor_id}').nextSibling);
}});
</script>
'''
return HTML(html_content)
# Usage
editor = create_monaco_editor(
initial_code="def hello_world():\n print('Hello from Monaco!')\n return 'success'",
language="python",
height="300px"
)
display(editor)
Method 2: Using ipywidgets (More Interactive)
First install the required packages:
pip install ipywidgets
jupyter nbextension enable --py widgetsnbextension
import ipywidgets as widgets
from IPython.display import display, HTML, Javascript
from traitlets import Unicode, Int
class MonacoWidget(widgets.DOMWidget):
_view_name = Unicode('MonacoView').tag(sync=True)
_view_module = Unicode('monaco_widget').tag(sync=True)
_view_module_version = Unicode('0.1.0').tag(sync=True)
value = Unicode('').tag(sync=True)
language = Unicode('python').tag(sync=True)
# JavaScript for the widget
js_code = """
require.undef('monaco_widget');
define('monaco_widget', ["@jupyter-widgets/base"], function(widgets) {
var MonacoView = widgets.DOMWidgetView.extend({
render: function() {
this.el.style.width = '100%';
this.el.style.height = '400px';
this.el.style.border = '1px solid #ccc';
// Load Monaco Editor
var script = document.createElement('script');
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.44.0/min/vs/loader.min.js';
script.onload = () => {
require.config({ paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.44.0/min/vs' }});
require(['vs/editor/editor.main'], () => {
this.editor = monaco.editor.create(this.el, {
value: this.model.get('value'),
language: this.model.get('language'),
theme: 'vs-dark',
automaticLayout: true
});
// Sync changes back to Python
this.editor.onDidChangeModelContent(() => {
this.model.set('value', this.editor.getValue());
this.touch();
});
});
};
document.head.appendChild(script);
},
value_changed: function() {
if (this.editor) {
this.editor.setValue(this.model.get('value'));
}
}
});
return {
MonacoView: MonacoView
};
});
"""
# Display the JavaScript
display(Javascript(js_code))
# Create and display the widget
monaco_widget = MonacoWidget()
monaco_widget.value = "def example():\n return 'Hello Monaco!'"
display(monaco_widget)
Method 3: Using Existing Packages
You can also try existing packages like jupyter-monaco:
pip install jupyter-monaco
from jupyter_monaco import Monaco
editor = Monaco(
value="print('Hello World')",
language='python',
theme='vs-dark'
)
display(editor)
Method 4: Simple Inline Solution
For a quick and dirty solution:
from IPython.display import HTML
HTML('''
<div id="editor" style="width: 100%; height: 400px;"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.44.0/min/vs/loader.min.js"></script>
<script>
require.config({ paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.44.0/min/vs' }});
require(['vs/editor/editor.main'], function() {
window.monacoEditor = monaco.editor.create(document.getElementById('editor'), {
value: 'print("Hello from Monaco Editor!")',
language: 'python',
theme: 'vs-dark'
});
});
</script>
''')
Getting Code Back to Python
To execute code from Monaco in your Jupyter environment:
from IPython.display import Javascript
# JavaScript to get code and execute it in Python
Javascript('''
const code = window.monacoEditor.getValue();
const command = `
executed_code = """${code}"""
exec(executed_code)
`;
IPython.notebook.kernel.execute(command);
''')
The first method (Direct HTML/JavaScript) is usually the most reliable and easiest to implement. Choose the method that best fits your specific needs and technical requirements.