
当我正在研究一个需要编辑器组件的项目时,我真的希望一种方法让编辑器突出显示键入的语法。有类似的项目,例如Codemirror,Ace和Monaco,但它们都是重量重量,功能丰富的编辑,而不仅仅是我想要的语法强调的可编辑Textareas。
这花了一些罚款,但是我最终做出了一些可以完成这项工作的东西,并想分享我的工作方式,因为它涉及将流行的语法集成到HTML的编辑功能,以及一些有趣的边缘案例以及一些有趣的案例。
继续前进,在我们挖进去时旋转!
建议之后,我还将其作为自定义元素在GitHub上发布,因此您可以快速将网页中的组件用作单个元素。</code-input></p>
<h3>问题</h3>
<p>首先,我尝试使用DIV上的可满足属性。我在DIV中键入了一些源代码,并通过JavaScript在输入上通过Prism.js(一种流行的语法荧光笔)进行了运行。似乎是一个体面的主意,对吧?我们有一个可以在前端进行编辑的元素,Prism.js将其语法样式应用于元素中的键入内容。</p>
<p>克里斯(Chris)涵盖了如何在此视频中使用Prism.js。</p>
<p>但这是不做的。每次元素中的内容更改时,都会操纵DOM并将<strong>用户的光标推回代码的开始</strong>,这意味着源代码向后出现,最后一个字符在开始,而第一个字符在末尾。</p>
<p>接下来,我尝试使用<textarea>,但这也不起作用,因为<strong>TextAreas只能包含纯文本</strong>。换句话说,我们无法为已输入的内容设计样式。文本方面似乎是编辑文本而没有不必要的错误的唯一方法 - 它不允许Prism.js做事。</textarea></p>
<p>当源代码包裹在典型的</p>
<pre class="brush:php;toolbar:false"> <code>标签组合中时,Prism.js的工作要好得多 - 仅缺少方程式的可编辑部分。<p>因此,似乎都不是独自工作。但是,我想,<em>为什么不呢?</em></p>
<h3>解决方案</h3>
<p>我在页面上添加了语法高点</p>
<pre class="brush:php;toolbar:false"> <code><em>和</em>textarea,并使用JavaScript函数使<pre class="brush:php;toolbar:false"> <code>更改instut的Innertext内容。我还向<pre class="brush:php;toolbar:false"> <code>结果添加了一个隐藏的属性,以便屏幕读取器只能读取输入的内容,而不是两次大声朗读。<pre rel="HTML" data-line=""> <textarea oninput="“" update> </textarea>
<pre aria-hidden="“" true>
<code> </code>
</pre></pre>
<pre rel="JavaScript" data-line="">功能更新(文本){
让结果= document.queryselector(“#imainmighting-content”);
//更新代码
result_element.innertext = text;
//语法亮点
prism.highlightelement(result_element);
}</pre>
<p>现在,当对文本方面进行编辑时 - 如在键盘上的一个按压键返回 - 语法高点的代码更改。我们将要遇到一些错误,但是我想首先专注于使其看起来像您直接编辑语法高光元素,而不是单独的textarea。</p>
<h3>使其像代码编辑器一样“感觉”</h3>
<p>这个想法是明显地将元素合并在一起,因此当实际上有两个元素的元素时,似乎我们正在与一个元素进行交互。我们可以添加一些CSS,这些CS基本上允许<textarea>和<pre class="brush:php;toolbar:false"> <code>元素的尺寸和间隔。</code></pre></textarea></p>
<pre rel="CSS" data-line=""> #编辑,#highlighting {
/ *这两个元素都需要相同的文本和空间样式,因此它们彼此直接在顶部 */
保证金:10px;
填充:10px;
边界:0;
宽度:计算(100%-32px);
身高:150px;
}
#编辑,#highlighting,#highlighting * {
/ *还添加文本样式以突出显示令牌 */
字体大小:15pt;
font-family:单域;
线高:20pt;
}</pre>
<p>然后,我们想将它们放在彼此的顶部:</p>
<pre rel="CSS" data-line=""> #编辑,#highlighting {
位置:绝对;
顶部:0;
左:0;
}</pre>
<p>从那里开始,z索引允许Textarea在前面堆放一个突出显示的结果:</p>
<pre rel="CSS" data-line=""> / *在结果的前面移动文本方面 */
#编辑{
z索引:1;
}
#highlighting {
Z-Index:0;
}</pre>
<p>如果我们在这里停下来,我们将看到第一个错误。看起来Prism.js并不强调语法,但这仅仅是因为文本方面掩盖了结果。</p>
<p>我们可以使用CSS解决此问题!<em>除了</em>Caret(光标)外,我们将使<textarea>完全透明:</textarea></p>
<pre rel="CSS" data-line=""> / *使Textarea几乎完全透明 */
#编辑{
颜色:透明;
背景:透明;
商彩色:白色; / *或选择您喜欢的颜色 */
}</pre>
<p>啊,好多了!</p>
<h3>更多修复!</h3>
<p>一旦我走了这么远,我就会与编辑器一起玩,并能够找到更多需要修复的东西。好处是,使用JavaScript,CSS甚至HTML,所有问题都很容易解决。</p>
<h4>删除本地拼写检查</h4>
<p>我们正在制作代码编辑器,并且代码具有许多单词和属性,浏览器的本机咒语检查器会认为是拼写错误。</p>
<p>拼写检查不是一件坏事。在这种情况下,这是无益的。标记不正确的原因是因为它拼写不正确还是代码无效?很难说。要解决此问题,我们只需要将<textarea>上的拼写检查属性设置为false:</textarea></p>
<pre rel="HTML" data-line=""> <textarea spellcheck="“" false ...></textarea></pre>
<h4>处理新线条</h4>
<p>事实证明,Innertext不支持Newlines(\ n)。</p>
<p>需要编辑更新功能。我们可以使用InnerHTML,而不是使用Innertext,而是用&lt;替换开放的括号字符(</p>
<pre rel="JavaScript" data-line=""> result_element.innerhtml = text.replace(new Regexp(“&”,“ g”),“&”)。替换(new Regexp(“ <h4>滚动和调整大小</h4><p>这是另一件事:进行编辑时,突出显示的代码无法滚动。当滚动文本方面时,突出显示的代码不会滚动。</p><p>首先,让我们确保textarea和结果支持滚动:</p><pre rel="CSS" data-line=""> / *可以滚动 */
#编辑,#highlighting {
溢出:自动;
白色空间:pre; / *允许Textarea水平滚动 */
}</pre><p>然后,为了确保结果滚动<em>使用</em>Textarea,我们将更新HTML和JavaScript:</p><pre rel="HTML" data-line=""> <textarea oninput="“" update sync_scroll onscroll="“"> </textarea></pre><pre rel="JavaScript" data-line="">函数sync_scroll(element){
/ *滚动结果到滚动坐标 - 与textarea同步 */
让Result_Element = Document.queryselector(“#突出显示”);
//获取并设置X和Y
result_element.scrolltop = element.scrolltop;
result_element.scrollleft = element.scrollleft;
}</pre><p>一些浏览器还允许调整文本方面的大小,但这意味着Textarea和结果可能会变成不同的大小。 CSS可以解决此问题吗?当然可以。我们将简单地禁用调整大小:</p><pre rel="CSS" data-line=""> / *在Textarea上没有大小 */
#编辑{
调整大小:无;
}</pre><h4>最终新线</h4><p>感谢此评论指出了此错误。</p><p>现在,滚动几乎总是同步的,但是仍然有<strong>一种情况仍然不起作用</strong>。当用户创建新行时,在新行上输入任何文本之前,光标和文本文本的文本<strong>暂时处于错误的位置</strong>。这是因为<strong>出于美学原因,<pre class="brush:php;toolbar:false"> <code>块忽略了空的最后一行。</code></pre></strong>因为这是用于功能代码输入的,而不是显示的代码,因此需要显示空的最终行。这是通过<strong>提供最终行内容来完成的,因此它不再为空</strong>,并且在更新功能中添加了几行JavaScript。我使用了一个空间字符,因为<strong>用户看不见</strong>。</p><pre rel="JavaScript" data-line="3-6">功能更新(文本){
让结果= document.queryselector(“#imainmighting-content”);
//处理最终新线(请参阅文章)
if(text [text.length-1] ==“ \ n”){//如果最后一个字符是newline字符
text =“”; //将占位符空间字符添加到最后一行
}
//更新代码
result_element.innerhtml = text.replace(new Regexp(“&”,“ g”),“&”)。替换(new Regexp(“ <h4>缩进线</h4><p>要调整的较棘手的事情之一是如何处理结果中的线压痕。当前设置编辑器的方式,带空格的缩进线正常。但是,如果您比空间更喜欢标签,那么您可能已经注意到这些空间无法正常工作。</p><p> JavaScript可用于使<kbd>TAB</kbd>键正确工作。我添加了评论,以清楚该功能中正在发生的事情。</p><pre rel="HTML" data-line=""> <textarea ... onkeydown="“" check_tab> </textarea></pre><pre rel="JavaScript" data-line="">函数check_tab(元素,事件){
令code = element.value;
if(event.key ==“ tab”){
/ * TAB键按 */
event.preventDefault(); //停止正常
让tre tre_tab = code.slice(0,element.SelectionStart); //在选项卡之前的文字
令After_tab = code.slice(element.SelectionEnd,element.value.length); //在选项卡之后发短信
令Cursor_pos = element.SelectionEnd 1; //光标在选项卡之后移动的位置 - 以1个字符向前移动到after选项卡
element.value = tre_tab“ \ t” after_tab; //添加标签char
//移动光标
element.SelectionStart = Cursor_pos;
element.SelectionEnd = cursor_pos;
更新(element.value); //更新文本以包含缩进
}
}</pre><p>为了确保在<textarea>和语法高点密码块中的选项<strong>卡字符的大小相同</strong>,请编辑CSS以包含Tab-Size属性:</textarea></p><pre rel="CSS" data-line="4"> #编辑,#highlighting,#highlighting * {
/ *还将文本样式添加到高亮令牌 */
/* ETC。 */
tab-size:2;
}</pre><h3>最终结果</h3><p>不太疯狂,对吧?我们所拥有的只是<textarea>,<pre class="brush:php;toolbar:false">和<code> html中的元素,将它们堆叠在一起的新系列的CSS和一个语法突出显示库,以格式化所输入的内容。我最喜欢的是,我们正在使用普通的语义HTML元素,利用本机属性来获得我们想要的行为,依靠CSS来产生一种幻觉,即我们只与一个元素进行交互,然后伸手求助于JavaScript来解决一些边缘案例。</code></pre></textarea></p><p>当我使用Prism.js进行语法强调时,该技术将与其他人一起使用。如果您愿意,它甚至可以与您创建的语法荧光笔一起使用。我希望这变得有用,并且可以在许多地方使用,无论是CMS的Wysiwyg编辑器,甚至是表格,其中输入源代码的能力是前端作业应用程序的要求还是测验。毕竟,它是一个<textarea>,因此它能够以任何形式使用 - 如果需要,您甚至可以添加占位符!</textarea></p><p><strong>更新(2024年8月27日):</strong>读者路易斯·洛博(Luis Lobo</p><h3>更新</h3></pre></pre>
<ul><li>
<strong>2025年1月13日:</strong>示例已更新了一个白色空间:pre;声明在所有浏览器中平均处理空格,从而可以更好地进行水平滚动。</li></ul>以上是创建一个支持语法高音代码的可编辑文本area的详细内容。更多信息请关注PHP中文网其他相关文章!