@nitra/cursor 1.0.0
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 +82 -0
- package/mdc/js-format.mdc +95 -0
- package/mdc/npm-module.mdc +14 -0
- package/mdc/spell.mdc +71 -0
- package/package.json +34 -0
- package/src/cli.js +141 -0
package/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# @nitra/cursor
|
|
2
|
+
|
|
3
|
+
Консольна утиліта для завантаження cursor-правил Nitra у локальний git-репозиторій.
|
|
4
|
+
|
|
5
|
+
## Як це працює
|
|
6
|
+
|
|
7
|
+
Репозиторій `@nitra/cursor` містить cursor-правила у директорії `mdc/`. CLI завантажує обрані правила з npm (через unpkg.com) і копіює їх у `.cursor/rules/` поточного проекту з префіксом `nitra-`.
|
|
8
|
+
|
|
9
|
+
Наприклад, правило `mdc/js-format.mdc` буде збережено як `.cursor/rules/nitra-js-format.mdc`.
|
|
10
|
+
|
|
11
|
+
## Підготовка
|
|
12
|
+
|
|
13
|
+
Перед першим запуском у вашому репозиторії створіть файл `nitra-cursor.json` у корені проекту зі списком правил для завантаження:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"rules": [
|
|
18
|
+
"js-format",
|
|
19
|
+
"npm-module",
|
|
20
|
+
"spell"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Доступні правила:
|
|
26
|
+
|
|
27
|
+
| Назва | Опис |
|
|
28
|
+
| ------------ | ------------------------------------------------- |
|
|
29
|
+
| `js-format` | Правила форматування JavaScript ecosystem (oxfmt) |
|
|
30
|
+
| `npm-module` | Структура репозиторію для npm-модуля (bun mono) |
|
|
31
|
+
| `spell` | Перевірка правопису через cspell |
|
|
32
|
+
|
|
33
|
+
Щоб завантажити правила конкретної версії пакету, додайте поле `version`:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"version": "2.5.0",
|
|
38
|
+
"rules": ["js-format", "spell"]
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Запуск
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx @nitra/cursor
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
CLI автоматично:
|
|
49
|
+
|
|
50
|
+
1. Знайде `nitra-cursor.json` у поточній директорії
|
|
51
|
+
2. Завантажить кожне з перелічених правил з unpkg.com
|
|
52
|
+
3. Створить директорію `.cursor/rules/` якщо вона відсутня
|
|
53
|
+
4. Збереже файли з префіксом `nitra-`
|
|
54
|
+
|
|
55
|
+
## Приклад виводу
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
🔧 @nitra/cursor — завантаження cursor-правил
|
|
59
|
+
|
|
60
|
+
📋 Правил до завантаження: 3
|
|
61
|
+
⬇ js-format → .cursor/rules/nitra-js-format.mdc ... ✅
|
|
62
|
+
⬇ npm-module → .cursor/rules/nitra-npm-module.mdc ... ✅
|
|
63
|
+
⬇ spell → .cursor/rules/nitra-spell.mdc ... ✅
|
|
64
|
+
|
|
65
|
+
✨ Готово: 3 завантажено, 0 з помилками
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Структура пакету
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
npm/
|
|
72
|
+
├── mdc/ # cursor-правила
|
|
73
|
+
│ ├── js-format.mdc
|
|
74
|
+
│ ├── npm-module.mdc
|
|
75
|
+
│ └── spell.mdc
|
|
76
|
+
└── src/
|
|
77
|
+
└── cli.js # CLI-скрипт
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Мета проекту
|
|
81
|
+
|
|
82
|
+
Консольна утиліта яка дозволить оновлювати в локальних GIT репозиторіях правила для cursor з можливістю наслідування правил від файлів в цьому репозиторії та забезпечення версійності правил для cursor.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Правила форматів JavaScript ecosystem
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
version: '1.0'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
В корені проекту є файл з правилами форматування для oxfmt:
|
|
8
|
+
|
|
9
|
+
```json title=".oxfmtrc.json"
|
|
10
|
+
{
|
|
11
|
+
"arrowParens": "avoid",
|
|
12
|
+
"printWidth": 120,
|
|
13
|
+
"bracketSpacing": true,
|
|
14
|
+
"bracketSameLine": true,
|
|
15
|
+
"embeddedLanguageFormatting": "auto",
|
|
16
|
+
"endOfLine": "lf",
|
|
17
|
+
"htmlWhitespaceSensitivity": "css",
|
|
18
|
+
"insertPragma": false,
|
|
19
|
+
"jsxSingleQuote": true,
|
|
20
|
+
"proseWrap": "preserve",
|
|
21
|
+
"quoteProps": "as-needed",
|
|
22
|
+
"requirePragma": false,
|
|
23
|
+
"semi": false,
|
|
24
|
+
"singleQuote": true,
|
|
25
|
+
"tabWidth": 2,
|
|
26
|
+
"trailingComma": "none",
|
|
27
|
+
"useTabs": false,
|
|
28
|
+
"vueIndentScriptAndStyle": false
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
в файлі .vscode/extensions.json є налаштування для oxfmt:
|
|
33
|
+
|
|
34
|
+
```json title=".vscode/extensions.json"
|
|
35
|
+
{
|
|
36
|
+
"recommendations": ["oxc.oxc-vscode"]
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
в файлі .vscode/settings.json є налаштування для oxfmt:
|
|
41
|
+
|
|
42
|
+
```json title=".vscode/settings.json"
|
|
43
|
+
{
|
|
44
|
+
"editor.formatOnSave": true,
|
|
45
|
+
"[css]": {
|
|
46
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
47
|
+
},
|
|
48
|
+
"[graphql]": {
|
|
49
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
50
|
+
},
|
|
51
|
+
"[handlebars]": {
|
|
52
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
53
|
+
},
|
|
54
|
+
"[html]": {
|
|
55
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
56
|
+
},
|
|
57
|
+
"[javascript]": {
|
|
58
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
59
|
+
},
|
|
60
|
+
"[json]": {
|
|
61
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
62
|
+
},
|
|
63
|
+
"[json5]": {
|
|
64
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
65
|
+
},
|
|
66
|
+
"[jsonc]": {
|
|
67
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
68
|
+
},
|
|
69
|
+
"[less]": {
|
|
70
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
71
|
+
},
|
|
72
|
+
"[markdown]": {
|
|
73
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
74
|
+
},
|
|
75
|
+
"[mdx]": {
|
|
76
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
77
|
+
},
|
|
78
|
+
"[scss]": {
|
|
79
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
80
|
+
},
|
|
81
|
+
"[toml]": {
|
|
82
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
83
|
+
},
|
|
84
|
+
"[typescript]": {
|
|
85
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
86
|
+
},
|
|
87
|
+
"[vue]": {
|
|
88
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
89
|
+
},
|
|
90
|
+
"[yaml]": {
|
|
91
|
+
"editor.defaultFormatter": "oxc.oxc-vscode"
|
|
92
|
+
},
|
|
93
|
+
"oxc.path.oxfmt": "/opt/homebrew/bin/oxfmt"
|
|
94
|
+
}
|
|
95
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Оформлення репозиторію для npm модуля
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
version: '1.0'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Проект представляє собою Bun monorepo
|
|
8
|
+
|
|
9
|
+
Структура проекту:
|
|
10
|
+
|
|
11
|
+
- .github/workflows/ - скрипти для github actions
|
|
12
|
+
- demo/ - опціонально демо проект
|
|
13
|
+
- npm/ - файли для npm модуля
|
|
14
|
+
- package.json
|
package/mdc/spell.mdc
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Перевірка правопису в текстових файлах
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
version: '1.1'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
У корені проекту має бути `.cspell.json` і залежності для cspell у кореневому `package.json` (зазвичай `devDependencies`).
|
|
8
|
+
|
|
9
|
+
## Базовий варіант (без окремого словника української)
|
|
10
|
+
|
|
11
|
+
Якщо текст переважно англійською та достатньо словника nitra:
|
|
12
|
+
|
|
13
|
+
```json title=".cspell.json"
|
|
14
|
+
{
|
|
15
|
+
"version": "0.2",
|
|
16
|
+
"language": "nitra",
|
|
17
|
+
"ignorePaths": ["**/node_modules/**", "**/vscode-extension/**", "**/.git/**", ".vscode", "report"],
|
|
18
|
+
"import": ["@nitra/cspell-dict/cspell-ext.json"],
|
|
19
|
+
"words": []
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```json title="package.json"
|
|
24
|
+
{
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@nitra/cspell-dict": "^1.0.185"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Проєкт з українською мовою
|
|
32
|
+
|
|
33
|
+
Якщо в репозиторії є українська документація, коментарі або рядки в коді — потрібен **окремий словник** `@cspell/dict-uk-ua`, інакше cspell не перевірятиме український правопис коректно.
|
|
34
|
+
|
|
35
|
+
**1. Залежності** — додай пакет словника поруч із `@nitra/cspell-dict`:
|
|
36
|
+
|
|
37
|
+
```json title="package.json"
|
|
38
|
+
{
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@nitra/cspell-dict": "^1.0.185",
|
|
41
|
+
"@cspell/dict-uk-ua": "^4.0.6"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Встановлення: `bun add -d @cspell/dict-uk-ua` (або `npm i -D @cspell/dict-uk-ua`).
|
|
47
|
+
|
|
48
|
+
**2. `.cspell.json`** — у полі `language` має бути `uk` (разом з іншими мовами через кому), у `import` — підключення розширення українського словника:
|
|
49
|
+
|
|
50
|
+
```json title=".cspell.json"
|
|
51
|
+
{
|
|
52
|
+
"version": "0.2",
|
|
53
|
+
"language": "en,uk,nitra",
|
|
54
|
+
"ignorePaths": ["**/node_modules/**", "**/vscode-extension/**", "**/.git/**", ".vscode", "report"],
|
|
55
|
+
"import": [
|
|
56
|
+
"@nitra/cspell-dict/cspell-ext.json",
|
|
57
|
+
"@cspell/dict-uk-ua/cspell-ext.json"
|
|
58
|
+
],
|
|
59
|
+
"words": []
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Підлаштуй `language` під проєкт (наприклад додай `ru-ru`, якщо потрібна перевірка російською). Порядок у `import` може впливати на пріоритет словників — тримай корпоративний `@nitra/cspell-dict` там, де зручно для ваших правил.
|
|
64
|
+
|
|
65
|
+
## Локальні виключення
|
|
66
|
+
|
|
67
|
+
У секції `words` у `.cspell.json` додають власні терміни, імена та скорочення, яких немає в словниках.
|
|
68
|
+
|
|
69
|
+
## Інші мови
|
|
70
|
+
|
|
71
|
+
Для іншої мови встанови відповідний пакет `@cspell/dict-*`, додай його `cspell-ext.json` у `import` і код мови в `language`. Огляд словників: [streetsidesoftware/cspell-dicts](https://github.com/streetsidesoftware/cspell-dicts).
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nitra/cursor",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI для завантаження cursor-правил Nitra у локальний репозиторій",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cli",
|
|
7
|
+
"cursor",
|
|
8
|
+
"cursor-rules",
|
|
9
|
+
"mdc",
|
|
10
|
+
"nitra"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/nitra/cursor#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/nitra/cursor/issues"
|
|
15
|
+
},
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"author": "v@nitra.ai",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/nitra/cursor.git"
|
|
21
|
+
},
|
|
22
|
+
"bin": {
|
|
23
|
+
"nitra-cursor": "./src/cli.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"mdc",
|
|
27
|
+
"src"
|
|
28
|
+
],
|
|
29
|
+
"type": "module",
|
|
30
|
+
"scripts": {
|
|
31
|
+
"test": "npx coverage-node test/index.js"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {}
|
|
34
|
+
}
|
package/src/cli.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @nitra/cursor CLI
|
|
5
|
+
*
|
|
6
|
+
* Завантажує cursor-правила з npm-пакету @nitra/cursor у локальний репозиторій.
|
|
7
|
+
*
|
|
8
|
+
* Використання:
|
|
9
|
+
* npx @nitra/cursor
|
|
10
|
+
*
|
|
11
|
+
* Перед запуском у цільовому репо потрібно створити файл nitra-cursor.json
|
|
12
|
+
* зі списком правил для завантаження.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises'
|
|
16
|
+
import { existsSync } from 'node:fs'
|
|
17
|
+
import { join, basename } from 'node:path'
|
|
18
|
+
import { cwd } from 'node:process'
|
|
19
|
+
|
|
20
|
+
const PACKAGE_NAME = '@nitra/cursor'
|
|
21
|
+
const UNPKG_BASE = 'https://unpkg.com'
|
|
22
|
+
const CONFIG_FILE = 'nitra-cursor.json'
|
|
23
|
+
const RULES_DIR = '.cursor/rules'
|
|
24
|
+
const RULE_PREFIX = 'nitra-'
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Завантажує текст з URL
|
|
28
|
+
* @param {string} url
|
|
29
|
+
* @returns {Promise<string>}
|
|
30
|
+
*/
|
|
31
|
+
async function fetchText(url) {
|
|
32
|
+
const response = await fetch(url)
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
throw new Error(`HTTP ${response.status} — не вдалося завантажити: ${url}`)
|
|
35
|
+
}
|
|
36
|
+
return response.text()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Зчитує конфіг nitra-cursor.json з поточної директорії
|
|
41
|
+
* @returns {Promise<{rules: string[], version?: string}>}
|
|
42
|
+
*/
|
|
43
|
+
async function readConfig() {
|
|
44
|
+
const configPath = join(cwd(), CONFIG_FILE)
|
|
45
|
+
if (!existsSync(configPath)) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Файл конфігурації не знайдено: ${CONFIG_FILE}\n` +
|
|
48
|
+
`Створіть файл ${CONFIG_FILE} у корені репозиторію.\n` +
|
|
49
|
+
`Приклад:\n` +
|
|
50
|
+
`{\n "rules": ["js-format", "npm-module", "spell"]\n}`
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
const raw = await readFile(configPath, 'utf8')
|
|
54
|
+
let config
|
|
55
|
+
try {
|
|
56
|
+
config = JSON.parse(raw)
|
|
57
|
+
} catch {
|
|
58
|
+
throw new Error(`Невірний JSON у файлі ${CONFIG_FILE}`)
|
|
59
|
+
}
|
|
60
|
+
if (!Array.isArray(config.rules) || config.rules.length === 0) {
|
|
61
|
+
throw new Error(`У ${CONFIG_FILE} має бути непорожній масив "rules"`)
|
|
62
|
+
}
|
|
63
|
+
return config
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Повертає URL для завантаження правила з unpkg
|
|
68
|
+
* @param {string} ruleName — ім'я без розширення, наприклад "js-format"
|
|
69
|
+
* @param {string} [version] — версія пакету (необов'язково, за замовчуванням "latest")
|
|
70
|
+
* @returns {string}
|
|
71
|
+
*/
|
|
72
|
+
function buildUrl(ruleName, version) {
|
|
73
|
+
const name = ruleName.endsWith('.mdc') ? ruleName : `${ruleName}.mdc`
|
|
74
|
+
const ver = version ? `@${version}` : '@latest'
|
|
75
|
+
return `${UNPKG_BASE}/${PACKAGE_NAME}${ver}/mdc/${name}`
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Витягує чисте ім'я файлу правила (без шляху, але зберігає .mdc)
|
|
80
|
+
* "npm/mdc/js-format.mdc" → "js-format.mdc"
|
|
81
|
+
* "js-format" → "js-format.mdc"
|
|
82
|
+
* @param {string} ruleName
|
|
83
|
+
* @returns {string}
|
|
84
|
+
*/
|
|
85
|
+
function normalizeRuleName(ruleName) {
|
|
86
|
+
const name = ruleName.endsWith('.mdc') ? ruleName : `${ruleName}.mdc`
|
|
87
|
+
return basename(name)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function main() {
|
|
91
|
+
console.log(`\n🔧 @nitra/cursor — завантаження cursor-правил\n`)
|
|
92
|
+
|
|
93
|
+
// 1. Зчитуємо конфіг
|
|
94
|
+
let config
|
|
95
|
+
try {
|
|
96
|
+
config = await readConfig()
|
|
97
|
+
} catch (err) {
|
|
98
|
+
console.error(`❌ ${err.message}`)
|
|
99
|
+
process.exit(1)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const { rules, version } = config
|
|
103
|
+
if (version) {
|
|
104
|
+
console.log(`📦 Версія пакету: ${version}`)
|
|
105
|
+
}
|
|
106
|
+
console.log(`📋 Правил до завантаження: ${rules.length}`)
|
|
107
|
+
|
|
108
|
+
// 2. Створюємо директорію .cursor/rules якщо не існує
|
|
109
|
+
const rulesDir = join(cwd(), RULES_DIR)
|
|
110
|
+
await mkdir(rulesDir, { recursive: true })
|
|
111
|
+
|
|
112
|
+
// 3. Завантажуємо та зберігаємо кожне правило
|
|
113
|
+
let successCount = 0
|
|
114
|
+
let failCount = 0
|
|
115
|
+
|
|
116
|
+
for (const rule of rules) {
|
|
117
|
+
const url = buildUrl(rule, version)
|
|
118
|
+
const fileName = `${RULE_PREFIX}${normalizeRuleName(rule)}`
|
|
119
|
+
const destPath = join(rulesDir, fileName)
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
process.stdout.write(` ⬇ ${rule} → ${RULES_DIR}/${fileName} ... `)
|
|
123
|
+
const content = await fetchText(url)
|
|
124
|
+
await writeFile(destPath, content, 'utf8')
|
|
125
|
+
console.log(`✅`)
|
|
126
|
+
successCount++
|
|
127
|
+
} catch (err) {
|
|
128
|
+
console.log(`❌`)
|
|
129
|
+
console.error(` Помилка: ${err.message}`)
|
|
130
|
+
failCount++
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// 4. Підсумок
|
|
135
|
+
console.log(`\n✨ Готово: ${successCount} завантажено, ${failCount} з помилками\n`)
|
|
136
|
+
if (failCount > 0) {
|
|
137
|
+
process.exit(1)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
main()
|