首页 > 解决方案 > 简单的基于多色文本区域的编辑器

问题描述

我需要为拆分 HTML/CSS/JS/Result 编辑工具着色 textarea 代码。在此示例中,我希望标签为一种颜色,而所有其他文本为另一种颜色。

始终使用等宽字体。

所以我决定将标签文本与其他部分分开,并将每个部分放在主要部分之上的自己的文本区域中。缺失的一半(标签的常规文本和其余的标签文本)被空格替换,以将所有内容保持在正确的位置。

下面是一个工作片段(我只做了简单的打字测试)。

我有一些问题:

  1. 这种方法有什么主要缺点吗?最终用户会不会在 textarea 中截断一些常用的文本操作?

  2. 我使用以下正则表达式将标签与文本的其余部分分开:

    elem.value.match(/(<[^<>]+>)|([\s\S]*?(?=(<[^<>]+>)))|((?<=(<[^<>]+>))[\s\S]*)/g);
    

这里的想法是匹配标签(<[^<>]+>)或标签后面的东西或标签后面的东西。

是否有可能使这个表达式更简单?

理想情况下,要说捕获“标签”或“不是标签”,我很难定义后者。

const TAB = '  ';

const get = id => document.getElementById(id);

const [main, tag, txt] = [get('main'), get('tag'), get('txt')];

const colorizeHTML = evt => { 
    const elem = evt.target;
    const arr = elem.value.split(/(?!^)(?=<[^<>]+>)|(?<=<[^<>]+>)(?!$)/);
    if (!arr) return;
    let [str_tag, str_txt] = ['', ''];
    arr.forEach(s => {
        const repl = s.replace(/[^\n ]/g, '\xa0');
        if (s[0] == '<' && s[s.length - 1] == '>') {
            str_tag += s;
            str_txt += repl;
        } else {
            str_tag += repl;
            str_txt += s;
        }
    });
    tag.value = str_tag;
    txt.value = str_txt;
}

const onKeyDownDefault = evt => {
    if (evt.key == "Tab") {
        evt.preventDefault();
        document.execCommand('insertText', false, TAB);
    }
}

const onScroll = evt => {
    const scr = evt.target.scrollTop;
    tag.scrollTop = scr;
    txt.scrollTop = scr;
}

main.addEventListener('keydown', onKeyDownDefault);
main.addEventListener('scroll', onScroll);

['input', 'keyup', 'mouseup', 'drop', 'paste'].forEach(nm => { main.addEventListener(nm, colorizeHTML) });

main.value = 'Chapter 12<div id="sec1">\n<div>Standard Curves</div>\n<div id="tot1"></div>\n<button id="btn1">Toggle points</button>\n</div>';
colorizeHTML({ target: main });
* {
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
}

body {
  background-color: #000;
  color: #999;
}

textarea:focus {
  outline: none;
}

#wrapper {
  margin: 5px;
  position: relative;
  width: 400px;
  height: 170px;
}

#tag, #txt {
  position: absolute;
  left: 0px;
  top: 0px;
  pointer-events: none;
}

#main, #tag, #txt {
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0);
  resize: none;
  font-family: monospace;
  padding: 3px;
}

#main {
  border: solid 1px #666;
  background: rgba(8, 15, 32, 1.0);
  caret-color: #91d6db;
}

#main::selection {
  background: rgba(0, 255, 128, 0.15);
}

#main::-moz-selection {
  background: rgba(0, 255, 128, 0.15);
}

#tag {
    color: #4576e6;
}

#txt {
    color: #9bc6ca;
}

.clean_scroll {
  overflow: scroll;
  -ms-overflow-style: none;
  scrollbar-width: none;
}

.clean_scroll::-webkit-scrollbar {
    display: none;
}
<div id="wrapper">
<textarea id="main" class="clean_scroll"></textarea>
<textarea id="tag" class="clean_scroll"></textarea>
<textarea id="txt" class="clean_scroll"></textarea>
</div>

标签: javascriptregex

解决方案


推荐阅读