Créer des extensions de crochets

Il y a quelques instants, j'ai écrit sur les dernières mises à jour de l'éditeur Brackets. Brackets est un projet open source axé sur les normes Web et construit avec les technologies Web. Il a une portée étroite et peut donc ne pas avoir une caractéristique particulière dont vous dépendez. Heureusement, Brackets est livré avec une API d'extension puissante qui vous permet d'ajouter un nombre illimité de nouvelles fonctionnalités. Dans cet article, je vais discuter de cette API et montrer comment vous pouvez créer vos propres extensions..

Il est crucial que vous vous rappelez que Brackets est en développement actif. Cet article est écrit en décembre 2013. Il est certainement possible que le code présenté ci-dessous soit maintenant obsolète. Gardez cela à l'esprit et vérifiez que le wiki contient les dernières mises à jour de l'API d'extension..


Commencer

Je vais supposer que vous avez lu mon dernier article et que vous connaissez déjà le gestionnaire d'extensions. Ceci fournit une méthode simple en un clic pour installer des extensions. L’une des meilleures façons d’apprendre à écrire des extensions est de regarder le travail effectué par d’autres (c’est ainsi que j’ai appris). Je vous recommande de prendre quelques extensions (il y en a presque 200 disponibles maintenant) et de séparer leur code. N'ayez pas peur de casser quelques-uns pendant que vous y êtes.

Les crochets placent toutes les extensions installées dans un dossier principal. Pour trouver ce dossier, allez à la Aidez-moi menu et sélectionnez "Afficher le dossier des extensions". Pour mon installation OS X, cela se trouvait à l'adresse / Utilisateurs / ray / Bibliothèque / Application Support / Brackets / extensions / user. Si vous sortez de ce dossier, vous remarquerez également un dossier désactivé. Brackets fera un effort vaillant pour charger quoi qu'il arrive, mais si jamais vous vous retrouvez dans une situation où Brackets a complètement craqué le lit et ne fonctionnera tout simplement pas, envisagez de déplacer des extensions potentiellement mauvaises dans le dossier désactivé. Plus loin dans cet article, nous verrons comment vous pouvez surveiller et déboguer des extensions pour éviter de tels problèmes..

Commencez par aller dans votre dossier utilisateur et créer un nouveau dossier, helloworld1. Oui, même si c'est complètement nul, nous allons construire une extension HelloWorld. Ne me déteste pas, j'aime simple. Dans ce dossier, créez un nouveau fichier appelé main.js. Le premier exemple montre le contenu de ce fichier. Notez que dans cet article, je vais passer en revue plusieurs versions du Bonjour le monde extension. Chacun sera nommé avec un nombre progressivement croissant. Donc, notre premier exemple est de helloworld1, le suivant helloworld2, etc. Il serait logique que vous copiez simplement le code dans un seul dossier., Bonjour le monde, au lieu de copier chacun par eux-mêmes. Si vous le faites, vous aurez plusieurs extensions connexes en cours d'exécution à la fois, ce qui peut définitivement créer de la confusion..

Exemple 1: helloworld1 / main.js define (fonction (require, exports, module) journal (s) de la fonction console.log ("[helloworld]" + s); log ("Hello from HelloWorld."); )

La première ligne définit notre extension comme un module qui sera capté automatiquement par les crochets lors du chargement de l’application. Le reste de l'extension est un message de journal personnalisé (vous verrez pourquoi dans un instant) et un appel à ce journal. Une fois que vous avez enregistré ce fichier, retournez à Brackets, sélectionnez le menu Déboguer, puis cliquez sur Recharger. (Vous pouvez aussi utiliser Commande / Contrôle + R à recharger aussi.)

Les crochets vont recharger et… rien ne se passera. L'extension que nous avons construite ne fait en réalité rien que nous puissions voir, mais se connecte à la console. Mais où est cette console? Les crochets permettent de visualiser facilement la console. Il suffit de retourner à la Déboguer menu et sélectionnez Afficher les outils de développement. Cela va ouvrir un nouvel onglet dans Chrome avec une interface utilisateur conviviale pour les outils de développement. Dans la capture d'écran ci-dessous, j'ai mis en évidence notre journal. Les autres extensions, et les crochets eux-mêmes, enregistreront également les messages sur cet écran. En préfixant mes messages de journal avec [Bonjour le monde], Je peux faire mes propres affaires un peu plus facilement à trouver.


Notez que l'intégralité de Chrome console.api travaille ici. Vous pouvez faire ce genre de choses pour formater les messages de votre console:

 journal (s) des fonctions console.log ("% c [helloworld]" + s, "couleur: bleu; taille de la police de caractères: grand"); 

Devenez fou, mais essayez de supprimer ces messages avant de partager votre code avec le reste du monde. Si vous êtes curieux, vous ne pouvez pas utiliser d'outils de développement dans un autre navigateur, comme Firefox, pour le moment..


Points d'intégration

Maintenant que vous connaissez les bases, parlons de ce que les extensions Brackets peuvent faire pour l'éditeur:

  • Ils peuvent créer des raccourcis clavier leur permettant de répondre aux frappes personnalisées..
  • Ils peuvent ajouter au menu de niveau supérieur.
  • Ils peuvent ajouter des menus contextuels (et à une zone spécifique, comme la liste de fichiers ou la fenêtre de l'éditeur).
  • Ils peuvent créer des éléments d'interface utilisateur. Cela peut être un dialogue modal ou même un panneau. (Actuellement, le panneau est verrouillé au bas de l'écran).
  • Ils peuvent créer un fournisseur de linting (essentiellement, ils peuvent s’inscrire eux-mêmes comme vérificateur de code pour un type de fichier)..
  • Ils peuvent créer leurs propres éditeurs intégrés (une caractéristique majeure de Brackets).
  • Ils peuvent s'inscrire en tant que fournisseur de documentation (par exemple, ajouter le support MDN pour les documents)..
  • Ils peuvent intégrer avec Quick Find et Quick Open.
  • Ils peuvent ajouter des indicateurs de code personnalisés et des couleurs de syntaxe.
  • Ils peuvent lire le fichier ouvert dans l'éditeur et le modifier. (Ils peuvent également voir le texte actuellement sélectionné, le cas échéant.)

Cela décrit comment les extensions peuvent modifier les crochets, mais que peuvent réellement faire les extensions en termes de code? En gardant à l'esprit que vous écrivez des extensions dans des normes Web pures (HTML, JavaScript et CSS), vous disposez de beaucoup de puissance. Les seules limites réelles concernent les données binaires. Il existe une API de système de fichiers qui vous permet de contrôler les fichiers mais est limitée aux données texte. Heureusement, vous avez un moyen de sortir.

Toute extension Brackets peut s’intégrer à Node.js. Si vous avez un paquet Node.js existant, votre extension peut y appeler et faire ce que Node.js peut faire, ce qui est essentiellement tout.

Mettons à jour notre extension pour mieux l'intégrer à l'éditeur. Je vais commencer par ajouter simplement un élément de menu pour l'extension.

Exemple 2: helloworld2 / main.js / * Basé - en partie - sur l’exemple d’extension HelloWorld sur le wiki Brackets: https://github.com/adobe/brackets/wiki/Simple-%22Hello-World%22-extension * / define (fonction (requis, exportations, module) var CommandManager = brackets.getModule ("commande / CommandManager"), Menus = brackets.getModule ("commande / Menus"), AppInit = brackets.getModule ("utils / AppInit" log; fonction log (s) console.log ("[[helloworld2]" + s); function handleHelloWorld () alert ("Tu m'as couru, merci!"); AppInit.appReady (function () log ( "Bonjour de la part de HelloWorld2."); Var HELLOWORLD_EXECUTE = "helloworld.execute"; CommandManager.register ("Run HelloWorld", HELLOWORLD_EXECUTE, handleHelloWorld); );););

Nous avons quelques changements ici alors abordons-les un à un. Vous remarquerez que l'extension commence par trois appels à brackets.getModule. Toutes les extensions ont accès à un objet entre crochets qui fournit une API permettant de charger les fonctionnalités principales à partir de l'éditeur. Dans ce cas, l'extension a chargé deux bibliothèques dont nous aurons besoin pour le menu (CommandManager et Menus) et une qui sera utilisée pour aider à initialiser l'extension (AppInit)..

Parlons d'AppInit. Vous pouvez voir que la majeure partie de l'extension est maintenant chargée avec un rappel appReady. Ce rappel est déclenché lorsque le chargement des supports est terminé et est généralement considéré comme la "meilleure pratique" pour que les extensions utilisent.

L'enregistrement d'un élément de menu prend quelques étapes. Je commence par définir un "ID de commande", un identifiant unique pour l'élément que je vais ajouter à l'interface utilisateur. La manière typique de faire ceci est avec le format extensionname.someaction. Dans mon cas, j'ai utilisé helloworld.execute. Je peux alors enregistrer cette commande avec la fonction (handleHelloWorld) qui devrait être appelé lorsque la commande est déclenchée.

La dernière étape consiste à ajouter cette commande au menu. Vous pouvez probablement deviner que mon élément de menu sera ajouté dans le menu Affichage en fonction de cette valeur: Menus.AppMenuBar.VIEW_MENU. Comment ai-je su cette valeur? Simple, j'ai vu d'autres extensions le faire. Sérieusement, il n’existe pas encore de liste spécifique d’articles de ce genre. N'oubliez pas que Brackets est open source. Je peux facilement accéder au dépôt GitHub et le vérifier. Dans ce cas, le fichier est Menus.js, situé sur Github. Je peux voir où sont définis les différents menus principaux:

/ ** * Constantes de menu de l'application * * @enum string * / var AppMenuBar = FILE_MENU: "menu-fichier", EDIT_MENU: "menu-édition", VIEW_MENU: "menu-vue", NAVIGATE_MENU: "navigateur-menu ", HELP_MENU:" help-menu ";

En règle générale, il est logique d'avoir au moins une compréhension sommaire de ce qui est disponible dans les crochets eux-mêmes. Vos extensions utiliseront de temps à autre plusieurs fonctionnalités différentes, il est donc dans votre intérêt de connaître au moins la configuration du terrain..

Après avoir rechargé les crochets, vous verrez maintenant l’option de menu dans Vue menu. Exactement où il se trouve peut être un peu aléatoire car vous pouvez avoir d’autres extensions installées.


Vous pouvez réellement être un peu plus précis sur votre position. Encore une fois, c’est là que le code source vous aidera. Le même fichier que je lie ci-dessus contient également la définition addMenuItem.


Mettez du rouge à lèvres sur ce cochon

Maintenant que vous avez vu un exemple simple de la manière dont une extension peut s'intégrer dans les crochets, voyons comment mettre à jour l'interface utilisateur. Dans la version précédente de notre code, une alerte était utilisée pour envoyer un message. Bien que cela fonctionne, ce n'est pas très joli. Votre code peut accéder à l'éditeur de crochets comme n'importe quel autre code de modification DOM. Pendant que tu pouvez faites tout ce que vous voulez, il existe quelques méthodes standard permettant aux extensions de mettre à jour l’UI entre parenthèses. (En guise d'avertissement, en général, vous ne souhaitez pas toucher au DOM de l'interface utilisateur de l'éditeur principal. Vous pouvez, mais avec les mises à jour futures, votre code risque de se briser. De plus, les utilisateurs risquent de ne pas être contents si votre extension modifie quelque chose de fondamental en supports. )

La première méthode que nous allons étudier utilise des dialogues modaux. Les crochets l'utilisent déjà et dispose d'une API permettant aux extensions d'appeler. Par exemple, mettons à jour l'extension HelloWorld pour utiliser un modal à la place..

Exemple 3: helloworld3 / main.js / * Basé - en partie - sur l’exemple d’extension HelloWorld sur le wiki Brackets: https://github.com/adobe/brackets/wiki/Simple-%22Hello-World%22-extension * / define (fonction (requis, exportations, module) var CommandManager = brackets.getModule ("commande / CommandManager"), Menus = brackets.getModule ("commande / Menus"), Dialogs = parenthèse.getModule ("widgets / Dialogues" ), DefaultDialogs = brackets.getModule ("widgets / DefaultDialogs"), AppInit = brackets.getModule ("utils / AppInit"); journal (s) de la fonction console.log ("[helloworld3]" + s); fonction handleHelloWorld () Dialogs.showModalDialog (DefaultDialogs.DIALOG_ID_INFO, "Hello World", "Même message important"); AppInit.appReady (function () log ("Hello from HelloWorld3."); Var HELLOWORLD_EXECUTE = "helloworld.execute" ; CommandManager.register ("Run HelloWorld", HELLOWORLD_EXECUTE, handleHelloWorld); var menu = Menus.getMenu (Menus.AppMenuBar.VIEW_MENU); menu.addMenuItem (HELLOWORLD_EXECUTE););

Notez l'ajout de deux modules de supports supplémentaires: Dialogues et DefaultDialogs. Le prochain changement est en handleHelloWorld. L'une des méthodes de la bibliothèque Dialog est la possibilité d'afficher un dialogue (sans surprise, je suppose). La méthode veut une classe, un titre et un corps, et c'est tout. Vous pouvez faire plus avec les boîtes de dialogue, mais pour l’instant, ceci illustre la fonctionnalité. Maintenant, lorsque nous exécutons la commande, nous obtenons une interface utilisateur beaucoup plus jolie. (Avec les boutons et les comportements par défaut pour gérer la fermeture de la boîte de dialogue.)


C’est un exemple, regardons maintenant un autre: créer un panneau inférieur. Comme pour les dialogues, nous avons le support de Brackets pour faciliter les choses. Regardons un exemple puis j'expliquerai les changements.

Exemple 4: helloworld4 / main.js / * Basé - en partie - sur l’exemple d’extension HelloWorld sur le wiki Brackets: https://github.com/adobe/brackets/wiki/Simple-%22Hello-World%22-extension * / define (fonction (requis, exportations, module) var CommandManager = brackets.getModule ("commande / CommandManager"), Menus = brackets.getModule ("commande / Menus"), PanelManager = brackets.getModule ("view / PanelManager" ), AppInit = brackets.getModule ("utils / AppInit"); var HELLOWORLD_EXECUTE = "helloworld.execute"; panneau var; journal (s) de la fonction console.log ("[helloworld4]" + s); fonction handleHelloWorld ( ) if (panel.isVisible ()) panel.hide (); CommandManager.get (HELLOWORLD_EXECUTE) .setChecked (false); else panel.show (); CommandManager.get (HELLOWORLD_EXECUTE) .setChecked (true);  AppInit.appReady (function () log ("Hello from HelloWorld4."); CommandManager.register ("Run HelloWorld", HELLOWORLD_EXECUTE, handleHelloWorld); var menu = Menus.getMenu (Menus.AppMenuBar.VIEW_MENU); menu. addMenuItem (HELLOWORLD_EXECUTE) ; panel = PanelManager.createBottomPanel (HELLOWORLD_EXECUTE, $ ("
HTML pour mon panel
"), 200);););

Concentrons-nous sur les changements. D'abord, j'ai abandonné les modules de dialogue car je ne les utilise plus. Au lieu de cela, nous chargeons le PanelManager. Dans le bloc appReady, j'ai défini un nouveau panneau à l'aide de la méthode createBottomPanel de l'API de PanelManager. Comme la commande de menu, cela prend un ID unique, donc je viens de le réutiliser HELLOWORLD_EXECUTE. Le second argument est un bloc HTML enveloppé par jQuery (et au cas où vous vous le demanderiez, nous pourrions faire cela plus facilement) et, enfin, une taille minimale. Ceci configure le panneau mais ne l'exécute pas réellement.

Dans le gestionnaire d'événements, nous avons lié au menu, nous pouvons demander au panneau s'il est visible et ensuite le masquer ou l'afficher. Cette partie devrait être assez triviale. Pour le plaisir, j'ai ajouté un peu plus de complexité. Remarquerez que CommandManager nous permet d'obtenir un élément de menu et de définir une propriété cochée. Cela peut être inutile car l'utilisateur peut facilement voir le panneau lui-même, mais l'ajout du contrôle rend les choses un peu plus évidentes. Dans la capture d'écran ci-dessous, vous pouvez voir le panneau dans son état visible..


Vous vous posez peut-être tout de suite des questions sur le panneau HTML. Existe-t-il un meilleur moyen de fournir le code HTML? Quoi qu'il en soit de le coiffer? Oui, regardons une version plus avancée.

Exemple 5: helloworld5 / main.js / * Basé - en partie - sur l’exemple d’extension HelloWorld sur le wiki Brackets: https://github.com/adobe/brackets/wiki/Simple-%22Hello-World%22-extension * / define (fonction (requis, exportations, module) var CommandManager = brackets.getModule ("commande / CommandManager"), Menus = brackets.getModule ("commande / Menus"), PanelManager = brackets.getModule ("view / PanelManager" ), ExtensionUtils = brackets.getModule ("utils / ExtensionUtils"), AppInit = brackets.getModule ("utils / AppInit"); var HELLOWORLD_EXECUTE = "helloworld.execute"; var panel; var panelHtml = require ("text! Panel). html "); log (s) de la fonction console.log (" [helloworld5] "+ s); function handleHelloWorld () if (panel.isVisible ()) panel.hide (); CommandManager.get (HELLOWORLD_EXECUTE) .setChecked (false); else panel.show (); CommandManager.get (HELLOWORLD_EXECUTE) .setChecked (true); AppInit.appReady (function () log ("Bonjour de HelloWorld5."); ExtensionUtils.loadStyleSheet (module, "helloworld.css"); CommandMa nager.register ("Run HelloWorld", HELLOWORLD_EXECUTE, handleHelloWorld); var menu = Menus.getMenu (Menus.AppMenuBar.VIEW_MENU); menu.addMenuItem (HELLOWORLD_EXECUTE); panel = PanelManager.createBottomPanel (HELLOWORLD_EXECUTE, $ (panelHtml), 200); ); );

Comme auparavant, je vais me concentrer sur les changements. D'abord, notez que j'ai inclus une variable appelée panelHtml qui est chargé via require. Cela me permet de définir mon code HTML en dehors de mon code JavaScript. (Vous pouvez également utiliser des moteurs de templates. Brackets est livré avec Moustache.) Le code HTML derrière le panneau est plutôt simple..

Exemple 6: helloworld5 / panel.html 

Mon panneau

Mon panneau amène tous les garçons dans la cour,
Et ils sont comme
C'est mieux que le tien,
Bon sang c'est mieux que le tien,
je peux t'apprendre,
Mais je dois charger

Retournant vers main.js, J'ai démontré une autre fonctionnalité, loadStyleSheet. Cela vous permet de charger une feuille de style spécifique à une extension. J'ai créé un fichier, helloworld.css, avec des styles CSS simples (mais de bon goût).

Exemple 7: helloworld5 / helloworld.css .helloworld-panel h1 couleur: rouge;  .helloworld-panel p couleur: bleu; poids de police: gras; 

Notez que j'ai préfixé mes styles avec un nom unique. Cela aide à éviter que mes classes ne soient en conflit avec quoi que ce soit construit dans Brackets. Grâce à ces changements simples, mon panneau a maintenant un aspect bien meilleur et vous pouvez comprendre pourquoi je suis connu dans le monde entier pour mes compétences supérieures en conception..



Emballage et partage de votre extension Kick Butt

Bien sûr, créer l’extension Brackets la plus cool ne suffit pas. Vous souhaitez probablement (espérons-le!) Le partager avec d'autres. Une option consiste à compresser le répertoire et à le placer sur votre site Web. Les gens peuvent télécharger le zip, l'extraire et le copier dans leur dossier d'extensions Brackets.

Mais ce n'est pas cool. Tu veux être cool, non? Pour partager votre extension et la rendre disponible via le gestionnaire d’extensions Brackets, il vous suffit d’ajouter un package.json déposer dans votre extension. Si vous avez déjà utilisé Node.js, cela vous semblera familier. Voici un exemple pour notre extension.

Exemple 8: helloworld6 / package.json "name": "camden.helloworld", "title": "HelloWorld", "description": "Ajoute le support HelloWorld à Brackets.", "Homepage": "https: // github .com / cfjedimaster / quelque chose de réel ici "," version ":" 1.0.0 "," auteur ":" Raymond Camden  (http://www.raymondcamden.com) "," licence ":" MIT "," moteurs ": " supports ":"<=0.34.0"  

La plupart de ces explications s’expliquent d’elles-mêmes, mais la vraie partie cruciale est le blocage des moteurs. Les crochets se mettent à jour assez rapidement. Si Brackets a ajouté une fonctionnalité particulière à un moment donné de votre extension, vous pouvez ajouter une simple condition ici pour éviter que les utilisateurs n'essayent d'installer votre extension sur une version incompatible. (Vous pouvez trouver une liste complète des paramètres possibles sur le wiki.)

Une fois que cela est fait, la prochaine étape consiste à le télécharger dans le registre Brackets. Vous devrez vous connecter via votre compte GitHub, mais une fois que vous aurez terminé, vous pourrez simplement télécharger votre zip. Votre extension sera alors disponible pour toute personne utilisant des crochets. Mieux encore, si vous mettez à jour votre extension, Extension Manager sera en mesure de l'indiquer à l'utilisateur pour qu'il sache qu'une mise à jour est disponible..


Quoi d'autre?

Espérons que vous avez vu à quel point il est facile d’étendre les crochets. Il y a bien d'autres choses que nous n'avons pas abordées, telles que l'API Linting et l'intégration NodeJS, mais cet article devrait être amplement suffisant pour vous aider à démarrer. Pour rappel, n'oubliez pas qu'une grande collection d'extensions vous est proposée pour commencer à jouer dès maintenant. Bonne chance!