Создание скобок Расширения

8 января 2018

Некоторое время назад я писал о последних обновлениях редактора скобок. Скобки - проект с открытым исходным кодом, ориентированный на веб-стандарты и построенный с использованием веб-технологий. Он имеет узкий фокус и, следовательно, может не иметь определенной функции, от которой вы зависите. К счастью, Brackets поставляется с мощным API расширения, который позволяет добавлять любое количество новых функций. В этой статье я расскажу об этом API и продемонстрирую, как вы можете создавать свои собственные расширения.

Очень важно помнить, что скобки находятся в активной разработке. Эта статья написана в декабре 2013 года. Несомненно, что приведенный ниже код теперь устарел. Помните об этом и не забудьте проверить вики для последних обновлений API расширения.


Начало работы

Я собираюсь предположить, что вы прочитали мою последнюю статью и уже знакомы с менеджером расширения. Это обеспечивает простой, один клик метод установки расширений. Один из лучших способов научиться писать расширения - это посмотреть на работу, проделанную другими (так я узнал). Я бы рекомендовал захватить несколько расширений (сейчас их почти 200) и разрывает их код. Не бойтесь сломать несколько, пока вы на нем.

Кронштейны помещают все установленные расширения в одну основную папку. Чтобы найти эту папку, перейдите в меню «Справка» и выберите «Показать папку расширений». Для установки моей ОС X это было расположено в приложении «Расширения пользователей приложений поддержки пользователей». Если вы выйдете из этой папки, вы также увидите папку с отключением. Кронштейны сделают отважную попытку загрузить независимо от того, что, но если вы когда-нибудь окажетесь в ситуации, когда скобки полностью убрали кровать и просто не сработают, подумайте о переносе потенциально плохих расширений в папку с отключением. Позже в этой статье я расскажу, как вы можете отслеживать и отлаживать расширения, чтобы в первую очередь предотвратить такие проблемы.

Начните с перехода в папку пользователя и создайте новую папку helloworld1. Да, даже если он полностью хромой, мы собираемся построить расширение HelloWorld. Не ненавидите меня, мне нравится просто. Внутри этой папки создайте новый файл main.js. В листинге 1 показано, как должно выглядеть содержимое этого файла. Обратите внимание, что в этой статье я рассмотрю несколько разных итераций расширения helloworld. Каждый из них будет называться с более высоким номером. Итак, наш первый пример - helloworld1, следующий helloworld2 и т. Д. Было бы разумно просто скопировать код в одну папку, helloworld, вместо того, чтобы копировать каждый из них. Если вы это сделаете, у вас будет сразу несколько связанных расширений, и это может определенно путать вещи.

Listing 1: helloworld1/main.js
define(function(require, exports, module) {

    function log(s) {
            console.log("[helloworld] "+s);
    }

    log("Hello from HelloWorld.");
});

Первая строка определяет наше расширение как модуль, который автоматически подбирается скобками при загрузке приложения. Остальная часть расширения представляет собой настраиваемое сообщение журнала (вы увидите, почему в секунду) и вызов этого регистратора. После сохранения этого файла вернитесь в скобки, выберите меню «Отладка» и нажмите «Обновить». (Вы также можете использовать Command Control + R для перезагрузки.)

Кронштейны перезагрузятся и... ничего больше не произойдет. Расширение, которое мы построили, фактически не делало ничего, что мы могли видеть, но он записывался на консоль. Но где эта консоль? Скобки обеспечивают простой способ просмотра консоли. Просто вернитесь в меню «Отладка» и выберите «Показать инструменты разработчика». Это откроет новую вкладку в Chrome со знакомым интерфейсом инструментов Dev Tools. На скриншоте ниже я выделил наш журнал. Другие расширения и сами скобки также будут регистрировать сообщения на этом экране. Префикс моих сообщений журнала с помощью [helloworld], я могу сделать свой собственный материал немного легче найти.

Обратите внимание, что здесь работает весь Chrome console.api. Вы можете делать такие вещи, чтобы форматировать консольные сообщения:

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

Сходите с ума, но попробуйте удалить эти сообщения, прежде чем делиться своим кодом с остальным миром. Если вам интересно, вы не можете использовать инструменты разработчика в другом браузере, например Firefox.


Точки интеграции

Теперь, когда вы знаете основы (очень), давайте поговорим о том, какие расширения для скобок могут сделать в редакторе:

Они могут создавать быстрые клавиши, позволяя им реагировать на пользовательские нажатия клавиш. Они могут добавить в меню верхнего уровня. Они могут добавлять контекстные меню (и в определенную область, такую ​​как список файлов или окно редактора). Они могут создавать элементы пользовательского интерфейса. Это может быть модальный диалог или даже панель. (В настоящее время панель заблокирована в нижней части экрана). Они могут создать поставщика линтирования (по существу, они могут регистрироваться как средство проверки кода для типа файла). Они могут создавать собственные встроенные редакторы (основная особенность скобок). Они могут зарегистрироваться как поставщик документации (например, добавление поддержки MDN для документов). Они могут интегрироваться с Quick Find и Quick Open. Они могут добавлять пользовательские подсказки кода и цвета синтаксиса. Они могут читать текущий файл, открытый в редакторе, а также изменять его. (Они также могут видеть текущий выделенный текст, если он есть.)

Это описывает, как расширения могут изменять скобки, но что могут делать расширения с точки зрения кода? Помня о том, что вы пишете расширения в чистых веб-стандартах (HTML, JavaScript и CSS), на самом деле у вас довольно много энергии. Единственные реальные ограничения относятся к двоичным данным. Существует API файловой системы, который дает вам контроль над файлами, но ограничивается только текстовыми данными. К счастью, у вас есть выход.

Любое расширение брекетов может быть интегрировано с Node.js. Если у вас есть существующий пакет Node.js, ваше расширение может совершать вызовы и делать, что бы ни делал Node.js, что по сути является чем угодно.

Давайте обновим наше расширение, чтобы лучше интегрировать его с редактором. Я начну с простого добавления элемента меню для расширения.

Listing 2: helloworld2/main.js
/*
Based - in part - on the HelloWorld sample extension on the Brackets wiki:
https://github.com/adobe/brackets/wiki/Simple-%22Hello-World%22-extension
*/
define(function(require, exports, 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 ran me, thanks!");
    }


    AppInit.appReady(function () {

            log("Hello from 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);

    });

});

Здесь у нас есть несколько изменений, поэтому давайте их решать один за другим. Вы заметите, что расширение начинается с трех вызовов в brackets.getModule. Все расширения имеют доступ к объекту скобок, который предоставляет API, где мы можем загружать основные функции из редактора. В этом случае расширение загрузило две библиотеки, которые нам понадобятся для меню (CommandManager и Menus), и расширение, которое будет использоваться для инициализации расширения (AppInit).

Давайте поговорим об AppInit. Вы можете видеть, что большая часть расширения теперь загружена обратным вызовом appReady. Этот обратный вызов запускается, когда скобки завершают загрузку, и обычно считается «лучшей практикой» для расширений, которые нужно использовать.

Регистрация элемента меню выполняется несколькими шагами. Я начинаю с определения «идентификатора команды», уникального идентификатора элемента, который я буду добавлять в пользовательский интерфейс. Типичный способ сделать это - с расширением имени формата. В моем случае я использовал helloworld.execute. Затем я могу зарегистрировать эту команду вместе с функцией (handleHelloWorld), которая должна быть вызвана при запуске команды.

Последний шаг - добавить эту команду в меню. Вероятно, вы можете предположить, что мой пункт меню будет добавлен в меню «Вид» на основе этого значения: Menus.AppMenuBar.VIEW_MENU. Откуда я знаю эту ценность? Простой, я видел, что другие расширения делают это. Серьезно, однако, конкретного списка таких элементов пока нет. Не забывайте, что кронштейны с открытым исходным кодом. Я могу легко перейти к репо GitHub и проверить его. В этом случае файл - Menus.js, расположенный на Github. Там я вижу, где определяются различные различные основные меню:

/**
  * Brackets Application Menu Constants
  * @enum {string}
*/
var AppMenuBar = {
     FILE_MENU       : "file-menu",
     EDIT_MENU       : "edit-menu",
     VIEW_MENU       : "view-menu",
     NAVIGATE_MENU   : "navigate-menu",
     HELP_MENU       : "help-menu"
};

Как общее правило, имеет смысл иметь хотя бы поверхностное понимание того, что доступно в скобках. Ваши расширения будут время от времени использовать несколько различных функций, поэтому вам, безусловно, в ваших интересах, по крайней мере, знать местность земли.

После перезагрузки скобок теперь вы увидите пункт меню в меню «Вид». Точно там, где это возможно, может быть немного случайным, так как у вас могут быть установлены другие расширения.

Фактически вы можете быть более конкретным относительно своей позиции. Опять же, здесь вам поможет исходный код. Тот же файл, который я связал с выше, также содержит определение addMenuItem.


Поместите немного губной помады на эту свинью

Теперь, когда вы видели простой пример того, как расширение может интегрироваться в скобки, давайте посмотрим, как мы обновляем пользовательский интерфейс. В предыдущей версии нашего кода для отправки сообщения использовалось предупреждение. Хотя это работает, это не очень красиво. Ваш код может получить доступ к редактору скобок, как и любой другой код модификации DOM. Хотя вы можете делать все, что хотите, есть несколько стандартных способов расширения, обновляющих пользовательский интерфейс в скобках. (В качестве предупреждения, в общем, вы не хотите прикасаться к DOM главного редактора UI, но с будущими обновлениями ваш код может сломаться. Кроме того, пользователи могут быть недовольны, если ваше расширение меняет что-то основное на скобки.)

В первом методе мы рассмотрим использование модальных диалогов. Кронштейны уже используют это и имеют API для расширений для вызова. В качестве простого примера давайте просто обновим расширение HelloWorld, чтобы вместо этого использовать modal.

Listing 3: helloworld3/main.js
/*
Based - in part - on the HelloWorld sample extension on the Brackets wiki:
https://github.com/adobe/brackets/wiki/Simple-%22Hello-World%22-extension
*/
define(function(require, exports, 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");

    function log(s) {
            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 = Menus.getMenu(Menus.AppMenuBar.VIEW_MENU);
        menu.addMenuItem(HELLOWORLD_EXECUTE);

    });

});

Обратите внимание на добавление двух дополнительных модулей скобок: Диалоги и DefaultDialogs. Следующее изменение - в handleHelloWorld. Один из методов в библиотеке Dialog - это возможность показать диалог (не удивительно, я полагаю). Метод хочет класс, заголовок и тело, и все. Больше можно сделать с диалоговыми окнами, но пока это демонстрирует эту функцию. Теперь, когда мы запускаем команду, мы получаем намного более красивый интерфейс. (Наряду с кнопками и поведением по умолчанию для обработки закрытия диалогового окна.)

Это один из примеров, теперь можно посмотреть на другое: создание нижней панели. Как и в случае с диалоговыми окнами, у нас есть поддержка от скобок, чтобы упростить работу. Давайте посмотрим на пример, а затем объясню изменения.

Listing 4: helloworld4/main.js
/*
Based - in part - on the HelloWorld sample extension on the Brackets wiki:
https://github.com/adobe/brackets/wiki/Simple-%22Hello-World%22-extension
*/
define(function(require, exports, 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);

            var menu = Menus.getMenu(Menus.AppMenuBar.VIEW_MENU);
            menu.addMenuItem(HELLOWORLD_EXECUTE);

            panel = PanelManager.createBottomPanel(HELLOWORLD_EXECUTE, $("
HTML for my panel
"),200); }); });

Давайте сосредоточимся на изменениях. Во-первых, я сбросил модули Dialog, поскольку я больше не использую их. Вместо этого мы загружаем PanelManager. Вниз в блоке appReady я определил новую панель, используя метод PanelManager API createBottomPanel. Как и команда меню, для этого требуется уникальный идентификатор, поэтому я просто повторно использую HELLOWORLD_EXECUTE. Второй аргумент - это блок HTML, обработанный jQuery, и, если вам интересно, да, мы можем сделать это лучше) и, наконец, минимальный размер. Это настраивает панель, но фактически не выполняет ее.

В обработчике событий мы привязаны к меню, мы можем спросить панель, если она видна, а затем либо скрыть, либо показать ее. Эта часть должна быть довольно тривиальной. Для удовольствия я добавил немного сложнее. Обратите внимание, что CommandManager позволяет нам получить пункт меню и установить свойство checked. Это может быть ненужным, так как пользователь может видеть панель достаточно легко, но добавление проверки просто делает вещи немного более очевидными. На приведенном ниже экране вы можете увидеть панель в ее видимом состоянии.

Сразу же вам может быть интересно узнать о панели HTML. Есть ли лучший способ предоставить HTML? В любом случае, чтобы стиль? Да, давайте посмотрим на более продвинутую версию.

Listing 5: helloworld5/main.js
/*
Based - in part - on the HelloWorld sample extension on the Brackets wiki:
https://github.com/adobe/brackets/wiki/Simple-%22Hello-World%22-extension
*/
define(function(require, exports, 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");

    function log(s) {
            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");
        CommandManager.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);

    });

});

Как и прежде, я собираюсь сосредоточиться на изменениях. Прежде всего обратите внимание, что я включил переменную, называемую panelHtml, которая загружается через require. Это позволяет мне определять мой HTML вне моего кода JavaScript. (Вы также можете использовать шаблонные механизмы. Кронштейны поставляются с Mustache.) HTML за панелью довольно прост.

Listing 6: helloworld5/panel.html
<div class="bottom-panel helloworld-panel" id="helloworldPanel">
<h1>My Panel</h1>
<p>
My panel brings all the boys to the yard,<br/>
And they're like<br/>
It's better than yours,<br/>
Damn right it's better than yours,<br/>
I can teach you,<br/>
But I have to charge
</p>
</div>

Вернувшись к main.js, я продемонстрировал еще одну функцию loadStyleSheet. Это позволяет загружать отдельную таблицу стилей расширения. Я создал файл helloworld.css с некоторыми простыми (но со вкусом) стилями CSS.

Listing 7: helloworld5/helloworld.css
.helloworld-panel h1 {
        color: red;
}
.helloworld-panel p {
        color: blue;
        font-weight: bold;
}

Обратите внимание, что я префикс моих стилей с уникальным именем. Это помогает гарантировать, что мои классы не конфликтуют ни с чем, встроенными в скобки. С помощью этих простых изменений моя панель теперь выглядит намного лучше, и вы можете понять, почему я известен во всем мире своими превосходными дизайнерскими навыками.


Упаковка и совместное использование расширения Kick Butt

Конечно, просто создание самого крутого брекетинга недостаточно. Вы, вероятно, (надеюсь)! Хотите поделиться им с другими. Один из вариантов - просто закрепить каталог и поместить его на свой сайт. Пользователи могут загружать zip-файлы, извлекать их и копировать в свою папку с расширениями скобок.

Но это не круто. Ты хочешь быть крутым, не так ли? Чтобы поделиться своим расширением и сделать его доступным через менеджер расширений скобок, вам просто нужно добавить файл package.json на ваш добавочный номер. Если вы когда-либо использовали Node.js, то это будет казаться знакомым. Вот пример для нашего расширения.

Listing 8: helloworld6/package.json
{
    "name": "camden.helloworld",
    "title": "HelloWorld",
    "description": "Adds HelloWorld support to Brackets.",
    "homepage": "https://github.com/cfjedimaster/something real here",
    "version": "1.0.0",
    "author": "Raymond Camden  (http://www.raymondcamden.com)",
    "license": "MIT",
    "engines": {
        "brackets": "<=0.34.0"
    }
}

Большинство из них самоочевидны, но реальной важной частью является блок двигателей. Скобки быстро обновляются. Если в какой-то момент Brackets добавила определенную функцию, на которую полагается ваше расширение, вы можете добавить здесь простой условный код, чтобы люди не пытались установить расширение на несовместимой версии. (Вы можете найти полный список возможных настроек в Wiki.)

После того, как вы это сделали, следующая часть - загрузить его в реестр скобок. Вам нужно будет войти в систему через свою учетную запись GitHub, но как только вы это сделаете, вы сможете просто загрузить свой почтовый индекс. Ваше расширение будет доступно любому, кто использует скобки. Еще лучше, если вы обновите расширение, диспетчер расширений фактически сможет указать это пользователю, чтобы они знали, что обновление доступно.


Что еще?

Надеюсь, вы видели, как легко распространять скобки. Больше мы не покрывали, как Linting API и интеграция NodeJS, но этой статьи должно быть более чем достаточно, чтобы вы начали. Напомним, что не забывайте, что сейчас есть большая коллекция расширений, с которой вы можете начать играть прямо сейчас. Удачи!