Maison > interface Web > tutoriel CSS > Création d'une TextArea modifiable qui prend en charge le code de syntaxe-éclairé

Création d'une TextArea modifiable qui prend en charge le code de syntaxe-éclairé

Christopher Nolan
Libérer: 2025-03-25 09:42:19
original
354 Les gens l'ont consulté

Création d'une TextArea modifiable qui prend en charge le code de syntaxe-éclairé

Lorsque je travaillais sur un projet qui avait besoin d'un composant d'éditeur pour le code source, je voulais vraiment un moyen de faire en sorte que cet éditeur mette en surbrillance la syntaxe qui est tapée. Il y a des projets comme celui-ci, comme Codemirror, Ace et Monaco, mais ce sont tous des éditeurs de poids lourds et complets, pas seulement des textares modifiables avec une syntaxe mettant en évidence comme je le voulais.

Il a fallu un peu de Finagling, mais j'ai fini par faire quelque chose qui fait le travail et je voulais partager comment je l'ai fait, car cela implique d'intégrer une bibliothèque de mise en évidence de syntaxe populaire avec les capacités d'édition de HTML, ainsi que quelques cas de bord intéressants à prendre en considération.

Allez-y et tournez-le pendant que nous creusons!

Après une suggestion, j'ai également publié cela en tant qu'élément personnalisé sur GitHub, afin que vous puissiez rapidement utiliser le composant dans une page Web en tant qu'élément .</code-input></p> <h3> Le problème</h3> <p> Tout d'abord, j'ai essayé d'utiliser l'attribut contenu sur un div. J'ai tapé un code source dans le div et je l'ai parcouru via Prism.js, un surligneur de syntaxe populaire, sur ONInput via JavaScript. Cela semble être une idée décente, non? Nous avons un élément qui peut être modifié sur l'avant, et Prism.js applique son style de syntaxe à ce qui est tapé dans l'élément.</p> <p> Chris couvre comment utiliser Prism.js dans cette vidéo.</p> <p> Mais c'était un non-go. Chaque fois que le contenu de l'élément change, le DOM est manipulé et le <strong>curseur de l'utilisateur est repoussé au début du code</strong> , ce qui signifie que le code source apparaît à l'envers, avec les derniers caractères au début et les premiers caractères à la fin.</p> <p> Ensuite, j'ai essayé d'utiliser un <textarea> mais cela n'a pas non plus fonctionné, car <strong>TextAreas ne peut contenir du texte brut</strong> . En d'autres termes, nous ne sommes pas en mesure de styliser le contenu entré. Une TextArea semble être le seul moyen de modifier le texte sans bugs indésirables - il ne laisse tout simplement pas Prism.js faire son truc.</textarea></p> <p> Prism.js fonctionne beaucoup mieux lorsque le code source est enveloppé dans un combo </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> &lt;code&gt; TAG typique - il ne manque que la partie modifiable de l'équation.&lt;p&gt; Donc, aucun ne semble fonctionner seul. Mais, je pensais, &lt;em&gt;pourquoi pas les deux?&lt;/em&gt;&lt;/p&gt; &lt;h3&gt; La solution&lt;/h3&gt; &lt;p&gt; J'ai ajouté à la fois une syntaxe-highlighted &lt;/p&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt; &lt;code&gt; &lt;em&gt;et&lt;/em&gt; une TextArea à la page, et j'ai fait le contenu de l'inter-texte de &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt; &lt;code&gt; Modifier OnInput, en utilisant une fonction JavaScript. J'ai également ajouté un attribut hidden Aria au résultat &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt; &lt;code&gt; afin que les lecteurs d'écran ne lisent que ce qui est entré dans le &lt;textarea&gt; au lieu d'être lu à haute voix deux fois.&lt;pre rel=&quot;HTML&quot; data-line=&quot;&quot;&gt; &lt;textarea oninput=&quot;Update (this.value);&quot;&gt; textarea&gt; &lt;pre aria-hidden=&quot;true&quot;&gt; &lt;code&gt; &lt;/code&gt; </pre><div class="contentsignin">Copier après la connexion</div></div></textarea></pre> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre rel="JavaScript" data-line=""> Function Update (texte) { let result_element = document.QuerySelector (&quot;# saillting-content&quot;); // Mettre à jour le code result_element.innertext = text; // Présentation de la syntaxe Prime.highlightElement (result_element); }</pre><div class="contentsignin">Copier après la connexion</div></div> <p> Maintenant, lorsque la TextArea est modifiée - comme dans, une touche pressée du clavier revient - le code de syntaxe est-il modifié. Il y a quelques bugs auxquels nous arrivons, mais je veux d'abord me concentrer sur le fait que vous modifiez directement l'élément de syntaxe-éclairé, plutôt qu'une textaire séparée.</p> <h3> Le faire «se sentir» comme un éditeur de code</h3> <p> L'idée est de fusionner visiblement les éléments ensemble afin qu'il semble que nous interagissons avec un élément alors qu'il y a en fait deux éléments au travail. Nous pouvons ajouter des CSS qui permet essentiellement que les éléments <textarea> et les <pr> <code> soient dimensionnés et espacés de manière cohérente.

 #Editing, #Highlighting {
  / * Les deux éléments ont besoin du même style de texte et d'espace afin qu'ils soient directement les uns sur les autres * /
  marge: 10px;
  rembourrage: 10px;
  bordure: 0;
  Largeur: calc (100% - 32px);
  hauteur: 150px;
}

#Editing, #highlighting, #highlighting * {
  / * Ajouter également des styles de texte à la mise en évidence des jetons * /
  taille de police: 15pt;
  Font-Family: Monospace;
  hauteur de ligne: 20pt;
}
Copier après la connexion

Ensuite, nous voulons les positionner les uns sur les autres:

 #Editing, #Highlighting {
  Position: absolue;
  en haut: 0;
  à gauche: 0;
}
Copier après la connexion

De là, Z-Index permet à TextArea de s'empiler devant le résultat en surbrillance:

 / * Déplacez la TextArea devant le résultat * /
#Editing {
  Z-Index: 1;
}

#Highlighting {
  Z-index: 0;
}
Copier après la connexion

Si nous nous arrêtons ici, nous verrons notre premier bug. Il ne semble pas que Prism.js met en évidence la syntaxe, mais c'est uniquement parce que la TextArea couvre le résultat.

Nous pouvons résoudre ce problème avec CSS! Nous rendrons le

 / * Rendre TextArea presque complètement transparent * /
#Editing {
  Couleur: transparent;
  Contexte: transparent;
  Color Caret: blanc; / * Ou choisissez votre couleur préférée * /
}
Copier après la connexion

Ah, beaucoup mieux!

Plus de fixation!

Une fois que je suis arrivé aussi loin, j'ai joué un peu avec l'éditeur et j'ai pu trouver quelques autres choses qui devaient être réparées. La bonne chose est que tous les problèmes sont assez faciles à résoudre en utilisant JavaScript, CSS ou même HTML.

Supprimer la vérification des orthographiques native

Nous faisons un éditeur de code, et le code a beaucoup de mots et d'attributs que le vérificateur orthographique natif d'un navigateur pense que ce sont des fautes d'orthographe.

La vérification orthographique n'est pas une mauvaise chose; C'est tout simplement inutile dans cette situation. Quelque chose est marqué incorrect car il est incorrectement orthographié ou parce que le code est invalide? C'est difficile à dire. Pour résoudre ce problème, tout ce dont nous avons besoin est de définir l'attribut orthographié sur le

 <textarea orthographe="false" ...></textarea>
Copier après la connexion

Gérer les nouvelles lignes

Il s'avère que InnerText ne prend pas en charge Newlines (\ n).

La fonction de mise à jour doit être modifiée. Au lieu d'utiliser InnerText, nous pouvons utiliser InnerHTML, en remplaçant le caractère du support ouvert (

 result_element.innerhtml = text.replace (new regexp ("&", "g"), "&"). remplacer (new regexp ("<h4> Défilement et redimensionnement</h4><p> Voici une autre chose: le code mis en évidence ne peut pas faire défiler pendant que l'édition a lieu. Et lorsque TextArea est défilé, le code en surbrillance ne fait pas défiler avec.</p><p> Tout d'abord, assurons que la TextArea et les résultats prennent en charge le défilement:</p><pre rel="CSS" data-line=""> / * Peut être défilé * /
#Editing, #Highlighting {
  débordement: auto;
  Espace blanc: pré; / * Permet à TextArea de faire défiler horizontalement * /
}
Copier après la connexion

Ensuite, pour nous assurer que le résultat défile avec la TextArea, nous mettrons à jour le HTML et JavaScript comme ceci:

 <textarea oninput="Update (this.value); sync_scroll (this);" onscroll="sync_scroll (this);">  textarea></textarea>
Copier après la connexion
 fonction sync_scroll (élément) {
  / * Résultat de défilement pour faire défiler les coordonnées de l'événement - Sync avec TextArea * /
  let result_element = document.QuerySelector ("# saillting");
  // Obtenez et définissez X et Y
  result_element.scrolltop = element.scrolltop;
  result_element.scrollleft = element.scrollleft;
}
Copier après la connexion

Certains navigateurs permettent également une redimension d'une textarea, mais cela signifie que la TextArea et le résultat pourraient devenir des tailles différentes. CSS peut-il résoudre ce problème? Bien sûr, cela peut. Nous désactiverons simplement le redimensionnement:

 / * Pas de redimensionner sur textarea * /
#Editing {
  redimensionner: aucun;
}
Copier après la connexion

Finales Newlines

Merci à ce commentaire pour avoir signalé ce bug.

Maintenant, le défilement est presque toujours synchronisé, mais il y a toujours un cas où il ne fonctionne toujours pas . Lorsque l'utilisateur crée une nouvelle ligne, le curseur et le texte du TextArea sont temporairement en mauvaise position avant que tout texte ne soit entré sur la nouvelle ligne. En effet Parce que c'est pour une entrée de code fonctionnel, plutôt qu'un morceau de code affiché, la ligne finale vide doit être affichée. Cela se fait en donnant le contenu de ligne final afin qu'il ne soit plus vide , avec quelques lignes de JavaScript ajoutées à la fonction de mise à jour. J'ai utilisé un caractère spatial car il est invisible pour l'utilisateur .

 Function Update (texte) {
  let result_element = document.QuerySelector ("# saillting-content");
  // Gire les nouvelles finales (voir article)
  if (text [text.length-1] == "\ n") {// Si le dernier caractère est un caractère Newline
    text = ""; // Ajouter un caractère d'espace d'espace réservé à la ligne finale 
  }
  // Mettre à jour le code
  result_element.innerhtml = text.replace (new regexp ("&", "g"), "&"). remplacer (new regexp ("<h4> Indentation des lignes</h4><p> L'une des choses les plus difficiles à régler est de savoir comment gérer les indentations de ligne dans le résultat. La façon dont l'éditeur est actuellement configuré, les lignes de mise en œuvre avec des espaces fonctionnent bien. Mais, si vous êtes plus dans des onglets que dans les espaces, vous avez peut-être remarqué que ceux-ci ne fonctionnent pas comme prévu.</p><p> JavaScript peut être utilisé pour faire fonctionner correctement la touche <kbd>de tabulation</kbd> . J'ai ajouté des commentaires pour indiquer clairement ce qui se passe dans la fonction.</p><pre rel="HTML" data-line=""> <textarea ... onkeydown="check_tab (this, event);">  textarea></textarea>
Copier après la connexion
 fonction check_tab (élément, événement) {
  Selt Code = element.Value;
  if (event.key == "tab") {
    / * Touche onglet appuyée sur * /
    event.PreventDefault (); // arrêter la normale
    SET AVANT_TAB = Code.slice (0, élément.SelectionStart); // texte avant l'onglet
    LET After_TAB = Code.slice (élément.Selectionend, élément.value.length); // texte après onglet
    Soit Cursor_pos = élément.SelectionenD 1; // où le curseur se déplace après l'onglet - aller de l'avant par 1 char à l'onglet après
    element.value = avant_tab "\ t" after_tab; // Ajouter un charbon d'onglet
    // déplacer le curseur
    element.selectionstart = cursor_pos;
    element.SelectionEnd = cursor_pos;
    Mise à jour (élément.Value); // Mette à jour le texte pour inclure le retrait
  }
}
Copier après la connexion

Pour vous assurer que les caractères d'onglet sont de la même taille dans le bloc de code

 #Editing, #highlighting, #highlighting * {
  / * Ajoutez également des styles de texte aux jetons highlighing * / /
  /* etc. */
  Tab-taille: 2;
}
Copier après la connexion

Le résultat final

Pas trop fou, non? Tout ce que nous avons, ce sont les éléments

Bien que j'utilise Prism.js pour la mise en évidence de la syntaxe, cette technique fonctionnera avec d'autres. Cela fonctionnerait même avec un surligneur de syntaxe que vous créez vous-même si vous le souhaitez. J'espère que cela deviendra utile et peut être utilisé dans de nombreux endroits, qu'il s'agisse d'un éditeur WYSIWYG pour un CMS ou même des formulaires où la possibilité de saisir le code source est une exigence comme une demande d'emploi frontal ou peut-être un quiz. C'est un

MISE À JOUR (27 août 2024): le lecteur Luis Lobo écrit avec une version React de ceci dans Codepen:

Mises à jour

  • 13 janvier 2025: L'exemple a été mis à jour avec un espace blanc: pré; Déclaration de traitement de l'espace également dans tous les navigateurs, permettant un meilleur défilement horizontal.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal