Мы будем использовать GitHub для размещения кода проекта, что позволит другим вносить свой вклад.

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

Важно: в оставшейся части статьи имя плагина будет ‹username›-number-input. Вам нужно будет заменить ‹username› своим именем пользователя GitHub, чтобы получить уникальное имя модуля, которое можно опубликовать в npm.

Вызов репозитория ‹username›-number-input и его инициализация пустым (без каких-либо файлов по умолчанию) выглядит так:

После создания репозитория мы можем клонировать его в новую папку:

$ git clone [email protected]:<username>/<username>-number-input.git
$ cd <username>-number-input

Инициализируйте репозиторий как новый плагин DoneJS.

Для инициализации нового плагина вам потребуется глобально установленная версия DoneJS 0.7.0+. Чтобы проверить версию DoneJS, запустите

$ donejs --version

Чтобы установить DoneJS или запустить последнюю версию:

$ npm install donejs -g

Теперь в папке ‹username›-number-input мы можем инициализировать новый плагин следующим образом:

$ donejs plugin

Генератор плагинов задаст несколько вопросов, на которые следует ответить следующим образом:

  • Название проекта: подтвердите значение по умолчанию, нажав Enter
  • Имя пользователя или организация GitHub: введите имя пользователя GitHub, где был создан репозиторий.
  • Во все остальные поля также можно ответить по умолчанию.

После того, как все сделано, окончательная подсказка выглядит примерно так:

Теперь генератор инициализирует макет плагина по умолчанию и установит все его зависимости.

Настройте непрерывную интеграцию с Travis CI

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

$ npm test

Это откроет браузер Firefox, запустит два автоматически сгенерированных теста и выведет результат на консоль.

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

Мы будем использовать Travis CI в качестве нашего размещенного решения, потому что оно бесплатно для проектов с открытым исходным кодом. Он автоматически работает с вашей учетной записью GitHub. После входа перейдите в «Учетные записи» (в раскрывающемся списке под своим именем), чтобы включить репозиторий ‹username›-number-input:

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

$ git add . --all
$ git commit -am "Initial commit"
$ git push origin master

Если вы сейчас перейдете на https://travis-ci.org/‹your-username›/‹username›-number-input/builds, вы увидите, что сборка запущена и в конечном итоге станет зеленой (что обновит значок, который получил добавлено в файл readme.md).

Запустить режим разработки

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

donejs develop

Сервер будет работать по адресу http://localhost:8080. Вы можете просмотреть главную тестовую страницу по адресу localhost:8080/src/test/test.html. Любые изменения в тестовом файле или модуле немедленно перезапустят тесты благодаря горячей замене модуля.

Реализовать функциональность и тесты компонента

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

$ donejs add component <username>-number-input

Это создает полный компонент с использованием тега ‹username›-number-input с тестами и документацией. Поскольку имя модуля совпадает с именем плагина (‹username›-number-input), генератор поместит файлы компонентов непосредственно в папку src/ (а не во вложенную папку). Подтвердите имя тега по умолчанию и подсказки о перезаписи существующих файлов, нажав клавишу ввода:

Инициализированный компонент теперь можно просмотреть по адресу localhost:8080/src/-number-input.html. Тесты компонентов доступны по адресу localhost:8080/src/test.html.

Создание и тестирование модели представления

Наша модель ввода чисел должна обеспечивать следующую функциональность:

  • Обновите его значение либо через поле ввода числа, либо с помощью кнопок +/-
  • Иметь максимальное и минимальное значение (которое также отключит соответствующую кнопку)

Мы можем использовать define plugin для определения минимального и максимального значения и setter для значения, чтобы убедиться, что оно всегда находится в пределах этих ограничений. Мы также добавим метод увеличения и уменьшения, который изменит значение на 1. Измените модель представления компонента (в src/‹username›-number-input.js), чтобы она выглядела следующим образом:

import Component from 'can/component/';
import Map from 'can/map/';
import 'can/map/define/';
import './<username>-number-input.less!';
import template from './<username>-number-input.stache!';

export const ViewModel = Map.extend({
  define: {
    value: {
      value: 0,
      type: 'number',
      set(value) {
        if(value > this.attr('max')) {
          return this.attr('max');
        }

        if(value < this.attr('min')) {
          return this.attr('min');
        }

        return value;
      }
    },
    max: {
      value: Number.MAX_VALUE,
      type: 'number'
    },
    min: {
      value: 0,
      type: 'number'
    }
  },

  increment() {
    this.attr('value', this.attr('value') + 1);
  },

  decrement() {
    this.attr('value', this.attr('value') - 1);
  }
});

export default Component.extend({
  tag: '<username>-number-input',
  viewModel: ViewModel,
  template
});

Чтобы протестировать эту функциональность, мы можем изменить тесты в src/‹username›-number-input_test.js, чтобы они выглядели следующим образом:

import QUnit from 'steal-qunit';
import { ViewModel } from './<username>-number-input.js';

// ViewModel unit tests
QUnit.module('<username>-number-input/component');

QUnit.test('Initializes the ViewModel', function(){
  var vm = new ViewModel();

  QUnit.equal(vm.attr('value'), 0,
    'Default value is 0');
  QUnit.equal(vm.attr('max'), Infinity,
    'Max value is infinity');
  QUnit.equal(vm.attr('min'), 0,
    'Max value is number max value');
});

QUnit.test('.increment', function(){
  var vm = new ViewModel();

  vm.increment();
  QUnit.equal(vm.attr('value'), 1, 'Value incremented');
});

QUnit.test('.decrement', function(){
  var vm = new ViewModel();

  vm.increment();
  vm.increment();
  vm.decrement();
  QUnit.equal(vm.attr('value'), 1, 'Value updated');
});

Вы можете запустить все тесты либо перейдя в localhost:8080/src/test/test.html в браузере, либо через

$ npm test

В шаблоне мы будем использовать Bootstrap, который сначала нужно установить как зависимость от плагина:

$ npm install bootstrap --save

Добавление шаблона

Затем мы можем обновить src/‹username›-number-input.stache, чтобы он выглядел следующим образом:

<can-import from="bootstrap/less/bootstrap.less!" />
<form class="form-inline">
  <div class="form-group">
    <div class="input-group">
      <div class="input-group-btn">
        <button class="btn btn-primary" type="button"
          {{#eq value min}}disabled{{/eq}}
          ($click)="decrement">
            -
          </button>
      </div>
      <input type="number" class="form-control"
        {($value)}="value">
      <div class="input-group-btn">
        <button class="btn btn-primary" type="button"
          {{#eq value max}}disabled{{/eq}}
          ($click)="increment">
            +
        </button>
      </div>
    </div>
  </div>
</form>

Обратите внимание на несколько особенностей этого шаблона:

  1. Этот шаблон сначала импортирует Bootstrap LESS.
  2. Затем мы создаем группу кнопок с кнопкой — слева, числовым вводом посередине и кнопкой + справа.
  3. Когда кнопки нажимаются, вызываются методы увеличения или уменьшения модели представления.
  4. Значение поля ввода двусторонне связано со свойством value модели представления.
  5. Когда значение минимальное или максимальное, кнопки - или + будут отключены.

Сделать запрос на включение в репозиторий

Хотя мы пока работаем над плагином сами, запросы на включение GitHub — отличный способ отслеживать наш прогресс и убедиться, что все тесты пройдены. В папке плагина мы можем запустить:

$ git checkout -b number-input-component
$ git add . --all
$ git commit -m "Implementing number-input component functionality, template and tests"
$ git push origin number-input-component

А затем создайте новый запрос на вытягивание, перейдя на https://github.com/‹your-username›/‹username›-number-input, который теперь покажет такую ​​​​опцию:

После того, как вы создали запрос на вытягивание, вы увидите сообщение «Некоторые проверки еще не завершены», которое в конечном итоге станет зеленым:

Теперь вы можете нажать кнопку «Merge pull request». Затем в консоли извлеките ветку master и вытащите последние изменения с помощью:

$ git checkout master
$ git pull origin master

Сделать сборку

Теперь, когда мы реализовали функцию ввода чисел и прошли все тесты, мы можем сделать сборку нашего плагина, которую можно использовать отдельно в браузере, с загрузчиком модулей AMD, например RequireJS, или как модуль CommonJS, который работает, например. с помощью Browserify.

$ donejs build

Создаст папку dist/ с глобальной, amd и cjs версией нашего плагина:

Опубликовать в нпм

npm — лучший способ поделиться модулями и сделать их легко устанавливаемыми без необходимости вручную управлять зависимостями. Чтобы иметь возможность публиковать собственные модули, создайте новую учетную запись, а затем запустите

$ npm login

Семантическое управление версиями — отличный способ сообщить о новых функциях и критических изменениях. Сгенерированный плагин уже поставляется со сценариями выпуска для публикации новых версий в соответствии со схемой major.minor.patch. В нашем случае для публикации начальной версии 0.1.0 мы можем запустить

$ donejs release:minor

Теперь версия 0.1.0 нашего плагина доступна на npm.

Используйте плагин в других проектах!

В другом приложении DoneJS теперь мы можем установить плагин с помощью

$ npm install <username>-number-input --save

Затем импортируйте его в шаблон и загрузите с помощью:

<can-import from="donejs-number-input" />
<donejs-number-input></donejs-number-input>

Замените donejs на ваше ‹имя пользователя›.

Подведение итогов

В этой статье мы создали многоразовый плагин счетчика чисел для DoneJS с кодом на GitHub и тестами, работающими в непрерывной интеграции. Мы опубликовали версию для различных загрузчиков модулей на npm, чтобы ее можно было установить и использовать в других приложениях DoneJS.

Теперь создайте несколько замечательных плагинов, сообщите нам о них и поделитесь ими с сообществом!