@7n/rules 1.29.3 → 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 (70) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/package.json +1 -1
  3. package/rules/k8s/dremio_logging/dremio_logging.mdc +1 -0
  4. package/scripts/docs/index.md +15 -14
  5. package/scripts/docs/tool-pins-refresh.md +28 -0
  6. package/scripts/docs/upgrade-n-rules-and-install.md +2 -1
  7. package/scripts/lib/docs/ensure-tool.md +69 -25
  8. package/scripts/lib/ensure-tool.mjs +150 -12
  9. package/scripts/lib/lint-surface/detect.mjs +22 -0
  10. package/scripts/lib/lint-surface/docs/detect.md +4 -4
  11. package/scripts/lib/tool-pins.json +15 -0
  12. package/scripts/tool-pins-refresh.mjs +54 -0
  13. package/scripts/upgrade-n-rules-and-install.mjs +86 -19
  14. package/skills/taze/js/docs/orchestrate.md +1 -1
  15. package/rules/style/admin_table/admin_table.mdc +0 -88
  16. package/rules/style/admin_table/concern.json +0 -7
  17. package/rules/style/admin_table/docs/index.md +0 -9
  18. package/rules/style/admin_table/docs/main.md +0 -14
  19. package/rules/style/admin_table/main.mjs +0 -46
  20. package/rules/style/colors/colors.mdc +0 -21
  21. package/rules/style/colors/concern.json +0 -3
  22. package/rules/style/docs/index.md +0 -11
  23. package/rules/style/gap/concern.json +0 -7
  24. package/rules/style/gap/docs/index.md +0 -9
  25. package/rules/style/gap/docs/main.md +0 -15
  26. package/rules/style/gap/gap.mdc +0 -22
  27. package/rules/style/gap/main.mjs +0 -51
  28. package/rules/style/lint/concern.json +0 -7
  29. package/rules/style/lint/docs/fix-lint.md +0 -29
  30. package/rules/style/lint/docs/index.md +0 -11
  31. package/rules/style/lint/docs/main.md +0 -29
  32. package/rules/style/lint/fix-lint.mjs +0 -66
  33. package/rules/style/lint/main.mjs +0 -68
  34. package/rules/style/main.json +0 -1
  35. package/rules/style/main.mdc +0 -12
  36. package/rules/style/package_json/concern.json +0 -9
  37. package/rules/style/package_json/docs/fix-package_json.md +0 -27
  38. package/rules/style/package_json/docs/index.md +0 -9
  39. package/rules/style/package_json/fix-package_json.mjs +0 -3
  40. package/rules/style/package_json/package_json.mdc +0 -18
  41. package/rules/style/package_json/package_json.rego +0 -31
  42. package/rules/style/package_json/template/package.json.snippet.json +0 -5
  43. package/rules/style/quasar/concern.json +0 -3
  44. package/rules/style/quasar/quasar.mdc +0 -7
  45. package/rules/style/quasar_fixes/concern.json +0 -7
  46. package/rules/style/quasar_fixes/docs/index.md +0 -9
  47. package/rules/style/quasar_fixes/docs/main.md +0 -16
  48. package/rules/style/quasar_fixes/main.mjs +0 -57
  49. package/rules/style/quasar_fixes/quasar_fixes.mdc +0 -32
  50. package/rules/style/tooling/concern.json +0 -14
  51. package/rules/style/tooling/docs/fix-tooling.md +0 -29
  52. package/rules/style/tooling/docs/index.md +0 -12
  53. package/rules/style/tooling/docs/main.md +0 -34
  54. package/rules/style/tooling/fix-tooling.mjs +0 -58
  55. package/rules/style/tooling/main.mjs +0 -73
  56. package/rules/style/tooling/tooling.mdc +0 -85
  57. package/rules/style/vscode_extensions/concern.json +0 -9
  58. package/rules/style/vscode_extensions/docs/fix-vscode_extensions.md +0 -25
  59. package/rules/style/vscode_extensions/docs/index.md +0 -11
  60. package/rules/style/vscode_extensions/fix-vscode_extensions.mjs +0 -1
  61. package/rules/style/vscode_extensions/template/extensions.json.snippet.json +0 -1
  62. package/rules/style/vscode_extensions/vscode_extensions.mdc +0 -13
  63. package/rules/style/vscode_extensions/vscode_extensions.rego +0 -13
  64. package/rules/style/vscode_settings/concern.json +0 -9
  65. package/rules/style/vscode_settings/docs/fix-vscode_settings.md +0 -27
  66. package/rules/style/vscode_settings/docs/index.md +0 -9
  67. package/rules/style/vscode_settings/fix-vscode_settings.mjs +0 -5
  68. package/rules/style/vscode_settings/template/settings.json.snippet.json +0 -5
  69. package/rules/style/vscode_settings/vscode_settings.mdc +0 -19
  70. package/rules/style/vscode_settings/vscode_settings.rego +0 -15
@@ -1,66 +0,0 @@
1
- /** @see ./docs/fix-lint.md */
2
-
3
- /**
4
- * T0-autofix для `style/lint` — детермінований прогін `stylelint --fix` по css/scss/vue.
5
- * Детектор емітить агрегований `stylelint-violation` без переліку файлів, тож фіксер
6
- * самостійно перелічує цільові файли (ctx.files у дельті або tracked css/scss/vue у повному
7
- * режимі), форматує їх і повертає лише фактично змінені. Запис permanent. Відсутній
8
- * stylelint → no-op.
9
- */
10
- import { readFileSync } from 'node:fs'
11
- import { resolve } from 'node:path'
12
-
13
- import { filterStyleFiles, resolveStylelint } from './main.mjs'
14
- import { spawnAsync } from '../../../scripts/utils/spawn-async.mjs'
15
-
16
- /**
17
- * Вміст файлу або null, якщо не читається.
18
- * @param {string} abs абсолютний шлях
19
- * @returns {string|null} вміст або null
20
- */
21
- function readOrNull(abs) {
22
- try {
23
- return readFileSync(abs, 'utf8')
24
- } catch {
25
- return null
26
- }
27
- }
28
-
29
- /**
30
- * Перелік цільових style-файлів: у дельті — з ctx.files; у повному режимі — tracked
31
- * css/scss/vue через `git ls-files`.
32
- * @param {string} cwd корінь
33
- * @param {string[]|undefined} ctxFiles файли з контексту (дельта) або undefined (повний режим)
34
- * @returns {Promise<string[]>} posix-relative шляхи
35
- */
36
- async function listStyleFiles(cwd, ctxFiles) {
37
- if (ctxFiles !== undefined) return filterStyleFiles(ctxFiles)
38
- const r = await spawnAsync('git', ['ls-files', '-z', '--', '*.css', '*.scss', '*.vue'], { cwd })
39
- if (r.exitCode !== 0) return []
40
- return (r.stdout ?? '').split('\0').filter(Boolean)
41
- }
42
-
43
- /** @type {import('../../../scripts/lib/lint-surface/types.mjs').T0Pattern[]} */
44
- export const patterns = [
45
- {
46
- id: 'style-stylelint-fix',
47
- standalone: true, // §8 Phase 2: apply бере ctx.files (не violations), stylelint --fix сам ре-аналізує
48
- test: violations => violations.some(v => v.reason === 'stylelint-violation'),
49
- apply: async (violations, ctx) => {
50
- const stylelint = resolveStylelint(ctx.cwd)
51
- if (!stylelint) return { touchedFiles: [] }
52
- const files = await listStyleFiles(ctx.cwd, ctx.files)
53
- if (files.length === 0) return { touchedFiles: [] }
54
-
55
- const abs = files.map(f => resolve(ctx.cwd, f))
56
- const before = new Map(abs.map(a => [a, readOrNull(a)]))
57
- await spawnAsync(stylelint, ['--fix', ...files], { cwd: ctx.cwd })
58
-
59
- const touchedFiles = abs.filter(a => readOrNull(a) !== before.get(a))
60
- for (const a of touchedFiles) ctx.recordWrite?.(a)
61
- return touchedFiles.length > 0
62
- ? { touchedFiles, message: `stylelint --fix: ${touchedFiles.length} файл(ів)` }
63
- : { touchedFiles: [] }
64
- }
65
- }
66
- ]
@@ -1,68 +0,0 @@
1
- /**
2
- * lint-поверхня style: read-only detector (stylelint без --fix) для css/scss/vue.
3
- * Per-file (ctx.files) або весь проєкт (ctx.files === undefined). Якщо stylelint
4
- * недоступний — крок пропускається (без npx-автовстановлення).
5
- */
6
- import { existsSync } from 'node:fs'
7
- import { join } from 'node:path'
8
-
9
- import { createViolationReporter } from '../../../scripts/lib/lint-surface/violation-reporter.mjs'
10
- import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
11
- import { spawnAsync } from '../../../scripts/utils/spawn-async.mjs'
12
-
13
- const STYLE_EXT_RE = /\.(?:css|scss|vue)$/u
14
-
15
- /**
16
- * @param {string[]} files список шляхів
17
- * @returns {string[]} лише css/scss/vue
18
- */
19
- export function filterStyleFiles(files) {
20
- return files.filter(f => STYLE_EXT_RE.test(f))
21
- }
22
-
23
- /**
24
- * Резолвить бінарник stylelint: спершу локальний node_modules/.bin, потім PATH.
25
- * @param {string} cwd корінь
26
- * @returns {string | null} абсолютний шлях або null
27
- */
28
- export function resolveStylelint(cwd) {
29
- const local = join(cwd, 'node_modules', '.bin', 'stylelint')
30
- if (existsSync(local)) return local
31
- return resolveCmd('stylelint')
32
- }
33
-
34
- /**
35
- * Detector style/lint (read-only).
36
- * @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd, files)
37
- * @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
38
- */
39
- export async function lint(ctx) {
40
- const reporter = createViolationReporter(ctx)
41
- const { fail } = reporter
42
- const cwd = ctx.cwd
43
- const files = ctx.files
44
-
45
- /** @type {string[]} */
46
- const targets = []
47
- if (files === undefined) {
48
- targets.push('**/*.{css,scss,vue}')
49
- } else {
50
- const style = filterStyleFiles(files)
51
- if (style.length === 0) return reporter.result()
52
- targets.push(...style)
53
- }
54
-
55
- const stylelint = resolveStylelint(cwd)
56
- if (!stylelint) {
57
- // stylelint недоступний → крок пропущено (без автовстановлення)
58
- return reporter.result()
59
- }
60
-
61
- const r = await spawnAsync(stylelint, targets, { cwd, shell: false })
62
- if (r.exitCode !== 0) {
63
- const out = `${r.stdout ?? ''}${r.stderr ?? ''}`.trim().slice(0, 2000)
64
- const outSuffix = out ? `\n${out}` : ''
65
- fail(`lint-style: stylelint — порушення (код ${r.exitCode ?? 1}, style.mdc)${outSuffix}`, 'stylelint-violation')
66
- }
67
- return reporter.result()
68
- }
@@ -1 +0,0 @@
1
- { "auto": { "glob": ["**/*.css", "**/*.vue"] } }
@@ -1,12 +0,0 @@
1
- ---
2
- description: Правила стилів CSS та SCSS
3
- version: '1.5'
4
- globs: "**/*.{css,scss,vue}"
5
- alwaysApply: false
6
- ---
7
-
8
- Правило **style** для Vue-проєктів: Quasar як стильова система, SCSS-конвенції кольорів і відступів, фікси компонентів, stylelint через `@nitra/stylelint-config`.
9
-
10
- - [settings.json.snippet.json](./vscode_settings/template/settings.json.snippet.json)
11
- - [extensions.json.snippet.json](./vscode_extensions/template/extensions.json.snippet.json)
12
- - [package.json.snippet.json](./package_json/template/package.json.snippet.json)
@@ -1,9 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "fixability": "config",
4
- "policy": {
5
- "files": {
6
- "single": "package.json"
7
- }
8
- }
9
- }
@@ -1,27 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: fix-package_json.mjs
4
- resource: npm/rules/style/package_json/fix-package_json.mjs
5
- docgen:
6
- crc: deb26703
7
- model: openai-codex/gpt-5.5
8
- tier: cloud-avg
9
- score: 100
10
- judgeModel: openai-codex/gpt-5.4-mini
11
- ---
12
-
13
- ## Огляд
14
-
15
- Надає `patterns` для визначення очікуваних перевірок, що спираються на `package.json`. Використовується як read-only опис вимог до конфігурації пакета, без самостійних змін файлової системи.
16
-
17
- ## Поведінка
18
-
19
- 1. `patterns` визначає правило виправлення для `package.json`.
20
-
21
- 2. `patterns` забезпечує приведення `package.json` до проєктного шаблону стилю.
22
-
23
- 3. `patterns` не змінює файлову систему самостійно, а лише описує доступний сценарій автоматичного виправлення для зовнішнього механізму перевірок.
24
-
25
- ## Гарантії поведінки
26
-
27
- - Read-only: не виконує операцій запису (ФС/БД).
@@ -1,9 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/style/package_json
4
- resource: npm/rules/style/package_json/
5
- ---
6
-
7
- | Файл | Тип |
8
- | ------------------------------------------- | --------- |
9
- | [fix-package_json.mjs](fix-package_json.md) | JS Module |
@@ -1,3 +0,0 @@
1
- import { createTemplateFixPattern } from '../../../scripts/lib/fix/template-deep-merge.mjs'
2
-
3
- export const patterns = [createTemplateFixPattern({ id: 'style-package_json-template', targetPath: 'package.json' })]
@@ -1,18 +0,0 @@
1
- ## package.json: stylelint-конфіг та devDependencies
2
-
3
- Rego-пакет: `style_lint.package_json`
4
-
5
- Цільовий файл: `package.json`
6
-
7
- Дві незалежні перевірки:
8
-
9
- 1. **snippet-walker** — якщо поле `stylelint` присутнє у `package.json`, перевіряє `stylelint.extends == "@nitra/stylelint-config"` (2-рівневий обхід через template).
10
- 2. **presence-check** — `@nitra/stylelint-config` має бути у `devDependencies` (ця перевірка завжди активна, не залежить від template).
11
-
12
- FS-альтернативи (`.stylelintrc.*` файли) та `.stylelintignore` перевіряються у JS, не в Rego.
13
-
14
- Канонічний template: [package.json.snippet.json](./template/package.json.snippet.json)
15
-
16
- **✓ Правильно** — `devDependencies` містить `@nitra/stylelint-config`; якщо є поле `stylelint` — `extends` дорівнює `"@nitra/stylelint-config"`.
17
-
18
- **✗ Неправильно** — відсутній `@nitra/stylelint-config` у `devDependencies`; або поле `stylelint.extends` має інше значення.
@@ -1,31 +0,0 @@
1
- # Порт перевірок `package.json` (style.mdc).
2
- #
3
- # Канон надходить через --data: { "template": { "contains": ..., "snippet": ... } }
4
- # Структура --data сформована з template/package.json.{contains,snippet}.json.
5
- # FS-альтернативи (`.stylelintrc.*` файли) + `.stylelintignore` — у JS.
6
- #
7
- # Логіка, що ЛИШАЄТЬСЯ у rego (inverse — не виноситься у template):
8
- # - `@nitra/stylelint-config` має бути у devDependencies (presence-check).
9
- package style.package_json
10
-
11
- import rego.v1
12
-
13
- # ── deny: 2-level snippet walker (для stylelint.extends, якщо поле є) ────
14
-
15
- deny contains msg if {
16
- some section, expected_inner in data.template.snippet
17
- cfg := object.get(input, section, null)
18
- is_object(cfg)
19
- some leaf_key, expected_value in expected_inner
20
- actual := object.get(cfg, leaf_key, null)
21
- actual != expected_value
22
- msg := sprintf("package.json: %s.%s має бути %q (style.mdc)", [section, leaf_key, expected_value])
23
- }
24
-
25
- # ── deny: @nitra/stylelint-config у devDependencies (inverse) ────────────
26
-
27
- deny contains msg if {
28
- dev := object.get(input, "devDependencies", {})
29
- not "@nitra/stylelint-config" in object.keys(dev)
30
- msg := "@nitra/stylelint-config відсутній — bun add -d @nitra/stylelint-config (style.mdc)"
31
- }
@@ -1,5 +0,0 @@
1
- {
2
- "stylelint": {
3
- "extends": "@nitra/stylelint-config"
4
- }
5
- }
@@ -1,3 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json"
3
- }
@@ -1,7 +0,0 @@
1
- ## Quasar як стильова основа
2
-
3
- У Vue-проектах використовуй **Quasar** як базову стильову систему:
4
-
5
- - **Класи компонентів:** `q-pa-*`, `q-ma-*`, `q-mt-*`, `q-mb-*`, `row`, `col`, `col-*`, `items-center`, `justify-between`, `text-*`, `bg-*`, `shadow-*` тощо — стандартні утиліти Quasar.
6
- - **Кольори:** використовуй Quasar CSS-змінні через класи (`text-primary`, `bg-accent`, `text-negative` тощо) або через SCSS-змінні (`$primary`, `$accent`) у `.scss`-файлах.
7
- - **Не пиши власні утиліти**, якщо є відповідний Quasar-клас.
@@ -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/quasar_fixes
4
- resource: npm/rules/style/quasar_fixes/
5
- ---
6
-
7
- | Файл | Тип |
8
- | ------------------- | --------- |
9
- | [main.mjs](main.md) | JS Module |
@@ -1,16 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/style/quasar_fixes/main.mjs
5
- docgen:
6
- crc: 3eecca4c
7
- ---
8
-
9
- ## Огляд
10
-
11
- Детектор concern-а `quasar_fixes` (read-only, whole-repo): якщо `.vue`-файл використовує
12
- `<q-scroll-area>` або `<q-tooltip>`, десь у `.scss`/`.css`/`.vue` проєкту має бути
13
- відповідний CSS-фікс (`.q-scrollarea` / `.q-tooltip`) — інакше порушення
14
- `missing-quasar-fix`. iOS-zoom-фікс (тригер на `input`/`textarea`/`select`) навмисно не
15
- перевіряється — надто загальний тригер, false-positive на майже будь-якій формі. Whole-repo
16
- сканування, не залежить від `ctx.files`.
@@ -1,57 +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
-
9
- /**
10
- * Пари (usage у `.vue` → очікуваний CSS-фікс) з guide `quasar_fixes.mdc`. Навмисно НЕ
11
- * включено iOS-zoom-фікс (тригер `input`/`textarea`/`select` — занадто загальний,
12
- * false-positive на майже будь-якій формі; консервативно залишено лише narrative).
13
- */
14
- const FIXES = [
15
- { usage: /<q-scroll-area\b/u, definition: /\.q-scrollarea\b/u, name: 'q-scroll-area', selector: '.q-scrollarea' },
16
- { usage: /<q-tooltip\b/u, definition: /\.q-tooltip\b/u, name: 'q-tooltip', selector: '.q-tooltip' }
17
- ]
18
-
19
- /**
20
- * Detector style/quasar_fixes (read-only, whole-repo): якщо `.vue` використовує
21
- * `<q-scroll-area>` або `<q-tooltip>`, у `.scss`/`.css`/`.vue` має бути відповідний
22
- * CSS-фікс (guide: `quasar_fixes.mdc`). Крос-файлова перевірка usage↔definition —
23
- * потребує whole-repo сканування незалежно від `ctx.files`.
24
- * @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd)
25
- * @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
26
- */
27
- export async function lint(ctx) {
28
- const reporter = createViolationReporter(ctx)
29
- const { fail } = reporter
30
- const cwd = ctx.cwd
31
-
32
- /** @type {string[]} */
33
- const files = []
34
- await walkDir(cwd, f => {
35
- if (RELEVANT_RE.test(f)) files.push(f)
36
- })
37
-
38
- const used = new Set()
39
- const defined = new Set()
40
- for (const file of files) {
41
- const content = await readFile(file, 'utf8')
42
- for (const fix of FIXES) {
43
- if (file.endsWith('.vue') && !used.has(fix.name) && fix.usage.test(content)) used.add(fix.name)
44
- if (!defined.has(fix.name) && fix.definition.test(content)) defined.add(fix.name)
45
- }
46
- }
47
-
48
- for (const fix of FIXES) {
49
- if (used.has(fix.name) && !defined.has(fix.name)) {
50
- fail(
51
- `Компонент \`${fix.name}\` використовується у \`.vue\`, але фікс \`${fix.selector}\` відсутній у \`.scss\`/\`.css\` (guide: style/quasar_fixes.mdc) — додай фікс до app.scss`,
52
- 'missing-quasar-fix'
53
- )
54
- }
55
- }
56
- return reporter.result()
57
- }
@@ -1,32 +0,0 @@
1
- ## Фікси компонентів Quasar
2
-
3
- При використанні компонента `q-scroll-area` або `q-tooltip` додай до `app.scss` відповідні фікси. Аналогічно — фікс масштабування на iOS.
4
-
5
- ```scss
6
- // FIX стилі для прокручуваної області по висоті екрана
7
- .q-scrollarea {
8
- display: flex;
9
- flex-direction: column;
10
- height: auto;
11
- min-height: 0;
12
- max-height: 100%;
13
-
14
- .scroll {
15
- flex: 10000 1 0%;
16
- }
17
- }
18
-
19
- // FIX tooltip
20
- .q-tooltip {
21
- font-size: 1em;
22
- }
23
-
24
- // FIX не зумувати на iOS
25
- @media (width <= 600px) {
26
- input,
27
- textarea,
28
- select {
29
- font-size: 16px;
30
- }
31
- }
32
- ```
@@ -1,14 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "fixability": "config",
4
- "lint": {
5
- "scope": "full",
6
- "glob": [
7
- "package.json",
8
- ".stylelintrc.{json,js,cjs,mjs}",
9
- "stylelint.config.{js,cjs,mjs}",
10
- ".stylelintignore",
11
- ".github/workflows/lint-style.yml"
12
- ]
13
- }
14
- }
@@ -1,29 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: fix-tooling.mjs
4
- resource: npm/rules/style/tooling/fix-tooling.mjs
5
- docgen:
6
- crc: a25e47d2
7
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
- score: 100
9
- issues: judge:inaccurate:0.98
10
- judgeModel: openai-codex/gpt-5.4-mini
11
- ---
12
-
13
- ## Огляд
14
-
15
- Виконую завдання як технічний письменник.
16
-
17
- Файл забезпечує детерміновані виправлення файлової системи для автоматичного налаштування інструменту Stylelint. Публічна функція `patterns` виконує перехоплення помилок (fail-safe), не генеруючи винятків. Код спирається на конфігурацію `package.json` і гарантує, що директорія `dist/` виключена з перевірки Stylelint через створення або доповнення `.stylelintignore`, а також додає необхідну конфігурацію Stylelint до `package.json`.
18
-
19
- ## Поведінка
20
-
21
- Поведінка:
22
-
23
- 1. Перевіряється наявність файлу `.stylelintignore`. Якщо він відсутній, створюється з вмістом `dist/`.
24
- 2. Якщо файл `.stylelintignore` існує, перевіряється, чи містить він рядок `dist/`. Якщо ні, до файлу додається рядок `dist/`.
25
- 3. Перевіряється, чи міститься конфігурація `stylelint` у файлі `package.json`. Якщо конфігурація відсутня, вона додається до `package.json` з посиланням на `@nitra/stylelint-config`.
26
-
27
- ## Гарантії поведінки
28
-
29
- - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
@@ -1,12 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/style/tooling
4
- resource: npm/rules/style/tooling/
5
- ---
6
-
7
- # npm/rules/style/tooling
8
-
9
- | Файл | Тип |
10
- | --------------------------------- | --------- |
11
- | [fix-tooling.mjs](fix-tooling.md) | JS Module |
12
- | [main.mjs](main.md) | JS Module |
@@ -1,34 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/style/tooling/main.mjs
5
- docgen:
6
- crc: 015d1c9a
7
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
- score: 90
9
- issues: anchor-miss:extensions.json,anchor-miss:settings.json,judge:inaccurate:0.99
10
- judgeModel: openai-codex/gpt-5.4-mini
11
- ---
12
-
13
- ## Огляд
14
-
15
- Please provide the code file you want me to document. I will then generate the "Огляд" section based on the provided "Поведінка" and the file's content, adhering to all specified rules.
16
-
17
- ## Поведінка
18
-
19
- Поведінка:
20
-
21
- 1. main: Перевіряє наявність конфігурації stylelint. Конфігурація може бути визначена у пакеті `package.json` або у зовнішніх файлах конфігурації, зокрема `.stylelintrc.json`, `.stylelintrc.js`, `.stylelintrc.cjs`, `.stylelintrc.mjs`, `stylelint.config.js`, `stylelint.config.cjs`, `stylelint.config.mjs`. Якщо жоден із цих варіантів відсутній, видається помилка, і пропонується додати конфігурацію до `package.json` з посиланням на `@nitra/stylelint-config` (згадка (js.mdc)).
22
- 2. main: Перевіряє існування файлу `.stylelintignore`. Якщо він не існує, видається помилка, і пропонується створити його з вмістом `dist/`.
23
- 3. main: Якщо `.stylelintignore` існує, він перевіряє, чи містить він рядок `dist/`. Якщо цього рядка немає, видається помилка з проханням додати його (згадка (style.mdc)).
24
- 4. main: Перевіряє існування файлу `.github/workflows/lint-style.yml`. Якщо він відсутній, видається помилка з проханням його створити.
25
- 5. Робота ігнорує шляхи в каталозі `.github` та `.git` під час перевірки.
26
-
27
- ## Публічний API
28
-
29
- main — забезпечує дотримання стандартів стилізації проєкту відповідно до правил style.mdc
30
-
31
- ## Гарантії поведінки
32
-
33
- - Read-only: не виконує операцій запису (ФС/БД).
34
- - Свідомо пропускає шляхи: `.github`, `.git`.
@@ -1,58 +0,0 @@
1
- /**
2
- * T0-autofix паттерни для `style/tooling` — детерміновані FS-виправлення:
3
- * створення або доповнення `.stylelintignore` та додавання `stylelint` до `package.json`.
4
- *
5
- * Unified lint surface: structured violations (test(violations)/apply(violations,ctx)).
6
- * Тип порушення визначається за `v.message`, не за агрегованим output-рядком.
7
- */
8
- import { appendFileSync, existsSync, readFileSync, writeFileSync } from 'node:fs'
9
- import { join } from 'node:path'
10
-
11
- const STYLELINTIGNORE_MISSING_RE = /\.stylelintignore не існує/u
12
- const STYLELINTIGNORE_NO_DIST_RE = /\.stylelintignore не містить рядка dist\//u
13
- const NO_STYLELINT_CONFIG_RE = /Немає конфігу stylelint/u
14
-
15
- /** @type {import('../../../scripts/lib/lint-surface/types.mjs').T0Pattern[]} */
16
- export const patterns = [
17
- {
18
- id: 'style-stylelintignore-create',
19
- test: violations => violations.some(v => STYLELINTIGNORE_MISSING_RE.test(v.message)),
20
- apply: (_violations, ctx) => {
21
- const target = join(ctx.cwd, '.stylelintignore')
22
- ctx.recordWrite?.(target)
23
- writeFileSync(target, 'dist/\n', 'utf8')
24
- return { touchedFiles: [target], message: 'створено .stylelintignore' }
25
- }
26
- },
27
-
28
- {
29
- id: 'style-stylelintignore-dist-add',
30
- test: violations => violations.some(v => STYLELINTIGNORE_NO_DIST_RE.test(v.message)),
31
- apply: (_violations, ctx) => {
32
- const target = join(ctx.cwd, '.stylelintignore')
33
- ctx.recordWrite?.(target)
34
- appendFileSync(target, '\ndist/\n', 'utf8')
35
- return { touchedFiles: [target], message: 'додано dist/ до .stylelintignore' }
36
- }
37
- },
38
-
39
- {
40
- id: 'style-pkg-stylelint-add',
41
- test: violations => violations.some(v => NO_STYLELINT_CONFIG_RE.test(v.message)),
42
- apply: (_violations, ctx) => {
43
- const pkgPath = join(ctx.cwd, 'package.json')
44
- if (!existsSync(pkgPath)) return { touchedFiles: [] }
45
- let pkg
46
- try {
47
- pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
48
- } catch {
49
- return { touchedFiles: [] }
50
- }
51
- if (pkg.stylelint) return { touchedFiles: [] }
52
- ctx.recordWrite?.(pkgPath)
53
- pkg.stylelint = { extends: '@nitra/stylelint-config' }
54
- writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8')
55
- return { touchedFiles: [pkgPath], message: 'додано stylelint до package.json' }
56
- }
57
- }
58
- ]
@@ -1,73 +0,0 @@
1
- /** @see ./docs/tooling.md */
2
- import { existsSync } from 'node:fs'
3
- import { readFile } from 'node:fs/promises'
4
- import { join } from 'node:path'
5
-
6
- import { createViolationReporter } from '../../../scripts/lib/lint-surface/violation-reporter.mjs'
7
-
8
- // Зовнішні файли конфігу stylelint, які підхоплює cosmiconfig. Канон нових
9
- // JS-конфігів — `.mjs`/`.cjs` (js.mdc), legacy `.js` лишається валідним.
10
- const STYLELINT_CONFIG_FILES = [
11
- '.stylelintrc.json',
12
- '.stylelintrc.js',
13
- '.stylelintrc.cjs',
14
- '.stylelintrc.mjs',
15
- 'stylelint.config.js',
16
- 'stylelint.config.cjs',
17
- 'stylelint.config.mjs'
18
- ]
19
-
20
- /**
21
- * Альтернатива полю `stylelint` у `package.json` — зовнішній файл конфігу. Якщо
22
- * поля немає і файлу немає, фейлимося; якщо є хоч щось — пропускаємо. Поле
23
- * `stylelint.extends == "@nitra/stylelint-config"` сам формат — у Rego.
24
- * @param {ReturnType<typeof createViolationReporter>} reporter репортер
25
- * @param {string} cwd корінь репозиторію
26
- */
27
- async function checkStylelintConfigPresence(reporter, cwd) {
28
- const { pass, fail } = reporter
29
- const pkgPath = join(cwd, 'package.json')
30
- if (!existsSync(pkgPath)) return
31
- const pkg = JSON.parse(await readFile(pkgPath, 'utf8'))
32
- const hasField = pkg.stylelint && typeof pkg.stylelint === 'object'
33
- const hasExternalCfg = STYLELINT_CONFIG_FILES.some(name => existsSync(join(cwd, name)))
34
- if (hasField || hasExternalCfg) {
35
- pass('Конфіг stylelint є — у package.json або окремим файлом')
36
- } else {
37
- fail('Немає конфігу stylelint — додай "stylelint": { "extends": "@nitra/stylelint-config" } до package.json')
38
- }
39
- }
40
-
41
- // `.vscode/extensions.json` (`stylelint.vscode-stylelint`) і `.vscode/settings.json`
42
- // (`css.validate`/`scss.validate`/`less.validate: false`) — у rego-пакетах
43
- // `style_lint.vscode_extensions` і `style_lint.vscode_settings`, прогоняє
44
- // `npx @7n/rules fix`. JS-копії видалено, щоб не було двох джерел істини.
45
-
46
- /**
47
- * Перевіряє відповідність проєкту правилам style.mdc
48
- * @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd тощо)
49
- * @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
50
- */
51
- export async function lint(ctx) {
52
- const cwd = ctx.cwd
53
- const reporter = createViolationReporter(ctx)
54
- const { pass, fail } = reporter
55
-
56
- await checkStylelintConfigPresence(reporter, cwd)
57
-
58
- const ignorePath = join(cwd, '.stylelintignore')
59
- if (existsSync(ignorePath)) {
60
- const ignoreContent = await readFile(ignorePath, 'utf8')
61
- if (ignoreContent.split('\n').some(line => line.trim() === 'dist/')) {
62
- pass('.stylelintignore існує і містить dist/')
63
- } else {
64
- fail('.stylelintignore не містить рядка dist/ — додай його (style.mdc)')
65
- }
66
- } else {
67
- fail('.stylelintignore не існує — створи з вмістом: dist/')
68
- }
69
-
70
- // Existence/структуру lint-style.yml вимагає провайдер-плагін @7n/rules-ci-github
71
- // (mixin style/lint_style_yml) — ядро провайдер-агностичне.
72
- return reporter.result()
73
- }