= 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('