= Creating the editor == Hello world! =======================JS // The Monaco Editor can be easily created, given an // empty container and an options literal. // Two members of the literal are "value" and "mode". // The editor takes the full size of its container. var container = document.getElementById("container"); var jsCode = "function hello() {\n\talert('Hello world!');\n}"; Monaco.Editor.create(container, { value: jsCode, mode: "text/javascript" }); =======================HTML
=======================END == Editor basic options =======================JS // Through the options literal, the behaviour of the editor can be easily customized. var container = document.getElementById("container"); var jsCode = "// First line\nfunction hello() {\n\talert('Hello world!');\n}\n// Last line"; // Here are the available config options that can be passed // to the editor and their default values. Try changing them! var editor = Monaco.Editor.create(container, { value: jsCode, mode: "text/javascript", // Show line numbers in the gutter ? lineNumbers: true, // Tab size in characters tabSize: "auto", // Insert spaces instead of tabs ? insertSpaces: "auto", // Rounded corners for rendering selection ? roundedSelection: true, // Scrolling one page after the last line ? scrollBeyondLastLine: true, // Scrollbars rendering scrollbar: { // other values are "visible" or "hidden" vertical: "auto", horizontal: "auto" }, // Automatic Layout: Should a timer be installed // which fires every 100ms to scan the editor's // container for size changes ? // Setting to true has a severe performance penalty. // One can call .layout() on the editor manually. automaticLayout: false, // Is the editor in read only mode ? readOnly: false, // What theme should be used ? // Values supported: vs, vs-dark theme: "vs", }); =======================HTML
=======================END == Hard wrapping =======================JS var container = document.getElementById("container"); var jsCode = "// jqeuery-min excerpt:\n// 1 2 3 4\n//34567890123456789012345678901234567890\n(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p=\"1.9.1\",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,w=/\\S+/g,T=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,N=/^(?:(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,C=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,k=/^[\\],:{}\\s]*$/,E=/(?:^|:|,)(?:\\s*\\[)+/g,S=/\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,A=/\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d+\\.|)\\d+(?:[eE][+-]?\\d+|)/g,j=/^-ms-/,D=/-([\\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||\"load\"===e.type||\"complete\"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener(\"DOMContentLoaded\",H,!1),e.removeEventListener(\"load\",H,!1)):(o.detachEvent(\"onreadystatechange\",H),e.detachEvent(\"onload\",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if(\"string\"==typeof e){if(i=\"<\"===e.charAt(0)&&\">\"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElemen"; var editor = Monaco.Editor.create(container, { value: jsCode, mode: "text/javascript", // If `wrappingColumn` is -1, then no wrapping occurs and // long lines are rendered on one line. However, this might // mean that not all code is rendered (... may be used). // If `wrappingColumn` is 0, then viewport width wrapping is set // If `wrappingColumn` is > 0, then the lines will wrap at its value // Defaults to 300 wrappingColumn: 40, // If more than half of the lines are on lines longer than // `longLineBoundary`, the editor forces viewport width wrapping // By default the value is 300, but here we're using a larger // value to circumvent this default behavior longLineBoundary: 1e4 }); =======================HTML
=======================END == Syntax highlighting for HTML elements =======================JS // The syntax highlighting functionality can be used independently of the editor. require(["vs/editor/editor.main"], function ($) { // The colorizeElement-function will read the data-lang-attribute // from the element to select the correct language mode. In this // sample it is text/css. Monaco.Editor.colorizeElement(document.getElementById('code')); }); =======================HTML
/* Some example CSS */

@import url("something.css");

body {
  margin: 0;
  padding: 3em 6em;
  font-family: tahoma, arial, sans-serif;
  color: #000;
}

#navigation a {
  font-weight: bold;
  text-decoration: none !important;
}

h1 {
  font-size: 2.5em;
}

h2 {
  font-size: 1.7em;
}

h1:before, h2:before {
  content: "some contents";
}

code {
  font-family: courier, monospace;
  font-size: 80%;
  color: #418A8A;
}
=======================CSS =======================END = Interacting with the editor == Adding a command =======================JS var KeyMod = require('vs/base/common/keyCodes').KeyMod; var KeyCode = require('vs/base/common/keyCodes').KeyCode; var container = document.getElementById("container"); var jsCode = [ '"use strict";', 'function Person(age) {', ' if (age) {', ' this.age = age;', ' }', '}', 'Person.prototype.getAge = function () {', ' return this.age;', '};' ].join('\n'); var editor = Monaco.Editor.create(container, { value: jsCode, mode: "text/javascript" }); var myCondition1 = editor.createContextKey(/*key name*/'myCondition1', /*default value*/false); var myCondition2 = editor.createContextKey(/*key name*/'myCondition2', /*default value*/false); editor.addCommand(KeyCode.Tab, function(ctx, args) { // services available in `ctx` alert('my command is executing with context: ' + JSON.stringify(args.context)); }, 'myCondition1 && myCondition2') myCondition1.set(true); setTimeout(function() { alert('now enabling also myCondition2, try pressing Tab!'); myCondition2.set(true); // you can use myCondition2.reset() to go back to the default }, 2000); =======================HTML
=======================END == Adding an action =======================JS var KeyMod = require('vs/base/common/keyCodes').KeyMod; var KeyCode = require('vs/base/common/keyCodes').KeyCode; var container = document.getElementById("container"); var jsCode = "var array = [3, 4, 5];\n"; var editor = Monaco.Editor.create(container, { value: [ '', 'class Example {', '\tprivate m:number;', '', '\tpublic met(): string {', '\t\treturn "Hello world!";', '\t}', '}' ].join('\n'), mode: "text/typescript" }); // Explanation: // Try right clicking on an identifier or keyword => the action will be enabled (due to `tokensAtPosition`) // Try right clicking on a string => the action will be disabled (due to `tokensAtPosition`) // Try right clicking on whitespace => the action will be disabled (due to `wordAtPosition`) // Press F1 (Alt-F1 in IE) => the action will appear and run if it is enabled // Press Ctrl-F10 => the action will run if it is enabled editor.addAction({ // An unique identifier of the contributed action. id: 'my-unique-id', // A label of the action that will be presented to the user. label: 'My Label!!!', // An optional array of keybindings for the action. keybindings: [KeyMod.CtrlCmd | KeyCode.F10], keybindingContext: null, // Control if the action should show up in the context menu and where. // Built-in groups: // 1_goto/* => e.g. 1_goto/1_peekDefinition // 2_change/* => e.g. 2_change/2_format // 3_edit/* => e.g. 3_edit/1_copy // 4_tools/* => e.g. 4_tools/1_commands // You can also create your own group. // Defaults to null (don't show in context menu). contextMenuGroupId: '2_change/2_bla', // Method that will be executed when the action is triggered. // @param editor The editor instance is passed in as a convinience run: function(ed) { alert("i'm running => " + ed.getPosition()); return null; }, // Optional enablement conditions. All members are optional enablement: { // The action is enabled only if text in the editor is focused (e.g. blinking cursor). // Warning: This condition will be disabled if the action is marked to be displayed in the context menu // Defaults to false. textFocus: true, // The action is enabled only if the editor or its widgets have focus (e.g. focus is in find widget). // Defaults to false. //widgetFocus: true, // The action is enabled only if the editor is not in read only mode. // Defaults to false. //writeableEditor: true, // The action is enabled only if the cursor position is over a word (i.e. not whitespace). // Defaults to false. wordAtPosition: true, // The action is enabled only if the cursor position is over tokens of a certain kind. // Defaults to no tokens required. tokensAtPosition: ['identifier', '', 'keyword'], } }); =======================HTML
=======================END == Inserting a code snippet =======================JS // There is a way to insert a snippet. The snippet syntax is very easy, use {{ and }} to indicate a placeholder. // Use the same value inside {{ and }} to have linked editing! That value will be the default entered text. // Use an empty placeholder {{}} to indicate the end position of the cursor if the user hits Enter. var container = document.getElementById("container"); var jsCode = "var array = [3, 4, 5];\n"; var editor = Monaco.Editor.create(container, { value: jsCode, mode: "text/javascript" }); var snippet = require("vs/editor/contrib/snippet/common/snippet"); var template = 'for (var {{index}} = 0; {{index}} < {{array}}.length; {{index}}++) {\n' + '\tvar {{element}} = {{array}}[{{index}}];\n' + '\t{{}}\n' + '}'; editor.setPosition({ lineNumber: 2, column :1 }); snippet.getSnippetController(editor).run(new snippet.CodeSnippet(template), 0, 0); editor.focus(); =======================HTML
=======================END == Revealing a position =======================JS var container = document.getElementById("container"); var jsCodeArr = [ '// ------------------------------', '// ------------------------------', 'function Person(age) {', ' if (age) {', ' this.age = age;', ' }', '}', 'Person.prototype.getAge = function () {', ' return this.age;', '};', '', '' ]; jsCodeArr = jsCodeArr.concat(jsCodeArr.slice(0)); jsCodeArr = jsCodeArr.concat(jsCodeArr.slice(0)); jsCodeArr = jsCodeArr.concat(jsCodeArr.slice(0)); jsCodeArr[49] += 'And this is some long line. And this is some long line. And this is some long line. And this is some long line. And this is some long line. '; var jsCode = jsCodeArr.join('\n'); var editor = Monaco.Editor.create(container, { value: jsCode, mode: "text/javascript" }); var shouldRevealLineInCenterOfViewport = true; var shouldRevealColumn = true; editor.revealPosition({ lineNumber: 50, column: 120 }, shouldRevealLineInCenterOfViewport, shouldRevealColumn); =======================HTML
=======================END == Rendering glyphs in the margin =======================JS var container = document.getElementById("container"); var jsCode = [ '"use strict";', 'function Person(age) {', ' if (age) {', ' this.age = age;', ' }', '}', 'Person.prototype.getAge = function () {', ' return this.age;', '};' ].join('\n'); var editor = Monaco.Editor.create(container, { value: jsCode, mode: "text/javascript", glyphMargin: true }); var decorationId = editor.changeDecorations(function(changeAccessor) { return changeAccessor.addDecoration({ startLineNumber: 3, startColumn: 1, endLineNumber: 3, endColumn: 1 }, { isWholeLine: true, className: 'myContentClass', glyphMarginClassName: 'myGlyphMarginClass' }); }); // You can now use `decorationId` to change or remove the decoration =======================HTML
=======================CSS .myGlyphMarginClass { background: red; } .myContentClass { background: lightblue; } =======================END == Line and Inline decorations =======================JS var container = document.getElementById("container"); var jsCode = [ '"use strict";', 'function Person(age) {', ' if (age) {', ' this.age = age;', ' }', '}', 'Person.prototype.getAge = function () {', ' return this.age;', '};' ].join('\n'); var editor = Monaco.Editor.create(container, { value: jsCode, mode: "text/javascript" }); var lineDecorationId = editor.changeDecorations(function(changeAccessor) { return changeAccessor.addDecoration({ startLineNumber: 3, startColumn: 1, endLineNumber: 5, endColumn: 1 }, { isWholeLine: true, linesDecorationsClassName: 'myLineDecoration' }); }); var inlineDecorationId = editor.changeDecorations(function(changeAccessor) { return changeAccessor.addDecoration({ startLineNumber: 7, startColumn: 1, endLineNumber: 7, endColumn: 24 }, { inlineClassName: 'myInlineDecoration' }); }); =======================HTML
=======================CSS .myInlineDecoration { color: red !important; cursor: pointer; text-decoration: underline; font-weight: bold; font-style: oblique; } .myLineDecoration { background: lightblue; width: 5px !important; left: 3px; } =======================END == Customizing the line numbers =======================JS function lineNumbersFunc(originalLineNumber) { var map = [ 'O', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X']; if (originalLineNumber < map.length) { return map[originalLineNumber]; } return originalLineNumber; } var container = document.getElementById("container"); var jsCode = [ '"use strict";', 'function Person(age) {', ' if (age) {', ' this.age = age;', ' }', '}', 'Person.prototype.getAge = function () {', ' return this.age;', '};' ].join('\n'); var editor = Monaco.Editor.create(container, { value: jsCode, mode: "text/javascript", lineNumbers: lineNumbersFunc }); =======================HTML
=======================CSS =======================END == Customizing the hover =======================JS require([ 'require', 'vs/base/common/winjs.base', 'vs/editor/common/core/range', 'vs/editor/contrib/hover/browser/hoverOperation', 'vs/editor/contrib/hover/browser/hoverWidgets' ], function(require, WinJS) { var Range = require('vs/editor/common/core/range').Range; var HoverOperation = require('vs/editor/contrib/hover/browser/hoverOperation').HoverOperation; var ContentHoverWidget = require('vs/editor/contrib/hover/browser/hoverWidgets').ContentHoverWidget; var ContentComputer = WinJS.Class.define(function ContentComputer(range, text, tokenType) { }, { setContext: function (range, text, tokenType) { this.a = range.startLineNumber; this.b = range.startColumn; this.result = [ 'Text: ' + text, 'Token type: ' + tokenType ]; }, computeAsync: function () { return WinJS.Promise.timeout(500).then(function() { return this.a + ' x ' + this.b + ' = ' + (this.a * this.b); }.bind(this)); }, computeSync: function () { return this.a + ' + ' + this.b + ' = ' + (this.a + this.b); }, onResult: function(r) { this.result.push(r); }, getResult: function() { return this.result; } }); var ContentWidget = WinJS.Class.derive(ContentHoverWidget, function ContentWidget(editor) { ContentHoverWidget.call(this, 'my.hover.widget.id', editor); this.lastRange = null; this.computer = new ContentComputer(); this.hoverOperation = new HoverOperation( this.computer, this.withResult.bind(this), null, this.withResult.bind(this) ); }, { startShowingAt: function (range, text, tokenType) { if (this.lastRange && this.lastRange.equalsRange(range)) { // We have to show the widget at the exact same range as before, so no work is needed return; } this.hoverOperation.cancel(); this.hide(); this.lastRange = range; this.computer.setContext(range, text, tokenType); this.hoverOperation.start(); }, hide: function () { this.lastRange = null; if (this.hoverOperation) { this.hoverOperation.cancel(); } ContentHoverWidget.prototype.hide.call(this); }, withResult: function (someResult) { this._domNode.innerHTML = someResult.join('
'); this.showAt({ lineNumber: this.lastRange.startLineNumber, column: this.lastRange.startColumn }); } }); var addCustomHoverTo = (function() { var editor = null; var contentWidget = null; function hide() { contentWidget.hide(); } function onMouseMove(e) { var targetType = e.target.type; if (targetType === Monaco.Editor.MouseTargetType.CONTENT_WIDGET && e.target.detail === 'my.hover.widget.id') { // mouse moved on top of content hover widget return; } if (targetType === Monaco.Editor.MouseTargetType.CONTENT_TEXT) { // Extract current token under cursor var currentTokenInfo = null; editor.getModel().tokenIterator(e.target.position, function (it) { currentTokenInfo = it.next(); }); if(currentTokenInfo) { var showRange = new Range(currentTokenInfo.lineNumber, currentTokenInfo.startColumn, currentTokenInfo.lineNumber, currentTokenInfo.endColumn); contentWidget.startShowingAt(showRange, editor.getModel().getValueInRange(showRange), currentTokenInfo.token.type); } } else { hide(); } } function setup(ed) { editor = ed; contentWidget = new ContentWidget(editor); editor.addListener(Monaco.Editor.EventType.MouseMove, onMouseMove); editor.addListener(Monaco.Editor.EventType.MouseLeave, hide); editor.addListener(Monaco.Editor.EventType.KeyDown, hide); editor.addListener(Monaco.Editor.EventType.ModelChanged, hide); editor.addListener('scroll', hide); } return setup; })(); var editor = createEditor(); addCustomHoverTo(editor); }); function createEditor() { var container = document.getElementById("container"); var jsCode = [ '"use strict";', 'function Person(age) {', ' if (age) {', ' this.age = age;', ' }', '}', 'Person.prototype.getAge = function () {', ' return this.age;', '};' ].join('\n'); return Monaco.Editor.create(container, { value: jsCode, mode: "text/javascript", glyphMargin: true, hover: false }); } =======================HTML
=======================CSS =======================END == Listening to Mouse Events =======================JS var container = document.getElementById("container"); var jsCode = [ '"use strict";', 'function Person(age) {', ' if (age) {', ' this.age = age;', ' }', '}', 'Person.prototype.getAge = function () {', ' return this.age;', '};' ].join('\n'); var editor = Monaco.Editor.create(container, { value: jsCode, mode: "text/javascript", glyphMargin: true, nativeContextMenu: false }); var decorationId = editor.changeDecorations(function(changeAccessor) { return changeAccessor.addDecoration({ startLineNumber: 3, startColumn: 1, endLineNumber: 3, endColumn: 1 }, { isWholeLine: true, className: 'myContentClass', glyphMarginClassName: 'myGlyphMarginClass' }); }); // Add a zone to make hit testing more interesting var viewZoneId = null; editor.changeViewZones(function(changeAccessor) { var domNode = document.createElement('div'); domNode.style.background = 'lightgreen'; viewZoneId = changeAccessor.addZone({ afterLineNumber: 3, heightInLines: 3, domNode: domNode }); }); // Add a content widget (scrolls inline with text) var contentWidget = { domNode: null, getId: function() { return 'my.content.widget'; }, getDomNode: function() { if (!this.domNode) { this.domNode = document.createElement('div'); this.domNode.innerHTML = 'My content widget'; this.domNode.style.background = 'grey'; } return this.domNode; }, getPosition: function() { return { position: { lineNumber: 7, column: 8 }, preference: [Monaco.Editor.ContentWidgetPositionPreference.ABOVE, Monaco.Editor.ContentWidgetPositionPreference.BELOW] }; } }; editor.addContentWidget(contentWidget); // Add an overlay widget var overlayWidget = { domNode: null, getId: function() { return 'my.overlay.widget'; }, getDomNode: function() { if (!this.domNode) { this.domNode = document.createElement('div'); this.domNode.innerHTML = 'My overlay widget'; this.domNode.style.background = 'grey'; this.domNode.style.right = '30px'; this.domNode.style.top = '50px'; } return this.domNode; }, getPosition: function() { return null; } }; editor.addOverlayWidget(overlayWidget); var output = document.getElementById('output'); function showEvent(str) { while(output.childNodes.length > 6) { output.removeChild(output.firstChild.nextSibling.nextSibling); } output.appendChild(document.createTextNode(str)); output.appendChild(document.createElement('br')); } editor.addListener(Monaco.Editor.EventType.MouseMove, function (e) { showEvent('mousemove - ' + e.target.toString()); }); editor.addListener(Monaco.Editor.EventType.MouseDown, function (e) { showEvent('mousedown - ' + e.target.toString()); }); editor.addListener(Monaco.Editor.EventType.ContextMenu, function (e) { showEvent('contextmenu - ' + e.target.toString()); }); editor.addListener(Monaco.Editor.EventType.MouseLeave, function (e) { showEvent('mouseleave'); }); =======================HTML
Last 3 events:
=======================CSS .myGlyphMarginClass { background: red; } .myContentClass { background: lightblue; } =======================END == Listening on keydown events =======================JS var KeyMod = require('vs/base/common/keyCodes').KeyMod; var KeyCode = require('vs/base/common/keyCodes').KeyCode; var container = document.getElementById("container"); var jsCode = "function hello() {\n\talert('Hello world!');\n}"; var editor = Monaco.Editor.create(container, { value: jsCode, mode: "text/javascript" }); function onF9() { alert('F9 pressed!'); // prevent default return true; } var myBinding = editor.addCommand(KeyCode.F9, onF9); // When cleaning up remember to call myBinding.dispose() =======================HTML
=======================CSS =======================END = Customizing the appearence == Exposed CSS classes =======================JS // The editor exposes a set of CSS classes that can be overwritten. var container = document.getElementById("container"); Monaco.Editor.create(container, { value: "My to-do list:\n* buy milk\n* buy coffee\n* write awesome code", mode: "text/plain" }); =======================HTML
=======================CSS /* The editor */ .monaco-editor { font-family: Arial; font-size: 20px; line-height: inherit; background: #EDF9FA; } /* The editor's background */ .monaco-editor-background { background: #EDF9FA; } /* Cursor */ .monaco-editor .cursor { background: darkblue; } /* Current line */ .monaco-editor .current-line { background: rgba(0, 0, 255, 0.1); } /* Line Numbers */ .monaco-editor .line-numbers { background-color: #EDF9FA; color: green; } /* Line Decorations */ .monaco-editor .lines-decorations { background-color: #EDF9FA; } /* Selection */ .monaco-editor .dynamic.focused > .selections-layer > .selected-text { background: rgba(128, 0, 0, 0.2) !important; } .monaco-editor .dynamic > .selections-layer > .selected-text { background: rgba(128, 0, 0, 0.1) !important; } /* Word Highlight */ .monaco-editor .wordHighlight { background-color: rgba(0, 0, 0, 0); -webkit-animation: none; -moz-animation: none; -ms-animation: none; animation: none; } =======================END == Scrollbars =======================JS // Remember to check out the CSS too! var container = document.getElementById("container"); var htmlCode = "\n\n \n \n