@7n/rules-lang-js 0.5.0 → 0.6.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/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/rules/style/admin_table/admin_table.mdc +88 -0
- package/rules/style/admin_table/concern.json +7 -0
- package/rules/style/admin_table/docs/index.md +9 -0
- package/rules/style/admin_table/docs/main.md +14 -0
- package/rules/style/admin_table/main.mjs +46 -0
- package/rules/style/colors/colors.mdc +21 -0
- package/rules/style/colors/concern.json +3 -0
- package/rules/style/docs/index.md +11 -0
- package/rules/style/gap/concern.json +7 -0
- package/rules/style/gap/docs/index.md +9 -0
- package/rules/style/gap/docs/main.md +15 -0
- package/rules/style/gap/gap.mdc +22 -0
- package/rules/style/gap/main.mjs +51 -0
- package/rules/style/lint/concern.json +7 -0
- package/rules/style/lint/docs/fix-lint.md +29 -0
- package/rules/style/lint/docs/index.md +11 -0
- package/rules/style/lint/docs/main.md +29 -0
- package/rules/style/lint/fix-lint.mjs +66 -0
- package/rules/style/lint/main.mjs +68 -0
- package/rules/style/main.json +1 -0
- package/rules/style/main.mdc +12 -0
- package/rules/style/package_json/concern.json +9 -0
- package/rules/style/package_json/docs/fix-package_json.md +26 -0
- package/rules/style/package_json/docs/index.md +9 -0
- package/rules/style/package_json/fix-package_json.mjs +3 -0
- package/rules/style/package_json/package_json.mdc +18 -0
- package/rules/style/package_json/package_json.rego +31 -0
- package/rules/style/package_json/template/package.json.snippet.json +5 -0
- package/rules/style/quasar/concern.json +3 -0
- package/rules/style/quasar/quasar.mdc +7 -0
- package/rules/style/quasar_fixes/concern.json +7 -0
- package/rules/style/quasar_fixes/docs/index.md +9 -0
- package/rules/style/quasar_fixes/docs/main.md +16 -0
- package/rules/style/quasar_fixes/main.mjs +57 -0
- package/rules/style/quasar_fixes/quasar_fixes.mdc +32 -0
- package/rules/style/tooling/concern.json +14 -0
- package/rules/style/tooling/docs/fix-tooling.md +29 -0
- package/rules/style/tooling/docs/index.md +12 -0
- package/rules/style/tooling/docs/main.md +34 -0
- package/rules/style/tooling/fix-tooling.mjs +58 -0
- package/rules/style/tooling/main.mjs +73 -0
- package/rules/style/tooling/tooling.mdc +85 -0
- package/rules/style/vscode_extensions/concern.json +9 -0
- package/rules/style/vscode_extensions/docs/fix-vscode_extensions.md +24 -0
- package/rules/style/vscode_extensions/docs/index.md +11 -0
- package/rules/style/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/style/vscode_extensions/template/extensions.json.snippet.json +1 -0
- package/rules/style/vscode_extensions/vscode_extensions.mdc +13 -0
- package/rules/style/vscode_extensions/vscode_extensions.rego +13 -0
- package/rules/style/vscode_settings/concern.json +9 -0
- package/rules/style/vscode_settings/docs/fix-vscode_settings.md +26 -0
- package/rules/style/vscode_settings/docs/index.md +9 -0
- package/rules/style/vscode_settings/fix-vscode_settings.mjs +5 -0
- package/rules/style/vscode_settings/template/settings.json.snippet.json +5 -0
- package/rules/style/vscode_settings/vscode_settings.mdc +19 -0
- package/rules/style/vscode_settings/vscode_settings.rego +15 -0
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
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-клас.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: main.mjs
|
|
4
|
+
resource: plugins/lang-js/rules/style/quasar_fixes/main.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: 0f9c4631
|
|
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`.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** @see ./docs/main.md */
|
|
2
|
+
import { readFile } from 'node:fs/promises'
|
|
3
|
+
|
|
4
|
+
import { createViolationReporter } from '@7n/rules/scripts/lib/lint-surface/violation-reporter.mjs'
|
|
5
|
+
import { walkDir } from '@7n/rules/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
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: fix-tooling.mjs
|
|
4
|
+
resource: plugins/lang-js/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).
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/style/tooling
|
|
4
|
+
resource: plugins/lang-js/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 |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: main.mjs
|
|
4
|
+
resource: plugins/lang-js/rules/style/tooling/main.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: c96a4b01
|
|
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`.
|
|
@@ -0,0 +1,58 @@
|
|
|
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
|
+
]
|
|
@@ -0,0 +1,73 @@
|
|
|
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 '@7n/rules/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
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
## Генерація та редагування стилів (Cursor і інші агенти)
|
|
2
|
+
|
|
3
|
+
- **Джерело правил:** перед тим як писати або суттєво змінювати **`.css`**, **`.scss`** або стилі в **`.vue`**, переглянь у корені проєкту (і в релевантних пакетах монорепо, якщо є) поле **`stylelint`** у **`package.json`** (зокрема `extends`), наявні **`.stylelintrc.*`**, **`stylelint.config.*`** та **`.stylelintignore`**. Не покладайся на «типові» правила stylelint з пам'яті — дотримуйся **проєктного** **`@nitra/stylelint-config`** і будь-яких локальних доповнень у репозиторії.
|
|
4
|
+
- **Форматування** узгоджуй з **`n-text.mdc`** (oxfmt / `.oxfmtrc.json` для css, scss тощо), щоб форматер і stylelint не суперечили один одному.
|
|
5
|
+
- **Запуск stylelint:** лише через **`n-rules lint style`** (локально — з auto-fix; у CI — `--no-fix`, нуль мутацій). Під капотом — `npx stylelint`; **не** використовуй **`bunx stylelint`**. Після змін запускай **`n-rules lint style`** і виправляй усе, що лишилось після auto-fix; за потреби — повний прогін `n-rules lint --full`.
|
|
6
|
+
- **Не розширюй винятки:** не додавай зайві **`stylelint-disable`** без потреби; краще підлаштувати стилі під правила проєкту.
|
|
7
|
+
|
|
8
|
+
## Канон налаштувань
|
|
9
|
+
|
|
10
|
+
### `package.json`
|
|
11
|
+
|
|
12
|
+
- `stylelint.extends`: [package.json.snippet.json](./policy/package_json/template/package.json.snippet.json)
|
|
13
|
+
|
|
14
|
+
Окремого `lint-style` скрипта немає — запуск через **`n-rules lint style`** (CI — `--no-fix`).
|
|
15
|
+
|
|
16
|
+
```json title="package.json"
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@nitra/stylelint-config": "^1.4.0"
|
|
19
|
+
},
|
|
20
|
+
"stylelint": {
|
|
21
|
+
"extends": "@nitra/stylelint-config"
|
|
22
|
+
},
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
У корені проєкту має бути **`.stylelintignore`**:
|
|
26
|
+
|
|
27
|
+
```text title=".stylelintignore"
|
|
28
|
+
dist/
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### `.vscode/extensions.json`
|
|
32
|
+
|
|
33
|
+
- Канон `recommendations`: [extensions.json.snippet.json](./policy/vscode_extensions/template/extensions.json.snippet.json)
|
|
34
|
+
|
|
35
|
+
### `.vscode/settings.json`
|
|
36
|
+
|
|
37
|
+
- Вимкнення вбудованої CSS-валідації VS Code: [settings.json.snippet.json](./policy/vscode_settings/template/settings.json.snippet.json)
|
|
38
|
+
|
|
39
|
+
### CI: `.github/workflows/lint-style.yml`
|
|
40
|
+
|
|
41
|
+
- Канон: [lint-style.yml.snippet.yml](./policy/lint_style_yml/template/lint-style.yml.snippet.yml)
|
|
42
|
+
|
|
43
|
+
Додай **`.github/workflows/lint-style.yml`** (лише **`.yml`**, **`ga.mdc`**): після **`checkout`** — локальний composite **`setup-bun-deps`**, далі `n-rules lint style --no-fix` у кроці **`run`**. **Не** дублюй окремі кроки **`setup-node`** / **`oven-sh/setup-bun`** / кеш / **`npm install`**.
|
|
44
|
+
|
|
45
|
+
```yaml title=".github/workflows/lint-style.yml"
|
|
46
|
+
name: StyleLint
|
|
47
|
+
|
|
48
|
+
on:
|
|
49
|
+
push:
|
|
50
|
+
branches:
|
|
51
|
+
- dev
|
|
52
|
+
- main
|
|
53
|
+
paths:
|
|
54
|
+
- '**/*.css'
|
|
55
|
+
- '**/*.scss'
|
|
56
|
+
- '**/*.vue'
|
|
57
|
+
|
|
58
|
+
pull_request:
|
|
59
|
+
branches:
|
|
60
|
+
- dev
|
|
61
|
+
- main
|
|
62
|
+
paths:
|
|
63
|
+
- '**/*.css'
|
|
64
|
+
- '**/*.scss'
|
|
65
|
+
- '**/*.vue'
|
|
66
|
+
|
|
67
|
+
concurrency:
|
|
68
|
+
group: ${{ github.ref }}-${{ github.workflow }}
|
|
69
|
+
cancel-in-progress: true
|
|
70
|
+
|
|
71
|
+
jobs:
|
|
72
|
+
stylelint:
|
|
73
|
+
runs-on: ubuntu-latest
|
|
74
|
+
permissions:
|
|
75
|
+
contents: read
|
|
76
|
+
steps:
|
|
77
|
+
- uses: actions/checkout@v6
|
|
78
|
+
with:
|
|
79
|
+
persist-credentials: false
|
|
80
|
+
|
|
81
|
+
- uses: ./.github/actions/setup-bun-deps
|
|
82
|
+
|
|
83
|
+
- name: StyleLint
|
|
84
|
+
run: npx stylelint '**/*.{css,scss,vue}'
|
|
85
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: fix-vscode_extensions.mjs
|
|
4
|
+
resource: plugins/lang-js/rules/style/vscode_extensions/fix-vscode_extensions.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: b6cffd44
|
|
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
|
+
Файл ініціює процес інтеграції визначених шаблонів у розширення VS Code шляхом запуску зовнішнього скрипта. Цей скрипт забезпечує впровадження архітектурних патернів у ці розширення.
|
|
16
|
+
|
|
17
|
+
## Поведінка
|
|
18
|
+
|
|
19
|
+
1. Ініціює процес застосування визначених шаблонів до розширень VS Code.
|
|
20
|
+
2. Використовує зовнішній скрипт для додавання необхідних патернів до розширень.
|
|
21
|
+
|
|
22
|
+
## Гарантії поведінки
|
|
23
|
+
|
|
24
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/style/vscode_extensions
|
|
4
|
+
resource: plugins/lang-js/rules/style/vscode_extensions/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# npm/rules/style/vscode_extensions
|
|
8
|
+
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------------------- | --------- |
|
|
11
|
+
| [fix-vscode_extensions.mjs](fix-vscode_extensions.md) | JS Module |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { patterns } from '@7n/rules/scripts/lib/fix/vscode-ext-add.mjs'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "recommendations": ["stylelint.vscode-stylelint"] }
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
## .vscode/extensions.json: розширення для stylelint
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `style_lint.vscode_extensions`
|
|
4
|
+
|
|
5
|
+
Цільовий файл: `.vscode/extensions.json`
|
|
6
|
+
|
|
7
|
+
Перевіряє, що масив `recommendations` містить усі записи з канонічного template (subset-check). Додаткові розширення поза списком — дозволені.
|
|
8
|
+
|
|
9
|
+
Канонічний template: [extensions.json.snippet.json](./template/extensions.json.snippet.json)
|
|
10
|
+
|
|
11
|
+
**✓ Правильно** — `recommendations` містить `"stylelint.vscode-stylelint"` (може бути і більше елементів).
|
|
12
|
+
|
|
13
|
+
**✗ Неправильно** — `recommendations` відсутній або не містить `"stylelint.vscode-stylelint"`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Перевірка `.vscode/extensions.json` для style (style.mdc).
|
|
2
|
+
#
|
|
3
|
+
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
+
# Структура --data сформована з template/extensions.json.snippet.json.
|
|
5
|
+
package style.vscode_extensions
|
|
6
|
+
|
|
7
|
+
import rego.v1
|
|
8
|
+
|
|
9
|
+
deny contains msg if {
|
|
10
|
+
some rec in data.template.snippet.recommendations
|
|
11
|
+
not rec in {r | some r in object.get(input, "recommendations", [])}
|
|
12
|
+
msg := sprintf(".vscode/extensions.json: recommendations має містити %q (style.mdc)", [rec])
|
|
13
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: fix-vscode_settings.mjs
|
|
4
|
+
resource: plugins/lang-js/rules/style/vscode_settings/fix-vscode_settings.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: 83090b09
|
|
7
|
+
model: openai-codex/gpt-5.4-mini
|
|
8
|
+
score: 100
|
|
9
|
+
issues: judge:inaccurate:0.98
|
|
10
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Огляд
|
|
14
|
+
|
|
15
|
+
`patterns` описує узгоджені шаблони для `settings.json` і визначає, які значення в ньому мають відповідати очікуваному формату. Це потрібно, щоб конфіг лишався передбачуваним і однаково трактувався в різних місцях, де його використовують.
|
|
16
|
+
|
|
17
|
+
## Поведінка
|
|
18
|
+
|
|
19
|
+
1. `patterns` описує набір правил для приведення `.vscode/settings.json` до узгодженого стану з шаблонним стилем проєкту.
|
|
20
|
+
2. На основі цього набору система знаходить конфігурацію `settings.json` і підтягує її в механізм виправлення, щоб зберігати єдиний формат налаштувань у робочому середовищі.
|
|
21
|
+
3. Результат роботи `patterns` використовується як джерело стандарту для перевірки та вирівнювання вмісту `settings.json` без ручного втручання.
|
|
22
|
+
4. Модуль не змінює файлову систему чи бази даних; він лише надає опис поведінки для подальшого застосування.
|
|
23
|
+
|
|
24
|
+
## Гарантії поведінки
|
|
25
|
+
|
|
26
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/style/vscode_settings
|
|
4
|
+
resource: plugins/lang-js/rules/style/vscode_settings/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
| Файл | Тип |
|
|
8
|
+
| ------------------------------------------------- | --------- |
|
|
9
|
+
| [fix-vscode_settings.mjs](fix-vscode_settings.md) | JS Module |
|