
當我正在研究一個需要編輯器組件的項目時,我真的希望一種方法讓編輯器突出顯示鍵入的語法。有類似的項目,例如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中文網其他相關文章!