@nitra/cursor 1.5.0 → 1.5.2
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/README.md +6 -6
- package/mdc/bun.mdc +7 -1
- package/mdc/js-lint.mdc +19 -5
- package/mdc/js-pino.mdc +1 -1
- package/mdc/text.mdc +219 -0
- package/mdc/vue.mdc +0 -2
- package/package.json +1 -1
- package/scripts/check-js-lint.mjs +38 -1
- package/scripts/check-text.mjs +139 -0
- package/skills/n-fix/SKILL.md +1 -0
- package/skills/n-publish-telegram/SKILL.md +8 -7
- package/mdc/spell.mdc +0 -155
- package/scripts/check-spell.mjs +0 -86
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
```json
|
|
16
16
|
{
|
|
17
|
-
"rules": ["js-format", "npm-module", "
|
|
17
|
+
"rules": ["js-format", "npm-module", "text"]
|
|
18
18
|
}
|
|
19
19
|
```
|
|
20
20
|
|
|
@@ -24,14 +24,14 @@
|
|
|
24
24
|
| ------------ | ------------------------------------------------- |
|
|
25
25
|
| `js-format` | Правила форматування JavaScript ecosystem (oxfmt) |
|
|
26
26
|
| `npm-module` | Структура репозиторію для npm-модуля (bun mono) |
|
|
27
|
-
| `
|
|
27
|
+
| `text` | Текстові файли: cspell, CI |
|
|
28
28
|
|
|
29
29
|
Щоб завантажити правила конкретної версії пакету, додайте поле `version`:
|
|
30
30
|
|
|
31
31
|
```json
|
|
32
32
|
{
|
|
33
33
|
"version": "2.5.0",
|
|
34
|
-
"rules": ["js-format", "
|
|
34
|
+
"rules": ["js-format", "text"]
|
|
35
35
|
}
|
|
36
36
|
```
|
|
37
37
|
|
|
@@ -56,7 +56,7 @@ CLI автоматично:
|
|
|
56
56
|
📋 Правил до завантаження: 3
|
|
57
57
|
⬇ js-format → .cursor/rules/n-js-format.mdc ... ✅
|
|
58
58
|
⬇ npm-module → .cursor/rules/n-npm-module.mdc ... ✅
|
|
59
|
-
⬇
|
|
59
|
+
⬇ text → .cursor/rules/n-text.mdc ... ✅
|
|
60
60
|
📝 Оновлено AGENTS.md з AGENTS.template.md
|
|
61
61
|
|
|
62
62
|
✨ Готово: 3 завантажено, 0 з помилками
|
|
@@ -70,7 +70,7 @@ npm/
|
|
|
70
70
|
├── mdc/ # cursor-правила
|
|
71
71
|
│ ├── js-format.mdc
|
|
72
72
|
│ ├── npm-module.mdc
|
|
73
|
-
│ └──
|
|
73
|
+
│ └── text.mdc
|
|
74
74
|
└── bin/
|
|
75
75
|
└── n-cursor.js # CLI-скрипт
|
|
76
76
|
```
|
|
@@ -96,7 +96,7 @@ npm/
|
|
|
96
96
|
{{/services}}
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
Під час запуску CLI тіло між `{{#services}}` і `{{/services}}` повторюється для кожного `*.mdc` у `.cursor/rules/`; у `{{name}}` підставляється вже готовий markdown-рядок (наприклад `- .cursor/rules/n-
|
|
99
|
+
Під час запуску CLI тіло між `{{#services}}` і `{{/services}}` повторюється для кожного `*.mdc` у `.cursor/rules/`; у `{{name}}` підставляється вже готовий markdown-рядок (наприклад `- .cursor/rules/n-text.mdc`).
|
|
100
100
|
|
|
101
101
|
3. Після змін у шаблоні перевірте локально: у тестовому репозиторії з `.n-cursor.json` виконайте `npx`/`bunx` на зібраному пакеті або `node npm/bin/n-cursor.js` з кореня того репозиторію і переконайтеся, що **`AGENTS.md`** виглядає як очікується.
|
|
102
102
|
|
package/mdc/bun.mdc
CHANGED
|
@@ -12,9 +12,11 @@ version: '1.1'
|
|
|
12
12
|
- Якщо новий виклик CLI додається з нуля і в цьому репозиторії прийнято лише Bun — можна `bunx <tool>`.
|
|
13
13
|
|
|
14
14
|
Заборонено використовувати як менеджер пакетів / lockfile:
|
|
15
|
+
|
|
15
16
|
- `npm install`, `yarn`, `pnpm` (і відповідні lockfile, крім `bun.lock`)
|
|
16
17
|
|
|
17
18
|
Дозволені команди:
|
|
19
|
+
|
|
18
20
|
- `bun i`
|
|
19
21
|
- `bun run <script>`
|
|
20
22
|
- `bun add <pkg>`
|
|
@@ -23,7 +25,6 @@ version: '1.1'
|
|
|
23
25
|
- `bunx <tool>`
|
|
24
26
|
- `npx <tool>`
|
|
25
27
|
|
|
26
|
-
|
|
27
28
|
- Для встановлення залежностей використовуй `bun i`.
|
|
28
29
|
- Для запуску скриптів використовуй `bun run <script>`.
|
|
29
30
|
- Для додавання залежностей:
|
|
@@ -32,6 +33,7 @@ version: '1.1'
|
|
|
32
33
|
- Для одноразових CLI-команд використовуй `bunx <tool>`.
|
|
33
34
|
|
|
34
35
|
Заборонено використовувати:
|
|
36
|
+
|
|
35
37
|
- `npm`
|
|
36
38
|
- `yarn`
|
|
37
39
|
- `pnpm`
|
|
@@ -41,6 +43,7 @@ Lockfile у репозиторії: `bun.lock`.
|
|
|
41
43
|
Видалити якщо вони є. Видалити .yarn та .yarnrc.yml якщо вони є.
|
|
42
44
|
|
|
43
45
|
Для Bun monorepo:
|
|
46
|
+
|
|
44
47
|
- Встановлювати залежності у відповідному пакеті, а не в корені без потреби.
|
|
45
48
|
- Якщо залежність потрібна лише одному пакету, додавати її в директорії цього пакета.
|
|
46
49
|
- У CI та локально запускати скрипти через `bun run`.
|
|
@@ -49,12 +52,15 @@ Lockfile у репозиторії: `bun.lock`.
|
|
|
49
52
|
|
|
50
53
|
Якщо в проекті використовується npx, то не заміняти його на bunx, а використовувати npx.
|
|
51
54
|
Коли зміна відбувається в Dockerfile, то використовувати
|
|
55
|
+
|
|
52
56
|
```dockerfile
|
|
53
57
|
FROM oven/bun:alpine AS build-env
|
|
54
58
|
```
|
|
59
|
+
|
|
55
60
|
замість образу node
|
|
56
61
|
|
|
57
62
|
В Github actions bun повинен налаштований так:
|
|
63
|
+
|
|
58
64
|
```yaml
|
|
59
65
|
- uses: oven-sh/setup-bun@v2
|
|
60
66
|
|
package/mdc/js-lint.mdc
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Перевірка JavaScript коду
|
|
3
3
|
alwaysApply: true
|
|
4
|
-
version: '1.
|
|
4
|
+
version: '1.4'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Перевірка виконується за допомогою **oxlint** та **
|
|
7
|
+
Перевірка виконується за допомогою **oxlint**, **ESLint** та **jscpd** (дублікати коду).
|
|
8
8
|
|
|
9
9
|
У файлі `.vscode/extensions.json` мають бути рекомендації розширень:
|
|
10
10
|
|
|
@@ -18,18 +18,30 @@ version: '1.2'
|
|
|
18
18
|
}
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
У кореневому `package.json` додай скрипт і
|
|
21
|
+
У кореневому `package.json` додай скрипт і залежності:
|
|
22
22
|
|
|
23
23
|
```json title="package.json"
|
|
24
24
|
"scripts": {
|
|
25
|
-
"lint-js": "oxlint --fix && bunx eslint --fix ."
|
|
25
|
+
"lint-js": "oxlint --fix && bunx eslint --fix . && bunx jscpd ."
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@nitra/eslint-config": "^3.3.0"
|
|
29
29
|
}
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
У `devDependencies` достатньо `@nitra/eslint-config` (залежності ESLint підтягуються разом із ним). **oxlint**
|
|
32
|
+
У `devDependencies` достатньо `@nitra/eslint-config` (залежності ESLint підтягуються разом із ним). **oxlint**, **eslint** та **jscpd** у скриптах викликай через `bunx`; окремо не додавай пакети `oxlint` / `eslint` / `jscpd`, якщо цього не вимагає ваш монорепо.
|
|
33
|
+
|
|
34
|
+
У корені проєкту має бути `.jscpd.json`. Мінімум: увімкнути облік `.gitignore`, ненульовий код виходу при знаходженні клонів, консольний звіт. За потреби додай `ignore` (дзеркальні каталоги, шаблони) та `minLines`, щоб відсікти дрібні збіги:
|
|
35
|
+
|
|
36
|
+
```json title=".jscpd.json"
|
|
37
|
+
{
|
|
38
|
+
"gitignore": true,
|
|
39
|
+
"exitCode": 1,
|
|
40
|
+
"reporters": ["console"],
|
|
41
|
+
"minLines": 25,
|
|
42
|
+
"ignore": []
|
|
43
|
+
}
|
|
44
|
+
```
|
|
33
45
|
|
|
34
46
|
Додай workflow `.github/workflows/lint-js.yml`:
|
|
35
47
|
|
|
@@ -49,6 +61,7 @@ on:
|
|
|
49
61
|
- '**/*.tsx'
|
|
50
62
|
- '**/*.vue'
|
|
51
63
|
- '**/eslint.config.*'
|
|
64
|
+
- '.jscpd.json'
|
|
52
65
|
|
|
53
66
|
pull_request:
|
|
54
67
|
branches:
|
|
@@ -83,6 +96,7 @@ jobs:
|
|
|
83
96
|
run: |
|
|
84
97
|
bunx oxlint
|
|
85
98
|
bunx eslint .
|
|
99
|
+
bunx jscpd .
|
|
86
100
|
```
|
|
87
101
|
|
|
88
102
|
**Без дублювання CI:** якщо в `.github/workflows` уже є `lint.yml` з тими самими кроками `oxlint` або `eslint`, видали зайвий workflow, а саме `lint.yml` — лінт JS має виконуватися в одному місці.
|
package/mdc/js-pino.mdc
CHANGED
package/mdc/text.mdc
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Обробка та перевірка текстових файлів (cspell, markdownlint-cli2, v8r, CI)
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
version: '1.12'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Правило описує роботу з **текстовими файлами** в репозиторії: перевірка правопису через **cspell**, стиль **Markdown** через **markdownlint-cli2**, валідація **JSON/YAML/TOML** через **[v8r](https://chris48s.github.io/v8r/)** ([Schema Store](https://www.schemastore.org/)), розширення **DavidAnson.vscode-markdownlint** у Cursor/VS Code та інтеграція в CI.
|
|
8
|
+
|
|
9
|
+
## Розширення Cursor / VS Code
|
|
10
|
+
|
|
11
|
+
У файлі `.vscode/extensions.json` **додай** `DavidAnson.vscode-markdownlint` у масив `recommendations` (разом із записами з інших правил, зокрема js-lint / js-format):
|
|
12
|
+
|
|
13
|
+
```json title=".vscode/extensions.json"
|
|
14
|
+
{
|
|
15
|
+
"recommendations": [
|
|
16
|
+
"dbaeumer.vscode-eslint",
|
|
17
|
+
"github.vscode-github-actions",
|
|
18
|
+
"oxc.oxc-vscode",
|
|
19
|
+
"DavidAnson.vscode-markdownlint"
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Скрипти та залежності в package.json
|
|
25
|
+
|
|
26
|
+
У кореневому `package.json` один скрипт **lint-text** має послідовно викликати **cspell**, **markdownlint-cli2** і **v8r** (і решту блоків з розділів нижче в одному файлі):
|
|
27
|
+
|
|
28
|
+
```json title="package.json"
|
|
29
|
+
"scripts": {
|
|
30
|
+
"lint-text": "npx cspell . && bunx markdownlint-cli2 --fix \"**/*.md\" \"**/*.mdc\" && (bunx v8r \"**/*.json\" || [ $? -eq 98 ]) && (bunx v8r \"**/*.yml\" || [ $? -eq 98 ]) && (bunx v8r \"**/*.yaml\" || [ $? -eq 98 ]) && (bunx v8r \"**/*.toml\" || [ $? -eq 98 ])"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"markdownlint-cli2": "^0.22.0"
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**markdownlint-cli2** і **v8r** у скрипті викликай через `bunx`. Окремо не додавай пакет `markdownlint`, якщо достатньо `markdownlint-cli2`. Маски `**/*.md` і `**/*.mdc` охоплюють Markdown і правила Cursor (`.mdc`); виключення з `.gitignore` для markdownlint задаються в `.markdownlint-cli2.jsonc` (`gitignore: true`). За потреби можна додати окремий скрипт `lint-md` лише для markdownlint — CI все одно має викликати повний `bun run lint-text`.
|
|
38
|
+
|
|
39
|
+
## v8r
|
|
40
|
+
|
|
41
|
+
[v8r](https://chris48s.github.io/v8r/) — CLI-валідатор: за іменем файлу знаходить схему в [Schema Store](https://www.schemastore.org/) і перевіряє вміст. У `lint-text` — чотири послідовні виклики з масками `**/*.json`, `**/*.yml`, `**/*.yaml`, `**/*.toml`, кожен у вигляді `(bunx v8r "<glob>" || [ $? -eq 98 ])`.
|
|
42
|
+
|
|
43
|
+
**Код 98:** якщо для glob **немає жодного файлу**, v8r дає **98**. Це стосується не лише TOML: репозиторій без `.yml`/`.yaml` зламає **один** спільний виклик `v8r` уже на `**/*.yml`. Окремі виклики з дозволом лише **98** покривають і такі репозиторії.
|
|
44
|
+
|
|
45
|
+
За замовчуванням v8r враховує **`.gitignore`**. **`.v8rignore` не створюй завчасно** — файл потрібен **лише коли** `bunx v8r` падає на JSON/YAML без схеми в каталозі (тоді додай у ignore відповідні glob’и).
|
|
46
|
+
|
|
47
|
+
Пакет **`v8r` у `devDependencies` не додавай** — у скрипті достатньо **`bunx v8r`**.
|
|
48
|
+
|
|
49
|
+
## Конфігурація markdownlint-cli2
|
|
50
|
+
|
|
51
|
+
У корені проєкту має бути **`.markdownlint-cli2.jsonc`** (документація: [DavidAnson/markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2)):
|
|
52
|
+
|
|
53
|
+
```json title=".markdownlint-cli2.jsonc"
|
|
54
|
+
{
|
|
55
|
+
"gitignore": true,
|
|
56
|
+
"config": {
|
|
57
|
+
"default": true,
|
|
58
|
+
"MD013": false,
|
|
59
|
+
"MD029": false,
|
|
60
|
+
"MD040": false,
|
|
61
|
+
"MD041": false
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`gitignore: true` змушує markdownlint-cli2 пропускати шляхи з `.gitignore` (у тому числі `node_modules`, якщо воно там є). Додатковий glob `"#node_modules"` у скрипті не потрібен. За потреби додай власні шляхи через `ignores` у цьому ж файлі.
|
|
67
|
+
|
|
68
|
+
За потреби увімкни окремі правила (наприклад `MD013` з `line_length: 120`), щоб узгодити довжину рядків з `.oxfmtrc.json`.
|
|
69
|
+
|
|
70
|
+
`MD041` вимкнено навмисно: файли `.mdc` (Cursor rules) мають YAML frontmatter, після якого перший абзац часто не є заголовком H1.
|
|
71
|
+
|
|
72
|
+
## Cspell
|
|
73
|
+
|
|
74
|
+
У корені проєкту має бути `.cspell.json` і залежності для cspell у кореневому `package.json` (зазвичай `devDependencies`).
|
|
75
|
+
|
|
76
|
+
Додай workflow `.github/workflows/lint-text.yml`:
|
|
77
|
+
|
|
78
|
+
```yaml
|
|
79
|
+
name: Lint Text
|
|
80
|
+
|
|
81
|
+
on:
|
|
82
|
+
push:
|
|
83
|
+
branches:
|
|
84
|
+
- dev
|
|
85
|
+
paths:
|
|
86
|
+
- '.cspell.json'
|
|
87
|
+
- '.gitignore'
|
|
88
|
+
- '.markdownlint-cli2.jsonc'
|
|
89
|
+
- '**/*.js'
|
|
90
|
+
- '**/*.ts'
|
|
91
|
+
- '**/*.vue'
|
|
92
|
+
- '**/*.html'
|
|
93
|
+
- '**/*.css'
|
|
94
|
+
- '**/*.scss'
|
|
95
|
+
- '**/*.less'
|
|
96
|
+
- '**/*.json'
|
|
97
|
+
- '**/*.jsonc'
|
|
98
|
+
- '**/*.yaml'
|
|
99
|
+
- '**/*.yml'
|
|
100
|
+
- '**/*.toml'
|
|
101
|
+
- '**/*.xml'
|
|
102
|
+
- '**/*.md'
|
|
103
|
+
- '**/*.mdc'
|
|
104
|
+
- '**/*.mdс'
|
|
105
|
+
- '**/*.txt'
|
|
106
|
+
- '**/*.go'
|
|
107
|
+
- '**/*.py'
|
|
108
|
+
- '**/*.php'
|
|
109
|
+
|
|
110
|
+
pull_request:
|
|
111
|
+
branches:
|
|
112
|
+
- dev
|
|
113
|
+
|
|
114
|
+
concurrency:
|
|
115
|
+
group: ${{ github.ref }}-${{ github.workflow }}
|
|
116
|
+
cancel-in-progress: true
|
|
117
|
+
|
|
118
|
+
jobs:
|
|
119
|
+
text:
|
|
120
|
+
runs-on: ubuntu-latest
|
|
121
|
+
steps:
|
|
122
|
+
- uses: actions/checkout@v4
|
|
123
|
+
|
|
124
|
+
- uses: oven-sh/setup-bun@v2
|
|
125
|
+
|
|
126
|
+
- name: Cache Bun dependencies
|
|
127
|
+
uses: actions/cache@v4
|
|
128
|
+
with:
|
|
129
|
+
path: |
|
|
130
|
+
~/.bun/install/cache
|
|
131
|
+
node_modules
|
|
132
|
+
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
|
|
133
|
+
restore-keys: |
|
|
134
|
+
${{ runner.os }}-bun-
|
|
135
|
+
|
|
136
|
+
- name: Install dependencies
|
|
137
|
+
run: bun install --frozen-lockfile
|
|
138
|
+
|
|
139
|
+
- name: Lint text
|
|
140
|
+
run: bun run lint-text
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Без дублювання CI:** якщо в `.github/workflows` уже є workflow з тими самими кроками `cspell` або `markdownlint-cli2`, видали зайвий — перевірки тексту та Markdown мають виконуватися в одному місці.
|
|
144
|
+
|
|
145
|
+
## Базовий варіант cspell (без окремого словника української)
|
|
146
|
+
|
|
147
|
+
Якщо текст переважно англійською та достатньо корпоративного словника (@nitra/cspell-dict; у полі `language` cspell лишається тег `nitra`):
|
|
148
|
+
|
|
149
|
+
```json title=".cspell.json"
|
|
150
|
+
{
|
|
151
|
+
"version": "0.2",
|
|
152
|
+
"language": "nitra",
|
|
153
|
+
"ignorePaths": ["**/node_modules/**", "**/vscode-extension/**", "**/.git/**", ".vscode", "report"],
|
|
154
|
+
"import": ["@nitra/cspell-dict/cspell-ext.json"],
|
|
155
|
+
"words": []
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
```json title="package.json"
|
|
160
|
+
{
|
|
161
|
+
"scripts": {
|
|
162
|
+
"lint-text": "npx cspell . && bunx markdownlint-cli2 --fix \"**/*.md\" \"**/*.mdc\" && (bunx v8r \"**/*.json\" || [ $? -eq 98 ]) && (bunx v8r \"**/*.yml\" || [ $? -eq 98 ]) && (bunx v8r \"**/*.yaml\" || [ $? -eq 98 ]) && (bunx v8r \"**/*.toml\" || [ $? -eq 98 ])"
|
|
163
|
+
},
|
|
164
|
+
"devDependencies": {
|
|
165
|
+
"@nitra/cspell-dict": "^1.0.185",
|
|
166
|
+
"markdownlint-cli2": "^0.22.0"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Проєкт з українською мовою
|
|
172
|
+
|
|
173
|
+
Якщо в репозиторії є українська документація, коментарі або рядки в коді — потрібен **окремий словник** `@cspell/dict-uk-ua`, інакше cspell не перевірятиме український правопис коректно.
|
|
174
|
+
|
|
175
|
+
**1. Залежності** — додай пакет словника поруч із `@nitra/cspell-dict`:
|
|
176
|
+
|
|
177
|
+
```json title="package.json"
|
|
178
|
+
{
|
|
179
|
+
"scripts": {
|
|
180
|
+
"lint-text": "npx cspell . && bunx markdownlint-cli2 --fix \"**/*.md\" \"**/*.mdc\" && (bunx v8r \"**/*.json\" || [ $? -eq 98 ]) && (bunx v8r \"**/*.yml\" || [ $? -eq 98 ]) && (bunx v8r \"**/*.yaml\" || [ $? -eq 98 ]) && (bunx v8r \"**/*.toml\" || [ $? -eq 98 ])"
|
|
181
|
+
},
|
|
182
|
+
"devDependencies": {
|
|
183
|
+
"@nitra/cspell-dict": "^1.0.185",
|
|
184
|
+
"@cspell/dict-uk-ua": "^4.0.6",
|
|
185
|
+
"markdownlint-cli2": "^0.22.0"
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Встановлення: `bun add -d @cspell/dict-uk-ua` (або `npm i -D @cspell/dict-uk-ua`).
|
|
191
|
+
|
|
192
|
+
**2. `.cspell.json`** — у полі `language` має бути `uk` (разом з іншими мовами через кому), у `import` — підключення розширення українського словника:
|
|
193
|
+
|
|
194
|
+
```json title=".cspell.json"
|
|
195
|
+
{
|
|
196
|
+
"version": "0.2",
|
|
197
|
+
"language": "en,uk,nitra",
|
|
198
|
+
"ignorePaths": ["**/node_modules/**", "**/vscode-extension/**", "**/.git/**", ".vscode", "report"],
|
|
199
|
+
"import": [
|
|
200
|
+
"@nitra/cspell-dict/cspell-ext.json",
|
|
201
|
+
"@cspell/dict-uk-ua/cspell-ext.json"
|
|
202
|
+
],
|
|
203
|
+
"words": []
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Підлаштуй `language` під проєкт (наприклад додай `ru-ru`, якщо потрібна перевірка російською). Порядок у `import` може впливати на пріоритет словників — тримай корпоративний `@nitra/cspell-dict` там, де зручно для ваших правил.
|
|
208
|
+
|
|
209
|
+
## Локальні виключення
|
|
210
|
+
|
|
211
|
+
У секції `words` у `.cspell.json` додають власні терміни, імена та скорочення, яких немає в словниках.
|
|
212
|
+
|
|
213
|
+
## Інші мови
|
|
214
|
+
|
|
215
|
+
Для іншої мови встанови відповідний пакет `@cspell/dict-*`, додай його `cspell-ext.json` у `import` і код мови в `language`. Огляд словників: [streetsidesoftware/cspell-dicts](https://github.com/streetsidesoftware/cspell-dicts).
|
|
216
|
+
|
|
217
|
+
## Перевірка
|
|
218
|
+
|
|
219
|
+
`npx @nitra/cursor check text`
|
package/mdc/vue.mdc
CHANGED
package/package.json
CHANGED
|
@@ -27,8 +27,15 @@ export async function check() {
|
|
|
27
27
|
|
|
28
28
|
if (pkg.scripts?.['lint-js']) {
|
|
29
29
|
pass('package.json містить скрипт lint-js')
|
|
30
|
+
if (String(pkg.scripts['lint-js']).includes('jscpd')) {
|
|
31
|
+
pass('lint-js містить jscpd')
|
|
32
|
+
} else {
|
|
33
|
+
fail('lint-js має викликати jscpd — додай "&& bunx jscpd ." у кінець скрипта')
|
|
34
|
+
}
|
|
30
35
|
} else {
|
|
31
|
-
fail(
|
|
36
|
+
fail(
|
|
37
|
+
'package.json не містить скрипт "lint-js" — додай: "oxlint --fix && bunx eslint --fix . && bunx jscpd ."'
|
|
38
|
+
)
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
if (pkg.devDependencies?.['@nitra/eslint-config']) {
|
|
@@ -63,10 +70,40 @@ export async function check() {
|
|
|
63
70
|
} else {
|
|
64
71
|
fail('lint-js.yml не містить eslint')
|
|
65
72
|
}
|
|
73
|
+
if (content.includes('jscpd')) {
|
|
74
|
+
pass('lint-js.yml містить jscpd')
|
|
75
|
+
} else {
|
|
76
|
+
fail('lint-js.yml не містить jscpd — додай крок bunx jscpd .')
|
|
77
|
+
}
|
|
66
78
|
} else {
|
|
67
79
|
fail('.github/workflows/lint-js.yml не існує — створи його')
|
|
68
80
|
}
|
|
69
81
|
|
|
82
|
+
if (existsSync('.jscpd.json')) {
|
|
83
|
+
let jscpdCfg
|
|
84
|
+
try {
|
|
85
|
+
jscpdCfg = JSON.parse(await readFile('.jscpd.json', 'utf8'))
|
|
86
|
+
} catch {
|
|
87
|
+
fail('.jscpd.json не є валідним JSON')
|
|
88
|
+
jscpdCfg = null
|
|
89
|
+
}
|
|
90
|
+
if (jscpdCfg) {
|
|
91
|
+
pass('.jscpd.json існує')
|
|
92
|
+
if (jscpdCfg.gitignore === true) {
|
|
93
|
+
pass('.jscpd.json: gitignore увімкнено')
|
|
94
|
+
} else {
|
|
95
|
+
fail('.jscpd.json має містити "gitignore": true')
|
|
96
|
+
}
|
|
97
|
+
if (jscpdCfg.exitCode === 1) {
|
|
98
|
+
pass('.jscpd.json: exitCode 1 при дублікатах')
|
|
99
|
+
} else {
|
|
100
|
+
fail('.jscpd.json має містити "exitCode": 1 (інакше CI не впаде на клонах)')
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
fail('.jscpd.json не існує — створи з gitignore, exitCode та reporters згідно js-lint.mdc')
|
|
105
|
+
}
|
|
106
|
+
|
|
70
107
|
for (const dup of ['.eslintrc', '.eslintrc.js', '.eslintrc.json', '.eslintrc.yml']) {
|
|
71
108
|
if (existsSync(dup)) fail(`Знайдено застарілий конфіг ESLint: ${dup} — видали, використовуй eslint.config.js`)
|
|
72
109
|
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { readFile } from 'node:fs/promises'
|
|
3
|
+
|
|
4
|
+
import { pass } from './utils/pass.mjs'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Перевіряє відповідність проєкту правилам text.mdc (cspell, markdownlint-cli2, v8r)
|
|
8
|
+
* @returns {Promise<number>} 0 — все OK, 1 — є проблеми
|
|
9
|
+
*/
|
|
10
|
+
export async function check() {
|
|
11
|
+
let exitCode = 0
|
|
12
|
+
const fail = msg => {
|
|
13
|
+
console.log(` ❌ ${msg}`)
|
|
14
|
+
exitCode = 1
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (existsSync('.vscode/extensions.json')) {
|
|
18
|
+
try {
|
|
19
|
+
const ext = JSON.parse(await readFile('.vscode/extensions.json', 'utf8'))
|
|
20
|
+
const rec = ext.recommendations
|
|
21
|
+
if (Array.isArray(rec) && rec.includes('DavidAnson.vscode-markdownlint')) {
|
|
22
|
+
pass('extensions.json містить DavidAnson.vscode-markdownlint')
|
|
23
|
+
} else {
|
|
24
|
+
fail('extensions.json: додай "DavidAnson.vscode-markdownlint" у recommendations (див. n-text.mdc)')
|
|
25
|
+
}
|
|
26
|
+
} catch {
|
|
27
|
+
fail('.vscode/extensions.json — невалідний JSON')
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
fail('.vscode/extensions.json не існує — створи з recommendations згідно n-text.mdc')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (existsSync('.markdownlint-cli2.jsonc')) {
|
|
34
|
+
try {
|
|
35
|
+
const ml = JSON.parse(await readFile('.markdownlint-cli2.jsonc', 'utf8'))
|
|
36
|
+
pass('.markdownlint-cli2.jsonc існує і є валідним JSON')
|
|
37
|
+
if (ml.gitignore === true) {
|
|
38
|
+
pass('.markdownlint-cli2.jsonc: gitignore увімкнено')
|
|
39
|
+
} else {
|
|
40
|
+
fail('.markdownlint-cli2.jsonc: додай на верхньому рівні "gitignore": true (див. n-text.mdc)')
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
fail('.markdownlint-cli2.jsonc — невалідний JSON; перевір синтаксис')
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
fail('.markdownlint-cli2.jsonc не існує — створи згідно n-text.mdc')
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (existsSync('.cspell.json')) {
|
|
50
|
+
const cfg = JSON.parse(await readFile('.cspell.json', 'utf8'))
|
|
51
|
+
|
|
52
|
+
if (cfg.version === '0.2') {
|
|
53
|
+
pass('.cspell.json version: 0.2')
|
|
54
|
+
} else {
|
|
55
|
+
fail('.cspell.json version має бути "0.2"')
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (cfg.language) {
|
|
59
|
+
pass(`.cspell.json language: "${cfg.language}"`)
|
|
60
|
+
} else {
|
|
61
|
+
fail('.cspell.json не містить поле language')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const imports = cfg.import || []
|
|
65
|
+
if (imports.some(i => i.includes('@nitra/cspell-dict'))) {
|
|
66
|
+
pass('.cspell.json імпортує @nitra/cspell-dict')
|
|
67
|
+
} else {
|
|
68
|
+
fail('.cspell.json не імпортує @nitra/cspell-dict/cspell-ext.json')
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (Array.isArray(cfg.ignorePaths)) {
|
|
72
|
+
pass('.cspell.json містить ignorePaths')
|
|
73
|
+
} else {
|
|
74
|
+
fail('.cspell.json не містить ignorePaths')
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
fail('.cspell.json не існує — створи його')
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (existsSync('package.json')) {
|
|
81
|
+
const pkg = JSON.parse(await readFile('package.json', 'utf8'))
|
|
82
|
+
const devDeps = pkg.devDependencies || {}
|
|
83
|
+
|
|
84
|
+
if (devDeps['@nitra/cspell-dict']) {
|
|
85
|
+
pass('@nitra/cspell-dict є в devDependencies')
|
|
86
|
+
} else {
|
|
87
|
+
fail('@nitra/cspell-dict відсутній — bun add -d @nitra/cspell-dict')
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (devDeps['markdownlint-cli2']) {
|
|
91
|
+
pass('markdownlint-cli2 є в devDependencies')
|
|
92
|
+
} else {
|
|
93
|
+
fail('markdownlint-cli2 відсутній — bun add -d markdownlint-cli2')
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const lintText = pkg.scripts?.['lint-text']
|
|
97
|
+
const v8rCalls = typeof lintText === 'string' ? (lintText.match(/bunx v8r/g) || []).length : 0
|
|
98
|
+
const eq98Hints = typeof lintText === 'string' ? (lintText.match(/eq 98/g) || []).length : 0
|
|
99
|
+
if (
|
|
100
|
+
typeof lintText === 'string' &&
|
|
101
|
+
lintText.includes('cspell') &&
|
|
102
|
+
lintText.includes('markdownlint-cli2') &&
|
|
103
|
+
lintText.includes('**/*.mdc') &&
|
|
104
|
+
v8rCalls >= 4 &&
|
|
105
|
+
eq98Hints >= 4 &&
|
|
106
|
+
lintText.includes('**/*.json') &&
|
|
107
|
+
lintText.includes('**/*.yml') &&
|
|
108
|
+
lintText.includes('**/*.yaml') &&
|
|
109
|
+
lintText.includes('**/*.toml')
|
|
110
|
+
) {
|
|
111
|
+
pass('package.json: lint-text — чотири виклики v8r з || [ $? -eq 98 ] для json/yml/yaml/toml')
|
|
112
|
+
} else {
|
|
113
|
+
fail(
|
|
114
|
+
'package.json: lint-text — чотири (bunx v8r "<glob>" || [ $? -eq 98 ]) для **/*.json **/*.yml **/*.yaml **/*.toml (див. n-text.mdc)'
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (existsSync('.github/workflows/lint-text.yml')) {
|
|
119
|
+
const wf = await readFile('.github/workflows/lint-text.yml', 'utf8')
|
|
120
|
+
if (wf.includes('bun run lint-text')) {
|
|
121
|
+
pass('lint-text.yml викликає bun run lint-text')
|
|
122
|
+
} else {
|
|
123
|
+
fail('lint-text.yml має містити крок bun run lint-text')
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
fail('.github/workflows/lint-text.yml не існує — створи згідно n-text.mdc')
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (existsSync('.cspell.json')) {
|
|
130
|
+
const cfg = JSON.parse(await readFile('.cspell.json', 'utf8'))
|
|
131
|
+
const hasUkImport = (cfg.import || []).some(i => i.includes('@cspell/dict-uk-ua'))
|
|
132
|
+
if (hasUkImport && !devDeps['@cspell/dict-uk-ua']) {
|
|
133
|
+
fail('.cspell.json імпортує @cspell/dict-uk-ua, але пакет відсутній в devDependencies')
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return exitCode
|
|
139
|
+
}
|
package/skills/n-fix/SKILL.md
CHANGED
|
@@ -47,11 +47,12 @@ Telegram підтримує моноширний шрифт через markdown-
|
|
|
47
47
|
<1-2 речення — що отримали, яка вигода>
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
якщо публікація стосовно
|
|
53
|
-
якщо публікація стосовно
|
|
54
|
-
якщо публікація стосовно
|
|
50
|
+
Теги (хештеги в кінці поста) — підбір за темою:
|
|
51
|
+
|
|
52
|
+
- якщо публікація стосовно AI, то `#ai`
|
|
53
|
+
- якщо публікація стосовно npm модуля, то `#npm`
|
|
54
|
+
- якщо публікація стосовно розробки, то `#dev`
|
|
55
|
+
- якщо публікація стосовно інфраструктури, скриптів, налаштувань, ефективності коду чи безпеки, то `#sre`
|
|
55
56
|
|
|
56
57
|
## Правила
|
|
57
58
|
|
|
@@ -68,6 +69,8 @@ Telegram підтримує моноширний шрифт через markdown-
|
|
|
68
69
|
|
|
69
70
|
````
|
|
70
71
|
```
|
|
72
|
+
#dev
|
|
73
|
+
|
|
71
74
|
📌 Міграція з Prettier на oxfmt
|
|
72
75
|
|
|
73
76
|
Проблема:
|
|
@@ -87,7 +90,5 @@ Prettier повільно форматував великі файли і
|
|
|
87
90
|
Результат:
|
|
88
91
|
Форматування працює миттєво при збереженні,
|
|
89
92
|
зникли конфлікти між форматером і лінтером.
|
|
90
|
-
|
|
91
|
-
#dx #tooling #oxfmt
|
|
92
93
|
```
|
|
93
94
|
````
|
package/mdc/spell.mdc
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Перевірка правопису в текстових файлах
|
|
3
|
-
alwaysApply: true
|
|
4
|
-
version: '1.3'
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
У корені проєкту має бути `.cspell.json` і залежності для cspell у кореневому `package.json` (зазвичай `devDependencies`).
|
|
8
|
-
|
|
9
|
-
У кореневому `package.json` додай скрипт CLI **cspell** (об’єднай з блоками з розділів нижче в одному файлі):
|
|
10
|
-
|
|
11
|
-
```json title="package.json"
|
|
12
|
-
"scripts": {
|
|
13
|
-
"lint-spell": "npx cspell ."
|
|
14
|
-
}
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Додай workflow `.github/workflows/lint-spell.yml`:
|
|
18
|
-
|
|
19
|
-
```yaml
|
|
20
|
-
name: Lint Spell
|
|
21
|
-
|
|
22
|
-
on:
|
|
23
|
-
push:
|
|
24
|
-
branches:
|
|
25
|
-
- dev
|
|
26
|
-
paths:
|
|
27
|
-
- '.cspell.json'
|
|
28
|
-
- '**/*.js'
|
|
29
|
-
- '**/*.ts'
|
|
30
|
-
- '**/*.vue'
|
|
31
|
-
- '**/*.html'
|
|
32
|
-
- '**/*.css'
|
|
33
|
-
- '**/*.scss'
|
|
34
|
-
- '**/*.less'
|
|
35
|
-
- '**/*.json'
|
|
36
|
-
- '**/*.jsonc'
|
|
37
|
-
- '**/*.yaml'
|
|
38
|
-
- '**/*.yml'
|
|
39
|
-
- '**/*.toml'
|
|
40
|
-
- '**/*.xml'
|
|
41
|
-
- '**/*.md'
|
|
42
|
-
- '**/*.mdс'
|
|
43
|
-
- '**/*.txt'
|
|
44
|
-
- '**/*.go'
|
|
45
|
-
- '**/*.py'
|
|
46
|
-
- '**/*.php'
|
|
47
|
-
|
|
48
|
-
pull_request:
|
|
49
|
-
branches:
|
|
50
|
-
- dev
|
|
51
|
-
|
|
52
|
-
concurrency:
|
|
53
|
-
group: ${{ github.ref }}-${{ github.workflow }}
|
|
54
|
-
cancel-in-progress: true
|
|
55
|
-
|
|
56
|
-
jobs:
|
|
57
|
-
cspell:
|
|
58
|
-
runs-on: ubuntu-latest
|
|
59
|
-
steps:
|
|
60
|
-
- uses: actions/checkout@v4
|
|
61
|
-
|
|
62
|
-
- uses: oven-sh/setup-bun@v2
|
|
63
|
-
|
|
64
|
-
- name: Cache Bun dependencies
|
|
65
|
-
uses: actions/cache@v4
|
|
66
|
-
with:
|
|
67
|
-
path: |
|
|
68
|
-
~/.bun/install/cache
|
|
69
|
-
node_modules
|
|
70
|
-
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
|
|
71
|
-
restore-keys: |
|
|
72
|
-
${{ runner.os }}-bun-
|
|
73
|
-
|
|
74
|
-
- name: Install dependencies
|
|
75
|
-
run: bun install --frozen-lockfile
|
|
76
|
-
|
|
77
|
-
- name: Cspell
|
|
78
|
-
run: bun run lint-spell
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
**Без дублювання CI:** якщо в `.github/workflows` уже є workflow з тими самими кроками `cspell`, видали зайвий — перевірка правопису має виконуватися в одному місці.
|
|
82
|
-
|
|
83
|
-
## Базовий варіант (без окремого словника української)
|
|
84
|
-
|
|
85
|
-
Якщо текст переважно англійською та достатньо корпоративного словника (@nitra/cspell-dict; у полі `language` cspell лишається тег `nitra`):
|
|
86
|
-
|
|
87
|
-
```json title=".cspell.json"
|
|
88
|
-
{
|
|
89
|
-
"version": "0.2",
|
|
90
|
-
"language": "nitra",
|
|
91
|
-
"ignorePaths": ["**/node_modules/**", "**/vscode-extension/**", "**/.git/**", ".vscode", "report"],
|
|
92
|
-
"import": ["@nitra/cspell-dict/cspell-ext.json"],
|
|
93
|
-
"words": []
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
```json title="package.json"
|
|
98
|
-
{
|
|
99
|
-
"scripts": {
|
|
100
|
-
"lint-spell": "npx cspell ."
|
|
101
|
-
},
|
|
102
|
-
"devDependencies": {
|
|
103
|
-
"@nitra/cspell-dict": "^1.0.185"
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## Проєкт з українською мовою
|
|
109
|
-
|
|
110
|
-
Якщо в репозиторії є українська документація, коментарі або рядки в коді — потрібен **окремий словник** `@cspell/dict-uk-ua`, інакше cspell не перевірятиме український правопис коректно.
|
|
111
|
-
|
|
112
|
-
**1. Залежності** — додай пакет словника поруч із `@nitra/cspell-dict`:
|
|
113
|
-
|
|
114
|
-
```json title="package.json"
|
|
115
|
-
{
|
|
116
|
-
"scripts": {
|
|
117
|
-
"lint-spell": "npx cspell ."
|
|
118
|
-
},
|
|
119
|
-
"devDependencies": {
|
|
120
|
-
"@nitra/cspell-dict": "^1.0.185",
|
|
121
|
-
"@cspell/dict-uk-ua": "^4.0.6"
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
Встановлення: `bun add -d @cspell/dict-uk-ua` (або `npm i -D @cspell/dict-uk-ua`).
|
|
127
|
-
|
|
128
|
-
**2. `.cspell.json`** — у полі `language` має бути `uk` (разом з іншими мовами через кому), у `import` — підключення розширення українського словника:
|
|
129
|
-
|
|
130
|
-
```json title=".cspell.json"
|
|
131
|
-
{
|
|
132
|
-
"version": "0.2",
|
|
133
|
-
"language": "en,uk,nitra",
|
|
134
|
-
"ignorePaths": ["**/node_modules/**", "**/vscode-extension/**", "**/.git/**", ".vscode", "report"],
|
|
135
|
-
"import": [
|
|
136
|
-
"@nitra/cspell-dict/cspell-ext.json",
|
|
137
|
-
"@cspell/dict-uk-ua/cspell-ext.json"
|
|
138
|
-
],
|
|
139
|
-
"words": []
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
Підлаштуй `language` під проєкт (наприклад додай `ru-ru`, якщо потрібна перевірка російською). Порядок у `import` може впливати на пріоритет словників — тримай корпоративний `@nitra/cspell-dict` там, де зручно для ваших правил.
|
|
144
|
-
|
|
145
|
-
## Локальні виключення
|
|
146
|
-
|
|
147
|
-
У секції `words` у `.cspell.json` додають власні терміни, імена та скорочення, яких немає в словниках.
|
|
148
|
-
|
|
149
|
-
## Інші мови
|
|
150
|
-
|
|
151
|
-
Для іншої мови встанови відповідний пакет `@cspell/dict-*`, додай його `cspell-ext.json` у `import` і код мови в `language`. Огляд словників: [streetsidesoftware/cspell-dicts](https://github.com/streetsidesoftware/cspell-dicts).
|
|
152
|
-
|
|
153
|
-
## Перевірка
|
|
154
|
-
|
|
155
|
-
`npx @nitra/cursor check spell`
|
package/scripts/check-spell.mjs
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs'
|
|
2
|
-
import { readFile } from 'node:fs/promises'
|
|
3
|
-
|
|
4
|
-
import { pass } from './utils/pass.mjs'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Перевіряє відповідність проєкту правилам spell.mdc
|
|
8
|
-
* @returns {Promise<number>} 0 — все OK, 1 — є проблеми
|
|
9
|
-
*/
|
|
10
|
-
export async function check() {
|
|
11
|
-
let exitCode = 0
|
|
12
|
-
const fail = msg => {
|
|
13
|
-
console.log(` ❌ ${msg}`)
|
|
14
|
-
exitCode = 1
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (existsSync('.cspell.json')) {
|
|
18
|
-
const cfg = JSON.parse(await readFile('.cspell.json', 'utf8'))
|
|
19
|
-
|
|
20
|
-
if (cfg.version === '0.2') {
|
|
21
|
-
pass('.cspell.json version: 0.2')
|
|
22
|
-
} else {
|
|
23
|
-
fail('.cspell.json version має бути "0.2"')
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (cfg.language) {
|
|
27
|
-
pass(`.cspell.json language: "${cfg.language}"`)
|
|
28
|
-
} else {
|
|
29
|
-
fail('.cspell.json не містить поле language')
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const imports = cfg.import || []
|
|
33
|
-
if (imports.some(i => i.includes('@nitra/cspell-dict'))) {
|
|
34
|
-
pass('.cspell.json імпортує @nitra/cspell-dict')
|
|
35
|
-
} else {
|
|
36
|
-
fail('.cspell.json не імпортує @nitra/cspell-dict/cspell-ext.json')
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (Array.isArray(cfg.ignorePaths)) {
|
|
40
|
-
pass('.cspell.json містить ignorePaths')
|
|
41
|
-
} else {
|
|
42
|
-
fail('.cspell.json не містить ignorePaths')
|
|
43
|
-
}
|
|
44
|
-
} else {
|
|
45
|
-
fail('.cspell.json не існує — створи його')
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (existsSync('package.json')) {
|
|
49
|
-
const pkg = JSON.parse(await readFile('package.json', 'utf8'))
|
|
50
|
-
const devDeps = pkg.devDependencies || {}
|
|
51
|
-
|
|
52
|
-
if (devDeps['@nitra/cspell-dict']) {
|
|
53
|
-
pass('@nitra/cspell-dict є в devDependencies')
|
|
54
|
-
} else {
|
|
55
|
-
fail('@nitra/cspell-dict відсутній — bun add -d @nitra/cspell-dict')
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const lintSpell = pkg.scripts?.['lint-spell']
|
|
59
|
-
if (typeof lintSpell === 'string' && lintSpell.includes('cspell')) {
|
|
60
|
-
pass('package.json містить скрипт lint-spell з cspell')
|
|
61
|
-
} else {
|
|
62
|
-
fail('package.json не містить скрипт "lint-spell": "npx cspell ." (див. n-spell.mdc)')
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (existsSync('.github/workflows/lint-spell.yml')) {
|
|
66
|
-
const wf = await readFile('.github/workflows/lint-spell.yml', 'utf8')
|
|
67
|
-
if (wf.includes('lint-spell')) {
|
|
68
|
-
pass('lint-spell.yml існує і викликає lint-spell')
|
|
69
|
-
} else {
|
|
70
|
-
fail('lint-spell.yml має містити виклик bun run lint-spell')
|
|
71
|
-
}
|
|
72
|
-
} else {
|
|
73
|
-
fail('.github/workflows/lint-spell.yml не існує — створи згідно n-spell.mdc')
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (existsSync('.cspell.json')) {
|
|
77
|
-
const cfg = JSON.parse(await readFile('.cspell.json', 'utf8'))
|
|
78
|
-
const hasUkImport = (cfg.import || []).some(i => i.includes('@cspell/dict-uk-ua'))
|
|
79
|
-
if (hasUkImport && !devDeps['@cspell/dict-uk-ua']) {
|
|
80
|
-
fail('.cspell.json імпортує @cspell/dict-uk-ua, але пакет відсутній в devDependencies')
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return exitCode
|
|
86
|
-
}
|