monaco-jsx-highlighter

An extensible library to highlight (and comment) JSX syntax in the Monaco Editor
using Babel. It exposes its AST after it does its magic, so you can add your own
syntax-based or custom highlights.

npm i @babel/parser @babel/traverse monaco-jsx-highlighter
yarn add @babel/parser @babel/traverse monaco-jsx-highlighter
TL;DR
import monaco from 'monaco-editor';
import {parse} from "@babel/parser";
import traverse from "@babel/traverse";
import MonacoJSXHighlighter, {makeBabelParse} from 'monaco-jsx-highlighter';
const babelParse = code => parse(code, {
sourceType: "module",
plugins: ["jsx"]
});
const monacoJSXHighlighter = new MonacoJSXHighlighter(
monaco, babelParse, traverse, getMonacoEditor()
);
monacoJSXHighlighter.highlightOnDidChangeModelContent(100);
monacoJSXHighlighter.addJSXCommentCommand();
function getMonacoEditor(){
return monaco.editor.create(
document.getElementById("editor"), {
value: 'const AB=<A x={d}><B>{"hello"}</B></A>;',
language: 'javascript'
});
}
NL;PR
New in v2
- Adds
makeBabelParse
: babel's parse configuration for JSX/TSX (thanks @HaimCandiTech)
- TS codebase migration start.
- Reported defect fixes(dispose).
New in v1
- Babel is now used directly instead of via JsCodeShift.
- React fragment, spread child, spread attribute, and container expression
highlighting.
- highlightOnDidChangeModelContent(debounceTime) method debounces highlight
updates.
- Several defect repairs.
Breaking Changes
If you have used 0.x versions, you'll notice JsCodeShift has been replaced with
Babel:
- import j from 'jscodeshift';
+ import {parse} from "@babel/parser";
+ import traverse from "@babel/traverse";
This only affects the constructor signature:
+ const babelParse = code => parse(code, {sourceType: "module", plugins: ["jsx"]});
const monacoJSXHighlighter = new MonacoJSXHighlighter(
monaco,
- j,
+ babelParse, traverse,
monacoEditor
);
Also, monacoJSXHighlighter.highlightOnDidChangeModelContent
method now has an
optional debounce time as first parameter on its signature:
monacoJSXHighlighter.highlightOnDidChangeModelContent(
- afterHighlight: func,
+ debounceTime: number, afterHighlight: func,
...)
Dependencies
It requires monaco-editor
, @babel/parser
and @babel/traverse
, for
convenience, they are listed as peer dependencies and passed by reference (so
you can do lazy loading). Please install them before monaco-jsx-highlighter
;
Installation
Install the package in your project directory with:
NPM:
npm install @babel/parser
npm install @babel/traverse
npm install monaco-jsx-highlighter
YARN:
yarn add @babel/parser
yarn add @babel/traverse
yarn add monaco-jsx-highlighter
Replacing CSS classes with your own
import {JSXTypes} from 'monaco-jsx-highlighter';
JSXTypes.JSXText.options.inlineClassName = "myCustomCSS";
Overriding CSS classes
Take a look of
the src/JSXColoringProvider.css
file
and override the CSS classes you need. Make sure to import your customization
CSS files after you import monaco-jsx-highlighter
.
Advanced Usage
After your have a Monaco JSX Highlighter instance, monacoJSXHighlighter
:
const defaultOptions = {
parser: 'babel',
isHighlightGlyph: false,
iShowHover: false,
isUseSeparateElementStyles: false,
isThrowJSXParseErrors: false,
};
const monacoJSXHighlighter = new MonacoJSXHighlighter(
monaco, babelParse, traverse, monacoEditor, defaultOptions
);
The highlight activation method, monacoJSXHighlighter.highlightOnDidChangeModelContent(debounceTime: number, afterHighlight: func, ...)
, accepts a callback among other parameters. The callback afterHighlight
passes the AST used to highlight the code. Passing parameters and using the disposer function returned by the call are optional.
Note: The disposer is always called when the editor is disposed.
const highlighterDisposeFunc = monacoJSXHighlighter.
highlightOnDidChangeModelContent(
100,
ast=>{}
);
highlighterDisposeFunc();
let tid = null;
let debounceTime = 100;
monacoEditor.onDidChangeModelContent(() => {
clearTimeout(tid);
tid = setTimeout(() => {
monacoJSXHighlighter.highlightCode();
},
debounceTime,
);
});
monacoJSXHighlighter.highlightCode();
const afterHighlight = (
ast
) => {
monacoJSXHighlighter.JSXDecoratorIds.push(...yourdecoratorsIds);
};
monacoJSXHighlighter.highlightCode(
afterHighlight,
onError,
getAstPromise,
onParseErrors,
);
Additionally, you can add JSX commenting to your monaco editor with
monacoJSXHighlighter.addJSXCommentCommand()
:
comments in JSX children will result in {/*...*/}
instead of //...
. It mimics the commenting behavior of
the WebStorm IDE.
Follow this code to find out other perks:
const commentDisposeFunc = monacoJSXHighlighter.addJSXCommentCommand();
commentDisposeFunc();
Creating Monaco compatible ranges from Babel
import {configureLocToMonacoRange} from 'monaco-jsx-highlighter';
const locToMonacoRange = configureLocToMonacoRange(monaco);
const monacoRange = locToMonacoRange(babelAstNode.loc);