= 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 "language". // The editor takes the full size of its container. monaco.editor.create(document.getElementById("container"), { value: "function hello() {\n\talert('Hello world!');\n}", language: "javascript" }); =======================HTML
=======================END == Editor basic options =======================JS // Through the options literal, the behaviour of the editor can be easily customized. // Here are a few examples of config options that can be passed to the editor. // You can also call editor.updateOptions at any time to change the options. var editor = monaco.editor.create(document.getElementById("container"), { value: "// First line\nfunction hello() {\n\talert('Hello world!');\n}\n// Last line", language: "javascript", lineNumbers: false, roundedSelection: false, scrollBeyondLastLine: false, readOnly: false, theme: "vs-dark", }); setTimeout(function() { editor.updateOptions({ lineNumbers: true }); }, 2000); =======================HTML
=======================END == Hard wrapping =======================JS var jsCode = "// jqeuery excerpt:\n// 1 2 3 4\n//34567890123456789012345678901234567890\n\/*!\r\n * Sizzle CSS Selector Engine v2.3.0\r\n * https:\/\/sizzlejs.com\/\r\n *\r\n * Copyright jQuery Foundation and other contributors\r\n * Released under the MIT license\r\n * http:\/\/jquery.org\/license\r\n *\r\n * Date: 2016-01-04\r\n *\/\r\n(function( window ) {\r\n\r\nvar i,\r\n\tsupport,\r\n\tExpr,\r\n\tgetText,\r\n\tisXML,\r\n\ttokenize,\r\n\tcompile,\r\n\tselect,\r\n\toutermostContext,\r\n\tsortInput,\r\n\thasDuplicate,\r\n\r\n\t\/\/ Local document vars\r\n\tsetDocument,\r\n\tdocument,\r\n\tdocElem,\r\n\tdocumentIsHTML,\r\n\trbuggyQSA,\r\n\trbuggyMatches,\r\n\tmatches,\r\n\tcontains,\r\n\r\n\t\/\/ Instance-specific data\r\n\texpando = \"sizzle\" + 1 * new Date(),\r\n\tpreferredDoc = window.document,\r\n\tdirruns = 0,\r\n\tdone = 0,\r\n\tclassCache = createCache(),\r\n\ttokenCache = createCache(),\r\n\tcompilerCache = createCache(),\r\n\tsortOrder = function( a, b ) {\r\n\t\tif ( a === b ) {\r\n\t\t\thasDuplicate = true;\r\n\t\t}\r\n\t\treturn 0;\r\n\t},\r\n\r\n\t\/\/ Instance methods\r\n\thasOwn = ({}).hasOwnProperty,\r\n\tarr = [],\r\n\tpop = arr.pop,\r\n\tpush_native = arr.push,\r\n\tpush = arr.push,\r\n\tslice = arr.slice,\r\n\t\/\/ Use a stripped-down indexOf as it\'s faster than native\r\n\t\/\/ https:\/\/jsperf.com\/thor-indexof-vs-for\/5\r\n\tindexOf = function( list, elem ) {\r\n\t\tvar i = 0,\r\n\t\t\tlen = list.length;\r\n\t\tfor ( ; i < len; i++ ) {\r\n\t\t\tif ( list[i] === elem ) {\r\n\t\t\t\treturn i;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn -1;\r\n\t},\r\n\r\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\r\n\r\n\t\/\/ Regular expressions\r\n\r\n\t\/\/ http:\/\/www.w3.org\/TR\/css3-selectors\/#whitespace\r\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\r\n\r\n\t\/\/ http:\/\/www.w3.org\/TR\/CSS21\/syndata.html#value-def-identifier\r\n\tidentifier = \"(?:\\\\\\\\.|[\\\\w-]|[^\\0-\\\\xa0])+\",\r\n\r\n\t\/\/ Attribute selectors: http:\/\/www.w3.org\/TR\/selectors\/#attribute-selectors\r\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + whitespace +\r\n\t\t\/\/ Operator (capture 2)\r\n\t\t\"*([*^$|!~]?=)\" + whitespace +\r\n\t\t\/\/ \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\r\n\t\t\"*(?:\'((?:\\\\\\\\.|[^\\\\\\\\\'])*)\'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\r\n\t\t\"*\\\\]\",\r\n\r\n\tpseudos = \":(\" + identifier + \")(?:\\\\((\" +\r\n\t\t\/\/ To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\r\n\t\t\/\/ 1. quoted (capture 3; capture 4 or capture 5)\r\n\t\t\"(\'((?:\\\\\\\\.|[^\\\\\\\\\'])*)\'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\r\n\t\t\/\/ 2. simple (capture 6)\r\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\r\n\t\t\/\/ 3. anything else (capture 2)\r\n\t\t\".*\" +\r\n\t\t\")\\\\)|)\",\r\n\r\n\t\/\/ Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\r\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\r\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\r\n\r\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\r\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\r\n\r\n\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]\'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\r\n\r\n\trpseudo = new RegExp( pseudos ),\r\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\r\n\r\n\tmatchExpr = {\r\n\t\t\"ID\": new RegExp( \"^#(\" + identifier + \")\" ),\r\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + identifier + \")\" ),\r\n\t\t\"TAG\": new RegExp( \"^(\" + identifier + \"|[*])\" ),\r\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\r\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\r\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\r\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\r\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\r\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\r\n\t\t\/\/ For use in libraries implementing .is()\r\n\t\t\/\/ We use this for POS matching in `select`\r\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\r\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\r\n\t},\r\n\r\n\trinputs = \/^(?:input|select|textarea|button)$\/i,\r\n\trheader = \/^h\\d$\/i,\r\n\r\n\trnative = \/^[^{]+\\{\\s*\\[native \\w\/,\r\n\r\n\t\/\/ Easily-parseable\/retrievable ID or TAG or CLASS selectors\r\n\trquickExpr = \/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$\/,\r\n\r\n\trsibling = \/[+~]\/,\r\n\r\n\t\/\/ CSS escapes\r\n\t\/\/ http:\/\/www.w3.org\/TR\/CSS21\/syndata.html#escaped-characters\r\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\r\n\tfunescape = function( _, escaped, escapedWhitespace ) {\r\n\t\tvar high = \"0x\" + escaped - 0x10000;\r\n\t\t\/\/ NaN means non-codepoint\r\n\t\t\/\/ Support: Firefox<24\r\n\t\t\/\/ Workaround erroneous numeric interpretation of +\"0x\"\r\n\t\treturn high !== high || escapedWhitespace ?\r\n\t\t\tescaped :\r\n\t\t\thigh < 0 ?\r\n\t\t\t\t\/\/ BMP codepoint\r\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\r\n\t\t\t\t\/\/ Supplemental Plane codepoint (surrogate pair)\r\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\r\n\t},\r\n\r\n\t\/\/ CSS string\/identifier serialization\r\n\t\/\/ https:\/\/drafts.csswg.org\/cssom\/#common-serializing-idioms\r\n\trcssescape = \/([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\x80-\\uFFFF\\w-]\/g,\r\n\tfcssescape = function( ch, asCodePoint ) {\r\n\t\tif ( asCodePoint ) {\r\n\r\n\t\t\t\/\/ U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\r\n\t\t\tif ( ch === \"\\0\" ) {\r\n\t\t\t\treturn \"\\uFFFD\";\r\n\t\t\t}\r\n\r\n\t\t\t\/\/ Control characters and (dependent upon position) numbers get escaped as code points\r\n\t\t\treturn ch.slice( 0, -1 ) + \"\\\\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + \" \";\r\n\t\t}\r\n\r\n\t\t\/\/ Other potentially-special ASCII characters get backslash-escaped\r\n\t\treturn \"\\\\\" + ch;\r\n\t},\r\n\r\n\t\/\/ Used for iframes\r\n\t\/\/ See setDocument()\r\n\t\/\/ Removing the function wrapper causes a \"Permission Denied\"\r\n\t\/\/ error in IE\r\n\tunloadHandler = function() {\r\n\t\tsetDocument();\r\n\t},\r\n\r\n\tdisabledAncestor = addCombinator(\r\n\t\tfunction( elem ) {\r\n\t\t\treturn elem.disabled === true;\r\n\t\t},\r\n\t\t{ dir: \"parentNode\", next: \"legend\" }\r\n\t);})"; var editor = monaco.editor.create(document.getElementById("container"), { value: jsCode, language: "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, // try "same", "indent" or "none" wrappingIndent: "indent" }); =======================HTML
=======================END == Syntax highlighting for HTML elements =======================JS // 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 to an editor instance =======================JS 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(document.getElementById("container"), { value: jsCode, language: "javascript" }); var myCondition1 = editor.createContextKey(/*key name*/'myCondition1', /*default value*/false); var myCondition2 = editor.createContextKey(/*key name*/'myCondition2', /*default value*/false); editor.addCommand(monaco.KeyCode.Tab, function() { // services available in `ctx` alert('my command is executing!'); }, '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 to an editor instance =======================JS var editor = monaco.editor.create(document.getElementById("container"), { value: [ '', 'class Example {', '\tprivate m:number;', '', '\tpublic met(): string {', '\t\treturn "Hello world!";', '\t}', '}' ].join('\n'), language: "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: [monaco.KeyMod.CtrlCmd | monaco.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 == Revealing a position =======================JS 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 editor = monaco.editor.create(document.getElementById("container"), { value: jsCodeArr.join('\n'), language: "javascript" }); editor.revealPositionInCenter({ lineNumber: 50, column: 120 }); // Also see: // - editor.revealLine // - editor.revealLineInCenter // - editor.revealLineInCenterIfOutsideViewport // - editor.revealLines // - editor.revealLinesInCenter // - editor.revealLinesInCenterIfOutsideViewport // - editor.revealPosition // - editor.revealPositionInCenter // - editor.revealPositionInCenterIfOutsideViewport // - editor.revealRange // - editor.revealRangeInCenter // - editor.revealRangeInCenterIfOutsideViewport =======================HTML
=======================END == Rendering glyphs in the margin =======================JS 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(document.getElementById("container"), { value: jsCode, language: "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 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(document.getElementById("container"), { value: jsCode, language: "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 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(document.getElementById("container"), { value: jsCode, language: "javascript", lineNumbers: lineNumbersFunc }); =======================HTML
=======================CSS =======================END == Listening to mouse events =======================JS 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(document.getElementById("container"), { value: jsCode, language: "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.onMouseMove(function (e) { showEvent('mousemove - ' + e.target.toString()); }); editor.onMouseDown(function (e) { showEvent('mousedown - ' + e.target.toString()); }); editor.onContextMenu(function (e) { showEvent('contextmenu - ' + e.target.toString()); }); editor.onMouseLeave(function (e) { showEvent('mouseleave'); }); =======================HTML
Last 3 events:
=======================CSS .myGlyphMarginClass { background: red; } .myContentClass { background: lightblue; } =======================END == Listening to key events =======================JS var editor = monaco.editor.create(document.getElementById("container"), { value: "function hello() {\n\talert('Hello world!');\n}", language: "javascript" }); var myBinding = editor.addCommand(monaco.KeyCode.F9, function() { alert('F9 pressed!'); }); // 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. monaco.editor.create(document.getElementById("container"), { value: "My to-do list:\n* buy milk\n* buy coffee\n* write awesome code", language: "text/plain", fontFamily: "Arial", fontSize: 20 }); =======================HTML
=======================CSS .monaco-editor, .monaco-editor-background { background: #EDF9FA; } /* Cursor */ .monaco-editor .cursor { background: darkred !important; } /* 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 .view-overlays.focused .selected-text { background: rgba(128, 0, 0, 0.2) !important; } .monaco-editor .view-overlays .selected-text { background: rgba(128, 0, 0, 0.1) !important; } =======================END == Scrollbars =======================JS // Remember to check out the CSS too! var htmlCode = "\n\n \n \n