# Definer — самая простая модульная система для JavaScript на клиенте

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

## Использование

### Установка

    npm install definer

### Подключение

Достаточно подключить [один файл](https://github.com/tenorok/definer/blob/master/definer.js).
```html
<script src="definer.js"></script>
```

### Объявление модулей

Пусть есть модули `a` и `b`, и модуль `c`, зависящий от них.

```javascript
var a = definer('a', function() { return 'a'; }); // a
var b = definer('b', function() { return 'b'; }); // b
var c = definer('c', function(a, b) { return a + b + 'c'; }); // abc
```

Модули должны быть объявлены в правильной последовательности, иначе возникнет ошибка.

```javascript
definer('b', function(a) {}); // ReferenceError: module a is not defined
definer('a', function() {});
```

### Экспорт в глобальный контекст

Внутри модулей `this` указывает на глобальный контекст. Используя это, модуль может легко экспортировать данные.

```javascript
definer('d', function() { this.d = 100; }); // Появилась глобальная переменная d
```

### Методы

#### Метод `export`

При выполнении собранного результата из Node.js в объект `module.exports` будет добавлен ключ `d` со значением `100`.

При выполнении в браузере будет создана аналогичная глобальная переменная.

```javascript
definer.export('d', function() { return 100; });
```

#### Метод `clean`

В качестве параметра метод `clean` принимает имя глобальной переменной или массив имён.

Указанные переменные удалятся из глобального контекста и будут объявлены одноимённые модули.

Например, скроем jQuery в модуль:

```javascript
definer.clean('$');
console.log($); // undefined
definer('a', function($) { $('html').text('a'); });
```

Очистка сразу нескольких переменных:

```javascript
definer.clean(['$', '_']);
```

[См. также: опция clean](#Опция-clean)

### Сборка

Представим, что имеется следующая файловая структура:

```
modules/
    sub/c.js
    a.js
    b.js
```

Находясь в директории `modules` для сборки проекта достаточно выполнить одну команду.

    ./node_modules/.bin/definer all.js

В процессе сборки definer выполнит рекурсивный поиск модулей в файлах `*.js` текущей директории и собранный результат будет сохранён в файл `all.js`:

```javascript
(function(global, undefined) {
var a = (function () { return 'a'; }).call(global),
    b = (function () { return 'b'; }).call(global),
    c = (function (a, b) { return a + b + 'c'; }).call(global, a, b);
})(this);
```

#### Опции сборки

По имеющимся опциям можно получить краткую справку прямо в терминале.

    ./node_modules/.bin/definer --help

##### Опция `-c, --config`

Если директория, в которой выполняется запуск `definer`, содержит файл `definer.json` — сборщик использует его как конфигурационный файл автоматически.

Опция указывает на конфигурационный файл, содержащий все возможные опции сборки в JSON-формате.

    ./node_modules/.bin/definer -c config/definer.json all.js

Пути до директорий и файлов следует указывать относительно расположения конфигурационного файла.

Опции, введённые в командной строке имеют приоритет над опциями из конфигурационного файла.

##### Опция `-d, --directory`

Опция указывает откуда следует начать искать модули в файловой системе. Поиск модулей выполняется рекурсивно по всем вложенным директориям.

    ./node_modules/.bin/definer -d modules/ all.js

Возможно указание нескольких директорий через запятую.

    ./node_modules/.bin/definer -d modules/,modules2/ all.js

По умолчанию definer ищет модули в текущей директории.

##### Опция `-p, --postfix`

Опция задаёт постфикс файлов, в которых будет производиться поиск модулей.

    ./node_modules/.bin/definer -p module.js all.js

По умолчанию опции установлено значение `js`.

##### Опция `-m, --module`

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

    ./node_modules/.bin/definer -m c all.js

По умолчанию собираются все найденные модули.

##### Опция `-i, --istanbul`

Опция позволяет перечислить имена модулей, для которых предполагается запуск [istanbul](https://github.com/gotwarlost/istanbul).
Для всех остальных модулей будет добавлен комментарий, исключающий их из оценки покрытия тестами.

    ./node_modules/.bin/definer -i b all.js

Возможно указание нескольких модулей через запятую.

    ./node_modules/.bin/definer -i b,c all.js

По умолчанию комментарии не добавляются, поскольку запуск оценки покрытия тестами не предполагается.

##### Опция `-v, --verbose`

Опция настраивает вывод информации о сборке.

Информация делится на типы:

1. `l`, log — информация о процессе сборки (синим цветом)
2. `i`, info — сообщение о результате сборки (зелёным)
3. `w`, warn — предупреждения (жёлтым)
4. `e`, error — ошибки (красным)

Следующий пример будет выводить только предупреждения и ошибки:

    ./node_modules/.bin/definer -v we all.js

Идентичный пример опции в конфигурационном файле:

```json
{
    "verbose": ["warn", "error"]
}
```

По умолчанию выводятся все типы информации.

##### Опция `clean`

*Опция может быть указана только в конфигурационном файле.*

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

Несколько файлов могут быть объединены в массив, при этом они будут собраны в указанном порядке.

```json
{
    "clean": {
        "$": [
            "jquery.js",
            "jquery.ui.js",
            "jquery.mobile.js"
        ],
        "_": "path/to/underscore.js"
    }
}
```

[См. также: метод clean](#Метод-clean)

##### Опция `jsdoc`

*Опция может быть указана только в конфигурационном файле.*

Опция формирует JSDoc, содержащий информацию о собранном файле.

Возможно указание относительного пути до JSON-файла, из которого сборщик получит значение одноимённого поля.

Тег `date` способен принять значение `true` и заменить его на текущую дату.

```json
{
    "jsdoc": {
        "file": "File description",
        "copyright": "2014 Artem Kurbatov, tenorok.ru",
        "license": "MIT license",
        "version": "another.json",
        "date": true
    }
}
```

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

```javascript
/*!
 * @file File description
 * @copyright 2014 Artem Kurbatov, tenorok.ru
 * @license MIT license
 * @version 0.0.7
 * @date 16 June 2014
 */
```
