
ソースコードにエディターコンポーネントを必要とするプロジェクトに取り組んでいたとき、そのエディターに入力された構文を強調表示する方法が本当に欲しかった。 Codemirror、Ace、Monacoのようなこのようなプロジェクトがありますが、それらはすべて、私が望んでいるように強調表示されている編集可能なTextareasだけでなく、すべての重量のあるフル機能の編集者です。
少し微調整されましたが、私は仕事をする何かを作って、私がそれをどのようにしたかを共有したいと思っていました。なぜなら、それは、人気のある構文ハイライトライブラリをHTMLの編集機能と考慮すべきいくつかの興味深いエッジケースを統合することを含むからです。
先に進んで、掘り下げながらスピンしてください!
提案の後、これをGitHubのカスタム要素としてリリースしたため、Webページのコンポーネントを単一の要素としてすばやく使用できます。</code-input></p>
<h3 id="問題">問題</h3>
<p>最初に、divでコンテンツ誘導属性を使用してみました。いくつかのソースコードをDIVに入力し、JavaScriptを介してOnInputで、人気のある構文ハイライターであるPrism.jsを介して実行しました。まともなアイデアのようですよね?フロントエンドで編集できる要素があり、prism.jsはその構文スタイリングを要素に入力するものに適用します。</p>
<p>クリスは、このビデオでprism.jsの使用方法を説明しています。</p>
<p>しかし、それはノーゴーでした。要素内のコンテンツが変更されるたびに、DOMが操作され、<strong>ユーザーのカーソルがコードの開始に戻されます</strong>。つまり、ソースコードが後方に表示され、最後の文字が最後に、最後に最初の文字が表示されます。</p>
<p>次に、<textarea>の使用を試みましたが、 <strong>Textareasには平易なテキストのみが含まれる</strong>ため、それも機能しませんでした。言い換えれば、入力されたコンテンツをスタイリングすることはできません。 Textareaは、不要なバグなしでテキストを編集する唯一の方法のようです。それは、Prism.jsにそのことをさせないようにしています。</textarea></p>
<p> prism.jsは、ソースコードが典型的な</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> <code>タグコンボにラップされている場合にはるかに優れています。方程式の編集可能な部分のみが欠落しています。<p>ですから、どちらも自分では機能しないようです。しかし、私はなぜ、<em>両方ではないのですか?</em></p>
<h3 id="解決策">解決策</h3>
<p>Syntax-Highlighted </p>
<pre class="brush:php;toolbar:false"> <code><em>と</em>Textareaの両方をページに追加し、JavaScript関数を使用して<pre class="brush:php;toolbar:false"> <code> onputの変更のInnertextコンテンツを作成しました。また、<pre class="brush:php;toolbar:false"> <code>結果にAria Hidden属性を追加して、スクリーンリーダーが2回読み取られるのではなく、<textarea>に入力されたもののみを読み取るようにします。<pre rel="HTML" data-line=""> <textarea oninput="update(this.value);"> </textarea>
<pre aria-hidden="true">
<code> </code>
</pre><div class="contentsignin">ログイン後にコピー</div></div></pre>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="JavaScript" data-line="">関数アップデート(テキスト){
let result_element = document.queryselector( "#highlighting-content");
//コードを更新します
result_element.innertext = text;
//構文ハイライト
prism.highlightelement(result_element);
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
<p>これで、Textareaが編集されると、ように編集されると、キーボードのプレスキーが戻ってきますが、Syntax Highlighted Code Changesが変更されます。いくつかのバグがありますが、最初に別のテキストエリアではなく、SynTax-Highlighted要素を直接編集しているように見えるようにすることに焦点を合わせたいと思います。</p>
<h3 id="コードエディターのように-感じ-ます">コードエディターのように「感じ」ます</h3>
<p>アイデアは、実際に2つの要素がある場合に1つの要素と相互作用しているように見えるように、目に見えるように要素を一緒にマージすることです。基本的に<textarea>および<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> <code>要素を一貫してサイズと間隔を置くことを許可するいくつかのCSSを追加できます。</code></pre><div class="contentsignin">ログイン後にコピー</div></div></textarea></p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line=""> #editing、#highlighting {
/ *両方の要素が同じテキストとスペースのスタイリングが必要なので、それらは互いに直接上にあります */
マージン:10px;
パディング:10px;
ボーダー:0;
幅:calc(100%-32px);
高さ:150px;
}
#editing、#highlighting、#highlighting * {{
/ *テキストスタイルを追加してトークンを強調表示します */
フォントサイズ:15pt;
フォントファミリー:モノスペース。
Line-Height:20pt;
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
<p>それから私たちはそれらを互いに正しく配置したい:</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line=""> #editing、#highlighting {
位置:絶対;
上:0;
左:0;
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
<p>そこから、Z-Indexを使用すると、Textareaが強調表示された結果を前に積み重ねることができます。</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line=""> / *結果の前でテキストアレアを移動します */
#editing {
z-index:1;
}
#highlighting {
z-index:0;
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
<p>ここで停止すると、最初のバグが表示されます。 Prism.jsが構文を強調しているようには見えませんが、それはテキストが結果をカバーしているからです。</p>
<p>これをCSSで修正できます! CARET(カーソル)<em>を除いて、</em> <textarea>を完全に透明にします。</textarea></p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line=""> / * textareaをほぼ完全に透明にする */
#editing {
色:透明;
背景:透明;
CARET-COLOR:白; / *またはお気に入りの色を選択 */
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
<p>ああ、はるかに良い!</p>
<h3 id="もっと修正">もっと修正!</h3>
<p>ここまで来たら、編集者と少し遊んで、修正が必要なものをいくつか見つけることができました。良いことは、すべての問題がJavaScript、CSS、またはHTMLを使用して簡単に修正できることです。</p>
<h4 id="ネイティブスペルチェックを削除します">ネイティブスペルチェックを削除します</h4>
<p>コードエディターを作成しています。コードには、ブラウザのネイティブスペルチェッカーが間違っていると考える単語や属性がたくさんあります。</p>
<p>スペルチェックは悪いことではありません。この状況では役に立たないだけです。誤って綴られているのか、それともコードが無効であるために、マークが正しくありませんか?伝えるのは難しいです。これを修正するために、必要なのは、<textarea>のスペルチェック属性をfalseに設定することだけです。</textarea></p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="HTML" data-line=""> <textarea spellcheck="false" ...></textarea></pre><div class="contentsignin">ログイン後にコピー</div></div>
<h4 id="新しい行の処理">新しい行の処理</h4>
<p>InnertextがNewLines(\ n)をサポートしていないことがわかりました。</p>
<p>更新機能を編集する必要があります。 Innertextを使用する代わりに、innerhtmlを使用して、オープンブラケット文字(</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="JavaScript" data-line=""> result_element.innerhtml = text.replace(new regexp( "&"、 "g")、 "&")。 / * global regexp */</pre><div class="contentsignin">ログイン後にコピー</div></div>
<h4 id="スクロールとサイズ変更">スクロールとサイズ変更</h4>
<p>別のことは次のとおりです。編集中に強調表示されたコードはスクロールできません。また、Textareaがスクロールされている場合、強調表示されたコードはスクロールしません。</p>
<p>まず、TextareaとResultの両方のサポートスクロールの両方を確認しましょう。</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line=""> / *スクロールすることができます */
#editing、#highlighting {
オーバーフロー:自動;
ホワイトスペース:pre; / * textareaが水平にスクロールできるようにします */
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
<p>次に、結果がTextarea<em>で</em>スクロールすることを確認するために、次のようにHTMLとJavaScriptを更新します。</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="HTML" data-line=""> <textarea oninput="update(this.value); sync_scroll(this);" onscroll="sync_scroll(this);"> </textarea></pre><div class="contentsignin">ログイン後にコピー</div></div>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="JavaScript" data-line=""> function sync_scroll(element){
/ *結果の結果をスクロールしてイベントの座標をスクロールする-Textareaと同期 */
let result_element = document.querySelector( "#highlighting");
// xとyを取得して設定します
result_element.scrolltop = element.scrolltop;
result_element.scrollleft = element.scrollleft;
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
<p>一部のブラウザでは、テキストアレアのサイズを変更することもできますが、これはテキストアレアと結果が異なるサイズになる可能性があることを意味します。 CSSはこれを修正できますか?もちろんそれはできます。変更を無効にするだけです。</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line=""> / * textareaにサイズを変更しない */
#editing {
サイズのサイズ:なし;
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
<h4 id="最終的なニューライン">最終的なニューライン</h4>
<p>このバグを指摘してくれたこのコメントに感謝します。</p>
<p>現在、スクロールはほとんど常に同期されていますが、<strong>まだ機能しない場合</strong>があります。ユーザーが新しい行を作成すると、新しい行にテキストが入力される前に、カーソルとテキストエリアのテキストが<strong>一時的に間違った位置に</strong>あります。これは<strong>、<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> <code>ブロックが審美的な理由で空の最終ラインを無視するためです。</code></pre><div class="contentsignin">ログイン後にコピー</div></div></strong>これは、表示されたコードの一部ではなく、機能的なコード入力用であるため、空の最終行を表示する必要があります。これは<strong>、最終的なラインコンテンツを提供することによって行われ、空にならないようにし</strong>、数行のJavaScriptが更新機能に追加されます。<strong>ユーザーには見えない</strong>ため、スペースキャラクターを使用しました。</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="JavaScript" data-line="3-6">関数アップデート(テキスト){
let result_element = document.queryselector( "#highlighting-content");
//最終ニューラインを処理する(記事を参照)
if(text [text.length-1] == "\ n"){//最後の文字が新しいライン文字の場合
text = ""; //最終行にプレースホルダースペース文字を追加する
}
//コードを更新します
result_element.innerhtml = text.replace(new regexp( "&"、 "g")、 "&")。 / * global regexp */
//構文ハイライト
prism.highlightelement(result_element);
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
<h4 id="インデントライン">インデントライン</h4>
<p>調整するのが難しいことの1つは、結果のラインインデントを処理する方法です。編集者の現在のセットアップ方法は、スペースのあるインデントラインが正常に機能します。しかし、もしあなたがスペースよりもタブに興味があるなら、あなたはそれらが期待どおりに機能していないことに気づいたかもしれません。</p>
<p> JavaScriptを使用して、 <kbd>TAB</kbd>キーを適切に機能させることができます。関数で何が起こっているのかを明確にするためにコメントを追加しました。</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="HTML" data-line=""> <textarea ... onkeydown="check_tab(this、event);"> </textarea></pre><div class="contentsignin">ログイン後にコピー</div></div>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="JavaScript" data-line=""> function check_tab(element、event){
let code = element.value;
if(event.key == "tab"){
/ * tabキーを押した */
event.preventdefault(); //通常の停止
let_tab = code.slice(0、element.selectionstart); //タブの前にテキスト
let_tab = code.slice(element.selectionEnd、element.value.length); //タブの後にテキスト
cursor_pos = element.selectionEnd 1; //タブの後にカーソルが移動する場所 - 1 charがタブの後に移動する
element.value = before_tab "\ t" afth_tab; //タブcharを追加します
//カーソルを移動します
element.selectionStart = cursor_pos;
element.SelectionEnd = cursor_pos;
update(element.value); //インデントを含めるようにテキストを更新します
}
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
<p><strong>タブ文字が<textarea>とSyntax-Highlightedコードブロックの両方で同じサイズであること</textarea></strong>を確認するには、CSSを編集して、タブサイズのプロパティを含めます。</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line="4"> #editing、#highlighting、#highlighting * {{
/ *テキストスタイルをハイレングトークンに追加する */
/ *など */
タブサイズ:2;
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
<h3 id="最終結果">最終結果</h3>
<p>クレイジーすぎませんよね?私たちが持っているのは、HTMLの<textarea>、<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">、および<code>要素、それらを積み重ねるCSSの新しい行、および入力したものをフォーマットするライブラリを強調表示する構文を強調します。そして、私がこれについて一番気に入っているのは、私たちが通常のセマンティックHTML要素を使用して、ネイティブの属性を活用して必要な動作を得ること、CSSに寄りかかって1つの要素とのみ相互作用しているという幻想を作成し、JavaScriptに手を伸ばしていくつかのエッジケースを解決することです。</code></pre><div class="contentsignin">ログイン後にコピー</div></div></textarea></p>
<p> Syntax HighlightingにPrism.jsを使用していましたが、この手法は他の人と連携します。必要に応じて自分で作成する構文ハイライターでも動作します。これが役に立つことを願っています。これは、CMSのWysiWygエディターであろうと、ソースコードを入力する機能がフロントエンドの求人アプリケーションなどの要件であろうとクイズなどの要件であろうと、多くの場所で使用できることを願っています。結局のところ、それは<textarea>なので、あらゆる形で使用できます。必要に応じてプレースホルダーを追加することもできます。</textarea></p>
<p><strong>更新(2024年8月27日):</strong>読者のルイス・ロボは、CodepenでこれのReactバージョンに書いています。</p>
<h3 id="更新">更新</h3>
<ul><li>
<strong>2025年1月13日:</strong>この例は、ホワイトスペースで更新されました。すべてのブラウザでホワイトスペースを均等に扱うための宣言により、より良い水平スクロールが可能になります。</li></ul></textarea>以上がSyntax-Highlightedコードをサポートする編集可能なTextareaを作成しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。