Uncover the History and Core Features of Monaco Editor, the Web‑Based Code Editor Behind VS Code
Monaco Editor, the browser‑based code editor powering VS Code, originated in 2011 under Erich Gamma’s team, offers a lightweight editor control with rich UI widgets, and Monarch‑based syntax highlighting, and LSP‑compatible APIs, making it ideal for embedding advanced editing features into any web application.
Monaco Editor is a browser‑based code editor library also used by VS Code. It provides a lightweight editor control with language‑specific APIs and can be embedded in any web project, while VS Code adds file management, version control, and extensions as a desktop application.
History
Although many assume Monaco was extracted from VS Code, its development actually predates VS Code. Created by Erich Gamma’s team in 2011, Monaco was first used internally at Microsoft and appeared in products such as SkyDrive, Azure, and TypeScript, later powering Visual Studio Online and eventually GitHub Codespaces.
Core Components
The editor shares most UI widgets with VS Code, including line numbers, overlay widgets, view lines, decorations, content widgets, and view zones.
Line numbers
Overlay Widget – renders arbitrary UI widgets positioned at top, bottom, or inside the editor (e.g., the find box).
ViewLine – each line displayed.
Decorations – style specific ranges (background, foreground, etc.).
Content Widget – similar to overlay but positioned by line/column (e.g., autocomplete list).
View Zone – inserts expandable space between lines.
Additional decorations can be added via the Decorations API, such as version‑control markers or breakpoint indicators.
Language Support
Monaco itself only provides a text editor; language syntax highlighting is supplied through the Monarch tokenizer. Monarch defines keywords, types, operators, and tokenizers using regular expressions, which are then mapped to theme colors.
<code>// Create your own language definition here
// You can safely look at other samples without losing modifications.
// Modifications are not saved on browser refresh/close -- copy often!
return {
// Set defaultToken to invalid to see what you do not tokenize yet
// defaultToken: 'invalid',
keywords: [
'abstract', 'continue', 'for', 'new', 'switch', 'assert', 'goto', 'do',
'if', 'private', 'this', 'break', 'protected', 'throw', 'else', 'public',
'enum', 'return', 'catch', 'try', 'interface', 'static', 'class2',
'finally', 'const', 'super', 'while', 'true', 'false'
],
typeKeywords: [
'boolean', 'double', 'byte', 'int', 'short', 'char', 'void', 'long', 'float'
],
operators: [
'=', '>', '<', '!', '~', '?', ':', '==', '<=', '>=', '!=',
'&&', '||', '++', '--', '+', '-', '*', '/', '&', '|', '^', '%',
'<<', '>>', '>>>', '+=', '-=', '*=', '/=', '&=', '|=', '^=',
'%=', '<<=', '>>=', '>>>='
],
// we include these common regular expressions
symbols: /[=&<>!~?:&|+\-*\/\^%]+/,
// C# style strings
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
// The main tokenizer for our languages
tokenizer: {
root: [
// identifiers and keywords
[/[a-z_$][\w$]*/, { cases: { '@typeKeywords': 'keyword', '@keywords': 'keyword', '@default': 'identifier' } }],
[/[A-Z][\w\$]*/, 'type.identifier'], // to show class names nicely
// whitespace
{ include: '@whitespace' },
// delimiters and operators
[/[{}()\[\]]/, '@brackets'],
[/[<>](?!@symbols)/, '@brackets'],
[/@symbols/, { cases: { '@operators': 'operator', '@default': '' } }],
// @ annotations.
// As an example, we emit a debugging log message on these tokens.
// Note: message are supressed during the first load -- change some lines to see them.
[/@\s*[a-zA-Z_\$][\w\$]*/, { token: 'annotation', log: 'annotation token: $0' }],
// numbers
[/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'],
[/0[xX][0-9a-fA-F]+/, 'number.hex'],
[/\d+/, 'number'],
// delimiter: after number because of .\d floats
[/[;,.]/, 'delimiter'],
// strings
["([^\"\\]|\\.)*$", 'string.invalid'], // non-terminated string
["\"", { token: 'string.quote', bracket: '@open', next: '@string' }],
// characters
[/'[^\\']'/, 'string'],
[/(')(@escapes)(')/, ['string','string.escape','string']],
[/'/, 'string.invalid']
],
comment: [
[/[^\/*]+/, 'comment' ],
[/\/\*/, 'comment', '@push' ], // nested comment
["\\*/", 'comment', '@pop' ],
[/[/\*]/, 'comment' ]
],
string: [
[/[^\\"]+/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/\"/, { token: 'string.quote', bracket: '@close', next: '@pop' } ]
],
whitespace: [
[/[[ \t\r\n]+/, 'white'],
[/\/\*/, 'comment', '@comment' ],
[/\/\/.*$/, 'comment']
],
},
};
</code>Monaco also supports the Language Server Protocol (LSP) for advanced features like autocomplete, hover, find references, and go‑to definition, and includes built‑in language services for TypeScript/JavaScript, CSS, and HTML.
Taobao Frontend Technology
The frontend landscape is constantly evolving, with rapid innovations across familiar languages. Like us, your understanding of the frontend is continually refreshed. Join us on Taobao, a vibrant, all‑encompassing platform, to uncover limitless potential.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.