
Als ich an einem Projekt arbeitete, das eine Editor -Komponente für Quellcode benötigte, wollte ich wirklich eine Möglichkeit, diesen Editor die eingegebene Syntax hervorzuheben. Es gibt solche Projekte wie Codemirror, Ace und Monaco, aber sie sind alle schwere, vollwertige Redakteure, nicht nur editable Textareas mit Syntax-Hervorhebung, wie ich es wollte.
Es dauerte ein wenig Finagling, aber ich machte etwas, das den Job macht und wollte mitteilen, wie ich es gemacht habe, da es darum geht, eine beliebte Syntax -Bibliothek mit den Bearbeitungsfunktionen von HTML sowie ein paar interessante Kantenfälle zu integrieren, um dies zu berücksichtigen.
Gehen Sie voran und drehen Sie es, während wir eingraben!
Nach einem Vorschlag habe ich dies auch als benutzerdefiniertes Element auf GitHub veröffentlicht, sodass Sie die Komponente in einer Webseite schnell als einzelnes -Element verwenden können.</code-input></p>
<h3> Das Problem</h3>
<p> Zuerst habe ich versucht, das inhaltliche Attribut auf einem Div zu verwenden. Ich tippte einen Quellcode in die DIV ein und leitete ihn durch Prism.js, einen beliebten Syntax -Highlighter, über JavaScript auf dem Ininput. Scheint eine anständige Idee, oder? Wir haben ein Element, das am vorderen Ende bearbeitet werden kann, und Prism.js wendet sein Syntax -Styling auf das an, was im Element getippt wird.</p>
<p> Chris deckt in diesem Video Prism.js ein.</p>
<p> Aber das war ein No-Go. Jedes Mal, wenn sich der Inhalt im Element ändert, wird das DOM manipuliert und der <strong>Cursor des Benutzers wird zum Start des Codes zurückgedrückt</strong> , was bedeutet, dass der Quellcode rückwärts angezeigt wird, wobei die letzten Zeichen am Start und die ersten Zeichen am Ende.</p>
<p> Als nächstes habe ich versucht, eine <textarea> zu verwenden, aber das hat auch nicht funktioniert, da <strong>Textbereich nur einen einfachen Text enthalten kann</strong> . Mit anderen Worten, wir können nicht den Inhalt stylen, der eingegeben wird. Ein Textbereich scheint der einzige Weg zu sein, den Text ohne unerwünschte Fehler zu bearbeiten - er lässt sich einfach nicht zu, dass Prism.js sein Ding tun.</textarea></p>
<p> Prism.js funktioniert viel besser, wenn der Quellcode in eine typische Combo </p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> <code> tag eingewickelt ist - er fehlt nur den bearbeitbaren Teil der Gleichung.<p> Also scheint auch nicht von selbst zu funktionieren. Aber ich dachte, <em>warum nicht beides?</em></p>
<h3> Die Lösung</h3>
<p> Ich habe sowohl eine syntax-highlierte </p>
<pre class="brush:php;toolbar:false"> <code> <em>als auch</em> eine textarea zur Seite hinzugefügt und den InnerText-Inhalt von <pre class="brush:php;toolbar:false"> <code> unter Verwendung einer JavaScript-Funktion auf der Einführung geändert. Ich habe dem Ergebnis <pre class="brush:php;toolbar:false"> <code> auch ein aria-verstecktes Attribut hinzugefügt, damit die Bildschirmleser nur lesen, was in die <textarea> eingegeben wurde, anstatt zweifellos vorgelesen zu werden.<pre rel="HTML" data-line=""> <textarea oninput="update (this.value);"> </textarea>
<pre aria-hidden="true">
<code> </code>
</pre><div class="contentsignin">Nach dem Login kopieren</div></div></pre>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="JavaScript" data-line=""> Funktion update (text) {
lass result_element = document.querySelector ("#Herdlighting-Content");
// Code aktualisieren
result_element.inNertext = text;
// Syntax Highlight
Prism.HighlightElement (result_element);
}</pre><div class="contentsignin">Nach dem Login kopieren</div></div>
<p> Wenn der Textbereich-wie in der Tastatur auf der Tastatur zurückgeht-wieder auftritt, ändert sich die Syntax-Highlight-Code. Es gibt ein paar Fehler, die wir erreichen werden, aber ich möchte mich zunächst darauf konzentrieren, dass es so aussieht, als würden Sie das Syntax-Highlighed-Element direkt bearbeiten, anstatt ein separates Textbereich.</p>
<h3> Es "anfühlt" wie ein Code -Editor</h3>
<p> Die Idee ist, die Elemente sichtbar zusammenzuführen, damit wir mit einem Element interagieren, wenn tatsächlich zwei Elemente bei der Arbeit sind. Wir können einige CSS hinzufügen, die es im Grunde genommen ermöglichen, die <textarea> und die <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> <code> -Elemente zu dimensionieren und konsequent zu verteilt.</code></pre><div class="contentsignin">Nach dem Login kopieren</div></div></textarea></p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line=""> #Editing, #Highlighting {
/ * Beide Elemente benötigen den gleichen Text und das gleiche Raumstyling, sodass sie sich direkt übereinander befinden *///////
Rand: 10px;
Polsterung: 10px;
Grenze: 0;
Breite: Calc (100% - 32px);
Höhe: 150px;
}
#Editing, #Highlighting, #Highlighting * {
/ * Fügen Sie auch Textstile zum Hervorheben von Token hinzu */
Schriftgröße: 15pt;
Schriftfamilie: Monospace;
Linienhöhe: 20PT;
}</pre><div class="contentsignin">Nach dem Login kopieren</div></div>
<p> Dann wollen wir sie direkt übereinander positionieren:</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line=""> #Editing, #Highlighting {
Position: absolut;
Top: 0;
links: 0;
}</pre><div class="contentsignin">Nach dem Login kopieren</div></div>
<p> Von dort aus ermöglicht Z-Index dem Textbereich, vor dem hervorgehobenen Ergebnis vorzugehen:</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line=""> / * Bewegen Sie den Textbereich vor dem Ergebnis */
#Editing {
Z-Index: 1;
}
#Highlighting {
Z-Index: 0;
}</pre><div class="contentsignin">Nach dem Login kopieren</div></div>
<p> Wenn wir hier anhalten, werden wir unseren ersten Fehler sehen. Es sieht nicht so aus, als ob Prism.js die Syntax hervorhebt, aber das liegt nur daran, dass der Textbereich das Ergebnis verdeckt.</p>
<p> Wir können dies mit CSS beheben! Wir werden die <textarea> völlig transparent machen, <em>außer</em> dem Pfarrer (Cursor):</textarea></p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line=""> / * Mach textarea fast vollständig transparent */
#Editing {
Farbe: transparent;
Hintergrund: transparent;
Pflegefarbe: weiß; / * Oder wählen Sie Ihre Lieblingsfarbe */
}</pre><div class="contentsignin">Nach dem Login kopieren</div></div>
<p> Ah, viel besser!</p>
<h3> Mehr reparieren!</h3>
<p> Als ich so weit gekommen war, habe ich ein bisschen mit dem Herausgeber herumgespielt und konnte ein paar weitere Dinge finden, die die Reparatur mussten. Das Gute ist, dass alle Probleme mit JavaScript, CSS oder sogar HTML recht einfach zu beheben sind.</p>
<h4> Entfernen Sie die native Zaubersprüche</h4>
<p> Wir erstellen einen Code -Editor, und Code hat viele Wörter und Attribute, die der native Zaubersprüche eines Browsers denken wird, dass es sich um Fehlschriften handelt.</p>
<p> Zauberprüfung ist keine schlechte Sache; Es ist in dieser Situation nur nicht hilfreich. Ist etwas falsch gekennzeichnet, weil es falsch geschrieben ist oder weil der Code ungültig ist? Es ist schwer zu sagen. Um dies zu beheben, müssen wir nur das Rechtschreibprüfungsattribut auf dem <textarea> auf false festlegen:</textarea></p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="HTML" data-line=""> <textarea bellscheck="false" ...></textarea></pre><div class="contentsignin">Nach dem Login kopieren</div></div>
<h4> Neue Linien umgehen</h4>
<p> Es stellt sich heraus, dass InnerText Newlines (\ n) nicht unterstützt.</p>
<p> Die Aktualisierungsfunktion muss bearbeitet werden. Anstatt InnerText zu verwenden, können wir Innerhtml verwenden, um den Open -Bracket -Charakter (</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="JavaScript" data-line=""> result_element.innerhtml = text.replace (neuer regexp ("&", "g"), "&"). Ersetzen (neuer Regexp ("<h4> Scrollen und Größenänderungen</h4><p> Hier ist eine andere Sache: Der hervorgehobene Code kann während der Bearbeitung nicht scrollen. Und wenn der Textbereich gescrollt wird, scrollt der hervorgehobene Code nicht damit.</p><p> Stellen Sie zunächst sicher, dass sowohl die Textbereich als auch das Ergebnis das Scrollen unterstützen:</p><pre rel="CSS" data-line=""> / * Kann gescrollt werden */
#Editing, #Highlighting {
Überlauf: Auto;
weißer Raum: PRE; / * Erlaubt textarea, horizontal zu scrollen */
}</pre><div class="contentsignin">Nach dem Login kopieren</div></div><p> Um sicherzustellen, dass das Ergebnis <em>mit</em> dem Textbereich scrolliert, aktualisieren wir das HTML und JavaScript wie folgt:</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">Nach dem Login kopieren</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="JavaScript" data-line=""> Funktion Sync_scroll (Element) {
/ * Scrollen Sie Ergebnis, um Ereigniskoordnungen zu scrollen - Synchronisieren Sie mit TextArea */
lass result_element = document.querySelector ("#hervorheben");
// x und y setze und setze
result_element.scrolltop = element.scrolltop;
result_element.scrollleft = element.scrollLeft;
}</pre><div class="contentsignin">Nach dem Login kopieren</div></div><p> Einige Browser erlauben auch, dass ein Textbereich geändert wird, aber dies bedeutet, dass das Textbereich und das Ergebnis zu unterschiedlichen Größen werden können. Kann CSS das beheben? Natürlich kann es. Wir werden einfach die Größenänderung deaktivieren:</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line=""> / * Keine Änderung in TextArea *//
#Editing {
Größenänderung: Keine;
}</pre><div class="contentsignin">Nach dem Login kopieren</div></div><h4> Letzte Neulinge</h4><p> Vielen Dank an diesen Kommentar für den Hinweis auf diesen Fehler.</p><p> Jetzt wird das Scrollen fast immer synchronisiert, aber es gibt immer noch <strong>einen Fall, in dem es immer noch nicht funktioniert</strong> . Wenn der Benutzer eine neue Zeile erstellt, befinden sich der Cursor und der Text des Textbereichs <strong>vorübergehend in der falschen Position,</strong> bevor ein Text in der neuen Zeile eingegeben wird. Dies liegt daran, dass <strong>der block <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> <code> eine leere endgültige Zeile aus ästhetischen Gründen ignoriert.</code></pre><div class="contentsignin">Nach dem Login kopieren</div></div></strong> Da dies für eine Funktionscodeeingabe und nicht für ein Stück angezeigtes Code gilt, muss die leere endgültige Zeile angezeigt werden. Dies geschieht, indem <strong>der endgültige Zeileninhalt angegeben wird, sodass er nicht mehr leer ist</strong> und ein paar Zeilen von JavaScript zur Aktualisierungsfunktion hinzugefügt werden. Ich habe einen Space -Charakter verwendet, weil er <strong>für den Benutzer unsichtbar</strong> ist.</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="JavaScript" data-line="3-6"> Funktion update (text) {
lass result_element = document.querySelector ("#Herdlighting-Content");
// endgültige Neulinge verarbeiten (siehe Artikel)
if (text [text.length-1] == "\ n") {// Wenn das letzte Zeichen ein neues Zeilenzeichen ist
text = ""; // Fügen Sie der endgültigen Zeile einen Platzhalter -Weltraumcharakter hinzu
}
// Code aktualisieren
result_element.innerhtml = text.replace (neuer regexp ("&", "g"), "&"). Ersetzen (neuer Regexp ("<h4> Einrückung von Linien</h4><p> Eines der schwierigeren Dinge, die Sie anpassen sollten, ist, wie man Linieneindrückung im Ergebnis behandelt. Die Art und Weise, wie der Editor derzeit eingerichtet ist, funktioniert einwandfrei. Wenn Sie sich jedoch mehr für Registerkarten als für Räume interessieren, haben Sie möglicherweise festgestellt, dass diese nicht wie erwartet funktionieren.</p><p> JavaScript kann verwendet werden, um die <kbd>Registerkartenschlüssel</kbd> ordnungsgemäß zu erstellen. Ich habe Kommentare hinzugefügt, um klar zu machen, was in der Funktion passiert.</p><pre rel="HTML" data-line=""> <textarea ... onkeydown="check_tab (this, Ereignis);"> </textarea></pre><div class="contentsignin">Nach dem Login kopieren</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="JavaScript" data-line=""> Funktion check_tab (Element, Ereignis) {
let code = element.Value;
if (event.key == "tab") {
/ * Registerkarte gedrückt */
Event.PreventDefault (); // Normal aufhören
let vor_tab = code.slice (0, Element.SelectionStart); // Text vor der Registerkarte
lass After_tab = code.slice (element.selectionEnd, Element.Value.Length); // Text After Tab
lass cursor_pos = element.selectionend 1; // wobei sich Cursor nach der Registerkarte bewegt - Fortsetzung mit 1 Zeichen zu After Tab
Element.Value = vorab "\ t" After_tab; // Registerkarte hinzufügen
// Cursor bewegen
Element.SelectionStart = cursor_pos;
Element.Selectionend = Cursor_Pos;
update (element.Value); // Text aktualisieren, um den Einzug einzuschließen
}
}</pre><div class="contentsignin">Nach dem Login kopieren</div></div><p> Um sicherzustellen, dass die <strong>Registerkartenzeichen sowohl in der <textarea> als auch im syntax-hohen Codeblock gleich groß sind</textarea></strong> , bearbeiten Sie die CSS, um die Eigenschaft der Registerkartengröße einzuschließen:</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="CSS" data-line="4"> #Editing, #Highlighting, #Highlighting * {
/ * Fügen Sie auch Textstile zu hohen Lebensmitteln hinzu */
/* usw. */
Registerkartengröße: 2;
}</pre><div class="contentsignin">Nach dem Login kopieren</div></div><h3> Das Endergebnis</h3><p> Nicht zu verrückt, oder? Alles, was wir haben, sind <textarea>, <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> und <code> Elemente in der HTML, neue CSS -Zeilen, die sie zusammenstellen, und eine Syntax -Bibliothek, um das zu formatieren, was eingegeben wird. Und was mir am besten gefällt, ist, dass wir mit normalen, semantischen HTML -Elementen arbeiten und native Attribute nutzen, um das gewünschte Verhalten zu erhalten, und uns auf CSS stützen, um die Illusion zu erzeugen, dass wir nur mit einem Element interagieren, und dann nach JavaScript greifen, um einige Randfälle zu lösen.</code></pre><div class="contentsignin">Nach dem Login kopieren</div></div></textarea></p><p> Während ich Prism.js für die Syntax -Hervorhebung verwendet habe, funktioniert diese Technik mit anderen. Es würde sogar mit einem Syntax Highlighter funktionieren, den Sie selbst erstellen, wenn Sie es möchten. Ich hoffe, dies wird nützlich und kann an vielen Orten verwendet werden, egal ob es sich um einen Wysiwyg-Editor für ein CMS oder sogar eine Formulierung handelt, bei denen die Möglichkeit, Quellcode einzugeben, eine Anforderung wie eine Front-End-Bewerbung oder möglicherweise ein Quiz ist. Schließlich ist es ein <textarea>, daher kann es in jeder Form verwendet werden - Sie können sogar einen Platzhalter hinzufügen, wenn Sie es brauchen!</textarea></p><p> <strong>Update (27. August 2024):</strong> Leser Luis Lobo schreibt mit einer React -Version davon in CodePen ein:</p><h3> Aktualisierungen</h3></pre></pre>
<ul><li> <strong>13. Januar 2025:</strong> Das Beispiel wurde mit einem weißen Raum aktualisiert: PRE; Deklaration zur gleichermaßen Behandlung von Whitespace in allen Browsern, was eine bessere horizontale Scrollen ermöglicht.</li></ul></textarea>Das obige ist der detaillierte Inhalt vonErstellen eines bearbeitbaren Textbereichs, der den syntax-highlierten Code unterstützt. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!