Brackets-extensies maken

Een tijdje geleden schreef ik over de recente updates van de Brackets-editor. Brackets is een open source project gericht op webstandaarden en gebouwd met webtechnologieën. Het heeft een smalle focus en heeft daarom mogelijk geen specifieke functie waarvan u afhankelijk bent. Gelukkig wordt Brackets geleverd met een krachtige uitbreidings-API waarmee je een onbeperkt aantal nieuwe functies kunt toevoegen. In dit artikel ga ik deze API bespreken en laten zien hoe u uw eigen uitbreidingen kunt bouwen.

Het is beslissend dat je je herinnert dat Brackets in actieve ontwikkeling is. Dit artikel wordt geschreven in december 2013. Het is zeker mogelijk dat de onderstaande code nu verouderd is. Houd dat in gedachten en zorg ervoor dat je de wiki raadpleegt voor de nieuwste updates van de extensie-API.


Ermee beginnen

Ik ga ervan uit dat je mijn laatste artikel hebt gelezen en al bekend bent met de extensiemanager. Dit biedt een eenvoudige, één klik-methode om extensies te installeren. Een van de beste manieren om extensies te leren schrijven, is door naar het werk van anderen te kijken (zo heb ik het geleerd). Ik zou aanraden om een ​​paar extensies te pakken (er zijn er nu bijna 200 beschikbaar) en hun code te scheuren. Wees niet bang om er een paar te breken terwijl je bezig bent.

Brackets plaatst alle geïnstalleerde extensies binnen één hoofdmap. Om die map te vinden, gaat u naar Helpen menu en selecteer "Map voor extensies weergevenVoor mijn OS X-installatie was dit te vinden op / Gebruikers / ray / Bibliotheek / Application Support / Brackets / extensions / user. Als je vanuit die map omhoog gaat, zul je ook een map met een handicap opmerken. Haakjes zullen een dappere poging doen om wat dan ook te laden, maar als je ooit in een situatie terecht komt waarin Brackets het bed volledig heeft geknikt en gewoon niet zal werken, overweeg dan het verplaatsen van mogelijk slechte extensies naar de uitgeschakelde map. Verderop in het artikel zal ik bespreken hoe u extensies kunt controleren en debuggen om dergelijke problemen te voorkomen.

Begin met naar je gebruikersmap te gaan en een nieuwe map te maken, HelloWorld1. Ja, ook al is het helemaal zwak, we gaan een HelloWorld-extensie maken. Haat me niet, ik hou van eenvoudig. Maak binnen die map een nieuw bestand met de naam main.js. Listing one laat zien wat de inhoud van dit bestand zou moeten zijn. Merk op dat ik in dit artikel een aantal verschillende iteraties van de. Zal doornemen Hallo Wereld uitbreiding. Elke naam krijgt een steeds hoger nummer. Dus ons eerste voorbeeld is van HelloWorld1, de volgende HelloWorld2, enzovoorts. Het zou logisch zijn om de code simpelweg in één map te kopiëren, Hallo Wereld, in plaats van ze allemaal zelf te kopiëren. Als je dat doet, heb je meerdere gerelateerde extensies die tegelijk worden uitgevoerd en die dingen absoluut kunnen verwarren.

Listing 1: helloworld1 / main.js define (functie (vereisen, exporteert, module) functie log (s) console.log ("[helloworld]" + s); log ("Hallo van HelloWorld."); );

De eerste regel definieert onze extensie als een module die door Brackets automatisch wordt opgehaald bij het laden van de applicatie. De rest van de extensie is een aangepast logbericht (u zult meteen zien waarom) en een oproep naar die logger. Zodra je dit bestand hebt opgeslagen, ga je terug naar haakjes, selecteer je het menu Foutopsporing en klik je op Opnieuw laden. (Je kan ook gebruiken Command / Control + R om opnieuw te laden.)

Brackets worden opnieuw geladen en ... er gebeurt niets anders. De extensie die we hebben gebouwd, heeft eigenlijk niets gedaan dat we konden zien, maar het heeft zich wel bij de console aangemeld. Maar waar is die console? Brackets biedt een eenvoudige manier om de console te bekijken. Ga gewoon terug naar de debug menu en selecteer Ontwikkelaarshulpprogramma's tonen. Hiermee wordt een nieuw tabblad in Chrome geopend met een vertrouwde gebruikersinterface van Dev Tools. In de onderstaande schermafbeelding heb ik ons ​​logboek gemarkeerd. Andere extensies en Brackets zelf, loggen ook berichten naar dit scherm. Door mijn logberichten voor te voegen met [Hallo Wereld], Ik kan mijn eigen dingen een beetje makkelijker vinden.


Merk op dat de volledige Chrome console.api werkt hier. U kunt dit soort dingen doen om uw consoleberichten te formatteren:

 functie log (en) console.log ("% c [helloworld]" + s, "color: blue; font-size: large"); 

Maak je gek, maar probeer deze berichten te verwijderen voordat je je code met de rest van de wereld deelt. In het geval dat je nieuwsgierig bent, kun je op dit moment geen dev-tools gebruiken in een andere browser, zoals Firefox.


Integratiepunten

Nu dat u de (zeer) basis kent, laten we het hebben over wat Brackets-extensies kunnen doen met de editor:

  • Ze kunnen sneltoetsen maken, zodat ze kunnen reageren op aangepaste toetsaanslagen.
  • Ze kunnen toevoegen aan het hoofdmenu.
  • Ze kunnen contextmenu's toevoegen (en aan een specifiek gebied, zoals de bestandsvermelding of het editorvenster).
  • Ze kunnen UI-items maken. Dit kan een modale dialoog zijn of zelfs een paneel. (Momenteel is het paneel vergrendeld aan de onderkant van het scherm).
  • Ze kunnen een pluisprovider maken (in wezen kunnen ze zichzelf als een codechecker voor een bestandstype registreren).
  • Ze kunnen hun eigen inline editors maken (een belangrijk kenmerk van Brackets).
  • Ze kunnen zich registreren als documentatieprovider (bijvoorbeeld MDN-ondersteuning voor documenten toevoegen).
  • Ze kunnen worden geïntegreerd met Snel zoeken en Snel openen.
  • Ze kunnen aangepaste coderingstips en syntaxekleuren toevoegen.
  • Ze kunnen het huidige geopende bestand in de editor lezen en aanpassen. (Ze kunnen ook de huidige geselecteerde tekst zien, indien aanwezig.)

Dat beschrijft hoe extensies haakjes kunnen wijzigen, maar wat kunnen extensies eigenlijk doen in termen van code? Houd er rekening mee dat je in pure webstandaarden (HTML, JavaScript en CSS) extensies schrijft, en dat je eigenlijk behoorlijk wat kracht hebt. De enige echte limieten hebben betrekking op binaire gegevens. Er is een API voor bestandssysteem die u controle geeft over bestanden, maar die alleen tekstgegevens bevat. Gelukkig heb je een uitweg.

Elke Brackets-extensie kan worden geïntegreerd met Node.js. Als je een bestaand Node.js-pakket hebt, kan je extensie ernaar bellen en doen, tja, wat Node.js ook kan doen, wat eigenlijk alles is.

Laten we onze extensie bijwerken om een ​​beetje beter te integreren met de editor. Ik begin met het toevoegen van een menu-item voor de extensie.

Listing 2: helloworld2 / main.js / * Gebaseerd - gedeeltelijk - op de voorbeelduitbreiding van HelloWorld op de Brackets-wiki: https://github.com/adobe/brackets/wiki/Simple-%22Hello-World%22-extension * / define (functie (vereisen, exporteert, module) var CommandManager = brackets.getModule ("command / CommandManager"), Menus = brackets.getModule ("command / Menus"), AppInit = brackets.getModule ("utils / AppInit" ); function log (s) console.log ("[helloworld2]" + s); function handleHelloWorld () alert ("You run me, thanks!"); AppInit.appReady (function () log ( "Hallo van HelloWorld2."); Var HELLOWORLD_EXECUTE = "helloworld.execute"; CommandManager.register ("Run HelloWorld", HELLOWORLD_EXECUTE, handleHelloWorld); var menu = Menus.getMenu (Menus.AppMenuBar.VIEW_MENU); menu.addMenuItem (HELLOWORLD_EXECUTE );););

We hebben hier een paar wijzigingen, dus laten we ze een voor een aanpakken. U zult merken dat de extensie begint met drie aanroepen naar haakjes.getModule. Alle extensies hebben toegang tot een haakjesobject dat een API biedt waarin we de kernfunctionaliteit van de editor kunnen laden. In dit geval heeft de extensie twee bibliotheken geladen die we nodig hebben voor het menu (CommandManager en menu's) en een die zal worden gebruikt om de extensie te initialiseren (AppInit).

Laten we praten over AppInit. U kunt zien dat het grootste deel van de extensie nu is geladen met een appReady-callback. Deze callback wordt afgevuurd wanneer Brackets het laden heeft voltooid en wordt over het algemeen beschouwd als de "beste werkwijze" voor uitbreidingen om gebruik van te maken.

Het registreren van een menu-item duurt enkele stappen. Ik begin met het definiëren van een "commando-ID", een unieke identificatie voor het item dat ik aan de gebruikersinterface zal toevoegen. De typische manier om dit te doen is met het formaat extensionname.someaction. In mijn geval gebruikte ik helloworld.execute. Ik kan dan deze opdracht samen met de functie registreren (handleHelloWorld) die moet worden aangeroepen wanneer het commando wordt geactiveerd.

De laatste stap is om deze opdracht aan het menu toe te voegen. U kunt waarschijnlijk raden dat mijn menu-item zal worden toegevoegd in het menu Beeld op basis van deze waarde: Menu's. AppMenuBar.VIEW_MENU. Hoe wist ik die waarde? Simpel, ik zag dat andere extensies het doen. Er is echter serieus geen specifieke lijst met items zoals deze. Vergeet niet dat Brackets open source is. Ik kan gemakkelijk naar de GitHub-repo springen en het bekijken. In dit geval is het bestand Menus.js, gelegen op Github. Daarin kan ik zien waar de verschillende kernmenu's zijn gedefinieerd:

/ ** * Brackets Toepassingsmenu Constanten * @enum string * / var AppMenuBar = FILE_MENU: "bestandsmenu", EDIT_MENU: "bewerkingsmenu", VIEW_MENU: "weergavemenu", NAVIGATE_MENU: "navigatiemenu ", HELP_MENU:" help-menu ";

Als algemene vuistregel is het logisch om op zijn minst een vluchtig inzicht te hebben in wat beschikbaar is in Brackets zelf. Uw extensies zullen van tijd tot tijd gebruikmaken van meerdere verschillende functies, dus het is absoluut in uw eigen belang om op zijn minst de lay van het land te kennen.

Na het opnieuw laden van haakjes, ziet u nu het menu-item in de Uitzicht menu. Precies waar het is, kan een beetje willekeurig zijn, omdat je misschien andere extensies hebt geïnstalleerd.


Je kunt een beetje specifieker zijn over je positie. Nogmaals, dit is waar de broncode u zal helpen. Hetzelfde bestand waarnaar ik heb gelinkt, bevat ook de definitie van addMenuItem.


Zet wat lippenstift op dat varken

Nu u een eenvoudig voorbeeld hebt gezien van hoe een extensie kan worden geïntegreerd in Brackets, laten we eens kijken naar hoe we de gebruikersinterface updaten. In de vorige versie van onze code werd een waarschuwing gebruikt om een ​​bericht te verzenden. Hoewel dit werkt, is het niet erg mooi. Uw code heeft net als elke andere DOM-wijzigingscode toegang tot de Brackets-editor. Terwijl jij kan doe alles wat u wilt, er zijn een paar standaardmanieren waarmee extensies de gebruikersinterface tussen haakjes bijwerken. (Als waarschuwing wil je over het algemeen de DOM van de hoofdeditor-interface niet aanraken, maar met toekomstige updates kan je code breken. Ook kunnen gebruikers niet blij zijn als je extensie iets kernachtig in Brackets verandert. )

De eerste methode die we zullen bekijken, maakt gebruik van modale dialogen. Brackets gebruikt dit al en heeft een API beschikbaar voor uitbreidingen om te bellen. Laten we als eenvoudig voorbeeld de HelloWorld-extensie bijwerken om in plaats daarvan een modaal te gebruiken.

Listing 3: helloworld3 / main.js / * Gebaseerd - gedeeltelijk - op de voorbeelduitbreiding van HelloWorld op de Brackets-wiki: https://github.com/adobe/brackets/wiki/Simple-%22Hello-World%22-extension * / define (functie (vereisen, exporteert, module) var CommandManager = brackets.getModule ("command / CommandManager"), Menus = brackets.getModule ("command / Menus"), Dialogs = brackets.getModule ("widgets / Dialogs" ), DefaultDialogs = brackets.getModule ("widgets / DefaultDialogs"), AppInit = brackets.getModule ("utils / AppInit"); functie log (ken) console.log ("[helloworld3]" + s); function handleHelloWorld () Dialogs.showModalDialog (DefaultDialogs.DIALOG_ID_INFO, "Hello World", "Same Important Message"); AppInit.appReady (function () log ("Hello from HelloWorld3."); Var HELLOWORLD_EXECUTE = "helloworld.execute" ; CommandManager.register ("Run HelloWorld", HELLOWORLD_EXECUTE, handleHelloWorld); var menu = Menu's.getMenu (Menu's. App. MenuBar.VIEW_MENU); menu.addMenuItem (HELLOWORLD_EXECUTE);););

Let op de toevoeging van twee extra Brackets-modules: dialogen en DefaultDialogs. De volgende verandering is binnen handleHelloWorld. Een van de methoden in de Dialog-bibliotheek is de mogelijkheid om een ​​dialoogvenster weer te geven (geen verrassing, neem ik aan). De methode wil een klasse, een titel en een lichaam, en dat is het. Er is meer dat u kunt doen met dialoogvensters, maar voor nu toont dit de functie. Wanneer we het commando uitvoeren, krijgen we een veel mooiere gebruikersinterface. (Samen met standaardknoppen en -gedragingen om het dialoogvenster te sluiten.)


Dat is een voorbeeld, laten we nu naar een ander kijken: een onderpaneel maken. Net als bij dialogen hebben we ondersteuning van Brackets om het eenvoudiger te maken. Laten we een voorbeeld bekijken en dan zal ik de veranderingen uitleggen.

Listing 4: helloworld4 / main.js / * Gebaseerd - gedeeltelijk - op de voorbeelduitbreiding van HelloWorld op de Brackets-wiki: https://github.com/adobe/brackets/wiki/Simple-%22Hello-World%22-extension * / define (functie (vereisen, exporteert, module) var CommandManager = brackets.getModule ("command / CommandManager"), Menus = brackets.getModule ("command / Menus"), PanelManager = brackets.getModule ("view / PanelManager" ), AppInit = brackets.getModule ("utils / AppInit"); var HELLOWORLD_EXECUTE = "helloworld.execute"; var panel; function log (s) console.log ("[helloworld4]" + 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 ("Hello from HelloWorld4."); CommandManager.register ("Run HelloWorld", HELLOWORLD_EXECUTE, handleHelloWorld); menu var menu = Menu Menus.getMenu (Menu's.AppMenuBar.VIEW_MENU) ;. addMenuItem (HELLOWORLD_EXECUTE) ; panel = PanelManager.createBottomPanel (HELLOWORLD_EXECUTE, $ ("
HTML voor mijn paneel
"), 200);););

Laten we ons concentreren op de veranderingen. Ten eerste heb ik de Dialoog-modules laten vallen omdat ik ze niet meer gebruik. In plaats daarvan laden we de PanelManager op. Beneden in het appReady-blok heb ik een nieuw paneel gedefinieerd met behulp van de PanelManager API-methode createBottomPanel. Net als de menu-opdracht neemt dit een uniek ID op, dus ik gebruik het gewoon opnieuw HELLOWORLD_EXECUTE. Het tweede argument is een jQuery-ingepakt HTML-blok (en in het geval je je afvraagt, ja, we kunnen dit mooier doen), en ten slotte een minimale grootte. Hiermee wordt het paneel ingesteld, maar wordt het niet daadwerkelijk uitgevoerd.

In het geval van handler hebben we het menu gekoppeld, we kunnen het panel vragen of het zichtbaar is en het dan verbergen of tonen. Dat deel zou best triviaal moeten zijn. Voor de lol heb ik iets ingewikkelder toegevoegd. Let erop dat CommandManager laat ons een menu-item krijgen en een gecontroleerde eigenschap instellen. Dit kan onnodig zijn, omdat de gebruiker het paneel zelf gemakkelijk genoeg kan zien, maar het toevoegen van de vinkjes maakt het alleen maar een beetje duidelijker. In de schermafbeelding hieronder ziet u het paneel in de zichtbare staat.


Meteen vraagt ​​u zich misschien af ​​over de HTML van het paneel. Is er een betere manier om de HTML te leveren? Hoe dan ook om het te stylen? Laten we eens kijken naar een geavanceerdere versie.

Listing 5: helloworld5 / main.js / * Gebaseerd - gedeeltelijk - op de voorbeelduitbreiding van HelloWorld op de Brackets-wiki: https://github.com/adobe/brackets/wiki/Simple-%22Hello-World%22-extension * / define (functie (vereisen, exporteert, module) var CommandManager = brackets.getModule ("command / CommandManager"), Menus = brackets.getModule ("command / 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 "); functie log (ken) 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 ("Hello from 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); ); );

Zoals eerder, zal ik me concentreren op de veranderingen. Merk allereerst op dat ik een variabele heb opgenomen met de naam panelHtml dat wordt geladen via vereisen. Hiermee kan ik mijn HTML buiten mijn JavaScript-code definiëren. (Je kunt ook template-engines gebruiken.) Brackets wordt met Moustache geleverd.) De HTML achter het paneel is vrij eenvoudig.

Listing 6: helloworld5 / panel.html 

Mijn panel

Mijn paneel brengt alle jongens naar de tuin,
En dat zijn ze
Het is beter dan het jouwe,
Verdorie, goed, het is beter dan het jouwe,
ik kan je leren,
Maar ik moet opladen

Terugkerend naar main.js, Ik heb een andere functie gedemonstreerd, loadStyleSheet. Hiermee kunt u een uitbreidingsspecifieke stylesheet laden. Ik heb een bestand gemaakt, helloworld.css, met enkele eenvoudige (maar smaakvolle) CSS-stijlen.

Listing 7: helloworld5 / helloworld.css. Harelloworelft h1 kleur: rood; . Werelddeelpaneel p kleur: blauw; lettertype: vet; 

Merk op dat ik mijn stijlen heb voorafgegaan door een unieke naam. Dit helpt ervoor te zorgen dat mijn lessen niet conflicteren met iets dat in Brackets is ingebouwd. Met deze eenvoudige wijzigingen ziet mijn paneel er nu veel beter uit, en u kunt zien waarom ik wereldwijd bekend sta vanwege mijn superieure ontwerpvaardigheden.



Verpakking en delen van je Kick Butt Extension

Het is natuurlijk niet voldoende om alleen de coolste Brackets-extensie te maken. Je wilt het waarschijnlijk (hopelijk!) Delen met anderen. Een optie is om gewoon de map dicht te ritsen en op je website te plaatsen. Mensen kunnen de zip downloaden, uitpakken en naar hun Brackets-extensiemap kopiëren.

Maar dat is niet cool. Je wilt cool zijn, toch? Om uw extensie te delen en beschikbaar te maken via de Brackets Extension Manager, hoeft u alleen maar een toe te voegen package.json bestand naar uw extensie. Als u ooit Node.js hebt gebruikt, dan zal dit bekend voorkomen. Hier is een voorbeeld voor onze extensie.

Listing 8: helloworld6 / package.json "name": "camden.helloworld", "title": "HelloWorld", "description": "Voegt HelloWorld-ondersteuning toe aan Brackets.", "Homepage": "https: // github .com / cfjedimaster / something real here "," version ":" 1.0.0 "," auteur ":" Raymond Camden  (http://www.raymondcamden.com) "," license ":" MIT "," engines ": " haakjes ":"<=0.34.0"  

Het grootste deel hiervan spreekt voor zich, maar het echte cruciale deel is het motorenblok. Brackets updaten zichzelf vrij snel. Als haakjes op een bepaald punt een specifieke functie hebben toegevoegd waarop uw extensie vertrouwt, kunt u hier een eenvoudige voorwaarde toevoegen om ervoor te zorgen dat mensen uw extensie niet proberen te installeren op een incompatibele versie. (Je vindt een volledige lijst van de mogelijke instellingen op de Wiki.)

Zodra je dit hebt gedaan, is het volgende deel om het te uploaden naar de Brackets Registry. Je moet inloggen via je GitHub-account, maar als je dat eenmaal hebt gedaan, kun je eenvoudig je zip uploaden. Uw extensie is dan beschikbaar voor iedereen die Brackets gebruikt. Sterker nog, als u uw extensie bijwerkt, kan Extension Manager dit feitelijk voor de gebruiker markeren, zodat zij weten dat er een update beschikbaar is.


Wat nog meer?

Hopelijk heb je gezien hoe gemakkelijk het is om haakjes uit te breiden. Er is meer dat we niet bedekten, zoals de Linting API en NodeJS-integratie, maar dit artikel zou meer dan genoeg moeten zijn om je op weg te helpen. Ter herinnering, vergeet niet dat er een grote verzameling extensies beschikbaar is waarmee u nu kunt beginnen spelen. Succes!