-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sometimes the syntax does not get highlighted correctly. #17
Comments
can I see a larger code snippet? |
Hey, I should have included more context. I've abstracted a lot into a separate class "MonacoTextmateManager" for my project; I'll share it here. The basic structure is: At the bottom of the MonacoTextmateManager.spawnEditor method is this line which solves the problem I'm referencing: setTimeout(this.wire.bind(this), 1) Here is the source
<template>
<div id="MonacoEditor"></div>
</template>
<script>
import MonacoTextmateManager from '@/src/monaco/MonacoTextmateManager'
import oneDarkTextmateTheme from '@/src/monaco/one-dark-textmate-theme'
const ENABLED = false
export default {
async mounted(){
const monacoManager = new MonacoTextmateManager({
languages: this.$config.languages,
initialLanguage: 'javascript',
pathToOnigWasm: '/monaco/onigasm.wasm'
})
// Spawn the editor
if(ENABLED){
await monacoManager.spawnEditor({
element: document.getElementById('MonacoEditor'),
theme: oneDarkTextmateTheme
})
}
}
}
</script>
import * as monaco from 'monaco-editor'
import { loadWASM } from 'onigasm' // peer dependency of 'monaco-textmate'
import { Registry } from 'monaco-textmate' // peer dependency
import { wireTmGrammars } from 'monaco-editor-textmate'
import ResourceCache from './ResourceCache'
export default class MonacoTextmateManager {
constructor({
languages = [],
initialLanguage = 'javascript',
pathToOnigWasm = '/monaco/onigasm.wasm',
diffEditor = false
}){
this.languages = languages
this.pathToOnigWasm = pathToOnigWasm
this.diffEditor = diffEditor
this.editor = null
this.registry = null
this.element = null
this.language = this.languages.find(lang => lang.id == initialLanguage)
this.cache = new ResourceCache({
getters: {
grammarFile: async grammarFileLocation => {
return (await fetch(grammarFileLocation)).text()
},
codeSample: async codeSampleLocation => {
return (await fetch(codeSampleLocation)).text()
}
}
})
}
// Set theme data for the editor
setTheme(themeData){
// Monaco's built-in themes aren't powereful enough to handle TM tokens
// https://github.com/Nishkalkashyap/monaco-vscode-textmate-theme-converter#monaco-vscode-textmate-theme-converter
// Important, so that plaintext appears the correct color
if(this.diffEditor){
const baseTextColor = themeData.rules.find(rule => rule.token == 'source').foreground
themeData = {
...themeData,
rules: [
...themeData.rules,
{ token: '', foreground: baseTextColor }
]
}
}
// Set the theme
monaco.editor.defineTheme('vscode-theme-editor', themeData)
}
// Set the language of the editor
async setLanguage(languageId){
// Set this.language to new language object
this.language = this.languages.find(lang => lang.id == languageId)
// Inject the code sample for this language into the editor
this.editor.setValue(
await this.getCurrentCodeSample()
)
// Fully-respawn the editor
return this.spawnEditor({ element: this.element })
}
// Spawn the editor instance
async spawnEditor({ element, theme }){
// Kill old editor if exists
if(this.editor){ this.editor.dispose() }
// Remember element
this.element = element
// Needed for monaco
this.setWebWorkerPaths()
// Define the theme
if(theme) this.setTheme(theme)
// Load WASM file for running onig regex in browser
await this.loadWASMOnce()
// Build the registry
this.registry = new Registry({
getGrammarDefinition: (async (scopeName) => {
const grammarDefinition = await this.getCurrentGrammar()
return {
format: 'json',
content: grammarDefinition
}
}).bind(this)
})
// Build the editor instance
this.editor = monaco.editor[this.diffEditor? 'createDiffEditor' : 'create'](element, {
value: await this.getCurrentCodeSample(),
language: this.language.id,
theme: 'vscode-theme-editor',
automaticLayout: true,
fontLigatures: true,
links: true,
minimap: {
enabled: true
},
rulers: [60]
})
// Set models for diff editor preview
if(this.diffEditor){
this.editor.setModel({
original: monaco.editor.createModel("This is what your diff editor will look like.\nYou should adjust these colors to fit nicely with your theme\nAnother line of text\nAnd another...", "text/plain"),
modified: monaco.editor.createModel("just some text\n\nHello World\n\nSome more text", "text/plain")
})
}
// Apply wireTMGrammars to the various objects
// For some reason, we have to push this operation into the event stack for it to always work properly
setTimeout(this.wire.bind(this), 1)
}
async wire(){
return wireTmGrammars(monaco, this.registry, this.grammars, this.editor)
}
// Return a map of monaco "language id's" to TextMate scopeNames
get grammars(){
const grammars = new Map()
this.languages.forEach(lang => grammars.set(lang.id, lang.scope))
return grammars
}
// Returns the grammar file for the current language
async getCurrentGrammar(){
return this.cache.get('grammarFile', this.language.grammarFile)
}
// Returns the code sample for the current language
async getCurrentCodeSample(){
return this.cache.get('codeSample', this.language.codeSampleFile)
}
// Fetch and load the onig regex WASM file
async loadWASMOnce(){
if(window._ONIG_WASM_LOADED){ return }
await loadWASM(this.pathToOnigWasm)
window._ONIG_WASM_LOADED = true
}
setWebWorkerPaths(){
// Since packaging is done by you, you need
// to instruct the editor how you named the
// bundles that contain the web workers.
window.MonacoEnvironment = {
getWorkerUrl: function (moduleId, label) {
if (label === 'json') {
return '/monaco/workers/json.worker.js';
}
if (label === 'css' || label === 'scss' || label === 'less') {
return '/monaco/workers/css.worker.js';
}
if (label === 'html' || label === 'handlebars' || label === 'razor') {
return '/monaco/workers/html.worker.js';
}
if (label === 'typescript' || label === 'javascript') {
return '/monaco/workers/ts.worker.js';
}
return '/monaco/workers/editor.worker.js';
}
}
}
}
export default class ResourceCache {
constructor({ getters }){
this.getters = getters
this.resources = {}
for(const getterId in this.getters){
this.resources[getterId] = {}
}
}
async get(getterId, resourceId){
// Hydrate cache
if(typeof this.resources[getterId][resourceId] == 'undefined'){
this.resources[getterId][resourceId] = this.getters[getterId](resourceId) // Set to a promise (this avoids concurrency bug)
}
// Return cached resource
return this.resources[getterId][resourceId]
}
} |
Here is a GIF of this where I am reloading the page... sometimes the syntax highlighting works, sometimes not.
In order to get the syntax highlighting to work 100% of the time, I had to make a minor adjustment to the example:
I guess this pushes the
wireTmGrammars
behind whatever internal monaco operations it depends on.Note: I'm using monaco-editor version 0.21.2 with this fork of monaco-editor-textmate: #16
The text was updated successfully, but these errors were encountered: