当前位置:首页 » 《我的小黑屋》 » 正文

web在线编辑器(vue版)

6 人参与  2024年09月11日 10:41  分类 : 《我的小黑屋》  评论

点击全文阅读


目录

前言一、monaco-editor1、编辑器源码2、对比diff2、体积优化 二、ace-editor?1、源码2、体积优化 3、codemirror1、diff 总结


前言

提示:这里可以添加本文要记录的大概内容:


提示:以下是本篇文章正文内容,下面案例可供参考

一、monaco-editor

“monaco-editor”: “^0.30.1”

点击进入api地址

1、编辑器源码

<template>  <div ref="monacoEditor" id="monacoEditor" :style="style"></div></template><script setup>import { nextTick, onMounted, ref, watch, onBeforeUnmount } from "vue";import * as monaco from "monaco-editor";const props = defineProps({  modelValue: {},  style: {},  readOnly: {},  language: {},  content: {},});const emit = defineEmits(["update:modelValue"]);const monacoEditor = ref();let editor;const init = () => {  /**   * @param wordWrap 自动换行,注意大小写   */  editor = monaco.editor.create(monacoEditor.value, {    automaticLayout: true,    value: props.modelValue,    readOnly: props.readOnly,    theme: "vs-dark",    language: props.language,    wordWrap: "on",    wrappingIndent: "indent",  });  // 监听值的变化  editor.onDidChangeModelContent(() => {    emit("update:modelValue", editor.getValue());  });};onMounted(() => {  init();});watch(  () => props.language,  (nv, ov) => {    monaco.editor.setModelLanguage(editor.getModel(), nv);  });function updateValue() {  setTimeout(() => {    editor.setValue(props.modelValue);  }, 200);}watch(  () => props.language,  (newValue) => {    monaco.editor.setModelLanguage(editor.getModel(), newValue);  });defineExpose({ updateValue });</script><style></style>
<config-edit     v-model="tempFlow.textareashow"    :language="tempFlow.language"     :readOnly="false"          style="height: 100%; width: 100%"></config-edit>

2、对比diff

在这里插入图片描述

ps:在比较过程中,支持在右侧的进行文件编辑。可通过界面顶部操作栏,查看当前修改个数(实时更改)。

当前修改处,可通过点击下一个,上一个跳转。当用户选择某行,当前修改处也会发生变化,

需要注意的是,如果当前选中行,不在修改的范围内,则显示0,点击跳转按钮,将跳转到离当前最近的一个修改,并且标识当前处于第几个修改

<template>  <div class="monaco-diff-box">    <div class="layout-start operate">      <div style="width: 50%">{{ leftText }}</div>      <div style="width: 10%">{{ rightText }}</div>      <div class="layout-end" style="width: 40%">        <span          >发现&nbsp;<span class="config-diff-count">{{ diffCount }}</span          >&nbsp;处修改</span        >        <span          >,当前第&nbsp;<span class="config-diff-count">{{            curDiffCount || 0          }}</span          >&nbsp;处&nbsp;&nbsp;</span        >        <span          title="上一个"          v-debounce-click="            () => {              exeCommand('goPrevDiff');            }          "          class="diffJump"        >          <el-icon><CaretLeft /></el-icon>          上一个        </span>        &nbsp;&nbsp;&nbsp;&nbsp;        <span          title="下一个"          v-debounce-click="            () => {              exeCommand('goNextDiff');            }          "          class="diffJump"        >          下一个          <el-icon><CaretRight /></el-icon>        </span>      </div>    </div>    <div ref="monacoDiff" id="monacoDiff" :style="style"></div>  </div></template><script setup>import {  nextTick,  onMounted,  ref,  watch,  onBeforeUnmount,  reactive,  computed,} from "vue";import * as monaco from "monaco-editor";const props = defineProps({  newCode: {},  oldCode: {},  params: {},  language: {},});let leftText = ref(props.params.leftText || "修改前");let rightText = ref(props.params.rightText || "修改后");const monacoDiff = ref();const lineChangesDataList = ref([]);// 当前一共有多少处修改let diffCount = computed(() => {  return lineChangesDataList.value.length;});// 当前cursor指示的几处修改let curDiffCount = ref(1);var editor = null;var decorations = null;var navi;var lineChangesDataMap = new Map();const init = () => {  editor = monaco.editor.createDiffEditor(monacoDiff.value, {    automaticLayout: true,    readOnly: false,    wordWrap: "on",    theme: "vs",    wrappingIndent: "indent",    bracketPairColorization: true,    diffCodeLens: true,    experimental: {      collapseUnchangedRegions: true, // 折叠未更改区域    },    enableSplitViewResizing: false, // 允许用户调整差异编辑器拆分视图的大小。默认为 true。  });  let originalModel = monaco.editor.createModel(props.oldCode, props.language);  let modifiedModel = monaco.editor.createModel(props.newCode, props.language);  editor.setModel({    original: originalModel,    modified: modifiedModel,  });  // decorations = editor.createDecorationsCollection([  //   {  //     range: new monaco.Range(3, 1, 3, 1),  //     options: {  //       isWholeLine: true,  //       className: "myContentClass",  //       glyphMarginClassName: "myGlyphMarginClass",  //     },  //   },  // ]);  navi = monaco.editor.createDiffNavigator(editor, {    followsCaret: true,    ignoreCharChanges: true,  });};onMounted(() => {  init();  setTimeout(() => {    editor.onDidUpdateDiff((val) => {      lineChangesDataList.value = editor.getLineChanges();      lineChangesDataList.value.forEach((item, index) => {        if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {          lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);        } else {          for (            let i = item.modifiedStartLineNumber;            i <= item.modifiedEndLineNumber;            i++          ) {            lineChangesDataMap.set(i, index + 1);          }        }      });      curDiffCount.value = lineChangesDataMap.get(        editor.getPosition().lineNumber      );    });    lineChangesDataList.value = editor.getLineChanges();    lineChangesDataList.value.forEach((item, index) => {      if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {        lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);      } else {        for (          let i = item.modifiedStartLineNumber;          i <= item.modifiedEndLineNumber;          i++        ) {          lineChangesDataMap.set(i, index + 1);        }      }    });    editor.getModifiedEditor().onMouseDown((e) => {      lineChangesDataList.value = editor.getLineChanges();      lineChangesDataList.value.forEach((item, index) => {        if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {          lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);        } else {          for (            let i = item.modifiedStartLineNumber;            i <= item.modifiedEndLineNumber;            i++          ) {            lineChangesDataMap.set(i, index + 1);          }        }      });      curDiffCount.value = lineChangesDataMap.get(e.target.position.lineNumber);    });    editor.getOriginalEditor().onMouseDown((e) => {      lineChangesDataList.value = editor.getLineChanges();      lineChangesDataList.value.forEach((item, index) => {        if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {          lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);        } else {          for (            let i = item.modifiedStartLineNumber;            i <= item.modifiedEndLineNumber;            i++          ) {            lineChangesDataMap.set(i, index + 1);          }        }      });      curDiffCount.value = lineChangesDataMap.get(e.target.position.lineNumber);    });  }, 200);});/** * @desc 跳转修改处 * @cmd string * goNextDiff 前进异步 * goPrevDiff 后退一步 */const exeCommand = (cmd) => {  let arr = Array.from(lineChangesDataMap.keys());  let positionIndex;  let lineNumber = editor.getPosition().lineNumber;  let hasNewNum = false;  if (arr.indexOf(lineNumber) == -1) {    hasNewNum = true;    arr.push(lineNumber);    arr = arr.sort((a, b) => {      return a - b;    });  }  positionIndex = arr.indexOf(lineNumber);  if (cmd === "goNextDiff") {    setTimeout(() => {      //下一步      if (        curDiffCount.value == lineChangesDataList.value.length ||        (hasNewNum && arr[arr.length - 1] == lineNumber)      ) {        curDiffCount.value = 1;      } else {        curDiffCount.value = lineChangesDataMap.get(arr[positionIndex + 1]);      }      navi.next();    }, 300);  } else if (cmd === "goPrevDiff") {    setTimeout(() => {      //上一步      if (curDiffCount.value == 1 || (hasNewNum && arr[0] == lineNumber)) {        curDiffCount.value = lineChangesDataList.value.length;      } else {        curDiffCount.value = lineChangesDataMap.get(arr[positionIndex - 1]);      }      nextTick(() => {        navi.previous();      });    });  }};/** * @desc 获取最新编辑数据 */const getValue = () => {  return editor.getModel().modified.getValue();}watch(  () => props.language,  (nv, ov) => {    // monaco.editor.setModelLanguage(editor.getModel(), nv);  });defineExpose({  getValue,});</script><style lang="less">.monaco-diff-box {  height: 100%;  .operate {    height: 36px;    .config-diff-count {      color: #ff5722;    }    .diffJump {      cursor: pointer;    }  }  #monacoDiff {    flex: 1;    height: calc(100% - 36px);    .monaco-editor .line-numbers.active-line-number {      color: #ff5722;    }  }}</style>

2023/12/05
支持相同代码可折叠
这个需要升级monaco的版本
“monaco-editor”: “^0.44.0”
由于这个需要和webpack5才能兼容,所以不是webpack5的需要升级(vue-cli5)
升级manaco之后createDiffNavigator,被删除了,在这个地方化解决了createDiffNavigator被删除之后的,修改处跳转的问题

<template>  <div class="monaco-diff-box">    <div class="layout-start operate">      <div style="width: 50%">{{ leftText }}</div>      <div style="width: 10%">{{ rightText }}</div>      <div class="layout-end" style="width: 40%">        <span          >发现&nbsp;<span class="config-diff-count">{{ diffCount }}</span          >&nbsp;处修改</span        >        <span          >,当前第&nbsp;<span class="config-diff-count">{{            curDiffCount || 0          }}</span          >&nbsp;处&nbsp;&nbsp;</span        >        <span          title="上一个"          v-debounce-click="            () => {              exeCommand('goPrevDiff');            }          "          class="diffJump"        >          <el-icon><CaretLeft /></el-icon>          上一个        </span>        &nbsp;&nbsp;&nbsp;&nbsp;        <span          title="下一个"          v-debounce-click="            () => {              exeCommand('goNextDiff');            }          "          class="diffJump"        >          下一个          <el-icon><CaretRight /></el-icon>        </span>      </div>    </div>    <div ref="monacoDiff" id="monacoDiff" :style="style"></div>  </div></template><script setup>import {  nextTick,  onMounted,  ref,  watch,  onBeforeUnmount,  reactive,  computed,} from "vue";import * as monaco from "monaco-editor";const props = defineProps({  newCode: {},  oldCode: {},  params: {},  language: {},});let leftText = ref(props.params.leftText || "修改前");let rightText = ref(props.params.rightText || "修改后");const monacoDiff = ref();const lineChangesDataList = ref([]);// 当前一共有多少处修改let diffCount = computed(() => {  return lineChangesDataList.value.length;});// 当前cursor指示的几处修改let curDiffCount = ref(1);var editor = null;var lineChangesDataMap = new Map();let monaco_languages = monaco.languages.getLanguages();const init = () => {  editor = monaco.editor.createDiffEditor(monacoDiff.value, {    automaticLayout: true,    readOnly: false,    wordWrap: "on",    theme: "vs",    wrappingIndent: "indent",    bracketPairColorization: true,    diffCodeLens: true,    ignoreTrimWhitespace: false, //是否忽略差异编辑器中的空格    enableSplitViewResizing: false, // 允许用户调整差异编辑器拆分视图的大小。默认为 true。    hideUnchangedRegions: {      enabled: true,    },  });  let id = "plaintext"; // 默认纯文本  monaco_languages.forEach((language) => {    language.extensions &&      language.extensions.forEach((ex) => {        if (props.language == ex.slice(1)) {          id = language.id;        }      });  });  let originalModel = monaco.editor.createModel(props.oldCode, id);  let modifiedModel = monaco.editor.createModel(props.newCode, id);  editor.setModel({    original: originalModel,    modified: modifiedModel,  });};onMounted(() => {  init();  setTimeout(() => {    editor.onDidUpdateDiff((val) => {      lineChangesDataList.value = editor.getLineChanges();      lineChangesDataList.value.forEach((item, index) => {        if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {          lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);        } else {          for (            let i = item.modifiedStartLineNumber;            i <= item.modifiedEndLineNumber;            i++          ) {            lineChangesDataMap.set(i, index + 1);          }        }      });      curDiffCount.value = lineChangesDataMap.get(        editor.getPosition().lineNumber      );    });    lineChangesDataList.value = editor.getLineChanges();    editor.setPosition({      column: 1,      lineNumber: lineChangesDataList.value[0].modifiedEndLineNumber,    });    editor      .getModifiedEditor()      .revealLineInCenter(        lineChangesDataList.value[0].modifiedStartLineNumber,        lineChangesDataList.value[0].modifiedEndLineNumber      );    lineChangesDataList.value.forEach((item, index) => {      if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {        lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);      } else {        for (          let i = item.modifiedStartLineNumber;          i <= item.modifiedEndLineNumber;          i++        ) {          lineChangesDataMap.set(i, index + 1);        }      }    });    editor.getModifiedEditor().onMouseDown((e) => {      if (e?.target?.position?.lineNumber) {        lineChangesDataList.value = editor.getLineChanges();        lineChangesDataList.value.forEach((item, index) => {          if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {            lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);          } else {            for (              let i = item.modifiedStartLineNumber;              i <= item.modifiedEndLineNumber;              i++            ) {              lineChangesDataMap.set(i, index + 1);            }          }        });        curDiffCount.value = lineChangesDataMap.get(          e.target.position.lineNumber        );      } else {        curDiffCount.value = 0;      }    });    editor.getOriginalEditor().onMouseDown((e) => {      if (e?.target?.position?.lineNumber) {        lineChangesDataList.value = editor.getLineChanges();        lineChangesDataList.value.forEach((item, index) => {          if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {            lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);          } else {            for (              let i = item.modifiedStartLineNumber;              i <= item.modifiedEndLineNumber;              i++            ) {              lineChangesDataMap.set(i, index + 1);            }          }        });        curDiffCount.value = lineChangesDataMap.get(          e.target.position.lineNumber        );      } else {        curDiffCount.value = 0;      }    });  }, 500);});/** * @desc 跳转修改处 * @cmd string * goNextDiff 前进异步 * goPrevDiff 后退一步 */const exeCommand = (cmd) => {  let arr = Array.from(lineChangesDataMap.keys());  let positionIndex;  let lineNumber = editor.getPosition().lineNumber;  let hasNewNum = false;  if (arr.indexOf(lineNumber) == -1) {    hasNewNum = true;    arr.push(lineNumber);    arr = arr.sort((a, b) => {      return a - b;    });  }  positionIndex = arr.indexOf(lineNumber);  if (cmd === "goNextDiff") {    setTimeout(() => {      //下一步      if (        curDiffCount.value == lineChangesDataList.value.length ||        (hasNewNum && arr[arr.length - 1] == lineNumber)      ) {        curDiffCount.value = 1;        editor          .getModifiedEditor()          .revealLineInCenter(            lineChangesDataList.value[0].modifiedStartLineNumber,            lineChangesDataList.value[0].modifiedEndLineNumber          );        editor.setPosition({          column: 1,          lineNumber: lineChangesDataList.value[0].modifiedEndLineNumber,        });      } else {        curDiffCount.value = lineChangesDataMap.get(arr[positionIndex + 1]);        editor          .getModifiedEditor()          .revealLineInCenter(arr[positionIndex + 1], arr[positionIndex + 1]);        editor.setPosition({          column: 1,          lineNumber: arr[positionIndex + 1],        });      }    }, 300);  } else if (cmd === "goPrevDiff") {    setTimeout(() => {      //上一步      if (curDiffCount.value == 1 || (hasNewNum && arr[0] == lineNumber)) {        let diffNum = lineChangesDataList.value.length;        curDiffCount.value = diffNum;        editor          .getModifiedEditor()          .revealLineInCenter(            lineChangesDataList.value[diffNum - 1].modifiedStartLineNumber,            lineChangesDataList.value[diffNum - 1].modifiedEndLineNumber          );        editor.setPosition({          column: 1,          lineNumber:            lineChangesDataList.value[diffNum - 1].modifiedEndLineNumber,        });      } else {        curDiffCount.value = lineChangesDataMap.get(arr[positionIndex - 1]);        editor          .getModifiedEditor()          .revealLineInCenter(arr[positionIndex - 1], arr[positionIndex - 1]);        editor.setPosition({          column: 1,          lineNumber: arr[positionIndex - 1],        });      }    });  }};/** * @desc 获取最新编辑数据 */const getValue = () => {  return editor.getModel().modified.getValue();};watch(  () => props.language,  (nv, ov) => {    // monaco.editor.setModelLanguage(editor.getModel(), nv);  });defineExpose({  getValue,});</script><style lang="less">.monaco-diff-box {  height: 100%;  .operate {    height: 36px;    .config-diff-count {      color: #ff5722;    }    .diffJump {      cursor: pointer;    }  }  #monacoDiff {    flex: 1;    height: calc(100% - 36px);    .monaco-editor .line-numbers.active-line-number {      color: #ff5722;    }  }}</style>

2024/04/12
修复格式校验,修改格式为正常之后,还是又报错标记返回

<template>  <div class="monaco-diff-box">    <div class="layout-start operate">      <div style="width: 50%">{{ leftText }}</div>      <div style="width: 10%">{{ rightText }}</div>      <div class="layout-end" style="width: 40%">        <span          >发现&nbsp;<span class="config-diff-count">{{ diffCount }}</span          >&nbsp;处修改</span        >        <span          >,当前第&nbsp;<span class="config-diff-count">{{            curDiffCount || 0          }}</span          >&nbsp;处&nbsp;&nbsp;</span        >        <span          title="上一个"          v-debounce-click="            () => {              exeCommand('goPrevDiff');            }          "          class="diffJump"        >          <el-icon><CaretLeft /></el-icon>          上一个        </span>        &nbsp;&nbsp;&nbsp;&nbsp;        <span          title="下一个"          v-debounce-click="            () => {              exeCommand('goNextDiff');            }          "          class="diffJump"        >          下一个          <el-icon><CaretRight /></el-icon>        </span>      </div>    </div>    <div ref="monacoDiff" id="monacoDiff" :style="style"></div>  </div></template><script setup>import {  nextTick,  onMounted,  ref,  watch,  onBeforeUnmount,  reactive,  computed,  onUnmounted,} from "vue";import * as monaco from "monaco-editor";const props = defineProps({  newCode: {},  oldCode: {},  params: {},  language: {},});let leftText = ref(props.params.leftText || "修改前");let rightText = ref(props.params.rightText || "修改后");let originalModel = "";let modifiedModel = "";const monacoDiff = ref();const lineChangesDataList = ref([]);// 当前一共有多少处修改let diffCount = computed(() => {  return lineChangesDataList.value?.length || 0;});// 当前cursor指示的几处修改let curDiffCount = ref(0);var editor = null;var lineChangesDataMap = new Map();let monaco_languages = monaco.languages.getLanguages();let id = "plaintext"; // 默认纯文本const init = async () => {  editor = await monaco.editor.createDiffEditor(monacoDiff.value, {    automaticLayout: true,    readOnly: false,    wordWrap: "on",    theme: "vs",    wrappingIndent: "indent",    bracketPairColorization: true,    diffCodeLens: true,    ignoreTrimWhitespace: false, //是否忽略差异编辑器中的空格    enableSplitViewResizing: false, // 允许用户调整差异编辑器拆分视图的大小。默认为 true。    hideUnchangedRegions: {      enabled: true,    },    diffWordWrap: "off",  });  monaco_languages.forEach((language) => {    language.extensions &&      language.extensions.forEach((ex) => {        if (props.language == ex.slice(1)) {          id = language.id;        }      });  });  // Set up the XML language  monaco.languages.register({ id: "xml" });  monaco.languages.setLanguageConfiguration("xml", {    comments: {      lineComment: "--",      blockComment: ["--[[", "]]"],    },  });  // Define the error checking function for XML  const checkXMLSyntax = (code) => {    let errorMessage, xmlDoc;    // code for IE    if (window.ActiveXObject) {      xmlDoc = new ActiveXObject("Microsoft.XMLDOM");      xmlDoc.async = "false";      xmlDoc.loadXML(xmlContent);      if (xmlDoc.parseError.errorCode != 0) {        errorMessage = "错误code: " + xmlDoc.parseError.errorCode + "\n";        errorMessage = errorMessage + "错误原因: " + xmlDoc.parseError.reason;        errorMessage = errorMessage + "错误位置: " + xmlDoc.parseError.line;        return [          {            severity: monaco.MarkerSeverity.Error,            message: errorMessage,            startLineNumber: xmlDoc.parseError.line - 1,            startColumn: 0,            endLineNumber: xmlDoc.parseError.line - 1,            endColumn: 1,          },        ];      } else {        return [];      }    } else if (document.implementation.createDocument) {      const parser = new DOMParser();      xmlDoc = parser.parseFromString(code, "text/xml");      const error = xmlDoc.getElementsByTagName("parsererror");      if (error.length > 0) {        errorMessage = xmlDoc          .getElementsByTagName("parsererror")[0]          .getElementsByTagName("div")[0].innerText;        let tmp = [];        let keyRexExp = new RegExp("(line 0)", "gi");        errorMessage.split(":").forEach(function (msg, index) {          if (index == errorMessage.split(":").length - 1) {            msg = msg.replace(keyRexExp, "");            tmp.push(msg);          } else {            tmp.push(msg);          }        });        errorMessage = tmp.join(":");        let match = errorMessage.match(/line (\d+) at column (\d+)/);        if (match) {          let lineNumber = +match[1];          let columnNumber = +match[2];          return [            {              severity: monaco.MarkerSeverity.Error,              message: errorMessage,              startLineNumber: lineNumber,              startColumn: columnNumber,              endLineNumber: lineNumber,              endColumn: columnNumber,            },          ];        } else {          return [];        }      } else {        return [];      }    }  };  // Set up the YAML language  monaco.languages.register({ id: "yaml" });  monaco.languages.setLanguageConfiguration("yaml", {    comments: {      lineComment: "--",      blockComment: ["--[[", "]]"],    },  });  // Define the error checking function for YAML  const checkYAMLSyntax = (code) => {    try {      yaml.load(code);      if (yaml == null) {      }      return [];    } catch (error) {      return [        {          severity: monaco.MarkerSeverity.Error,          message: error.message,          startLineNumber: error.mark.line,          startColumn: error.mark.column,          endLineNumber: error.mark.line,          endColumn: error.mark.column + 1,        },      ];    }  };  // Set up the Lua language  monaco.languages.register({ id: "lua" });  monaco.languages.setLanguageConfiguration("lua", {    comments: {      lineComment: "--",      blockComment: ["--[[", "]]"],    },  });  // Define the error checking function  function checkLuaSyntax(code) {    try {      luaparse.parse(code);      return [];    } catch (error) {      return [        {          severity: monaco.MarkerSeverity.Error,          message: error.message,          startLineNumber: error.line,          startColumn: error.column + 1,          endLineNumber: error.line,          endColumn: error.column + 2,        },      ];    }  }  originalModel = await monaco.editor.createModel(props.oldCode, id);  modifiedModel = await monaco.editor.createModel(props.newCode, id);  editor.setModel({    original: originalModel,    modified: modifiedModel,  });  let markers = [];  if (id === "xml") {    markers = checkXMLSyntax(modifiedModel.getValue());  } else if (id === "yaml") {    markers = checkYAMLSyntax(modifiedModel.getValue());  } else if (id === "lua") {    markers = checkLuaSyntax(modifiedModel.getValue());  }  monaco.editor.setModelMarkers(modifiedModel, id, markers);  modifiedModel.onDidChangeContent(() => {    let markers = [];    if (id === "xml") {      markers = checkXMLSyntax(modifiedModel.getValue());    } else if (id === "yaml") {      markers = checkYAMLSyntax(modifiedModel.getValue());    } else if (id === "lua") {      markers = checkLuaSyntax(modifiedModel.getValue());    }    monaco.editor.setModelMarkers(modifiedModel, id, markers);  });  editor.onDidUpdateDiff((val) => {    lineChangesDataList.value = editor.getLineChanges();    if (lineChangesDataList.value?.length > 0) {      lineChangesDataList.value.forEach((item, index) => {        if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {          lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);        } else {          for (            let i = item.modifiedStartLineNumber;            i <= item.modifiedEndLineNumber;            i++          ) {            lineChangesDataMap.set(i, index + 1);          }        }      });      curDiffCount.value = lineChangesDataMap.get(        editor.getPosition().lineNumber      );    }  });  lineChangesDataList.value = editor.getLineChanges();  if (lineChangesDataList.value?.length > 0) {    curDiffCount.value = 1;    editor.setPosition({      column: 1,      lineNumber: lineChangesDataList.value[0].modifiedEndLineNumber,    });    editor      .getModifiedEditor()      .revealLineInCenter(        lineChangesDataList.value[0].modifiedStartLineNumber,        lineChangesDataList.value[0].modifiedEndLineNumber      );    lineChangesDataList.value.forEach((item, index) => {      if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {        lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);      } else {        for (          let i = item.modifiedStartLineNumber;          i <= item.modifiedEndLineNumber;          i++        ) {          lineChangesDataMap.set(i, index + 1);        }      }    });  }  editor.getModifiedEditor().onMouseDown((e) => {    if (e?.target?.position?.lineNumber) {      lineChangesDataList.value = editor.getLineChanges();      if (lineChangesDataList.value?.length > 0) {        lineChangesDataList.value.forEach((item, index) => {          if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {            lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);          } else {            for (              let i = item.modifiedStartLineNumber;              i <= item.modifiedEndLineNumber;              i++            ) {              lineChangesDataMap.set(i, index + 1);            }          }        });      }      curDiffCount.value = lineChangesDataMap.get(e.target.position.lineNumber);    } else {      curDiffCount.value = 0;    }  });  editor.getOriginalEditor().onMouseDown((e) => {    if (e?.target?.position?.lineNumber) {      lineChangesDataList.value = editor.getLineChanges();      if (lineChangesDataList.value?.length > 0) {        lineChangesDataList.value.forEach((item, index) => {          if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {            lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);          } else {            for (              let i = item.modifiedStartLineNumber;              i <= item.modifiedEndLineNumber;              i++            ) {              lineChangesDataMap.set(i, index + 1);            }          }        });      }      curDiffCount.value = lineChangesDataMap.get(e.target.position.lineNumber);    } else {      curDiffCount.value = 0;    }  });};onMounted(() => {  init();});/** * @desc 跳转修改处 * @cmd string * goNextDiff 前进异步 * goPrevDiff 后退一步 */const exeCommand = (cmd) => {  if (lineChangesDataList.value.length === 0) return;  let arr = Array.from(lineChangesDataMap.keys());  let positionIndex;  let lineNumber = editor.getPosition().lineNumber;  let hasNewNum = false;  if (arr.indexOf(lineNumber) == -1) {    hasNewNum = true;    arr.push(lineNumber);    arr = arr.sort((a, b) => {      return a - b;    });  }  positionIndex = arr.indexOf(lineNumber);  if (cmd === "goNextDiff") {    setTimeout(() => {      //下一步      if (        curDiffCount.value == lineChangesDataList.value?.length ||        (hasNewNum && arr[arr.length - 1] == lineNumber)      ) {        curDiffCount.value = 1;        editor          .getModifiedEditor()          .revealLineInCenter(            lineChangesDataList.value[0].modifiedStartLineNumber,            lineChangesDataList.value[0].modifiedEndLineNumber          );        editor.setPosition({          column: 1,          lineNumber: lineChangesDataList.value[0]?.modifiedEndLineNumber,        });      } else {        curDiffCount.value = lineChangesDataMap.get(arr[positionIndex + 1]);        editor          .getModifiedEditor()          .revealLineInCenter(arr[positionIndex + 1], arr[positionIndex + 1]);        editor.setPosition({          column: 1,          lineNumber: arr[positionIndex + 1],        });      }    }, 300);  } else if (cmd === "goPrevDiff") {    setTimeout(() => {      //上一步      if (curDiffCount.value == 1 || (hasNewNum && arr[0] == lineNumber)) {        let diffNum = lineChangesDataList.value.length;        curDiffCount.value = diffNum;        editor          .getModifiedEditor()          .revealLineInCenter(            lineChangesDataList.value[diffNum - 1]?.modifiedStartLineNumber,            lineChangesDataList.value[diffNum - 1]?.modifiedEndLineNumber          );        editor.setPosition({          column: 1,          lineNumber:            lineChangesDataList.value[diffNum - 1]?.modifiedEndLineNumber,        });      } else {        curDiffCount.value = lineChangesDataMap.get(arr[positionIndex - 1]);        editor          .getModifiedEditor()          .revealLineInCenter(arr[positionIndex - 1], arr[positionIndex - 1]);        editor.setPosition({          column: 1,          lineNumber: arr[positionIndex - 1],        });      }    });  }};/** * @desc 获取最新编辑数据 */const getValue = () => {  return editor.getModel().modified.getValue();};/** * @desc 判断当前的languageId */function getLanguageId(curLanguage) {  return id;}/** * @desc 设置编辑器的位置 */function setPosition(column, lineNumber) {  editor.setPosition({    column: column,    lineNumber: lineNumber,  });  editor.getModifiedEditor().revealLineInCenter(lineNumber);  lineChangesDataList.value = editor.getLineChanges();  if (lineChangesDataList.value?.length > 0) {    lineChangesDataList.value.forEach((item, index) => {      if (item.modifiedEndLineNumber == item.modifiedStartLineNumber) {        lineChangesDataMap.set(item.modifiedStartLineNumber, index + 1);      } else {        for (          let i = item.modifiedStartLineNumber;          i <= item.modifiedEndLineNumber;          i++        ) {          lineChangesDataMap.set(i, index + 1);        }      }    });  }  curDiffCount.value = lineChangesDataMap.get(lineNumber);}/** * @desc 获取标记的信息 */function getModelMarkers() {  // setTimeout(() => {  // console.log("editor.getModel().modified.", editor.getModel().modified.getModelMarkers())  console.log("modifiedModel.uri", modifiedModel.uri);  console.log(    "monaco.editor.getModelMarkers();",    monaco.editor.getModelMarkers(modifiedModel.uri)  );  console.log(    "1111111111111",    monaco.editor.getModelMarkers({      resource: modifiedModel.uri,    })  );  return monaco.editor.getModelMarkers({    resource: modifiedModel.uri,  });  // })}/** * @desc monaco注销 */function dispose() {  editor.dispose();}defineExpose({  getValue,  getLanguageId,  setPosition,  getModelMarkers,  dispose,});/** * @desc 清理缓存 */onUnmounted(() => {});</script><style lang="less">.monaco-diff-box {  height: 100%;  .operate {    height: 36px;    .config-diff-count {      color: #ff5722;    }    .diffJump {      cursor: pointer;    }  }  #monacoDiff {    flex: 1;    height: calc(100% - 36px);    .monaco-editor .line-numbers.active-line-number {      color: #ff5722;    }  }}</style>

2、体积优化

待续…

二、ace-editor?

1、源码

代码如下(示例):

<template>  <v-ace-editor    v-model:value="modelValue"    @init="init"    lang="json"    :theme="theme"    :options="options"    :readonly="readonly"    :style="style"    /></template><script setup>import { VAceEditor } from "vue3-ace-editor";import "ace-builds/webpack-resolver";import "ace-builds/src-noconflict/mode-json";import "ace-builds/src-noconflict/theme-chrome";import "ace-builds/src-noconflict/ext-language_tools";const props = defineProps({    modelValue: {},    theme: {},    options: {},    readonly: {},    //自定义行内样式    style: {},})</script><style></style>
<ace-editor  v-model:value="tempFlow.textareashow"  @init="initFail"  lang="json"  :theme="aceConfig.theme"  :options="aceConfig.options"  :readonly="aceConfig.readOnly"  class="ace-editor"/>

2、体积优化

待续…

3、codemirror

1、diff

在这里插入图片描述

<template>  <div class="config-diff">    <div class="config-diff-title">      <div class="layout-start">        <div style="width: 50%">{{ leftText }}</div>        <div style="width: 10%">{{ rightText }}</div>        <div class="layout-end" style="width: 40%">          <span            >发现&nbsp;<span class="config-diff-count">{{ diffCount }}</span            >&nbsp;处修改</span          >          <span            >,当前第&nbsp;<span class="config-diff-count">{{              curDiffCount            }}</span            >&nbsp;处</span          >          <span            title="上一个"            v-debounce-click="              () => {                exeCommand('goPrevDiff');              }            "            class="diffJump"          >            <el-icon><CaretLeft /></el-icon>            上一个          </span>          &nbsp;&nbsp;&nbsp;&nbsp;          <span            title="下一个"            v-debounce-click="              () => {                exeCommand('goNextDiff');              }            "            class="diffJump"          >            下一个            <el-icon><CaretRight /></el-icon>          </span>        </div>      </div>    </div>    <div class="merge-view-main">      <div class="file-editor" id="config-diff-view" ref="configDiffView"></div>    </div>  </div></template><script setup>import { ref, getCurrentInstance, onMounted, watch } from "vue";import _ from "lodash";// 引入全局实例import CodeMirror from "codemirror";// 核心样式import "codemirror/lib/codemirror.css";// 引入主题后还需要在 options 中指定主题才会生效import "codemirror/theme/idea.css";// 需要引入具体的语法高亮库才会有对应的语法高亮效果// codemirror 官方其实支持通过 /addon/mode/loadmode.js 和 /mode/meta.js 来实现动态加载对应语法高亮库// 但 vue 貌似没有无法在实例初始化后再动态加载对应 JS ,所以此处才把对应的 JS 提前引入import "codemirror/mode/javascript/javascript.js";import "codemirror/mode/css/css.js";import "codemirror/mode/xml/xml.js";import "codemirror/mode/shell/shell.js";import "codemirror/mode/sql/sql.js";//代码补全提示import "codemirror/addon/hint/anyword-hint.js";import "codemirror/addon/hint/css-hint.js";import "codemirror/addon/hint/html-hint.js";import "codemirror/addon/hint/javascript-hint.js";import "codemirror/addon/hint/show-hint.css";import "codemirror/addon/hint/show-hint.js";import "codemirror/addon/hint/sql-hint.js";import "codemirror/addon/hint/xml-hint.js";//代码版本差异比较import "codemirror/addon/merge/merge.js";import "codemirror/addon/merge/merge.css";import DiffMatchPatch from "diff-match-patch";window.diff_match_patch = DiffMatchPatch;window.DIFF_DELETE = -1;window.DIFF_INSERT = 1;window.DIFF_EQUAL = 0;const props = defineProps({  newCode: {},  oldCode: {},  params: {},});const { proxy } = getCurrentInstance();//文件后缀和codemirror模式const FILE_POSTFIX = {  xml: "application/xml",  json: "application/json",  txt: "text/html",  lua: "text/x-lua",  py: "text/x-python",  js: "text/javascript",  sh: "text/x-sh",  other: "text/x-textile",};let configDiffView = ref(null);var dv;// 当前一共有多少处修改let diffCount = ref(0);// 当前cursor指示的几处修改let curDiffCount = ref(0);let newCode = "";let oldCode = "";let leftText = ref(props.params.leftText || "修改前");let rightText = ref(props.params.rightText || "修改后");const postfix = proxy.$commonSvc.getFilePostfix(props.params.name);const mode = FILE_POSTFIX[postfix] || FILE_POSTFIX.other;function initUI(target) {  if (oldCode == null) return;  target.innerHTML = "";  dv = CodeMirror.MergeView(target, {    value: newCode,    origLeft: oldCode,    orig: null,    lineNumbers: true, //显示行号    lineWrapping: true,    readOnly: false,    mode: mode,    autofocus: true,    foldGutter: true, //代码折叠    highlightDifferences: "highlight", //有差异的地方是否高亮    collapseIdentical: true,    connect: null,  });  setTimeout(function () {    dv.editor().refresh();    dv.leftOriginal() && dv.leftOriginal().refresh();  }, 500);  var diffs = dv.leftChunks();  diffCount.value = (diffs && diffs.length) || 0;  curDiffCount.value = 0;}/** * @desc exeCommand 执行codemirror mergeview的命令类型 * @param {*} cmd * 前进一步(goNextDiff) or * 后退异步(goPrevDiff) */const exeCommand = (cmd) => {  if (diffCount.value == 0) {    return;  } else {    return new Promise((resolve, reject) => {      if (dv) {        if (cmd === "goNextDiff") {          //下一步          if (curDiffCount.value < diffCount.value) {            ++curDiffCount.value;          } else {            curDiffCount.value = 1;          }        } else if (cmd === "goPrevDiff") {          //上一步          if (curDiffCount.value > 1) {            curDiffCount.value--;          } else {            curDiffCount.value = diffCount.value;          }        }        if (curDiffCount.value === 0) return;        // 延时,等待diffView刷新后,在定位,存在一定的误差,主要在于不确定diffView刷新需要的时间        setTimeout(function () {          proxy.$commonSvc.highlightCodeMirror(            configDiffView.value,            curDiffCount.value          );        }, 300);      }    });  }};/** * @desc getMergeConfig */const getMergeConfig = () => {  if (!dv) {    return;  }  var edit = dv.edit;  if (!edit) {    return;  }  return edit.getValue();};onMounted(() => {  newCode = props.newCode;  oldCode = props.oldCode;  var target = configDiffView.value;  initUI(target);});watch(  () => [props.newCode, props.params],  (newValue) => {    newCode = props.newCode;    oldCode = props.oldCode;    var target = configDiffView.value;    initUI(target);  },  {    deep: true,  });defineExpose({  getMergeConfig,});</script><style lang="less" scoped>.config-diff {  height: 100%;  display: flex;  flex-direction: column;  padding: 0 16px;  .config-diff-title {    height: 36px;    .config-diff-count {      color: #ff5722;    }  }  .merge-view-main {    flex: 1;    .file-editor {      height: 600px;      .CodeMirror-merge,      .CodeMirror {        z-index: 88888;        height: 520px !important;      }    }    .light-cursor {      background: #b390f7;    }  }  @media (min-width: 760px) {    .merge-view-main {      .file-editor {        .CodeMirror-merge,        .CodeMirror {          height: 290px !important;        }      }    }  }  @media (min-width: 1440px) {    .merge-view-main {      .file-editor {        .CodeMirror-merge,        .CodeMirror {          height: 520px !important;        }      }    }  }  .dev-test {    .cm-s-blackboard.CodeMirror,    .CodeMirror-merge-copybuttons-right,    svg,    .CodeMirror-merge-2pane .CodeMirror-merge-gap {      height: 100%;    }  }  .merge-event {    .CodeMirror-merge-copy {      pointer-events: auto !important;    }  }}.diffJump {  cursor: pointer;}</style>
  /**   * @desc codemirror merge next和pre 高亮   * @param codeWrap {{string|Dom Element}} 需要检查的code所属的一个dom元素,目的缩小查询范围   *  @param lineNumber {{number}} 需要高亮的行   */  highlightCodeMirror(codeWrap, curDiffCount) {    if (!codeWrap) {      return false;    }    var lines_left = $(".CodeMirror-merge-left", $(codeWrap))      .find(".CodeMirror-linebackground")      .get();    var lines_right = $(".CodeMirror-merge-editor", $(codeWrap))      .find(".CodeMirror-linebackground")      .get();    var merge_left = $(".CodeMirror-merge-left", $(codeWrap))      .find(".CodeMirror-merge-l-chunk")      .get();    var merge_right = $(".CodeMirror-merge-editor", $(codeWrap))      .find(".CodeMirror-merge-l-chunk")      .get();    var lineNumber_left;    var lineNumber_right;    var merge_left_end = $(".CodeMirror-merge-left", $(codeWrap)).find(      ".CodeMirror-merge-l-chunk-end"    );    var merge_right_end = $(".CodeMirror-merge-editor", $(codeWrap)).find(      ".CodeMirror-merge-l-chunk-end"    );    var lineNumber_left_end = merge_left_end      .eq(curDiffCount - 1)      .parent()      .find(".CodeMirror-linenumber")      .text();    var lineNumber_right_end = merge_right_end      .eq(curDiffCount - 1)      .parent()      .find(".CodeMirror-linenumber")      .text();    /**     * @desc 定位每次修改高亮的起始和结束位置     */    for (var i = lines_left.length - 1; i >= 0; i--) {      var temp = $(lines_left[i]).parent().find(".CodeMirror-linenumber");      var value = parseInt($(temp).text());      var value_end = parseInt(lineNumber_left_end);      if (value <= value_end) {        if (          value < value_end &&          $(lines_left[i]).attr("class").indexOf("-end") != -1        ) {          break;        }        if ($(lines_left[i]).attr("class").indexOf("-start") != -1) {          lineNumber_left = $(temp).text();        }      }    }    for (var i = lines_right.length - 1; i >= 0; i--) {      var temp = $(lines_right[i]).parent().find(".CodeMirror-linenumber");      var value = parseInt($(temp).text());      var value_end = parseInt(lineNumber_right_end);      if (value <= value_end) {        if (          value < value_end &&          $(lines_right[i]).attr("class").indexOf("-end") != -1        ) {          break;        }        if ($(lines_right[i]).attr("class").indexOf("-start") != -1) {          lineNumber_right = $(temp).text();        }      }    }    /**     * @desc 注入样式     */    merge_left.forEach(function (item) {      var temp = $(item).parent().find(".CodeMirror-linenumber");      if (        lineNumber_left &&        parseInt($(temp).text()) >= parseInt(lineNumber_left) &&        parseInt($(temp).text()) <= parseInt(lineNumber_left_end)      ) {        $(item).addClass("light-cursor");      } else {        $(item).removeClass("light-cursor");      }    });    merge_right.forEach(function (item) {      var temp = $(item).parent().find(".CodeMirror-linenumber");      if (        lineNumber_right &&        parseInt($(temp).text()) >= parseInt(lineNumber_right) &&        parseInt($(temp).text()) <= parseInt(lineNumber_right_end)      ) {        $(item).addClass("light-cursor");      } else {        $(item).removeClass("light-cursor");      }    });  },

总结

提示:这里对文章进行总结:

记录web在线编辑器的~


点击全文阅读


本文链接:http://zhangshiyu.com/post/158115.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1