npm package: @m4reve/eslint-plugin-ru-preposition-validator
Description: ESLint plugin for Russian typography rules - prevents hanging prepositions by inserting non-breaking spaces
Latest version: 1.0.0

# @m4reve/eslint-plugin-ru-preposition-validator

ESLint плагин для проверки русской типографики в JSX коде. Предотвращает "висящие" предлоги путём автоматической вставки неразрывных пробелов.

## Возможности

- ✅ Проверяет предлоги и частицы в русском тексте внутри JSX
- ✅ Автоматически заменяет обычные пробелы на неразрывные (`\u00A0`)
- ✅ Оборачивает исправленный текст в JSX expression `{\`text\`}`
- ✅ Поддерживает более 70 русских предлогов и частиц
- ✅ Работает с организационными формами (ООО, АО, ПАО)
- ✅ Обрабатывает специальные символы (№, §)

## Установка

```bash
npm install @m4reve/eslint-plugin-ru-preposition-validator --save-dev
```

или

```bash
yarn add -D @m4reve/eslint-plugin-ru-preposition-validator
```

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

### Настройка ESLint

Добавьте плагин в секцию plugins вашего `.eslintrc`:

```json
{
  "plugins": ["@m4reve/ru-preposition-validator"],
  "rules": {
    "@m4reve/ru-preposition-validator/no-hanging-prepositions": "warn"
  }
}
```

Или используйте рекомендованную конфигурацию:

```json
{
  "extends": ["plugin:@m4reve/ru-preposition-validator/recommended"]
}
```

### Flat Config (ESLint 9+)

```js
import ruPrepositionValidator from '@m4reve/eslint-plugin-ru-preposition-validator';

export default [
  {
    plugins: {
      '@m4reve/ru-preposition-validator': ruPrepositionValidator
    },
    rules: {
      '@m4reve/ru-preposition-validator/no-hanging-prepositions': 'warn'
    }
  }
];
```

## Правило: no-hanging-prepositions

Это правило проверяет JSX текст на наличие "висящих" предлогов и частиц в русском языке.

### Что проверяется

#### Предлоги (должен быть неразрывный пробел ПОСЛЕ)

```
а, б, без, безо, будто, бы, в, во, ведь, вне, вот, всё, где, да, даже,
для, до, если, есть, ещё, же, за, и, из, изо, из-за, из-под, или, иль,
к, ко, как, ли, либо, между, на, над, надо, не, ни, но, о, об, обо,
около, оно, от, ото, перед, по, по-за, по-над, под, подо, после, при,
про, ради, с, со, сквозь, так, также, там, тем, то, тогда, того, тоже,
у, хоть, хотя, чего, через, что, чтобы, это
```

#### Специальные символы и аббревиатуры

```
№, §, АО, ОАО, ЗАО, ООО, ПАО
```

#### Частицы (должен быть неразрывный пробел ПЕРЕД)

```
б, бы, ж, же, ли, ль
```

### Примеры

#### ❌ Неправильно

```jsx
// Обычный пробел после предлога
<div>Текст в коробке</div>
<p>Работа с данными</p>
<span>Дом № 5</span>

// Обычный пробел перед частицей
<div>Пойдём же</div>
<p>Правда ли это</p>
```

#### ✅ Правильно (после автофикса)

```jsx
// Неразрывный пробел вставлен, текст обернут в JSX expression
<div>{`Текст в\u00A0коробке`}</div>
<p>{`Работа с\u00A0данными`}</p>
<span>{`Дом №\u00A05`}</span>

<div>{`Пойдём\u00A0же`}</div>
<p>{`Правда\u00A0ли это`}</p>
```

### Автофикс

Правило поддерживает автоматическое исправление через `--fix`:

```bash
eslint --fix src/
```

При автофиксе:
1. Обычные пробелы заменяются на **видимый литерал** `\u00A0` (unicode escape sequence)
2. Весь текст оборачивается в JSX expression с template literal: `{\`text\`}`

**Важно**: В код вставляется видимая последовательность `\u00A0`, а не невидимый символ неразрывного пробела. Это обеспечивает читаемость кода и явное указание на использование неразрывного пробела.

## Как это работает

### До исправления

```jsx
<div>Он пошёл в магазин за хлебом</div>
```

### После исправления

```jsx
<div>{`Он пошёл в\u00A0магазин за\u00A0хлебом`}</div>
```

В браузере это будет отображаться как:
```
Он пошёл в магазин за хлебом
```

Но предлоги "в" и "за" не смогут оторваться от следующих слов при переносе строки.

## Запуск тестов

```bash
npm test
```

Тесты используют Jest и ESLint RuleTester.

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

```
eslint-plugin-ru-typography/
├── lib/
│   ├── index.js                          # Экспорт плагина
│   └── rules/
│       └── no-hanging-prepositions.js    # Правило проверки предлогов
├── tests/
│   └── rules/
│       └── no-hanging-prepositions.test.js
├── package.json
├── jest.config.js
└── README.md
```

## Примеры использования в реальных проектах

### React приложение

```jsx
function Article() {
  return (
    <article>
      <h1>{`Статья о\u00A0типографике`}</h1>
      <p>{`Мы работаем с\u00A0текстом каждый день`}</p>
      <p>{`Правда\u00A0ли это важно?`}</p>
    </article>
  );
}
```

### Next.js страница

```jsx
export default function HomePage() {
  return (
    <div>
      <h1>{`Добро пожаловать на\u00A0сайт`}</h1>
      <p>{`ООО\u00A0"Компания"`}</p>
      <p>{`Адрес: ул. Ленина, дом №\u00A027`}</p>
    </div>
  );
}
```

## Производительность

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

## Совместимость

- ESLint: >= 7.0.0
- Node.js: >= 12.0.0
- React/JSX: все версии

## Лицензия

MIT

## Вклад в проект

Приветствуются pull requests и issue! Если вы нашли баг или хотите предложить улучшение, пожалуйста:

1. Создайте issue с описанием проблемы
2. Форкните репозиторий
3. Создайте ветку для вашей фичи
4. Напишите тесты
5. Отправьте pull request

## Авторы

Dmitriy Meshcheryakov

## Благодарности

Плагин следует best practices из [Vercel React Best Practices](https://github.com/vercel/react-best-practices) для оптимальной производительности и качества кода.