Monaco tree-sitter
Highlight your Monaco Editor with tree-sitter grammar.
Install
Install via NPM:
$ yarn add monaco-tree-sitter
Use
You can use it with Webpack. You'll need monaco-editor-webpack-plugin to load Monaco Editor and file-loader to load WASM.
Notice that the Webpack support of web-tree-sitter is broken, see tree-sitter/tree-sitter#559 for detail and demo
for a workaround.
The minimal Webpack config required is like:
module: {
rules: [
// This is required for web-tree-sitter
{
test: /\.wasm$/,
loader: "file-loader",
type: "javascript/auto" // Disable Webpack's built-in WASM loader
},
// These two are required for monaco-editor-webpack-plugin
// See https://github.com/microsoft/monaco-editor-webpack-plugin
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.ttf$/,
use: ["file-loader"]
}
]
},
plugins: [
new MonacoWebpackPlugin()
],
node: {
fs: "empty" // See https://github.com/tree-sitter/tree-sitter/issues/466
}
After setting-up Webpack, you can starting using it in your project.
First, you need a theme, a theme file is like tomorrow.json
in the themes directory, containing theme for both monaco-editor and our highlighter based on tree-sitter. Load it with:
import { Theme } from "monaco-tree-sitter";
Theme.load(require("monaco-tree-sitter/themes/tomorrow"));
You also need to initialize web-tree-sitter
, the bind library for tree-sitter:
import Parser = require("web-tree-sitter");
import { Theme } from "monaco-tree-sitter";
Theme.load(require("monaco-tree-sitter/themes/tomorrow"));
(async () => {
await Parser.init().then(/* initialized */);
})();
To parse a language with tree-sitter, you need the language's parser. A full list of supported languages by tree-sitter is available here. There're also official prebuilt WASM binaries here can be downloaded.
Tree-sitter could only give us the AST of the code. To highlight we need some grammar rules (one rule is like: an identifier in an call expression is a function name). You can find the grammar rules for various languages in the grammars directory.
import Parser = require("web-tree-sitter");
import { Theme, Language } from "monaco-tree-sitter";
import treeSitterCpp from "./tree-sitter-cpp.wasm"; // Path to the language parser library WASM file
Theme.load(require("monaco-tree-sitter/themes/tomorrow"));
(async () => {
await Parser.init();
// Load the language's grammar rules
const language = new Language(require("monaco-tree-sitter/grammars/cpp"));
// Load the language's parser library's WASM binary
await language.init(treeSitterCpp, Parser);
})();
Since this module provides highlighting both for Monaco Editor and without Monaco Editor. For better Webpack code splitting, we don't import monaco-editor
module and you should provide the module you imported to us.
Create your Monaco Editor and apply the highlight on it:
import Monaco = require("monaco-editor");
import Parser = require("web-tree-sitter");
import { Theme, Language } from "monaco-tree-sitter";
import treeSitterCpp from "./tree-sitter-cpp.wasm"; // Path to the language parser library WASM file
Theme.load(require("monaco-tree-sitter/themes/tomorrow"));
(async () => {
await Parser.init();
// Load the language's grammar rules
const language = new Language(require("monaco-tree-sitter/grammars/cpp"));
// Load the language's parser library's WASM binary
await language.init(treeSitterCpp, Parser);
window.editor = Monaco.editor.create(document.body, {
value: "int main() { return 0; }",
// This "language" property only affects the monaco-editor's built-in syntax highlighter
language: "cpp"
});
const monacoTreeSitter = new MonacoTreeSitter(Monaco, editor, language);
// You can change the language with monacoTreeSitter.changeLanguage()
// Or change the theme with Theme.load()
// Remember to refresh highlight with monacoTreeSitter.refresh() after changing the theme.
})();
Highlight
You can also use this module just as a code highlighter. In this case you don't need a Monaco Editor.
First, load a theme and initialize your language as above. Then just call the highlight()
function:
import Parser = require("web-tree-sitter");
import { Theme, Language } from "monaco-tree-sitter";
import treeSitterCpp from "./tree-sitter-cpp.wasm"; // Path to the language parser library WASM file
Theme.load(require("monaco-tree-sitter/themes/tomorrow"));
(async () => {
await Parser.init();
// Load the language's grammar rules
const language = new Language(require("monaco-tree-sitter/grammars/cpp"));
// Load the language's parser library's WASM binary
await language.init(treeSitterCpp, Parser);
document.body.innerHTML = highlight(cppCode, language);
// You can use highlight(code, language, true) to generate self-contained HTML code.
// i.e. Use inline style instead of class name.
})();
Demo
You can find a demo in the demo directory. Just yarn build
and python3 -m http.server
then open it in your browser.
License
This project is licensed under the MIT license.
Credits
This project used code and assets from: