@bonesofspring/ai-rules 0.1.36 → 0.1.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/presets/cursor/next/rules/README.md +1 -0
- package/presets/cursor/next/rules/code-quality-and-refactoring.mdc +6 -0
- package/presets/cursor/next/rules/css-property-order-stylelint.mdc +25 -0
- package/presets/cursor/next/rules/no-cross-component-styles-import.mdc +55 -0
- package/presets/cursor/next/rules/no-props-spread.mdc +26 -3
- package/presets/cursor/next/rules/react-ui.mdc +21 -2
- package/presets/cursor/next/rules/tests-unit.mdc +1 -0
package/package.json
CHANGED
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
| `code-review-mr.mdc` | Чеклист ревью MR, в т.ч. HTTP‑клиент и тесты |
|
|
37
37
|
| `tests-unit.mdc` | Unit‑тесты и behavior‑тесты HTTP‑клиента |
|
|
38
38
|
| `playwright-agents.mdc`, `tests-e2e-structure.mdc` | E2E |
|
|
39
|
+
| `react-ui.mdc` | React/Next UI: структура компонентов, соседние `ComponentName.data.ts` / `.utils.ts`, стили, пропсы |
|
|
39
40
|
|
|
40
41
|
**Коллизии формулировок:** если в разных `.mdc` расходятся детали **импорта типов**, источник правды — **`types-public-imports.mdc`** (`@/types`, `@/types/enums`); по **импорту из API‑слоя** (store, UI, прочий код вне `app/src/api/**`) — **`api-public-imports.mdc`** (`@/api`), в том же смысле что правило ESLint `no-restricted-imports` в `app/eslint.config.mjs`.
|
|
41
42
|
|
|
@@ -35,6 +35,12 @@ alwaysApply: true
|
|
|
35
35
|
- сначала локально улучшить архитектуру минимальными шагами;
|
|
36
36
|
- оставить код в консистентном состоянии.
|
|
37
37
|
|
|
38
|
+
# ESLint и плагины
|
|
39
|
+
|
|
40
|
+
- Учитывать **все активные правила ESLint** и **подключённые плагины** проекта (конфиг: `app/eslint.config.mjs`, базовые пресеты в т.ч. `@sh/eslint-config-react`, `@sh/eslint-config-boundaries` и локальные overrides).
|
|
41
|
+
- Новый или изменённый код не должен нарушать эти правила. Перед завершением правок по возможности прогонять ESLint на затронутых файлах.
|
|
42
|
+
- Отключение правила (`eslint-disable`) — только **точечно** (строка/небольшой блок) и с **кратким комментарием**, зачем это нужно; отключать «на весь файл» без веской причины не следует.
|
|
43
|
+
|
|
38
44
|
# Требование к агенту
|
|
39
45
|
|
|
40
46
|
При каждом изменении:
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Порядок CSS-свойств по Stylelint (idiomatic-order) — для любых стилей в проекте
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Порядок CSS-свойств (как в Stylelint)
|
|
7
|
+
|
|
8
|
+
Действует для **любого** CSS в репозитории: `.css`, стилевые блоки в `styles.ts` / `styles.tsx`, `styled` / Linaria и другой CSS-in-JS в `.ts` / `.tsx`, если этот код попадает под `yarn lint:css`.
|
|
9
|
+
|
|
10
|
+
Источник: `app/.stylelintrc` → `@sh/stylelint-config-react` → пакет **`stylelint-config-idiomatic-order`** (правило `order/properties-order`). Свойства, не попавшие в список, идут **в конце блока в алфавитном порядке** (`unspecified: bottomAlphabetical`).
|
|
11
|
+
|
|
12
|
+
Пиши объявления в **одном** блоке в такой последовательности групп:
|
|
13
|
+
|
|
14
|
+
1. **`composes`** — только для CSS Modules (если есть).
|
|
15
|
+
2. **`all`**
|
|
16
|
+
3. **Позиционирование:** `position`, `z-index`, затем `top`, `right`, `bottom`, `left`.
|
|
17
|
+
4. **Отображение и раскладка:** `display`, `overflow`.
|
|
18
|
+
5. **Размеры:** `width`, `min-width`, `max-width`, `height`, `min-height`, `max-height`, `box-sizing`.
|
|
19
|
+
6. **Flex:** `flex`, `flex-basis`, `flex-direction`, `flex-flow`, `flex-grow`, `flex-shrink`, `flex-wrap`, `align-content`, `align-items`, `align-self`, `justify-content`, `order`.
|
|
20
|
+
7. **Внутренние отступы:** `padding-top`, `padding-right`, `padding-bottom`, `padding-left`.
|
|
21
|
+
8. **Рамка:** общие `border`, `border-width`, `border-style`, `border-color`, `border-radius`; затем для сторон **сверху по часовой** — `border-top` и его `-width`, `-style`, `-color`, `-radius`, то же для `right`, `bottom`, `left`.
|
|
22
|
+
9. **Внешние отступы:** `margin-top`, `margin-right`, `margin-bottom`, `margin-left`.
|
|
23
|
+
10. **Остальные свойства** — после перечисленных, **по алфавиту** (типографика, фон, анимации, `cursor`, и т.д.).
|
|
24
|
+
|
|
25
|
+
Автоисправление из каталога `app`: `yarn lint:css --fix` (проверяет `**/*.{css,ts}`).
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Стили компонентов — колокация, импорты, корневой styled как Root
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Стили только рядом с компонентом
|
|
7
|
+
|
|
8
|
+
## Имя корневого styled-элемента: `Root`
|
|
9
|
+
|
|
10
|
+
- В `styles.ts` (или аналоге) **корневой** styled-элемент — тот, что оборачивает весь JSX компонента — экспортируется как **`Root`**.
|
|
11
|
+
- В разметке: `<s.Root>...</s.Root>` при `import * as s from './styles'`.
|
|
12
|
+
- Вложенные и соседние примитивы именуются по смыслу: `Title`, `List`, `Item`, `Header` и т.д.
|
|
13
|
+
- Если нет одной styled-обёртки на весь компонент (только фрагмент или один нативный тег без своего styled), экспорта `Root` может не быть. Когда вводится **одна** внешняя styled-обёртка всего JSX — она называется **`Root`**, а не `Container`, `Wrapper`, `Block` и т.п.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
// ✅ Хорошо
|
|
17
|
+
export const Root = styled.div` ... `
|
|
18
|
+
// в компоненте: <s.Root>...</s.Root>
|
|
19
|
+
|
|
20
|
+
// ❌ Плохо для единственной обёртки всего компонента
|
|
21
|
+
export const Service = styled.div` ... `
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Правило
|
|
25
|
+
|
|
26
|
+
**Запрещено** импортировать модули стилей, которые лежат в каталоге **другого** UI-компонента или блока (не в том же каталоге, что и текущий файл).
|
|
27
|
+
|
|
28
|
+
Под «модулями стилей» имеются в виду в первую очередь:
|
|
29
|
+
|
|
30
|
+
- `styles.ts` / `styles.tsx` рядом с компонентом;
|
|
31
|
+
- `*.module.css`, `*.module.scss` и аналоги, принадлежащие конкретному компоненту;
|
|
32
|
+
- любые файлы, которые **экспортируют только styled-примитивы** для одного компонента.
|
|
33
|
+
|
|
34
|
+
## Разрешено
|
|
35
|
+
|
|
36
|
+
- `import * as s from './styles'` — стили **в той же папке**, что и компонент.
|
|
37
|
+
- Импорты **общих** примитивов дизайн-системы, токенов, общих UI из `@/ui/components/...` или пакетов, если это **не** приватный `styles` чужой фичи.
|
|
38
|
+
- Повторное использование визуала через **сам компонент** (композиция), а не через его `styles`.
|
|
39
|
+
|
|
40
|
+
## Примеры
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
// ✅ Хорошо — локальный styles
|
|
44
|
+
import * as s from './styles'
|
|
45
|
+
|
|
46
|
+
// ❌ Плохо — стили родителя/соседа
|
|
47
|
+
import * as s from '../../styles'
|
|
48
|
+
import * as s from '../RequestForAnalysisServices/styles'
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Почему
|
|
52
|
+
|
|
53
|
+
- Единое имя **`Root`** ускоряет чтение: сразу видно входную точку разметки компонента.
|
|
54
|
+
- Стили и разметка компонента должны меняться вместе, без скрытой связи через чужие файлы.
|
|
55
|
+
- Упрощается рефакторинг и поиск владельца стилей.
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Избегать спред-а пропов при передаче в компоненты
|
|
3
3
|
alwaysApply: true
|
|
4
|
+
globs: app/src/**/*.tsx
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Не использовать спред пропов при передаче в компоненты
|
|
7
8
|
|
|
8
|
-
При вызове React-компонентов **передавать пропы явно**, а не через spread (`{...props}`).
|
|
9
|
+
При вызове **пользовательских** React-компонентов (имя с заглавной буквы: `IconBox`, `TextField`, ваши `FooBar`) **передавать пропы явно**, а не через spread (`{...props}`, `{...obj}`).
|
|
10
|
+
|
|
11
|
+
**Агентам и при ревью:** не «упрощать» JSX через объект с последующим spread — это нарушение. Если ветвление по пропам длинное, используйте два явных JSX-блока (`condition ? <A … /> : <B … />`) или отдельные маленькие компоненты, а не `{...mergedProps}`.
|
|
9
12
|
|
|
10
13
|
## Почему
|
|
11
14
|
|
|
@@ -13,6 +16,11 @@ alwaysApply: true
|
|
|
13
16
|
- Упрощает рефакторинг и поиск использований.
|
|
14
17
|
- Снижает риск случайно пробросить лишние или устаревшие пропы.
|
|
15
18
|
|
|
19
|
+
## Проверка в репозитории
|
|
20
|
+
|
|
21
|
+
- Для файлов `app/src/ui/**/*.tsx` включено ESLint-правило `react/jsx-props-no-spreading` (`app/eslint.config.mjs`): несоблюдение увидит линтер и CI.
|
|
22
|
+
- Легитимное исключение в конкретном месте — **однострочный** `eslint-disable-next-line react/jsx-props-no-spreading` с кратким комментарием «почему»; для редких обёрток допустим disable на файл (как в `PromocodeInput`).
|
|
23
|
+
|
|
16
24
|
## Примеры
|
|
17
25
|
|
|
18
26
|
```tsx
|
|
@@ -23,6 +31,10 @@ return <Child {...commonProps} />
|
|
|
23
31
|
// ❌ Плохо
|
|
24
32
|
return <Child {...props} />
|
|
25
33
|
|
|
34
|
+
// ❌ Плохо (spread из соседнего модуля стилей тоже не оправдание)
|
|
35
|
+
const iconProps = cond ? { name, size: 'm' } : { name, size: 'm', ...styles.IconBoxAccent }
|
|
36
|
+
return <IconBox {...iconProps} />
|
|
37
|
+
|
|
26
38
|
// ✅ Хорошо
|
|
27
39
|
return (
|
|
28
40
|
<Child
|
|
@@ -31,9 +43,20 @@ return (
|
|
|
31
43
|
c={c}
|
|
32
44
|
/>
|
|
33
45
|
)
|
|
46
|
+
|
|
47
|
+
// ✅ Хорошо — явные пропсы по веткам
|
|
48
|
+
return cond ? (
|
|
49
|
+
<IconBox name={name} size="m" variant="warning" />
|
|
50
|
+
) : (
|
|
51
|
+
<IconBox
|
|
52
|
+
customColors={styles.IconBoxAccent.customColors}
|
|
53
|
+
name={name}
|
|
54
|
+
size="m"
|
|
55
|
+
/>
|
|
56
|
+
)
|
|
34
57
|
```
|
|
35
58
|
|
|
36
59
|
## Исключения
|
|
37
60
|
|
|
38
|
-
- Передача
|
|
39
|
-
- Делегирование пропов в обёртку (wrapper) допустимо, если это явно документировано и
|
|
61
|
+
- Передача пропов в **нативный** DOM-элемент (`<div {...rest} />`) допустима, если `rest` содержит только валидные HTML-атрибуты.
|
|
62
|
+
- Делегирование пропов в обёртку (wrapper) допустимо, если это явно документировано и обосновано; при необходимости пометьте файл или строку через ESLint-disable, как выше.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Паттерны React/Next UI и стилей (preset)
|
|
3
|
-
globs: app/src/ui/**/*.tsx
|
|
3
|
+
globs: app/src/ui/**/*.tsx,app/src/ui/**/*.ts
|
|
4
4
|
alwaysApply: false
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -26,10 +26,28 @@ alwaysApply: false
|
|
|
26
26
|
- Папка с именем компонента:
|
|
27
27
|
- `ComponentName.tsx`
|
|
28
28
|
- файлы стилей по принятой схеме;
|
|
29
|
-
- опционально: `types.ts`, `hooks.ts
|
|
29
|
+
- опционально: `types.ts`, `ComponentName.hooks.ts` (см. ниже про префикс).
|
|
30
|
+
|
|
31
|
+
## Вспомогательные модули рядом с компонентом (именование)
|
|
32
|
+
|
|
33
|
+
**Префикс имени файла = публичное имя компонента** (как у `ComponentName.tsx` в этой папке), в **PascalCase**. Не вводить отдельные «говорящие» имена файлов по смыслу содержимого (`analysisPreparationIconMap.ts`, `buildAnalysisIdToNameMap.ts` и т.п.) — так теряется связь с компонентом и плодятся одноразовые названия.
|
|
34
|
+
|
|
35
|
+
**Суффикс по роли:**
|
|
36
|
+
|
|
37
|
+
| Суффикс | Назначение | Примеры содержимого |
|
|
38
|
+
|--------|------------|---------------------|
|
|
39
|
+
| `ComponentName.data.ts` | Статические данные и конфигурация для UI | мапы `id → иконка/лейбл`, константы списков, таблицы соответствий для отображения |
|
|
40
|
+
| `ComponentName.utils.ts` | Чистые функции без React | форматирование, предобработка пропсов/данных для рендера, `build…`/`map…`‑хелперы |
|
|
41
|
+
| `ComponentName.hooks.ts` | Хуки, используемые только этим блоком | локальные `use…` (если не вынесены в `src/ui/hooks/**`) |
|
|
42
|
+
|
|
43
|
+
- Несколько констант/мапов или несколько функций — **по-прежнему один** `.data.ts` и один `.utils.ts`, не дробить по «темам» отдельными файлами без веской причины (размер, разные зоны ответственности на уровне подкомпонентов).
|
|
44
|
+
- Если логика принадлежит **подкомпоненту** в подпапке (`components/Child/Child.tsx`), те же правила применяются к **`Child.data.ts`**, **`Child.utils.ts`** относительно этого подкомпонента.
|
|
45
|
+
- Тесты для утилит и данных — рядом в `__tests__/` или с суффиксом `.test.ts`, согласно `tests-unit.mdc`, с тем же префиксом (`RequestForAnalysisRecommendations.utils.test.ts` и т.д.).
|
|
30
46
|
|
|
31
47
|
# Стили и дизайн‑токены
|
|
32
48
|
|
|
49
|
+
- **Корневой** styled-элемент компонента в соседнем `styles` — **`Root`** (`<s.Root>`). Подробнее: `no-cross-component-styles-import.mdc`.
|
|
50
|
+
- Порядок объявлений в CSS / `styled` — как требует Stylelint: см. `css-property-order-stylelint.mdc`.
|
|
33
51
|
- Для визуала использовать **тот стек стилей и токенов, который уже в проекте** (переменные, тема, общие классы, дизайн‑пакет).
|
|
34
52
|
- Избегать:
|
|
35
53
|
- inline‑стилей, кроме простых случаев;
|
|
@@ -39,6 +57,7 @@ alwaysApply: false
|
|
|
39
57
|
|
|
40
58
|
# Пропсы и типизация
|
|
41
59
|
|
|
60
|
+
- **Не передавать пропы в компоненты через spread** (`<Foo {...x} />`). Только явные атрибуты; подробности и исключения — `no-props-spread.mdc` (в `app/src/ui` это дополнительно ловит ESLint).
|
|
42
61
|
- Описывать пропсы через `type Props = { ... }` или `interface Props { ... }`.
|
|
43
62
|
- Не использовать `any`; при необходимости:
|
|
44
63
|
- обобщения (`<T>`), `unknown`, тип‑предикаты и user‑defined type guards.
|
|
@@ -15,6 +15,7 @@ alwaysApply: false
|
|
|
15
15
|
- **Именование unit‑тестов** (строки в `describe` / `it` / `test`):
|
|
16
16
|
- формулировки **только на русском языке** — понятные бизнес‑фразы (что проверяется и какой ожидается результат);
|
|
17
17
|
- **каждое предложение** в названии **начинается с заглавной буквы** (в том числе после `.`, `!`, `?` и при нескольких предложениях в одной строке); первая буква всей строки — тоже заглавная.
|
|
18
|
+
- **Проверка в CI:** ESLint (`jest/valid-title` в `app/eslint.config.mjs`) требует, чтобы строка начиналась с русской заглавной (А–Я, Ё), и запрещает пробел после точки, за которым сразу идёт строчная буква (типичный случай нарушения «с заглавной после точки»).
|
|
18
19
|
|
|
19
20
|
```typescript
|
|
20
21
|
// ✅ Хорошо
|