javascript - 简单的基于多色文本区域的编辑器
问题描述
我需要为拆分 HTML/CSS/JS/Result 编辑工具着色 textarea 代码。在此示例中,我希望标签为一种颜色,而所有其他文本为另一种颜色。
始终使用等宽字体。
所以我决定将标签文本与其他部分分开,并将每个部分放在主要部分之上的自己的文本区域中。缺失的一半(标签的常规文本和其余的标签文本)被空格替换,以将所有内容保持在正确的位置。
下面是一个工作片段(我只做了简单的打字测试)。
我有一些问题:
这种方法有什么主要缺点吗?最终用户会不会在 textarea 中截断一些常用的文本操作?
我使用以下正则表达式将标签与文本的其余部分分开:
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>
解决方案
推荐阅读
- javascript - 我无法在 React JS 中传递动态创建的单选按钮值
- amazon-web-services - 客户端错误后如何将消息发送到死信队列?
- cxf-codegen-plugin - CXF 2.x 代码生成不生成引用类
- django - Django Follow-Unfollow 系统问题
- vba - 如何将收件箱 ItemAdd 转换为在子文件夹上运行?
- reactjs - React-Router 渲染道具
- java - okhhtp3 mockserver:连接被拒绝
- node.js - 如何使用 prisma 和 postgresql 处理条件准备语句?
- node.js - 如何在 NodeJS 和 ExpressJS 中获取客户端时区?
- javascript - React/Material UI:Cmd+Click 未在新选项卡中打开链接