# Bloko - Библиотека компонентов [hh.ru](http://hh.ru/)

[Документация](http://hhru.github.io/bloko/)

## Содержание:

-   <a href="#log">Changelog</a>
-   <a href="#deps">Зависимости</a>
-   <a href="#install">Установка зависимостей</a>
-   <a href="#build">Сборка проекта</a>
-   <a href="#external">Использование bloko в других проектах</a>
-   <a href="#external-eslint-rules">Использование eslint правил блоко в других проектах</a>
-   <a href="#development">Разработка bloko</a>
-   <a href="#server">Встроенный сервер для тестирования документации</a>
-   <a href="#semver">Версионирование bloko</a>
-   <a href="#release">Как собрать релиз bloko</a>
-   <a href="#release-manual">Как собрать релиз bloko руками</a>
-   <a href="#test">Как подготовить ветку для тестирования с другим проектом</a>
-   <a href="#faq">Вопросы-ответы</a>

<a name="semver"></a>

## Версионирование bloko

Bloko использует [semver](http://semver.org/).

Версии именуются по шаблону `МАЖОРНАЯ`.`МИНОРНАЯ`.`ПАТЧ`:

-   `МАЖОРНАЯ` версия — когда сделаны обратно несовместимые изменения API.
-   `МИНОРНАЯ` версия — когда добавлен новый функционал, не нарушая обратной совместимости.
-   `ПАТЧ`-версия — когда сделаны обратно совместимые исправления.
    Дополнительные обозначения для предрелизных и билд-метаданных возможны как дополнения к `МАЖОРНАЯ`.`МИНОРНАЯ`.`ПАТЧ` формату.

<a name="log"></a>

## Changelog

Changelog проекта доступен в [CHANGELOG.md](https://github.com/hhru/bloko/blob/master/CHANGELOG.md)

При разработке задачи, в папке `changes/` нужно обязательно создать `HH-{task}.md` файл с описанием изменений, например: `HH-55143.md`.
При сборке релиза содержимое файла будет автоматически добавлено в общий `CHANGELOG.md`. Информация о каждом изменении должна начинаться с символа `*`, чтобы после добавления в общий `CHANGELOG.md` получался список.

<a name="deps"></a>

## Зависимости

Для работы блоко-компонентов требуется:

1. Синхронное подключение скрипта [`bloko/common/raw/htmlClasses.js`](bloko/common/raw/htmlClasses.js)
   до загрузки стилей. Этот скрипт проставляет в `<html>` [глобальные классы](https://hhru.github.io/bloko/globalClasses.html),
   которые используются стилями.
2. Библиотека [core-js](https://github.com/zloirock/core-js). Требуется версия не ниже `3.0.0-beta16`, так как нужна поддержка `URL` + `UrlSearchParams` для `urlParser`
3. Для lux компонентов, необходим `react` и `react-dom`

Сборщик:

-   `yarn`

<a name="install"></a>

## Установка зависимостей

```bash
yarn install
```

<a name="build"></a>

## Сборка проекта

Сборка осуществляется командой:

```bash
yarn build
```

Сборка нужна для запуска юнит тестов и генерирования документации. Для клиентов предполагается использовать несобранный блоко.

Ниже перечислены основные задачи, которые понимает сборщик:

-   `yarn build` — создает новую полную сборку библиотеки и документации, запускает все проверки и тесты. Перед каждой
    новой сборкой предыдущая папка `build` удаляется со всем ее содержимым. Данный таск запускает по умолчанию минификацию
    css, оптимизацию картинок.
-   `yarn build-watch` — создает новую сборку и затем запускает вотчер. Также вотчится документация lux компонентов и используется hot reload.
-   `yarn test` — запускает все юнит-тесты.
-   `yarn clean` — удаляет старую сборку, а именно полностью удаляет папку `build` со всем ее содержимым.
-   `yarn lint` — запуск линтинга.
-   `yarn jest` — запускает только jest юнит-тесты
-   `yarn jest -u` — обновляет снепшоты для юнит тестов, которые используют снепшоты
-   `yarn styleguide` — запускает lux документацию на отдельном порту, автоматически работает hot-reload.

<a name="external"></a>

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

Чтобы подключить блоко нужно:

1. Добавить зависимость `yarn add @hh.ru/bloko`;
2. В сборке добавить процессинг для бабеля папки `node_modules/@hh.ru/bloko`;
3. Подключить raw bloko скрипты (`bloko/raw`) на страницу до остальных скриптов.

<a name="external-eslint-rules"></a>

## Использование eslint правил блоко в других проектах

Для подключения правил из модуля `eslint-rules` в свой проект нужно:

1. Установить плагин [eslint-plugin-local-rules](https://www.npmjs.com/package/eslint-plugin-local-rules):
    ```bash
    yarn add eslint-plugin-local-rules
    ```
2. Создать в корне проекта модуль `./eslint-local-rules.js`, экспортирующий объект с правилами:
    ```javascript
    'use strict';
    module.exports = require('@hh.ru/bloko/eslint-rules');
    ```
3. Добавить плагин `eslint-plugin-local-rules` и указать необходимые правила в конфиг eslint (пример для .eslintrc);
    ```json
    {
        "plugins": ["local-rules"],
        "rules": {
            "local-rules/bloko-no-class-name-literals": ["error"],
            "local-rules/bloko-use-selectable-attributes": ["error"]
        }
    }
    ```
<a name="development"></a>

### eslint-baked-rules

Для правила `bloko-use-selectable-attributes` генерируется конфиг [`eslint-rules/baked-rules-config.json`](eslint-rules/baked-rules-config.json),
собирающий информацию о текущих компонентах.

Он добавляется/обновляется в репозитории автоматически при релизе и необходим для правильной работы правила. В файле хранится мэппинг перечисляемых props к атрибутам компонентов.
При добавлении нового или изменении `PropTypes` существующего компонента, можно протестировать правильность генерации этого конфига, выполнив команду `gulp eslint-baked-rules`.

## Разработка bloko

Любые изменения в репозитории должны проходить под определенной задачей в `jira`.
Обязательна практика создания `pull request` для ревью.

<a name="server"></a>

## Встроенный сервер для тестирования документации

```bash
yarn storybook
```

<a name="release"></a>

## Как собрать релиз

[Hornet](http://release.pyn.ru/) полностью поддерживает автоматизированную сборку bloko.

<a name="release-manual"></a>

## Как собрать релиз руками

Предположим у нас есть ветка HH-12345.

```sh
git fetch --tags
git checkout master
git reset --hard origin/master
git merge --no-ff --no-edit HH-12345
yarn install
yarn prepare-release
yarn version --new-version [patch | minor | major] --no-git-tag-version
git add -A
git commit --no-verify -m "release <версия> [ваша.почта@hh.ru]"
git push --tags origin master <версия>
git checkout -b build-<версия>
yarn release
git add -f build
git commit --no-verify -m "build-<версия> build directory"
git push origin build-<версия>
```

После этого пишем письмо на [hh-dev@hh.ru](mailto:hh-dev@hh.ru) о выходе нового релиза.

<a name="test"></a>

### Как подготовить ветку для тестирования с другим проектом

Находясь в нужной feature-ветке (например, HH-12345):

```
yarn push-test-branch
```

На основе текущей ветки HH-12345 выполняет команду, которая собирает тестовую ветку HH-12345-testing, которая подготовлена к релизу таской `prepare-release` и содержит папку `build`.
Команда вернет версию блоко вашей ветки, например:

```
npm-зависимость для проекта:
git+ssh://git@github.com/hhru/bloko.git#35a45e6a99e37461ad472df2f8d26dafb794d6ca
ветка:
HH-12345-testing
```

Обновить у соответствующего проекта версию bloko:

```
yarn add git+ssh://git@github.com/hhru/bloko.git#35a45e6a99e37461ad472df2f8d26dafb794d6ca
```

<a name="faq"></a>

## Вопросы-ответы

**Можно ли выпускать несовместимую с одним из клиентов (клиент — проект-пользователь библиотеки) версию?
Нужно ли при выпуске bloko для одного клиента тестировать все остальные клиенты и править их или заниматься этим будет тот, кому это понадобится?**

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

При выпуске bloko тестируется и выпускается только тот клиент, под который сделаны изменения.
Остальные клиенты тестируются и переводятся на новую версию теми, кому это понадобится.

**Можно ли добавлять в bloko компоненты, использующиеся только одним клиентом?
Какие критерии переноса компонента в bloko?**

Перед тем, как добавить какой-либо компонент в bloko, нужно посоветоваться с [Мишей Калашником](mailto:m.kalashnik@hh.ru).

Если попробовать кратко сформулировать — в bloko уносим всё, что относится к проекту в целом, а не к конкретной странице.

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

bloko ничего не знает про клиентов, использующих библиотеку, поэтому внесение клиенто-зависимой логики в проект не допускается.

В некоторых ситуациях допускаетcя стилизация медиа-выражениями или изменение стиля/логики работы модами, такие ситуации обсуждаются отдельно.
