美文网首页
monaco-editor代码编辑器插件源代码

monaco-editor代码编辑器插件源代码

作者: 糖小羊儿 | 来源:发表于2021-12-24 16:10 被阅读0次
    效果预览

    1安装 npm install monaco-editor -S
    2.组件引用

    属性:

    • language:默认值 javascript
    • height:默认值400
    • value/v-model
    • disabled:是否禁用
    <template>
      <monaco-editor v-model="code" height="200"></monaco-editor>
    </template>
    
    <script>
    import MonacoEditor from "@/components/monacoEditor/index.vue";
    export default {
      components: { MonacoEditor },
      data() {
        return {
          code: "",
        };
      },
    
      watch: {
        code(val) {
          console.log(val);
        },
      },
    };
    </script>
    
    

    3.组件代码:新建monacoEditor文件夹,文件夹里面分别建index.vue和index.js
    index.vue代码如下

    <template>
      <monaco-editor
        v-model="code"
        :read-only="disabled"
        :language="language"
        :options="options"
        :height="height"
      ></monaco-editor>
    </template>
    
    <script>
    import MonacoEditor from "./index";
    export default {
      components: { MonacoEditor },
      data() {
        return {
          code: "",
          options: {
            fontSize: 14,
          },
        };
      },
      props: {
        language: {
          type: String,
          default: "javascript",
        },
        disabled: Boolean,
        height: {
          type: [String, Number],
          default: 400,
        },
        value: [String, Object, Array],
      },
      watch: {
        code(val) {
          this.$emit("input", val);
        },
        value: {
          handler(val) {
            if (typeof val == "object") {
              this.code = JSON.stringify(val, null, 4);
            } else {
              this.code = val || "";
            }
          },
          immediate: true,
          deep: true,
        },
      },
    };
    </script>
    

    index.js代码如下

    import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
    import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution';
    import 'monaco-editor/esm/vs/basic-languages/sql/sql.contribution';
    import 'monaco-editor/esm/vs/editor/contrib/find/findController.js';
    let
      escapable = /[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
      keyable = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/,
      gap,
      indent,
      meta = {    // table of character substitutions
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '"': '\\"',
        "'": "\\'",
        '\\': '\\\\'
      },
      rep;
    
    function beautifier(object, options = {}) {
      var space = options.space || 2,
        dropQuotesOnKeys = options.dropQuotesOnKeys == false ? false : true,
        dropQuotesOnNumbers = options.dropQuotesOnNumbers || false,
        inlineShortArrays = options.inlineShortArrays || false,
        inlineShortArraysDepth = options.inlineShortArraysDepth || 1,
        quoteType = options.quoteType || 'single',
        minify = options.minify || false;
    
      if (dropQuotesOnNumbers) walkObjectAndDropQuotesOnNumbers(object);
    
      var result = stringify(object, null, minify ? undefined : space, dropQuotesOnKeys, quoteType);
      if (inlineShortArrays && !minify) {
        var newResult = inlineShortArraysInResult(result);
        if (inlineShortArraysDepth > 1) {
          for (var i = 1; i < inlineShortArraysDepth; i++) {
            result = newResult;
            newResult = inlineShortArraysInResult(result);
            if (newResult == result) break;
          }
        }
        result = newResult;
      }
    
      return result;
    }
    
    function walkObjectAndDropQuotesOnNumbers(object) {
      if (!isObject(object)) return;
      var keys = Object.keys(object);
      if (!keys) return;
    
      keys.forEach(function (key) {
        var value = object[key];
        if (typeof value == 'string') {
          var number = value - 0;
          object[key] = isNaN(number) ? value : number;
        } else if (isObject(value) || Array.isArray(value)) {
          walkObjectAndDropQuotesOnNumbers(value);
        }
      });
    }
    
    function isObject(o) {
      return o && typeof o == 'object';
    }
    
    // Collapses arrays inline when they fit inside the specified width 
    // in characters (including indentation).
    function inlineShortArraysInResult(result, width) {
      width || (width = 80);
      if (typeof width != 'number' || width < 20) {
        throw "Invalid width '" + width + "'. Expecting number equal or larger than 20."
      }
      var list = result.split('\n'),
        i = 0,
        start = null,
        content = [];
      while (i < list.length) {
        var startMatch = !!list[i].match(/\[/),
          endMatch = !!list[i].match(/\],?/);
    
        if (startMatch && !endMatch) {
          content = [list[i]];
          start = i;
        } else if (endMatch && !startMatch && start) {
          content.push((list[i] || '').trim());
          var inline = content.join(' ');
          if (inline.length < width) {
            list.splice(start, i - start + 1, inline);
            i = start;
          }
          start = null;
          content = [];
        } else {
          if (start) content.push((list[i] || '').trim());
        }
        i += 1;
      }
      return list.join('\n');
    }
    
    function stringify(value, replacer, space, dropQuotesOnKeys, quoteType) {
      var i;
      gap = '';
      indent = '';
      if (typeof space === 'number') {
        for (i = 0; i < space; i += 1) {
          indent += ' ';
        }
    
      } else if (typeof space === 'string') {
        indent = space;
      }
    
      rep = replacer;
      if (replacer && typeof replacer !== 'function' &&
        (typeof replacer !== 'object' ||
          typeof replacer.length !== 'number')) {
        throw new Error('JSON.stringify');
      }
      return str('', { '': value }, dropQuotesOnKeys, quoteType);
    }
    function str(key, holder, dropQuotesOnKeys, quoteType) {
      var i,
        k,
        v,
        length,
        mind = gap,
        partial,
        value = holder[key];
    
      if (value && typeof value === 'object' &&
        typeof value.toJSON === 'function') {
        value = value.toJSON(key);
      }
    
      if (typeof rep === 'function') {
        value = rep.call(holder, key, value);
      }
      switch (typeof value) {
        case 'function':
          return value;
        case 'string':
          return quote(value, quoteType);
        case 'number':
          return isFinite(value) ? String(value) : 'null';
        case 'boolean':
        case 'null':
          return String(value);
        case 'object':
          if (!value) {
            return 'null';
          }
          gap += indent;
          partial = [];
          if (Object.prototype.toString.apply(value) === '[object Array]') {
            length = value.length;
            for (i = 0; i < length; i += 1) {
              partial[i] = str(i, value, dropQuotesOnKeys, quoteType) || 'null';
            }
            v = partial.length === 0
              ? '[]'
              : gap
                ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
                : '[' + partial.join(',') + ']';
            gap = mind;
            return v;
          }
          if (rep && typeof rep === 'object') {
            length = rep.length;
            for (i = 0; i < length; i += 1) {
              if (typeof rep[i] === 'string') {
                k = rep[i];
                v = str(k, value, dropQuotesOnKeys, quoteType);
                if (v) {
                  partial.push((dropQuotesOnKeys ? condQuoteKey(k, quoteType) : quote(k, quoteType)) + (gap ? ': ' : ':') + v);
                }
              }
            }
          } else {
            for (k in value) {
              if (Object.prototype.hasOwnProperty.call(value, k)) {
                v = str(k, value, dropQuotesOnKeys, quoteType);
                if (v) {
                  partial.push((dropQuotesOnKeys ? condQuoteKey(k, quoteType) : quote(k, quoteType)) + (gap ? ': ' : ':') + v);
                }
              }
            }
          }
          v = partial.length === 0
            ? '{}'
            : gap
              ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
              : '{' + partial.join(',') + '}';
          gap = mind;
          return v;
      }
    }
    
    function quote(string, quoteType) {
      escapable.lastIndex = 0;
      var surroundingQuote = '"';
      if (quoteType === 'single') {
        surroundingQuote = "'";
      }
    
      return escapable.test(string) ? surroundingQuote + string.replace(escapable, function (a) {
        var c = meta[a];
        return typeof c === 'string'
          ? c
          : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
      }) + surroundingQuote : surroundingQuote + string + surroundingQuote;
    }
    
    function condQuoteKey(string, quoteType) {
      return keyable.test(string) ? string : quote(string, quoteType);
    }
    
    function noop() { }
    
    export { monaco };
    
    export default {
      name: 'MonacoEditor',
      props: {
        diffEditor: { type: Boolean, default: false },      //是否使用diff模式
        width: { type: [String, Number], default: '100%' },
        height: { type: [String, Number], default: '100%' },
        original: String,       //只有在diff模式下有效
        value: [String, Object],
        language: { type: String, default: 'javascript' },
        theme: { type: String, default: 'vs-dark' },
        readOnly: { type: Boolean, default: false },
        options: { type: Object, default() { return {}; } },
        editorMounted: { type: Function, default: noop },
        editorBeforeMount: { type: Function, default: noop },
        keyIndex: { type: String }
      },
    
      watch: {
        options: {
          deep: true,
          handler(options) {
            this.editor && this.editor.updateOptions(options);
          }
        },
        value() {
          let data = this.value
          if (this.editor && data !== this._getValue()) {
            this._setValue(data)
          }
        },
    
        language() {
          if (!this.editor) return;
          if (this.diffEditor) {      //diff模式下更新language
            const { original, modified } = this.editor.getModel();
            monaco.editor.setModelLanguage(original, this.language);
            monaco.editor.setModelLanguage(modified, this.language);
          } else
            monaco.editor.setModelLanguage(this.editor.getModel(), this.language);
        },
    
        theme() {
          this.editor && monaco.editor.setTheme(this.theme);
        },
    
        style() {
          this.editor && this.$nextTick(() => {
            this.editor.layout();
          });
        }
      },
    
      computed: {
        style() {
          return {
            width: !/^\d+$/.test(this.width) ? this.width : `${this.width}px`,
            height: !/^\d+$/.test(this.height) ? this.height : `${this.height}px`
          }
        }
      },
    
      mounted() {
        this.initMonaco();
      },
    
      beforeDestroy() {
        this.editor && this.editor.dispose();
      },
    
      render() {
        return (
          <div class="monaco_editor_container" style={this.style}></div>
        );
      },
    
      methods: {
        initMonaco() {
          const { value, language, theme, readOnly, options } = this;
          Object.assign(options, this._editorBeforeMount());      //编辑器初始化前
          this.editor = monaco.editor[this.diffEditor ? 'createDiffEditor' : 'create'](this.$el, {
            value: (typeof value == 'string') ? value : beautifier(value),
            language: language,
            theme: theme,
            readOnly: readOnly,
            ...options
          });
          this.diffEditor && this._setModel(this.value, this.original);
          this._editorMounted(this.editor);      //编辑器初始化后
        },
    
        _getEditor() {
          if (!this.editor) return null;
          return this.diffEditor ? this.editor.modifiedEditor : this.editor;
        },
    
        _setModel(value, original) {     //diff模式下设置model
          const { language } = this;
          const originalModel = monaco.editor.createModel(original, language);
          const modifiedModel = monaco.editor.createModel(value, language);
          this.editor.setModel({
            original: originalModel,
            modified: modifiedModel
          });
        },
    
        _setValue(value) {
          let editor = this._getEditor();
          if (editor) return editor.setValue(value);
        },
    
        _getValue() {
          let editor = this._getEditor();
          if (!editor) return '';
          return editor.getValue();
        },
    
        _editorBeforeMount() {
          const options = this.editorBeforeMount(monaco);
          return options || {};
        },
    
        _editorMounted(editor) {
          this.editorMounted(editor, monaco);
          if (this.diffEditor) {
            editor.onDidUpdateDiff((event) => {
              const value = this._getValue();
              this._emitChange(value, event);
            });
          } else {
            editor.onDidChangeModelContent(event => {
              const value = this._getValue();
              this._emitChange(value, event);
            });
          }
        },
    
        _emitChange(value, event) {
          this.$emit('change', value, event);
          this.$emit('input', value);
        }
      }
    }
    

    相关文章

      网友评论

          本文标题:monaco-editor代码编辑器插件源代码

          本文链接:https://www.haomeiwen.com/subject/tmnlqrtx.html