Vue uses monaco to achieve code highlighting

Vue uses monaco to achieve code highlighting

Using the Vue language and element components, we need to make an online code editor that requires the input of code content, which can be highlighted, can switch between different languages, support keyword completion, and have a left-right comparison of code between different versions. This is the requirement.

As for why monaco was chosen, please check out the comprehensive comparison of code highlighting plugins in vue (element)

Okay, now let’s get started!

First you need to download the monaco-editor component and the monaco-editor-webpack-plugin component

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

Of course, npm downloads are very slow, so change to a domestic mirror, such as Taobao's. Sure enough, the speed increased rapidly.

npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install

cnpm install monaco-editor
cnpm install monaco-editor-webpack-plugin

You can see its directory structure under node_modules

The core code is as follows

First, write a component for other pages to import and call.

CodeEditor.vue

<template>
 <div class="code-container" ref="container"></div>
</template>

<script>
 import * as monaco from "monaco-editor";
 let sqlStr =
 "ADD EXCEPT PERCENT ALL EXEC PLAN ALTER EXECUTE PRECISION AND EXISTS PRIMARY ANY EXIT PRINT AS FETCH PROC ASC FILE PROCEDURE AUTHORIZATION FILLFACTOR PUBLIC BACKUP FOR RAISERROR BEGIN FOREIGN READ BETWEEN FREETEXT READTEXT BREAK FREETEXTTABLE RECONFIGURE BROWSE FROM REFERENCES BULK FULL REPLICATION BY FUNCTION RESTORE CASCADE GOTO RESTRICT CASE GRANT RETURN CHECK GROUP REVOKE CHECKPOINT HAVING RIGHT CLOSE HOLDLOCK ROLLBACK CLUSTERED IDENTITY ROWCOUNT COALESCE IDENTITY_INSERT ROWGUIDCOL COLLATE IDENTITYCOL RULE COLUMN IF SAVE COMMIT IN SCHEMA COMPUTE INDEX SELECT CONSTRAINT INNER SESSION_USER CONTAINS INSERT SET CONTAINSTABLE INTERSECT SETUSER CONTINUE INTO SHUTDOWN CONVERT IS SOME CREATE JOIN STATISTICS CROSS KEY SYSTEM_USER CURRENT KILL TABLE CURRENT_DATE LEFT TEXTSIZE CURRENT_TIME LIKE THEN CURRENT_TIMESTAMP LINENO TO CURRENT_USER LOAD TOP CURSOR NATIONAL TRAN DATABASE NOCHECK TRANSACTION DBCC NONCLUSTERED TRIGGER DEALLOCATE NOT TRUNCATE DECLARE NULL TSEQUAL DEFAULT NULLIF UNION DELETE OF UNIQUE DENY OFF UPDATE DESC OFFSETS UPDATETEXT DISK ON USE DISTINCT OPEN USER DISTRIBUTED OPENDATASOURCE VALUES DOUBLE OPENQUERY VARYING DROP OPENROWSET VIEW DUMMY OPENXML WAITFOR DUMP OPTION WHEN ELSE OR WHERE END ORDER WHILE ERRLVL OUTER WITH ESCAPE OVER WRITETEXT";
 export default {
 name: "codeEditor",

 props: {
  options:
  type: Object,
  default() {
   return {
   language: "java", // shell, sql, python
   readOnly: true // cannot be edited};
  }
  },

  value: {
  type: String,
  default: ""
  }
 },

 data() {
  return {
  monacoInstance: null,
  provider: null,
  hints: [
   "SELECT",
   "INSERT",
   "DELETE",
   "UPDATE",
   "CREATE TABLE",
   "DROP TABLE",
   "ALTER TABLE",
   "CREATE VIEW",
   "DROP VIEW",
   "CREATE INDEX",
   "DROP INDEX",
   "CREATE PROCEDURE",
   "DROP PROCEDURE",
   "CREATE TRIGGER",
   "DROP TRIGGER",
   "CREATE SCHEMA",
   "DROP SCHEMA",
   "CREATE DOMAIN",
   "ALTER DOMAIN",
   "DROP DOMAIN",
   "GRANT",
   "DENY",
   "REVOKE",
   "COMMIT",
   "ROLLBACK",
   "SET TRANSACTION",
   "DECLARE",
   "EXPLAN",
   "OPEN",
   "FETCH",
   "CLOSE",
   "PREPARE",
   "EXECUTE",
   "DESCRIBE",
   "FORM",
   "ORDER BY"
  ]
  };
 },
 created() {
  this.initHints();
 },
 mounted() {
  this.init();
 },
 beforeDestroy() {
  this.dispose();
 },

 methods: {
  dispose() {
  if (this.monacoInstance) {
   if (this.monacoInstance.getModel()) {
   this.monacoInstance.getModel().dispose();
   }
   this.monacoInstance.dispose();
   this.monacoInstance = null;
   if (this.provider) {
   this.provider.dispose();
   this.provider = null
   }
  }
  },
  initHints() {
  let sqlArr = sqlStr.split(" ");
  this.hints = Array.from(new Set([...this.hints, ...sqlArr])).sort();
  },
  init() {
  let that = this;
  this.dispose();
  let createCompleters = textUntilPosition => {
   //Filter special characters let _textUntilPosition = textUntilPosition
   .replace(/[\*\[\]@\$\(\)]/g, "")
   .replace(/(\s+|\.)/g, " ");
   //Cut into array let arr = _textUntilPosition.split(" ");
   //Get the current input value let activeStr = arr[arr.length - 1];
   //Get the length of the input value let len ​​= activeStr.length;

   //Get the existing content in the editing area let rexp = new RegExp('([^\\w]|^)'+activeStr+'\\w*', "gim");
   let match = that.value.match(rexp);
   let _hints = !match ? [] : match.map(ele => {
   let rexp = new RegExp(activeStr, "gim");
   let search = ele.search(rexp);
   return ele.substr(search)
   })

   // Find elements that match the current input value let hints = Array.from(new Set([...that.hints, ..._hints])).sort().filter(ele => {
   let rexp = new RegExp(ele.substr(0, len), "gim");
   return match && match.length === 1 && ele === activeStr || ele.length === 1
    ? false
    : activeStr.match(rexp);
   });
   //Add content hints let res = hints.map(ele => {
   return {
    label: ele,
    kind: that.hints.indexOf(ele) > -1 ? monaco.languages.CompletionItemKind.Keyword : monaco.languages.CompletionItemKind.Text,
    documentation: ele,
    insertText:ele
   };
   });
   return res;
  };
  this.provider = monaco.languages.registerCompletionItemProvider("sql", {
   provideCompletionItems(model, position) {
   var textUntilPosition = model.getValueInRange({
    startLineNumber: position.lineNumber,
    startColumn: 1,
    endLineNumber: position.lineNumber,
    endColumn: position.column
   });
   var suggestions = createCompleters(textUntilPosition);
   return {
    suggestions: suggestions
   };

   return createCompleters(textUntilPosition);
   }
  });

  // Initialize the editor instance this.monacoInstance = monaco.editor.create(this.$refs["container"], {
   value: this.value,
   theme: "vs-dark",
   autoIndex: true,
   ...this.options
  });

  // Listen for editor content change events this.monacoInstance.onDidChangeModelContent(() => {
   this.$emit("contentChange", this.monacoInstance.getValue());
  });
  }
 }
 };
</script>

<style lang="scss" scope>
 .code-container {
 width: 100%;
 height: 100%;
 overflow: hidden;
 border: 1px solid #eaeaea;
 .monaco-editor .scroll-decoration {
  box-shadow: none;
 }
 }
</style>

Import page for use on this page

index.vue

<template>
 <div class="container">
 <code-editor
  :options="options"
  :value="content"
  @contentChange="contentChange"
  style="height: 400px; width: 600px;"
 ></code-editor>
 </div>
</template>

<script>
 import CodeEditor from "@/components/CodeEditor";
 export default {
 name: "SQLEditor",
 components:
  CodeEditor
 },
 data() {
  return {
  content: "",
  options:
   language: "sql",
   theme: 'vs',
   readOnly: false
  }
  };
 },
 created() {},
 methods: {
  // Changes in the value of the binding editor contentChange(val) {
  this.content = val;
  }
 }
 };
</script>


<style scoped lang="scss">
 .container {
 text-align: left;
 padding: 10px;
 }
</style>

The effect is as follows

The code automatically prompts the effect, as shown below

Code highlighting effect, code segment folding effect, and the preview effect on the right are as follows

The above is the details of how Vue uses monaco to achieve code highlighting. For more information about Vue code highlighting, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Vue code highlighting plug-in comprehensive comparison and evaluation
  • Use highlight.js in Vue to achieve code highlighting and click copy

<<:  Graphic tutorial on configuring log server in Linux

>>:  CentOS 6.5 installation mysql5.7 tutorial

Recommend

Detailed explanation of the life cycle of Angular components (Part 2)

Table of contents 1. View hook 1. Things to note ...

Analysis of Linux configuration to achieve key-free login process

1.ssh command In Linux, you can log in to another...

How to add Nginx proxy configuration to allow only internal IP access

location / { index index.jsp; proxy_next_upstream...

Nodejs uses readline to prompt for content input example code

Table of contents Preface 1. bat executes js 2. T...

jQuery plugin to implement search history

A jQuery plugin every day - to make search histor...

How to solve the problem that MySQL cannot start because it cannot create PID

Problem Description The MySQL startup error messa...

How to recompile Nginx and add modules

When compiling and installing Nginx, some modules...

Sample code for highlighting search keywords in WeChat mini program

1. Introduction When you encounter a requirement ...

Linux command line operation Baidu cloud upload and download files

Table of contents 0. Background 1. Installation 2...

Analyzing the MySql CURRENT_TIMESTAMP function by example

When creating a time field DEFAULT CURRENT_TIMEST...

MySQL constraint types and examples

constraint Constraints ensure data integrity and ...

VUE+Canvas implements the sample code of the desktop pinball brick-breaking game

Everyone has played the pinball and brick-breakin...

A detailed explanation of how React Fiber works

Table of contents What is React Fiber? Why React ...