@7n/rules 1.30.0 → 1.31.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.
Files changed (62) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/package.json +1 -1
  3. package/rules/k8s/dremio_logging/dremio_logging.mdc +1 -0
  4. package/scripts/docs/upgrade-n-rules-and-install.md +2 -1
  5. package/scripts/upgrade-n-rules-and-install.mjs +86 -19
  6. package/skills/taze/js/docs/orchestrate.md +1 -1
  7. package/rules/style/admin_table/admin_table.mdc +0 -88
  8. package/rules/style/admin_table/concern.json +0 -7
  9. package/rules/style/admin_table/docs/index.md +0 -9
  10. package/rules/style/admin_table/docs/main.md +0 -14
  11. package/rules/style/admin_table/main.mjs +0 -46
  12. package/rules/style/colors/colors.mdc +0 -21
  13. package/rules/style/colors/concern.json +0 -3
  14. package/rules/style/docs/index.md +0 -11
  15. package/rules/style/gap/concern.json +0 -7
  16. package/rules/style/gap/docs/index.md +0 -9
  17. package/rules/style/gap/docs/main.md +0 -15
  18. package/rules/style/gap/gap.mdc +0 -22
  19. package/rules/style/gap/main.mjs +0 -51
  20. package/rules/style/lint/concern.json +0 -7
  21. package/rules/style/lint/docs/fix-lint.md +0 -29
  22. package/rules/style/lint/docs/index.md +0 -11
  23. package/rules/style/lint/docs/main.md +0 -29
  24. package/rules/style/lint/fix-lint.mjs +0 -66
  25. package/rules/style/lint/main.mjs +0 -68
  26. package/rules/style/main.json +0 -1
  27. package/rules/style/main.mdc +0 -12
  28. package/rules/style/package_json/concern.json +0 -9
  29. package/rules/style/package_json/docs/fix-package_json.md +0 -27
  30. package/rules/style/package_json/docs/index.md +0 -9
  31. package/rules/style/package_json/fix-package_json.mjs +0 -3
  32. package/rules/style/package_json/package_json.mdc +0 -18
  33. package/rules/style/package_json/package_json.rego +0 -31
  34. package/rules/style/package_json/template/package.json.snippet.json +0 -5
  35. package/rules/style/quasar/concern.json +0 -3
  36. package/rules/style/quasar/quasar.mdc +0 -7
  37. package/rules/style/quasar_fixes/concern.json +0 -7
  38. package/rules/style/quasar_fixes/docs/index.md +0 -9
  39. package/rules/style/quasar_fixes/docs/main.md +0 -16
  40. package/rules/style/quasar_fixes/main.mjs +0 -57
  41. package/rules/style/quasar_fixes/quasar_fixes.mdc +0 -32
  42. package/rules/style/tooling/concern.json +0 -14
  43. package/rules/style/tooling/docs/fix-tooling.md +0 -29
  44. package/rules/style/tooling/docs/index.md +0 -12
  45. package/rules/style/tooling/docs/main.md +0 -34
  46. package/rules/style/tooling/fix-tooling.mjs +0 -58
  47. package/rules/style/tooling/main.mjs +0 -73
  48. package/rules/style/tooling/tooling.mdc +0 -85
  49. package/rules/style/vscode_extensions/concern.json +0 -9
  50. package/rules/style/vscode_extensions/docs/fix-vscode_extensions.md +0 -25
  51. package/rules/style/vscode_extensions/docs/index.md +0 -11
  52. package/rules/style/vscode_extensions/fix-vscode_extensions.mjs +0 -1
  53. package/rules/style/vscode_extensions/template/extensions.json.snippet.json +0 -1
  54. package/rules/style/vscode_extensions/vscode_extensions.mdc +0 -13
  55. package/rules/style/vscode_extensions/vscode_extensions.rego +0 -13
  56. package/rules/style/vscode_settings/concern.json +0 -9
  57. package/rules/style/vscode_settings/docs/fix-vscode_settings.md +0 -27
  58. package/rules/style/vscode_settings/docs/index.md +0 -9
  59. package/rules/style/vscode_settings/fix-vscode_settings.mjs +0 -5
  60. package/rules/style/vscode_settings/template/settings.json.snippet.json +0 -5
  61. package/rules/style/vscode_settings/vscode_settings.mdc +0 -19
  62. package/rules/style/vscode_settings/vscode_settings.rego +0 -15
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.31.0] - 2026-07-19
4
+
5
+ ### Changed
6
+
7
+ - sync: діапазони вже оголошених плагінів @7n/rules-* у package.json підіймаються до ^latest тим самим кроком, що й ядро — фікси плагінів доїжджають без ручного bun update (bun i сам по собі поважає lockfile); недоступний registry для окремого плагіна — warning і пропуск
8
+ - lint: правило style (stylelint/css/vue-стилі) переїхало з ядра у @7n/rules-lang-js — фінальний крок фази 5 spec lang-plugins-extraction по фронтенд-сімʼї
9
+
3
10
  ## [1.30.0] - 2026-07-19
4
11
 
5
12
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7n/rules",
3
- "version": "1.30.0",
3
+ "version": "1.31.0",
4
4
  "description": "CLI еталонних правил і skills (префікс n-): синк у репозиторій, дельта-lint, конформність",
5
5
  "keywords": [
6
6
  "cli",
@@ -39,6 +39,7 @@ JS-детектор (не rego): `main.mjs`, `lint(ctx)`, per-file, glob `**/dre
39
39
  **Що перевіряється:** якщо файл визначає `ConfigMap` з `data["logback.xml"]` (bundled-конфіг образу `zookeeper:3.8.4-jre-17`, монтується поверх `/conf/logback.xml`), його `<root level="...">` має бути `warn`/`error`/`off` (case-insensitive) — не `info`/`debug`/`trace` (дефолт бандлованого файлу) і не відсутній.
40
40
 
41
41
  **Чому:** readiness/liveness `ruok`-проби виконуються кожні ~10s на кожен zk-под; `NIOServerCnxn` логує це на INFO незалежно від навантаження. Керувати рівнем ззовні НЕ вдається для цього образу:
42
+
42
43
  - `ZOO_LOG4J_PROP` — змінна Bitnami-образів, тут взагалі не читається жодним скриптом.
43
44
  - `-Dzookeeper.console.threshold=WARN` через `JVMFLAGS` — перебивається `<property name="zookeeper.console.threshold" value="INFO"/>` у бандлованому файлі.
44
45
 
@@ -3,7 +3,7 @@ type: JS Module
3
3
  title: upgrade-n-rules-and-install.mjs
4
4
  resource: npm/scripts/upgrade-n-rules-and-install.mjs
5
5
  docgen:
6
- crc: f33841b9
6
+ crc: ab3a4cc2
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 100
9
9
  issues: judge:inaccurate:0.98
@@ -28,6 +28,7 @@ shouldSkipNpmVersionUpgrade — Визначає, чи можна замінит
28
28
  fetchLatestNRulesVersionFromNpm — Отримує актуальну версію пакета `@7n/rules` з реєстру npm (через поле `version` у JSON dist-tag `latest`), що доступно на https://registry.npmjs.org/@7n/rules/latest.
29
29
  resolveInstalledPackageRoot — Знаходить абсолютний шлях до встановленого пакета у директорії `node_modules`, або надає резервний шлях.
30
30
  upgradeNRulesToLatestAndBunInstall — Оновлює `@7n/rules` до останньої версії з npm (якщо це дозволено конфігурацією), виконує встановлення залежностей за допомогою `bun i`, і повертає корінь пакета для подальшої синхронізації конфігураційних файлів, таких як `mdc/`.
31
+ upgradePluginRanges — Підіймає діапазони вже оголошених плагінів `@7n/rules-*` у dependencies/devDependencies до `^latest` з npm (мутує pkg; той самий крок, що й для ядра — бо `bun i` поважає lockfile і фікси плагінів інакше не доїжджають). Специфікатори поза npm-semver (workspace:, file:, git…) не чіпає; недоступний registry для окремого плагіна — warning і пропуск.
31
32
 
32
33
  ## Гарантії поведінки
33
34
 
@@ -22,6 +22,11 @@ const PACKAGE_NAME = '@7n/rules'
22
22
  const LEGACY_PACKAGE_NAME = '@nitra/cursor'
23
23
  const NPM_LATEST_URL = 'https://registry.npmjs.org/@7n/rules/latest'
24
24
 
25
+ // Плагіни екосистеми (@7n/rules-lang-js, -ci-github, …) — їх діапазони sync
26
+ // підіймає до ^latest тим самим механізмом, що й ядро: `bun i` сам по собі
27
+ // поважає lockfile, і фікси плагінів навіть у межах діапазону не доїжджали б.
28
+ const PLUGIN_NAME_RE = /^@7n\/rules-/
29
+
25
30
  const execFileAsync = promisify(execFile)
26
31
 
27
32
  const WORKSPACE_RE = /^workspace:/i
@@ -67,23 +72,71 @@ export function shouldSkipNpmVersionUpgrade(specifier) {
67
72
  }
68
73
 
69
74
  /**
70
- * Остання версія пакета з npm (поле `version` у JSON dist-tag `latest`).
75
+ * Остання версія довільного пакета з npm (поле `version` у dist-tag `latest`).
76
+ * @param {string} packageName npm-ім'я пакета
71
77
  * @returns {Promise<string>} semver без префікса `^`
72
78
  */
73
- export async function fetchLatestNRulesVersionFromNpm() {
74
- const res = await fetch(NPM_LATEST_URL, {
79
+ async function fetchLatestVersionFromNpm(packageName) {
80
+ const url = packageName === PACKAGE_NAME ? NPM_LATEST_URL : `https://registry.npmjs.org/${packageName}/latest`
81
+ const res = await fetch(url, {
75
82
  headers: { accept: 'application/json' }
76
83
  })
77
84
  if (!res.ok) {
78
- throw new Error(`npm registry: ${res.status} ${res.statusText} для ${PACKAGE_NAME}`)
85
+ throw new Error(`npm registry: ${res.status} ${res.statusText} для ${packageName}`)
79
86
  }
80
87
  const data = await res.json()
81
88
  if (!data || typeof data.version !== 'string' || !data.version.trim()) {
82
- throw new Error(`npm registry: у відповіді для ${PACKAGE_NAME} немає поля version`)
89
+ throw new Error(`npm registry: у відповіді для ${packageName} немає поля version`)
83
90
  }
84
91
  return data.version.trim()
85
92
  }
86
93
 
94
+ /**
95
+ * Остання версія пакета `@7n/rules` з npm.
96
+ * @returns {Promise<string>} semver без префікса `^`
97
+ */
98
+ export async function fetchLatestNRulesVersionFromNpm() {
99
+ return await fetchLatestVersionFromNpm(PACKAGE_NAME)
100
+ }
101
+
102
+ /**
103
+ * Підіймає діапазони встановлених плагінів `@7n/rules-*` у package.json до
104
+ * `^latest` з npm (мутує `pkg`). Специфікатори поза npm-semver
105
+ * (`workspace:`, `file:`, git тощо) не чіпає; недоступний registry для
106
+ * окремого плагіна — warning і пропуск (sync не має падати без мережі).
107
+ * @param {{ dependencies?: Record<string, string>, devDependencies?: Record<string, string> }} pkg розпарсений package.json проєкту
108
+ * @returns {Promise<string[]>} імена плагінів, чиї діапазони змінено
109
+ */
110
+ export async function upgradePluginRanges(pkg) {
111
+ /** @type {Array<{ section: 'dependencies' | 'devDependencies', name: string, value: string }>} */
112
+ const candidates = []
113
+ for (const section of /** @type {const} */ (['dependencies', 'devDependencies'])) {
114
+ const deps = pkg[section]
115
+ if (!deps || typeof deps !== 'object' || Array.isArray(deps)) continue
116
+ for (const [name, value] of Object.entries(deps)) {
117
+ if (PLUGIN_NAME_RE.test(name) && typeof value === 'string' && !shouldSkipNpmVersionUpgrade(value)) {
118
+ candidates.push({ section, name, value })
119
+ }
120
+ }
121
+ }
122
+ const changed = []
123
+ const latests = await Promise.allSettled(candidates.map(c => fetchLatestVersionFromNpm(c.name)))
124
+ for (const [i, settled] of latests.entries()) {
125
+ const { section, name, value } = candidates[i]
126
+ if (settled.status === 'rejected') {
127
+ console.warn(`⚠️ ${name}: npm registry недоступний (${settled.reason?.message ?? settled.reason}) — пропускаю\n`)
128
+ continue
129
+ }
130
+ const desired = `^${settled.value}`
131
+ if (value !== desired) {
132
+ pkg[section][name] = desired
133
+ changed.push(name)
134
+ console.log(`⬆️ Оновлено ${name} ${value} → ${desired} у ${section}\n`)
135
+ }
136
+ }
137
+ return changed
138
+ }
139
+
87
140
  /**
88
141
  * Версія з package.json вказаного кореня пакету (fallback, коли registry недоступний).
89
142
  * @param {string} packageRoot корінь пакету поточного процесу CLI
@@ -113,6 +166,25 @@ export function resolveInstalledPackageRoot(projectRoot, fallbackPackageRoot, pa
113
166
  return fallbackPackageRoot
114
167
  }
115
168
 
169
+ /**
170
+ * Остання версія ядра з npm; коли registry недоступний (або до першої
171
+ * публікації — 404) — fallback на версію пакету поточного процесу.
172
+ * @param {string} fallbackPackageRoot корінь пакету з поточного процесу CLI
173
+ * @returns {Promise<string>} semver без префікса `^`
174
+ */
175
+ async function resolveLatestCoreVersion(fallbackPackageRoot) {
176
+ try {
177
+ return await fetchLatestNRulesVersionFromNpm()
178
+ } catch (error) {
179
+ const bundled = await readPackageVersionSafe(fallbackPackageRoot)
180
+ if (!bundled) {
181
+ throw error
182
+ }
183
+ console.log(`⚠️ npm registry недоступний для ${PACKAGE_NAME} — використовую bundled-версію ${bundled}\n`)
184
+ return bundled
185
+ }
186
+ }
187
+
116
188
  /**
117
189
  * Запускає `bun i` у вказаному каталозі з виводом у поточний stdio.
118
190
  * @param {string} projectRoot cwd для процесу
@@ -221,18 +293,11 @@ export async function upgradeNRulesToLatestAndBunInstall(projectRoot, fallbackPa
221
293
  return resolveInstalledPackageRoot(projectRoot, fallbackPackageRoot)
222
294
  }
223
295
 
224
- let latest
225
- try {
226
- latest = await fetchLatestNRulesVersionFromNpm()
227
- } catch (error) {
228
- // До першої публікації @7n/rules registry віддає 404 — fallback на версію пакету поточного процесу
229
- latest = await readPackageVersionSafe(fallbackPackageRoot)
230
- if (!latest) {
231
- throw error
232
- }
233
- console.log(`⚠️ npm registry недоступний для ${PACKAGE_NAME} — використовую bundled-версію ${latest}\n`)
234
- }
235
- const desired = `^${latest}`
296
+ const desired = `^${await resolveLatestCoreVersion(fallbackPackageRoot)}`
297
+
298
+ // Діапазони вже оголошених плагінів @7n/rules-* — до ^latest тим самим
299
+ // кроком (мутує pkg; запис на диск — разом із записом по ядру нижче).
300
+ const upgradedPlugins = await upgradePluginRanges(pkg)
236
301
 
237
302
  if (!found) {
238
303
  if (!pkg.devDependencies || typeof pkg.devDependencies !== 'object' || Array.isArray(pkg.devDependencies)) {
@@ -246,7 +311,7 @@ export async function upgradeNRulesToLatestAndBunInstall(projectRoot, fallbackPa
246
311
  return resolveInstalledPackageRoot(projectRoot, fallbackPackageRoot)
247
312
  }
248
313
 
249
- if (found.value === desired) {
314
+ if (found.value === desired && upgradedPlugins.length === 0) {
250
315
  console.log(`📌 ${PACKAGE_NAME} уже ${desired} у package.json — виконуємо bun i\n`)
251
316
  } else {
252
317
  if (found.section === 'devDependencies') {
@@ -255,7 +320,9 @@ export async function upgradeNRulesToLatestAndBunInstall(projectRoot, fallbackPa
255
320
  pkg.dependencies[PACKAGE_NAME] = desired
256
321
  }
257
322
  await writeFile(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`, 'utf8')
258
- console.log(`📝 Оновлено ${PACKAGE_NAME} → ${desired} у package.json\n`)
323
+ if (found.value !== desired) {
324
+ console.log(`📝 Оновлено ${PACKAGE_NAME} → ${desired} у package.json\n`)
325
+ }
259
326
  }
260
327
 
261
328
  await runBunInstall(projectRoot)
@@ -3,7 +3,7 @@ type: JS Module
3
3
  title: orchestrate.mjs
4
4
  resource: npm/skills/taze/js/orchestrate.mjs
5
5
  docgen:
6
- crc: 9e3842cb
6
+ crc: 7bf5d0c0
7
7
  model: openai-codex/gpt-5.4-mini
8
8
  score: 100
9
9
  issues: judge:inaccurate:0.98
@@ -1,88 +0,0 @@
1
- ## Адмінські таблиці — n-admin-table
2
-
3
- Для таблиць, що мають займати всю висоту сторінки (або блоку), додавай клас `n-admin-table` і атрибути `hide-no-data`, `dense`, `flat`. Таблиця автоматично розтягнеться на весь доступний простір. У блоках меншої висоти — задай їм явний `height`.
4
-
5
- ```vue
6
- <!-- ТАБЛИЦЯ -->
7
- <q-table class="n-admin-table" hide-no-data flat dense />
8
- ```
9
-
10
- Якщо клас `.n-admin-table` не визначено в `app.scss` — додай:
11
-
12
- ```scss
13
- // ADMIN TABLE
14
- .n-admin-table {
15
- height: calc(100vh - 106px);
16
-
17
- thead {
18
- position: sticky;
19
- z-index: 3;
20
- top: 0;
21
-
22
- tr th {
23
- background-color: $grey-3;
24
- height: 36px !important;
25
- }
26
- }
27
-
28
- // tbody td {
29
- // font-size: 14px;
30
- // }
31
-
32
- tbody tr:last-child td {
33
- border-bottom: 1px solid rgb(0 0 0 / 12%) !important;
34
- }
35
-
36
- th:first-child,
37
- td:first-child,
38
- th:last-child,
39
- td:last-child {
40
- width: 1px;
41
- white-space: nowrap;
42
- }
43
-
44
- .q-table__bottom {
45
- background-color: $grey-3;
46
- }
47
-
48
- .q-table__progress th {
49
- height: 1px !important;
50
- }
51
-
52
- .text-wrap {
53
- max-width: 250px;
54
- white-space: normal;
55
- }
56
-
57
- // sticky columns
58
- td.sticky-left {
59
- position: sticky;
60
- left: 0;
61
- z-index: 2;
62
- background-color: white;
63
- box-shadow: 2px 0 5px #0002;
64
- }
65
-
66
- td.sticky-right {
67
- position: sticky;
68
- right: 0;
69
- z-index: 2;
70
- background-color: white;
71
- box-shadow: -2px 0 5px #0002;
72
- }
73
-
74
- th.sticky-left {
75
- position: sticky;
76
- left: 0;
77
- z-index: 3;
78
- box-shadow: 2px 0 5px #0002;
79
- }
80
-
81
- th.sticky-right {
82
- position: sticky;
83
- right: 0;
84
- z-index: 3;
85
- box-shadow: -2px 0 5px #0002;
86
- }
87
- }
88
- ```
@@ -1,7 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "lint": {
4
- "scope": "full",
5
- "glob": ["**/*.vue", "**/*.scss", "**/*.css"]
6
- }
7
- }
@@ -1,9 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/style/admin_table
4
- resource: npm/rules/style/admin_table/
5
- ---
6
-
7
- | Файл | Тип |
8
- | ------------------- | --------- |
9
- | [main.mjs](main.md) | JS Module |
@@ -1,14 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/style/admin_table/main.mjs
5
- docgen:
6
- crc: 9e484318
7
- ---
8
-
9
- ## Огляд
10
-
11
- Детектор concern-а `admin_table` (read-only, whole-repo): якщо десь у `.vue`-файлі
12
- використано клас `n-admin-table`, він має бути визначений хоч в одному `.scss`/`.css`/`.vue`
13
- файлі проєкту, інакше — порушення `missing-admin-table-style`. Потребує whole-repo
14
- сканування (usage і definition можуть бути в різних файлах), тому не залежить від `ctx.files`.
@@ -1,46 +0,0 @@
1
- /** @see ./docs/main.md */
2
- import { readFile } from 'node:fs/promises'
3
-
4
- import { createViolationReporter } from '../../../scripts/lib/lint-surface/violation-reporter.mjs'
5
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
6
-
7
- const RELEVANT_RE = /\.(?:vue|scss|css)$/u
8
- const USAGE_RE = /\bn-admin-table\b/u
9
- const DEFINITION_RE = /\.n-admin-table\b/u
10
-
11
- /**
12
- * Detector style/admin_table (read-only, whole-repo): якщо десь у `.vue` використано
13
- * клас `n-admin-table`, він має бути визначений хоч в одному `.scss`/`.css`/`.vue`
14
- * (guide: `admin_table.mdc`). Для усунення false positives — крос-файлова перевірка,
15
- * тож потребує whole-repo сканування незалежно від `ctx.files`.
16
- * @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd)
17
- * @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
18
- */
19
- export async function lint(ctx) {
20
- const reporter = createViolationReporter(ctx)
21
- const { fail } = reporter
22
- const cwd = ctx.cwd
23
-
24
- /** @type {string[]} */
25
- const files = []
26
- await walkDir(cwd, f => {
27
- if (RELEVANT_RE.test(f)) files.push(f)
28
- })
29
-
30
- let used = false
31
- let defined = false
32
- for (const file of files) {
33
- const content = await readFile(file, 'utf8')
34
- if (!used && file.endsWith('.vue') && USAGE_RE.test(content)) used = true
35
- if (!defined && DEFINITION_RE.test(content)) defined = true
36
- if (used && defined) break
37
- }
38
-
39
- if (used && !defined) {
40
- fail(
41
- 'Клас `.n-admin-table` використовується у `.vue`, але не визначений у жодному `.scss`/`.css` (guide: style/admin_table.mdc) — додай фікс до app.scss',
42
- 'missing-admin-table-style'
43
- )
44
- }
45
- return reporter.result()
46
- }
@@ -1,21 +0,0 @@
1
- ## Кольори: quasar-variables.scss і app.scss
2
-
3
- Основні кольори визначай виключно через стандартні Quasar-змінні: `$primary`, `$secondary`, `$accent`, `$positive`, `$negative`, `$warning`.
4
-
5
- Якщо потрібен додатковий колір — визнач його в `quasar-variables.scss`, і **обов'язково** додай до `app.scss` відповідні `.text-*` / `.bg-*` класи:
6
-
7
- ```scss
8
- /* quasar-variables.scss */
9
- $white-a1: color.adjust(white, $alpha: -0.85);
10
- ```
11
-
12
- ```scss
13
- /* app.scss */
14
- .text-white-a1 {
15
- color: $white-a1 !important;
16
- }
17
-
18
- .bg-white-a1 {
19
- background-color: $white-a1 !important;
20
- }
21
- ```
@@ -1,3 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json"
3
- }
@@ -1,11 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/style
4
- resource: npm/rules/style/
5
- ---
6
-
7
- # npm/rules/style
8
-
9
- | Файл | Тип |
10
- | ------------------- | --------- |
11
- | [main.mjs](main.md) | JS Module |
@@ -1,7 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "lint": {
4
- "scope": "full",
5
- "glob": ["**/*.vue", "**/*.scss", "**/*.css"]
6
- }
7
- }
@@ -1,9 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/style/gap
4
- resource: npm/rules/style/gap/
5
- ---
6
-
7
- | Файл | Тип |
8
- | ------------------- | --------- |
9
- | [main.mjs](main.md) | JS Module |
@@ -1,15 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/style/gap/main.mjs
5
- docgen:
6
- crc: dcba23e0
7
- ---
8
-
9
- ## Огляд
10
-
11
- Детектор concern-а `gap` (read-only, whole-repo): кожен суфікс утиліти
12
- `.n-gap-{xs,sm,md,lg}`, використаний у `.vue`-файлі, має бути визначений хоч в одному
13
- `.scss`/`.css`/`.vue` файлі проєкту — інакше порушення `missing-gap-style` для цього
14
- суфіксу. Суфікси відстежуються незалежно один від одного, тож часткове покриття все одно
15
- виявляє відсутній. Whole-repo сканування, не залежить від `ctx.files`.
@@ -1,22 +0,0 @@
1
- ## Gap між flex/grid-елементами — .n-gap-*
2
-
3
- Для відступів між плаваючими елементами (flex, grid) використовуй класи `.n-gap-*` замість `q-gutter-*`. Якщо класів немає в `app.scss` — додай:
4
-
5
- ```scss
6
- // GAP
7
- .n-gap-xs {
8
- gap: 4px;
9
- }
10
-
11
- .n-gap-sm {
12
- gap: 8px;
13
- }
14
-
15
- .n-gap-md {
16
- gap: 16px;
17
- }
18
-
19
- .n-gap-lg {
20
- gap: 24px;
21
- }
22
- ```
@@ -1,51 +0,0 @@
1
- /** @see ./docs/main.md */
2
- import { readFile } from 'node:fs/promises'
3
-
4
- import { createViolationReporter } from '../../../scripts/lib/lint-surface/violation-reporter.mjs'
5
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
6
-
7
- const RELEVANT_RE = /\.(?:vue|scss|css)$/u
8
- const USAGE_RE = /\bn-gap-(xs|sm|md|lg)\b/gu
9
- const DEFINITION_RE = /\.n-gap-(xs|sm|md|lg)\b/gu
10
-
11
- /**
12
- * Detector style/gap (read-only, whole-repo): кожен суфікс `.n-gap-{xs,sm,md,lg}`,
13
- * використаний у `.vue`, має бути визначений хоч в одному `.scss`/`.css`/`.vue`
14
- * (guide: `gap.mdc`). Крос-файлова перевірка usage↔definition — потребує whole-repo
15
- * сканування незалежно від `ctx.files`.
16
- * @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd)
17
- * @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
18
- */
19
- export async function lint(ctx) {
20
- const reporter = createViolationReporter(ctx)
21
- const { fail } = reporter
22
- const cwd = ctx.cwd
23
-
24
- /** @type {string[]} */
25
- const files = []
26
- await walkDir(cwd, f => {
27
- if (RELEVANT_RE.test(f)) files.push(f)
28
- })
29
-
30
- /** @type {Set<string>} */
31
- const used = new Set()
32
- /** @type {Set<string>} */
33
- const defined = new Set()
34
- for (const file of files) {
35
- const content = await readFile(file, 'utf8')
36
- if (file.endsWith('.vue')) {
37
- for (const m of content.matchAll(USAGE_RE)) used.add(m[1])
38
- }
39
- for (const m of content.matchAll(DEFINITION_RE)) defined.add(m[1])
40
- }
41
-
42
- for (const suffix of used) {
43
- if (!defined.has(suffix)) {
44
- fail(
45
- `Клас \`.n-gap-${suffix}\` використовується у \`.vue\`, але не визначений у жодному \`.scss\`/\`.css\` (guide: style/gap.mdc) — додай клас до app.scss`,
46
- 'missing-gap-style'
47
- )
48
- }
49
- }
50
- return reporter.result()
51
- }
@@ -1,7 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "lint": {
4
- "scope": "per-file",
5
- "glob": ["**/*.{css,scss,vue}"]
6
- }
7
- }
@@ -1,29 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: fix-lint.mjs
4
- resource: npm/rules/style/lint/fix-lint.mjs
5
- docgen:
6
- crc: 140458e8
7
- ---
8
-
9
- ## Огляд
10
-
11
- T0-autofix для `style/lint`: детермінований прогін `stylelint --fix` по css/scss/vue-файлах.
12
- Виправляє авто-fixable правила stylelint; решта лишається детектору на re-check, далі — LLM-ладдеру.
13
- Запис незворотний (поза rollback).
14
-
15
- ## Поведінка
16
-
17
- - Перелічує цільові файли: у дельта-режимі — зі списку змінених (лише css/scss/vue); у повному —
18
- tracked css/scss/vue через git.
19
- - Застосовує `stylelint --fix` на них; до списку змінених потрапляють лише файли з фактичною зміною.
20
-
21
- ## Публічний API
22
-
23
- - `patterns` — масив T0-патернів; єдиний `style-stylelint-fix` спрацьовує на агрегованому
24
- порушенні детектора (`stylelint-violation`).
25
-
26
- ## Гарантії поведінки
27
-
28
- - Відсутній stylelint → no-op (без змін).
29
- - Записуються лише фактично змінені файли; кожен реєструється через `recordWrite`.
@@ -1,11 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/style/lint
4
- resource: npm/rules/style/lint/
5
- ---
6
-
7
- # npm/rules/style/lint
8
-
9
- | Файл | Тип |
10
- | ------------------- | --------- |
11
- | [main.mjs](main.md) | JS Module |
@@ -1,29 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/style/lint/main.mjs
5
- docgen:
6
- crc: cd4833fb
7
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
- score: 100
9
- issues: judge:inaccurate:0.99
10
- judgeModel: openai-codex/gpt-5.4-mini
11
- ---
12
-
13
- ## Огляд
14
-
15
- Файл відповідає за вибірку стильових файлів у проекті, що реалізується через функцію `filterStyleFiles`. Він також забезпечує валідацію якості коду в цих файлах шляхом виконання перевірок, що реалізується функцією `lint`.
16
-
17
- ## Поведінка
18
-
19
- filterStyleFiles відбирає з наданого списку шляхів лише ті, які мають розширення CSS, SCSS або Vue.
20
- lint виконує форматування та перевірку стильових файлів у проекті, застосовуючи автоматичне виправлення, якщо це не режим лише для читання.
21
-
22
- ## Публічний API
23
-
24
- filterStyleFiles — Відбирає файли стилів для подальшої обробки.
25
- lint — Перевіряє стилі у файлах (CSS/SCSS/Vue) окремо для кожного або для всього проєкту.
26
-
27
- ## Гарантії поведінки
28
-
29
- - Read-only: не виконує операцій запису (ФС/БД).