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
#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; }
Ensuite, nous voulons les positionner les uns sur les autres:
#Editing, #Highlighting { Position: absolue; en haut: 0; à gauche: 0; }
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; }
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 * / }
Ah, beaucoup mieux!
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.
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>
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 * / }
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>
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; }
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; }
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>
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 } }
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; }
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:
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!