vue中使用CodeMirror解析yaml语言

一、CodeMirror插件使用

1.CodeMirror插件安装

下载插件:npm install codemirror @5.59.1
这里使用的是codemirror5,现在codemirror最新已经是6了,不过参考文档相对较少,使用起来不是那么方便。后续文档丰富之后可以考虑使用6

二、CodeMirror基本配置

这里使用到的配置如下

    const options = {
    
    
      mode: 'yaml',
      // 缩进格式
      tabSize: 2,
      // 主题,对应主题库 JS 需要提前引入
      theme: 'base16-dark',
      // 行号码
      lineNumbers: true,
      line: true,
      readOnly: false,
      // 是否开启语法校验
      lint: true,
      // 使用的语法校验工具
      gutters: ['CodeMirror-lint-markers'],
      // 光标背景行高亮
      styleActiveLine: true,
      // 自动刷新
      autoRefresh: true,
      height: '500px'
    }

三、CodeMirror具体使用

1.首先创建一个textarea标签

<textarea ref="textarea" v-model="code"></textarea>

2.然后引入相关依赖

// 基础依赖
import CodeMirror from 'codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/javascript/javascript.js'
import 'codemirror/mode/css/css.js'
// 语法模式 这里我使用的是yaml,各位按需引入(json、html等等)
import 'codemirror/mode/${props.mode}/yaml.js'
// 主题样式
import 'codemirror/theme/base16-dark.css'
// 自动刷新依赖
import 'codemirror/addon/display/autorefresh'
// 行高亮依赖
import 'codemirror/addon/selection/active-line'

3.最后初始化编辑器

	// textarea为textarea标签的ref,vue3写法
	const textarea = ref(null)
	// 初始化编辑器实例,传入需要被实例化的文本域对象和默认配置
 	coder = CodeMirror.fromTextArea(textarea.value, options)
   	coder.on('blur', coder => {
    
    
   		// 获取文本内容
        const newValue = coder.getValue()
        // 抛出事件
        emit('update:modelValue', newValue)
      })

四、CodeMirror语法校验

1.引入语法校验依赖

// 语法校验基础依赖
import 'codemirror/addon/lint/lint.js'
import 'codemirror/addon/lint/lint.css'
// yaml校验js,按需引入(json-lint、html-lint等)
import 'codemirror/addon/lint/yaml-lint.js'

codemirror支持的校验库如下
在这里插入图片描述

2.配置options中开启校验

// 是否开启语法校验
lint: true,
// 使用的语法校验工具
gutters: ['CodeMirror-lint-markers'],

3.安装lint需要的其他依赖

仅仅是这样还是不够的,因为codemirror对应的校验插件中可能还依赖其他的库
比如yaml:
在这里插入图片描述
可以看到他还依赖js-yaml,所以我们需要下载js-yaml插件 npm install js-yaml
在代码中引入: import jsYaml from 'js-yaml' 绑定到window上 window.jsyaml = jsYaml
其他语法也类似,例如json需要json-lint,然后绑定到window.jsonlint上:在这里插入图片描述

五、完整代码

我将codemirror封装为一个vue3组件,各位可以参考一下

<template>
  <div class="in-coder-panel">
    <textarea ref="textarea" v-model="code"></textarea>
  </div>
</template>

<script>
import {
      
       onMounted, ref, watch } from 'vue'
import CodeMirror from 'codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/javascript/javascript.js'
import 'codemirror/mode/css/css.js'
import 'codemirror/addon/lint/yaml-lint.js'
import jsYaml from 'js-yaml'
window.jsyaml = jsYaml
export default {
      
      
  components: {
      
      },
  props: {
      
      
    modelValue: {
      
      
      type: String,
      default: ``
    },
    mode: {
      
      
      type: String,
      default: 'javascript'
    },
    lint: {
      
      
      // codemirror仅支持html、css、json、javascript、yaml这几种,请手动引入,且需要下载相关插件,具体插件参考源码(node_modules/codemirror/addon/lint/)或官方文档
      type: Boolean,
      default: false
    },
    readonly: {
      
      
      type: Boolean,
      default: false
    },
    // 主题
    theme: {
      
      
      type: String,
      default: 'base16-dark' // 编辑器主题色
    },
    // 高亮选中行
    styleActiveLine: {
      
      
      type: Boolean,
      default: true
    },
    // 自动刷新
    autoRefresh: {
      
      
      type: Boolean,
      default: true
    }
  },
  emits: ['update:modelValue'],
  setup(props, {
       
        emit }) {
      
      
    const textarea = ref(null)
    const code = ref(props.modelValue)
    // 编辑器实例
    let coder
    watch(
      () => props.modelValue,
      val => {
      
      
        coder?.setValue(val)
      }
    )
    const options = {
      
      
      mode: props.mode,
      // 缩进格式
      tabSize: 2,
      // 主题,对应主题库 JS 需要提前引入
      theme: props.theme,
      // 行号码
      lineNumbers: true,
      line: true,
      // extraKeys: {'Ctrl': 'autocomplete'},//自定义快捷键
      readOnly: props.readonly,
      lint: props.lint,
      gutters: ['CodeMirror-lint-markers'],
      // 光标背景行高亮
      styleActiveLine: props.styleActiveLine,
      // 自动刷新
      autoRefresh: props.autoRefresh,
      height: '500px'
    }
    const initialize = async () => {
      
      
      try {
      
      
      // 动态引入相关依赖
        await import(`codemirror/theme/${ 
        props.theme}.css`)
        if (props.lint) {
      
      
          await import('codemirror/addon/lint/lint.js')
          await import('codemirror/addon/lint/lint.css')
        }
        if (props.mode) {
      
      
          await import(`codemirror/mode/${ 
        props.mode}/${ 
        props.mode}.js`)
        }
        if (props.autoRefresh) {
      
      
          await import('codemirror/addon/display/autorefresh')
        }
        if (props.styleActiveLine) {
      
      
          await import('codemirror/addon/selection/active-line')
        }
      } catch (e) {
      
      
        console.log(e)
      }
      // 初始化编辑器实例,传入需要被实例化的文本域对象和默认配置
      coder = CodeMirror.fromTextArea(textarea.value, options)
      coder.on('blur', coder => {
      
      
        const newValue = coder.getValue()
        emit('update:modelValue', newValue)
      })
    }
    onMounted(() => {
      
      
      initialize()
    })
    const checkYaml = async val => {
      
      
      jsYaml.load(val)
    }
    return {
      
      
      code,
      options,
      textarea,
      checkYaml
    }
  }
}
</script>

<style lang="scss" scoped>
.in-coder-panel {
      
      
  width: 100%;
  height: 100%;
  :deep(.CodeMirror) {
      
      
    border: 1px solid #eee;
    height: 100%;
    width: 100%;
    .CodeMirror-code {
      
      
      line-height: 19px;
    }
  }
}
</style>
<style>
.CodeMirror-lint-tooltip {
      
      
  z-index: 10000 !important;
}
</style>

具体使用:

<template>
  <div>
    <base-codemirror
      ref="yamlRef"
      v-model="code"
      mode="yaml"
      style="height: 200px"
      :lint="true"
      :readonly="true"
    ></base-codemirror>
    <el-button @click="btnClick">点击</el-button>
  </div>
</template>

<script>
import BaseCodemirror from '@/components/Base/BaseCodemirror'
import {
      
       ref } from 'vue'
export default {
      
      
  name: 'Demo',
  components: {
      
      
    BaseCodemirror
  },
  setup() {
      
      
    const yamlRef = ref(null)
    const code = ref(`apiVersion: apps/v1
kind: DaemonSet
metadata:
  annotations:
    deprecated.daemonset.template.generation: "1"
    field.cattle.io/creatorId: user-jsgrs
  creationTimestamp: "2022-05-16T03:08:58Z"
  generation: 1
  labels:
    cattle.io/creator: norman
    workload.user.cattle.io/workloadselector: daemonSet-default-asdf`)
    const btnClick = () => {
      
      
      yamlRef.value.checkYaml(code).then(() => {
      
      
        console.log(11)
      })
    }
    return {
      
      
      code,
      yamlRef,
      btnClick
    }
  }
}
</script>

<style scoped></style>

猜你喜欢

转载自blog.csdn.net/weixin_43845090/article/details/125403699