monaco编辑器使用方法

2022-07-25,,

monaco

微软之前有个项目叫做Monaco Workbench,后来这个项目变成了VSCode,而Monaco Editor就是从这个项目中成长出来的一个web编辑器,他们很大一部分的代码(monaco-editor-core)都是共用的,所以monaco和VSCode在编辑代码,交互以及UI上几乎是一摸一样的,有点不同的是,两者的平台不一样,monaco基于浏览器,而VSCode基于electron,所以功能上VSCode更加健全,并且性能比较强大。,[Monaco Editor GitHub地址](https://github.com/Microsoft/monaco-editor)

1.安装monaco

npm install monaco-editor -S
npm install monaco-editor-webpack-plugin -S

vue.config.js中引入monaco-editor-webpack-plugin (monaco是基于本地工作的,即:file://,所以在web端需要替换为http://,引入monaco-editor-plugin即可达到这个效果)

const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
// 自定义webpack配置
  configureWebpack: {
    output: {
      library: `${name}`,
      libraryTarget: 'umd',// 把子应用打包成 umd 库格式
      jsonpFunction: `webpackJsonp_${name}`,
    },
      plugins: [
          new MonacoWebpackPlugin()
      ]
  },

2.引入并使用monaco

html

<div ref="container">
</div>

js

import * as monaco from 'monaco-editor';
//create  [options参数官网地址](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandaloneeditorconstructionoptions.html)
this.monacoEditor=monaco.editor.create(this.$refs.container,{
            value:`console.log("hello,world")`,
            language:"javascript",
            theme: 'vs-dark', // 编辑器主题:vs, hc-black, or vs-dark,更多选择详见官网 
            editorOptions: {
	        automaticLayout: true, // 自动布局,
	        autoIndent:true//自动缩进
	      } // 同codes
})

3.监听事件

监听内容被修改:onDidChangeModelContent

this.monacoEditor.onDidChangeModelContent((e) => { 
   console.log(e)   
});

监听blur事件

this.monacoEditor.onDidBlurEditor((e) => { 
     console.log(e); 
});

监听resize

//编辑器随窗口自适应
window.addEventListener('resize',function(){
    initEditor();//重新初始化monacoEditor对象
})

4. 部分api

  1. 获取输入内容this.xxx = this.monacoEditor.getValue()
  2. 切换格式动态修改 language方法 : this.monacoEditor.setModelLanguage(this.monacoEditor.getModel(), language);
  3. 动态设置主题颜色 this.monacoEditor.setTheme('xxxxxx')

5.代码格式校验

比如:{name:"zzz"} text 不会提示无法错误,而json提示语法有误(正确应为{"name":"zzz"})

引入nacos的校验文件,代码如下:
nacos GitHub地址

/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import * as yamljs from 'yamljs';

/**
 * 校验一个配置项
 */
function validateProperty(property) {
  const { length } = property;
  let keyLen = 0;
  let valueStart = length;
  let hasSep = false;
  let precedingBackslash = false;
  let c;
  // 解析 key
  while (keyLen < length) {
    c = property[keyLen];
    if ((c === '=' || c === ':') && !precedingBackslash) {
      valueStart = keyLen + 1;
      hasSep = true;
      break;
    }

    if ((c === ' ' || c === '\t' || c === '\f') && !precedingBackslash) {
      valueStart = keyLen + 1;
      break;
    }

    if (c === '\\') {
      precedingBackslash = !precedingBackslash;
    } else {
      precedingBackslash = false;
    }
    keyLen++;
  }
  // 解析 value
  while (valueStart < length) {
    c = property[valueStart];
    if (c !== ' ' && c !== '\t' && c !== '\f') {
      if (!hasSep && (c === '=' || c === ':')) {
        hasSep = true;
      } else {
        break;
      }
    }
    valueStart++;
  }

  return (
    validateKeyOrValueForProperty(property, 0, keyLen) &&
    validateKeyOrValueForProperty(property, valueStart, length)
  );
}

function validateKeyOrValueForProperty(property, start, end) {
  // check null
  if (start >= end) {
    return false;
  }
  let index = 0;
  let c;
  while (index < property.length) {
    c = property[index++];
    if (c !== '\\') {
      continue;
    }

    c = property[index++];
    // check backslash
    if (!isPropertyEscape(c)) {
      return false;
    }

    // check Unicode
    if (c === 'u') {
      const unicode = property.slice(index, index + 4).join('');
      if (unicode.match(/^[a-f0-9]{4}$/i) === null) {
        return false;
      }
      index += 4;
    }
  }

  return true;
}

function isPropertyEscape(c = '') {
  return 'abfnrt\\"\'0! #:=u'.includes(c);
}

export default {
  /**
   * 检测json是否合法
   */
  validateJson(str) {
    try {
      return !!JSON.parse(str);
    } catch (e) {
      return false;
    }
  },

  /**
   * 检测xml和html是否合法
   */
  validateXml(str) {
    try {
      if (typeof DOMParser !== 'undefined') {
        const parserObj =
          new window.DOMParser()
            .parseFromString(str, 'application/xml')
            .getElementsByTagName('parsererror') || {};
        return parserObj.length === 0;
      } else if (typeof window.ActiveXObject !== 'undefined') {
        const xml = new window.ActiveXObject('Microsoft.XMLDOM');
        xml.async = 'false';
        xml.loadXML(str);
        return xml;
      }
    } catch (e) {
      return false;
    }
  },

  /**
   * 检测yaml是否合法
   */
  validateYaml(str) {
    try {
      return yamljs.parse(str);
    } catch (e) {
      return false;
    }
  },

  /**
   * 检测属性是否正确
   */
  validateProperties(str = '') {
    let isNewLine = true;
    let isCommentLine = false;
    let isSkipWhiteSpace = true;
    let precedingBackslash = false;
    let appendedLineBegin = false;
    let skipLF = false;
    let hasProperty = false;
    let property = [];
    for (let i = 0; i < str.length; i++) {
      const c = str[i];

      if (skipLF) {
        skipLF = false;
        if (c === '\n') {
          continue;
        }
      }
      // 跳过行首空白字符
      if (isSkipWhiteSpace) {
        if (c === ' ' || c === '\t' || c === '\f') {
          continue;
        }
        if (!appendedLineBegin && (c === '\r' || c === '\n')) {
          continue;
        }
        appendedLineBegin = false;
        isSkipWhiteSpace = false;
      }

      // 判断注释行
      if (isNewLine) {
        isNewLine = false;
        if (c === '#' || c === '!') {
          isCommentLine = true;
          continue;
        }
      }

      if (c !== '\n' && c !== '\r') {
        property.push(c);
        if (c === '\\') {
          precedingBackslash = !precedingBackslash;
        } else {
          precedingBackslash = false;
        }
        continue;
      }

      // 跳过注释行
      if (isCommentLine || property.length === 0) {
        isNewLine = true;
        isCommentLine = false;
        isSkipWhiteSpace = true;
        property = [];
        continue;
      }

      // 处理转移字符
      if (precedingBackslash) {
        property.pop();
        precedingBackslash = false;
        isSkipWhiteSpace = true;
        appendedLineBegin = true;
        if (c === '\r') {
          skipLF = true;
        }
        continue;
      }
      // 解析出配置项
      // 进行校验
      if (!validateProperty(property)) {
        return false;
      }
      hasProperty = true;
      property = [];
      isNewLine = true;
      isSkipWhiteSpace = true;
    }

    // 校验最后一行
    if (property.length > 0 && !isCommentLine) {
      return validateProperty(property);
    }

    return hasProperty;
  },

  /**
   * 根据类型验证类型
   */
  validate({ content, type }) {
    const validateObj = {
      json: this.validateJson,
      xml: this.validateXml,
      'text/html': this.validateXml,
      html: this.validateXml,
      properties: this.validateProperties,
      yaml: this.validateYaml
    };

    if (!validateObj[type]) {
      return true;
    }

    return validateObj[type](content);
  }
};

创建validateContent.js后,在代码内引入

import validateContent from '@/utils/validateContent';
if (validateContent.validate({ content: this.queryFormData.content, type: xxxx })) { //type xml text json 等
        console.log('格式没问题逻辑');
      } else {
        console.log('提示格式错误');
      }

本文地址:https://blog.csdn.net/qq_36736475/article/details/112562226

《monaco编辑器使用方法.doc》

下载本文的Word格式文档,以方便收藏与打印。