@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 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()