Open Raathigesh opened 7 years ago
Looks like Monaco doesn't support JSX right now.
I'm a little bit confusing cause Monaco support Typescript and Javascript Syntax,and they both came from monaco-typescript;But if now I want to implement JSX Support based on Monaco API, seems like I have to write those tokenize provider and auto complete things again(include Javascript support) ? Looks like a bit duplicate works.
I don't know if I get wrong with something... Maybe It would be better that monaco-typescript support JSX?
Spent some time trying to get this working and it seems like monaco-typescript doesn't expose a few options that might enable JSX support. Don't have enough experience with the codebase to create a pull request, but I'll document what I found incase it helps someone else - or if @alexandrudima or someone else who regularly works on monaco could give some help, I could give this a shot later in the week.
Looking through monaco-typescript, it seems like https://github.com/Microsoft/monaco-typescript/blob/master/src/monaco.contribution.ts has a ScriptKind enum defined for JSX and TSX support, but it doesn't look like diagnostic or compiler options takes ScriptKind as a parameter.
According to https://github.com/Microsoft/monaco-typescript/blob/master/lib/typescriptServices.d.ts , there seems to be a ScriptKind and a LanguageVariant which could be set to support JSX files. LanguageVariant is used by a Scanner class which doesn't seem to be exposed via monaco-typescript.
Using the existing API, I could at least disable the warnings that the diagnostics were displaying on JSX, but couldn't get syntax highlighting support (and this isn't a great solution):
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
noSemanticValidation: true,
noSyntaxValidation: true, // This line disables errors in jsx tags like <div>, etc.
});
// I don't think the following makes any difference
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
// jsx: 'react',
jsx: monaco.languages.typescript.JsxEmit.React,
jsxFactory: 'React.createElement',
reactNamespace: 'React',
allowNonTsExtensions: true,
allowJs: true,
target: monaco.languages.typescript.ScriptTarget.Latest,
});
Similarly, setting for monaco.languages.typescript.javascriptDefaults didn't get very far either.
The other (admittedly bad) option would be to update a monarch syntax definition to add JSX support, then use that instead of using monaco-typescript: https://microsoft.github.io/monaco-editor/monarch.html (essentially start with javascript or typescript and add jsx support).
I didn't even bother pursuing that since I think it would be far better to get proper react support from monaco-typescript.
I think this would be a great feature to have to support editing react components in a browser. It would be great to get some support on getting it implemented - or if its already being worked on, some timeframe on implementation / testing / release (I'm not sure when monaco-editor is updated with respect to vs-code).
@Flux159 Any Idea how VSCode does it?
This seems to suggest with extensions we can do it, but I can't find how to add extensions in Monaco.
Basarat got JSX/TSX working with Alm.tools. Looking into it might help. https://twitter.com/Raathigesh/status/798145470803701760
Had some time to look a bit more into this... unfortunately it seems like this would require some significant changes to monaco-typescript's tokenization.ts which would be better done by a maintainer of monaco-typescript.
@abhishiv VSCode probably uses a typescript compiler API that monaco editor doesn't expose (look at the createScanner function in the typescript compiler - one of the arguments is languageVariant which is usually passed via a ts.sourceFile object). In monaco-typescript's tokenization.ts, the classifier internally calls createScanner but doesn't expose anything around the a sourceFile object (I don't think that monaco-typescript has a concept of a sourceFile since its based in a browser).
For more info, have a look at createClassifier and createScanner in (warning: large text file) https://raw.githubusercontent.com/Microsoft/monaco-typescript/master/lib/typescriptServices.js which I believe is a single js file that contains the entire typescript compiler.
Monaco doesn't support extensions as far as I know since its a subset of the code in vscode that removes things like local file handling, electron support, and extension support.
@Raathigesh Basarat ended up forking monaco-typescript to get JSX support in ALM but didn't make a pull request into monaco-typescript: https://github.com/alm-tools/alm/blob/c77c89c5efb3b6ef6f978df2b9f5b76540cb25e0/src/app/monaco/languages/typescript/tokenization.ts
Looking through @basarat code, I don't think he's setting anything related to sourceFile.languageVariant anywhere and is manually parsing the JSX tokens.
I think i have this working. It was simply a matter of ensuring there's a .tsx
in the URI to the createModel function
. The same I assume would apply to JSX.
model: monaco.editor.createModel(myCode, "typescript", monaco.Uri.parse("file:///main.tsx"));
Hey @joewood
Awesome, thanks! Seems to working! But now I'm getting this
Did you encounter it as well?
Remember to set Jsx to react
in the compiler options. And I did not set these two options (I left them as the default):
jsxFactory: 'React.createElement',
reactNamespace: 'React',
Also, I had to wrap the react declaration file with an ambient module definition. e.g.:
declare module "react" {
<react.d.ts goes here>
}
At least until somebody answers this: http://stackoverflow.com/questions/43058191/how-to-use-addextralib-in-monaco-with-an-external-type-definition
One thing that I haven't tried is to set-up file URIs like a typescript project. That may solve the ambient/external module import issue.
I worked out the solution to the external declaration file issue. The File URI solves that problem too. Here's an example that works in the playground. This should work equally well with the react.d.ts
file, and therefore enable full JSX/TSX:
// compiler options
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES2016,
allowNonTsExtensions: true,
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
module: monaco.languages.typescript.ModuleKind.CommonJS,
noEmit: true,
typeRoots: ["node_modules/@types"]
});
// extra libraries
monaco.languages.typescript.typescriptDefaults.addExtraLib(
`export declare function next() : string`,
'node_modules/@types/external/index.d.ts');
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
noSemanticValidation: false,
noSyntaxValidation: false
})
var jsCode = `import * as x from "external"
const tt : string = x.dnext();`;
monaco.editor.create(document.getElementById("container"), {
model: monaco.editor.createModel(jsCode,"typescript",new monaco.Uri("file:///main.tsx")),
});
is there any progress?
@jasonHzq - did you not manage to get it working?
@joewood if i want to set the value of a new component in jsx syntax,how can i make it work? this is my screenshoot:
Hi @dandingol03. Those squiggles look like it's parsing that file as JavaScript and not JSX. Did you set the filename URL as per my comment above, when you create the model?
@joewood my operate system is mac,so i use monaco.Uri.file instead.here is my code:
editor=monaco.editor.create(containerElement, {
model: monaco.editor.createModel(jsCode,"javascript",new monaco.Uri.file("./Containre.jsx")),
});
it works well,thanks.By the way,do you have any idea about navigating between modules when i click the module name.For example,there is a statement like import React from 'react'
,and when i click the react,it will navigate to the {workspace}/node_modules/react/react.js
Are there any official docs or references on how to implement this?
In the meanwhile...
For syntax recognition:
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
jsx: "react"
});
function isApplePlatform() {
return (window && window.navigator && window.navigator.platform) ?
window.navigator.platform.match(/(Mac|iPhone|iPod|iPad)/i) ? true : false
: true;
}
monaco.editor.create(DOMElement, {
model: monaco.editor.createModel(text, "javascript",
isApplePlatform() ?
new monaco.Uri.file('./editor_name.jsx')
: new monaco.Uri('./editor_name.jsx')
);
});
For syntax highlighting: https://github.com/alm-tools/alm/issues/421
I've worked out the solution by using prismjs as a tokenlizer to support jsx syntax highlight, see the live demo at: http://demo.rekit.org/element/src%2Ffeatures%2Fhome%2FElementPage.js/code
And here is the web worker to do tokenlize: http://demo.rekit.org/element/src%2Ffeatures%2Fcommon%2Fmonaco%2Fworkers%2FsyntaxHighlighter.js/code
@supnate that second link that you posted is a 404. Do you have another link to the source code? (Also, is that project open source / on GitHub?)
Satya wrote a blog that shows how they got JSX syntax highlighting working for snack. https://blog.expo.io/building-a-code-editor-with-monaco-f84b3a06deaf
Besides syntax highlighting I was able to make it work perfectly, 100% type checked thanks to comments in this issue and make a HOWTO document here: https://github.com/cancerberoSgx/jsx-alone/blob/master/jsx-explorer/HOWTO_JSX_MONACO.md
Thanks!
@supnate would you explain how did you use prism js tokenizer in monaco editor? Sample code would be really appreciated.
@smupyknight I believe @supnate meant to share this link, which looks like the actual highlighter. here is where it is loaded and here is the editor config to support JSX.
@supnate 's great solution also works for tsx:
const tokens = Prism.tokenize(data.code, Prism.languages.tsx);
// See PR https://github.com/PrismJS/prism/pull/1357/files
Prism.hooks.run('after-tokenize', {
code: data.code,
grammar: Prism.languages.tsx,
language: 'tsx',
tokens,
});
deltaDecorations
using the workers response.//prismjs
start/endAfter more fiddling, @cancerberoSgx 's approach seems best.
Unfortunately Prismjs handles generic types incorrectly, and confuses comments with JsxText
.
Rather than concatenating CSS classes, we can decorate intervals with a unique class e.g. jsx-text
, jsx-tag
, jsx-attr
and jsx-brace
. These intervals can be found using ts-morph
(formerly ts-simple-ast
).
I have a custom JSX highlighting in my project, so I take Monaco's highlighting:
And customize it like this:
This issue comes and goes often, so I decided to share it as a npm package that you can use like this:
//this should be already in your code
import monaco from 'monaco-editor';
// here we go...
import j from 'jscodeshift';
import MonacoJSXHighlighter from 'monaco-jsx-highlighter';
const elem = document.getElementById("editor");
const monacoEditor = monaco.editor.create(elem, {
value: 'const AB=<A x={d}><B>{"hello"}</B></A>;',
language: 'javascript'
});
const monacoJSXHighlighter = new MonacoJSXHighlighter(monaco, j, monacoEditor);
// for the first time
monacoJSXHighlighter.colorizeCode(monacoEditor.getValue());
// triggering the highlighter after each code change
monacoEditor.onDidChangeModelContent(() => {
monacoJSXHighlighter.colorizeCode(monacoEditor.getValue());
});
Hope it helps =)
@luminaxster Nice, I'll look into jscodeshift
. However your highlighting is a bit off:
const foo = (
<div>
// foo
</div>
)
The // foo
should be literal text (not a comment). The markdown highlighting above is also wrong.
@rob-myers, thanks for the feedback. I added support for that case:
Interestingly, Monaco itself was coloring the text as a comment, not my package, I was ignoring JsxText expressions and letting Monaco handle them. I didn't know Rouge, GitHub's syntax highlighter, is making the same mistake, nice catch! I checked WebStorm and CodeSandBox, they do not have this issue.
@luminaxster there is another issue:
<div>
// foo {'bar'}
</div>
where {'bar'}
is incorrectly highlighted by Monaco's js highlighter.
Although it seems like an edge case, it comes up frequently when toggling comments.
Rather than fix this issue by adding decorations, I intend to override editor.action.commentLine
.
@rob-myers I ran it through eslint: "Comments inside children section of tag should be placed inside braces (react/jsx-no-comment-textnodes)", so that is why the parser is confused. So issues in total: 1) Fix comment highlighting within React children, I know the guys at CodeSandBox fixed it, but I have to look at their Monaco config; and 2) Enable JSX commenting, if I understood correctly, what you want is enable commenting like {/* .... */}
when is JSX context, I'll add that feature to monaco-jsx-highlighter
during the week. If you are trying to do it yourself, this is a start:
const myBinding = editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.US_SLASH, () =>{
const selection = editor.getSelection();
const model = editor.getModel();
const range = new monaco.Range(selection.startLineNumber, 0, selection.endLineNumber, model.getLineMaxColumn(selection.endLineNumber));
const id = { major: 1, minor: 1 };
console.log();
const text = model.getValueInRange(range);
// here I will check wether the current selection is not is JSX context
if(true){
editor.getAction("editor.action.commentLine").run();
return;
}
// here then I will do JSX commenting
if(!text || !text.match(/{\/\*/)){
text = '{/*'+ text+'*/}';
}else{
text =text.replace(/{\/\*/, '');
text =text.replace(/\*\/}/, '');
}
const op = { identifier: id, range: range, text: text, forceMoveMarkers: true };
editor.executeEdits("custom-edit", [op]);
});
I added the JSX commenting. It is supported by monaco-jsx-highlighter@ ^0.0.14. Feedback is more than welcome =).
@luminaxster your comment-toggling code was really helpful.
I detect JSX comment contexts as follows:
import { Project, ts, JsxText } from 'ts-morph';
const project = new Project({ compilerOptions: { jsx: ts.JsxEmit.React } });
const srcFile = project.createSourceFile('main.tsx', code);
const node = srcFile.getDescendantAtPos(startLineStartPos)!;
const isJsxCommentCtxt = [node].concat(node.getAncestors()).some(node =>
node instanceof JsxText && node.containsRange(startLineStartPos, startLineStartPos));
I finally have a demo online: https://rob-myers.github.io/dev.
@luminaxster your comment-toggling code was really helpful.
I detect JSX comment contexts as follows:
import { Project, ts, JsxText } from 'ts-morph'; const project = new Project({ compilerOptions: { jsx: ts.JsxEmit.React } }); const srcFile = project.createSourceFile('main.tsx', code); const node = srcFile.getDescendantAtPos(startLineStartPos)!; const isJsxCommentCtxt = [node].concat(node.getAncestors()).some(node => node instanceof JsxText && node.containsRange(startLineStartPos, startLineStartPos));
I finally have a demo online: https://rob-myers.github.io/dev.
Wow, impressive, can we take a look at the code how to implement them ?
@rizkyramadhan, if the rest of the implementation of the JSX comment command is what you are asking, based on Rob's:
import { Project, ts, JsxText } from 'ts-morph';
const project = new Project({ compilerOptions: { jsx: ts.JsxEmit.React } });
const srcFile = project.createSourceFile('main.tsx', code);
const node = srcFile.getDescendantAtPos(startLineStartPos)!;
const isJsxCommentCtxt = [node].concat(node.getAncestors()).some(node =>
node instanceof JsxText && node.containsRange(startLineStartPos, startLineStartPos));
This is my follow-up:
let isUnCommentAction = true;
const commentsData = [];
for (let i = selection.startLineNumber;
i <= selection.endLineNumber;
i++) {
const commentRange = new monaco.Range(
i,
model.getLineFirstNonWhitespaceColumn(i),
i,
model.getLineMaxColumn(i),
);
const commentText = model.getValueInRange(commentRange);
commentsData.push({
commentRange,
commentText
});
isUnCommentAction = isUnCommentAction &&
!!commentText.match(/{\/\*/);
}
if (!isJsxCommentCtxt
&& !isUnCommentAction) {
editor.getAction(this.commentActionId).run();
return;
}
let editOperations = [];
let commentsDataIndex = 0;
for (let i = selection.startLineNumber;
i <= selection.endLineNumber;
i++) {
let {
commentText,
commentRange,
} = commentsData[commentsDataIndex++];
if (isUnCommentAction) {
commentText = commentText.replace(/{\/\*/, '');
commentText = commentText.replace(/\*\/}/, '');
} else {
commentText = `{/*${commentText}*/}`;
}
editOperations.push({
identifier: {major: 1, minor: 1},
range: commentRange,
text: commentText,
forceMoveMarkers: true,
});
}
editOperations.length &&
editor.executeEdits(this.commandActionId, editOperations);
Note: Since Monaco does not expose the ASTs, due to them being in web workers (some API is being discussed to expose them), to get an editor content's AST, Rob uses ts-morph and I use jscodeshift.
@rizkyramadhan, if the rest of the implementation of the JSX comment command is what you are asking, based on Rob's:
import { Project, ts, JsxText } from 'ts-morph'; const project = new Project({ compilerOptions: { jsx: ts.JsxEmit.React } }); const srcFile = project.createSourceFile('main.tsx', code); const node = srcFile.getDescendantAtPos(startLineStartPos)!; const isJsxCommentCtxt = [node].concat(node.getAncestors()).some(node => node instanceof JsxText && node.containsRange(startLineStartPos, startLineStartPos));
This is my follow-up:
let isUnCommentAction = true; const commentsData = []; for (let i = selection.startLineNumber; i <= selection.endLineNumber; i++) { const commentRange = new monaco.Range( i, model.getLineFirstNonWhitespaceColumn(i), i, model.getLineMaxColumn(i), ); const commentText = model.getValueInRange(commentRange); commentsData.push({ commentRange, commentText }); isUnCommentAction = isUnCommentAction && !!commentText.match(/{\/\*/); } if (!isJsxCommentCtxt && !isUnCommentAction) { editor.getAction(this.commentActionId).run(); return; } let editOperations = []; let commentsDataIndex = 0; for (let i = selection.startLineNumber; i <= selection.endLineNumber; i++) { let { commentText, commentRange, } = commentsData[commentsDataIndex++]; if (isUnCommentAction) { commentText = commentText.replace(/{\/\*/, ''); commentText = commentText.replace(/\*\/}/, ''); } else { commentText = `{/*${commentText}*/}`; } editOperations.push({ identifier: {major: 1, minor: 1}, range: commentRange, text: commentText, forceMoveMarkers: true, }); } editOperations.length && editor.executeEdits(this.commandActionId, editOperations);
Note: Since Monaco does not expose the ASTs, due to them being in web workers (some API is being discussed to expose them), to get an editor content's AST, Rob uses ts-morph and I use jscodeshift.
Nice, thanks. Maybe I'll try using babel, since babel-standalone is only 1mb when compiled using browserify. Compared to ts-morph 4.5mb and jscodeshift 3.6mb.
For new comers who want to add JSX. Monaco already support JSX out of the box (minus commenting bug above) , and for TSX you need right configuration (but no external dependencies).
My setup code:
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.Latest,
allowNonTsExtensions: true,
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
module: monaco.languages.typescript.ModuleKind.CommonJS,
noEmit: true,
esModuleInterop: true,
jsx: monaco.languages.typescript.JsxEmit.React,
reactNamespace: "React",
allowJs: true,
typeRoots: ["node_modules/@types"],
});
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
noSemanticValidation: false,
noSyntaxValidation: false,
});
monaco.languages.typescript.typescriptDefaults.addExtraLib(
'<<react-definition-file>>',
`file:///node_modules/@react/types/index.d.ts`
);
The last line is important, <<react-definition-file>>
not a file path, it is a string.
Replace <<react-definition-file>>
with content from https://cdn.jsdelivr.net/npm/@types/react@16.9.41/index.d.ts, you can fetch them first and then put the content string to replace <<react-definition-file>>
.
@rizkyramadhan just to clarify, what do you mean by "Monaco already support JSX out of the box(minus commenting bug above)", do you mean syntax recognition, syntax highlighting, or commenting? My understanding is that syntax is recognized with the code you shared, however, syntax highlighting is not (thus, several approaches have been made available), and commenting is more like a feature rather than a defect.
@rizkyramadhan
can we take a look at the code how to implement them ?
My implementation of JSX commenting is a hack. With proper code indentation, we probably only need to check if the 1st character is JsxText. The hackiness comes from the other cases. It isn't even correct e.g. try commenting <Item ... />
in demo.
I also patch monaco's js syntax highlighting with jsx syntax highlighting, in combination with this css.
Maybe I'll try using babel, since babel-standalone is only 1mb when compiled using browserify. Compared to ts-morph 4.5mb and jscodeshift 3.6mb.
Fair point. My 'syntax' webworker contains both babel standalone and ts-morph and is 1.4Mb gzipped. I'm using babel because I'm trying to integrate react-refresh
i.e. replacement for react-hot-loader
.
@rizkyramadhan just to clarify, what do you mean by "Monaco already support JSX out of the box(minus commenting bug above)", do you mean syntax recognition, syntax highlighting, or commenting? My understanding is that syntax is recognized with the code you shared, however, syntax highlighting is not (thus, several approaches have been made available), and commenting is more like a feature rather than a defect.
Yes, although the only thing that highlighted are <Component />
and { expression }
- It works. It depends on what expectation of "Syntax Highlighting", but for me it's enough.
For new comers who want to add JSX. Monaco already support JSX out of the box (minus commenting bug above) , and for TSX you need right configuration (but no external dependencies).
My setup code:
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({ target: monaco.languages.typescript.ScriptTarget.Latest, allowNonTsExtensions: true, moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs, module: monaco.languages.typescript.ModuleKind.CommonJS, noEmit: true, esModuleInterop: true, jsx: monaco.languages.typescript.JsxEmit.React, reactNamespace: "React", allowJs: true, typeRoots: ["node_modules/@types"], }); monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({ noSemanticValidation: false, noSyntaxValidation: false, }); monaco.languages.typescript.typescriptDefaults.addExtraLib( '<<react-definition-file>>', `file:///node_modules/@react/types/index.d.ts` );
The last line is important,
<<react-definition-file>>
not a file path, it is a string.Replace
<<react-definition-file>>
with content from https://cdn.jsdelivr.net/npm/@types/react@16.9.41/index.d.ts, you can fetch them first and then put the content string to replace<<react-definition-file>>
.
I can't get this working, but I'm not sure what I'm doing wrong. I copied your code example. I'm using webpack to replace <
I get this error: "Error in event handler: ReferenceError: Component is not defined" from this code ${Component.displayName||Component.name} that's in the index.d.ts file.
I don't have any file at file:///node_modules/@react/types/index.d.ts
this location, but don't know if that matters. There is no @react package that I can tell, so I'm not sure where that would be from.
Update: Just manually created the file path with that file in it, but that didn't seem to do anything.
Any help on how to get this working?
Update: Got it working by including Component from React in the file in which I was creating the editor.
So strange that the JSX support is partial, given how close it is to full support. From what I can tell, only the child content of a JSX block is mistakenly styled with standard language keys (e.g. the "for" here is the same as in a for
loop). The rest of the highlighting works as expected.
Monaco-editor can use monaco-textmate to highlight jsx
import cssGrammar from 'raw-loader!./grammars/css.json.tmLanguage'
import htmlGrammar from 'raw-loader!./grammars/html.json.tmLanguage'
import tsGrammar from 'raw-loader!./grammars/TypeScriptReact.tmLanguage'
import { loadWASM } from 'onigasm'
import { Registry } from 'monaco-textmate'
import { wireTmGrammars } from './set-gammars'
let grammarsLoaded = false
export async function liftOff(monaco) {
if (grammarsLoaded) {
return
}
grammarsLoaded = true
await loadWASM(`/onigasm.wasm`) // See https://www.npmjs.com/package/onigasm#light-it-up
const registry = new Registry({
getGrammarDefinition: async (scopeName) => {
if (scopeName === 'source.css') {
return {
format: 'json',
content: cssGrammar,
}
}
if (scopeName === 'text.html.basic') {
return {
format: 'json',
content: htmlGrammar,
}
}
return {
format: 'plist',
content: tsGrammar,
}
}
})
const grammars = new Map()
grammars.set('css', 'source.css')
grammars.set('html', 'text.html.basic')
grammars.set('vue', 'text.html.basic')
grammars.set('typescript', 'source.tsx')
grammars.set('javascript', 'source.js')
await wireTmGrammars(monaco, registry, grammars)
}```
Use this package https://www.npmjs.com/package/monaco-jsx-syntax-highlight
This missing JSX lang support issue has been ongoing for 7 years
I would like to hear from @microsoft proper to address why this hasn't/can't be done.
It seems everyone wants this, and now more than ever with WebXR VR coding exploding with all the pushes for headsets. Why is this such an issue?
FYI, my solution was @shikijs/monaco
https://shiki.style/packages/monaco
It supports languages other than JSX as well.
FYI, my solution was
@shikijs/monaco
https://shiki.style/packages/monaco
It supports languages other than JSX as well.
Love open source for this exact reason thank you!
That guys just made my day
How did you use Shiki in monaco-react
? @kagankan
Maybe I'm missing something, but why is everyone in this thread trying to implement this either by hacking textmate parsers into this, or by hacking the ast in the web workers? I definitely implemented this a few years ago using nothing but the vanilla Monaco tokenizer (https://github.com/microsoft/monaco-editor/issues/1609), although I don't know where the code for that is, so I'll have to do it again this week. Is there a reason to need to go beyond this method?
@sdegutis Could you share the code if you figure it out?
I think the issue is none of us have figured it out.
Does monaco support Jsx? I couldn't find any reference or samples. Any pointers would be appreciated.