<template>
  <div>
    <codemirror v-model="content" :options="editorOptions" @input="handletextContentChange" class="content"></codemirror>
    <div slot="footer" class="dialog-footer">
      <div class="left">
        <el-button type="primary" @click="formateXml(content)">格式化</el-button>
      </div>
      <div class="right">
        <el-button type="primary" @click="determine">确定修改</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </div>
  </div>
</template>

<script>
//xml编辑器
import { codemirror } from 'vue-codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/xml/xml.js'
import 'codemirror/theme/ssms.css' // 根据需要选择主题
import 'codemirror/keymap/sublime'
import "codemirror/addon/hint/xml-hint.js";
export default {
  name: 'XmlEditor',
  components: {
    codemirror,
  },
  props:[ 'textContent','closeEditor','dataType'],
  data() {
    return {
      // 初始的 text 内容
      content: this.textContent, 
      // 绑定的数据
      bindContentData:this.textContent,
      editorOptions: null,
    }
  },
  created(){
    if(this.dataType==='XML'){
      this.editorOptions={
        mode: 'xml',
        theme: 'ssms', // 根据需要选择主题
        // 缩进格式
				tabSize: 2,
        autocorrect: true, // 自动更正
        spellcheck: true, // 拼写检查
        lint: true, // 检查格式
        lineNumbers: true, //是否显示行数
        lineWrapping: true, //是否自动换行
        styleActiveLine: true, //line选择是是否高亮
        keyMap: 'sublime', // sublime编辑器效果
        matchBrackets: true, //括号匹配
        autoCloseBrackets: true, // 在键入时将自动关闭括号和引号
        matchTags: { bothTags: true }, // 将突出显示光标周围的标签
        autoFormatOnLoad: true
      }
      this.formateXml(this.content)
    }
  },
  methods:{
    handletextContentChange(textContent) {
      // 在这里处理 XML 内容的变化
      // console.log(textContent)
    },
    // xml格式化
    formateXml(xmlStr){
      var that = this;
        var text = xmlStr;
        //使用replace去空格
        text = '\n' + text.replace(/(<\w+)(\s.*?>)/g,function($0, name, props){
            return name + ' ' + props.replace(/\s+(\w+=)/g," $1");
        }).replace(/>\s*?</g,">\n<");
        //处理注释
        text = text.replace(/\n/g,'\r').replace(/<!--(.+?)-->/g,function($0, text){
            var ret = '<!--' + escape(text) + '-->';
            return ret;
        }).replace(/\r/g,'\n');
        //调整格式  以压栈方式递归调整缩进
        var rgx = /\n(<(([^\?]).+?)(?:\s|\s*?>|\s*?(\/)>)(?:.*?(?:(?:(\/)>)|(?:<(\/)\2>)))?)/mg;
        var nodeStack = [];
        var output = text.replace(rgx,function($0,all,name,isBegin,isCloseFull1,isCloseFull2 ,isFull1,isFull2){
            var isClosed = (isCloseFull1 == '/') || (isCloseFull2 == '/' ) || (isFull1 == '/') || (isFull2 == '/');
            var prefix = '';
            if(isBegin == '!'){//!开头
                prefix = that.setPrefix(nodeStack.length);
            }else {
                if(isBegin != '/'){///开头
                    prefix = that.setPrefix(nodeStack.length);
                    if(!isClosed){//非关闭标签
                        nodeStack.push(name);
                    }
                }else{
                    nodeStack.pop();//弹栈
                    prefix = that.setPrefix(nodeStack.length);
                }
            }
            var ret =  '\n' + prefix + all;
            return ret;
        });
        var prefixSpace = -1;
        var outputText = output.substring(1);
        //还原注释内容
        outputText = outputText.replace(/\n/g,'\r').replace(/(\s*)<!--(.+?)-->/g,function($0, prefix,  text){
            if(prefix.charAt(0) == '\r')
                prefix = prefix.substring(1);
            text = unescape(text).replace(/\r/g,'\n');
            var ret = '\n' + prefix + '<!--' + text.replace(/^\s*/mg, prefix ) + '-->';
            return ret;
        });
        outputText= outputText.replace(/\s+$/g,'').replace(/\r/g,'\r\n');
        this.content=outputText
        // return outputText;
    },
    //计算头函数 用来缩进
    setPrefix(prefixIndex) {
        var result = '';
        var span = '    ';//缩进长度
        var output = [];
        for(var i = 0 ; i < prefixIndex; ++i){
            output.push(span);
        }
        result = output.join('');
        return result;
    },
    determine(){
      this.closeEditor(this.content)
    },
    cancel(){
      this.closeEditor('no')
    }
  }
}
</script>

<style scoped>
::v-deep .CodeMirror-code{
  font-size: 18px;
}
.dialog-footer{
  margin-top: 20px;
  display: flex;
  justify-content: space-around;
  
}
</style>