@nitra/cursor 1.13.43 → 1.13.45
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 +15 -1
- package/package.json +1 -1
- package/rules/abie/abie.mdc +10 -1
- package/rules/abie/policy/package_json_docs/package_json_docs.rego +16 -0
- package/rules/abie/policy/package_json_docs/target.json +5 -0
- package/rules/efes/efes.mdc +18 -2
- package/rules/efes/policy/package_json_docs/package_json_docs.rego +16 -0
- package/rules/efes/policy/package_json_docs/target.json +5 -0
- package/rules/ga/lint/lint.mjs +1 -4
- package/rules/image-avif/fix/avif_generation/check.mjs +58 -22
- package/rules/image-avif/image-avif.mdc +6 -5
- package/rules/text/lint/lint.mjs +4 -7
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@
|
|
|
4
4
|
|
|
5
5
|
Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
|
|
6
6
|
|
|
7
|
+
## [1.13.45] - 2026-05-19
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- `inlineTemplateLinks` tests: оновлено очікувані рядки для фікстури `__fixtures__/inline-template/fix/foo/template/snippet.json` (перейшла на форматований варіант `{ "key": "val" }` ще в 1.13.38) та для інтеграційного тесту `security.mdc` (snippet `package.json` тепер multi-line після lint-проходу). Без зміни рантайм-логіки.
|
|
12
|
+
- `check-ga` тестова фікстура `setupCanonicalGaProject`: додано крок `Install conftest` у `.github/workflows/lint-ga.yml`, без якого `ga.lint_ga` rego-полісі забороняє workflow і `check()` повертав 1.
|
|
13
|
+
|
|
14
|
+
## [1.13.44] - 2026-05-18
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- `abie` rule: новий policy-концерн `abie.package_json_docs` — у кореневому `package.json` `devDependencies` має містити `@nitra/abie-docs` (presence-only, версію не фіксуємо). Реалізація: `npm/rules/abie/policy/package_json_docs/` (target.json + .rego + _test.rego). Bump `abie.mdc` `1.20` → `1.21`.
|
|
19
|
+
- `efes` rule: перший policy-концерн `efes.package_json_docs` — у кореневому `package.json` `devDependencies` має містити `@nitra/efes-docs` (узгоджено з `graphql.mdc`, де схема береться з `node_modules/@nitra/efes-docs/schema/maya.graphql`). Реалізація: `npm/rules/efes/policy/package_json_docs/`. Bump `efes.mdc` `1.0` → `1.1`.
|
|
20
|
+
|
|
7
21
|
## [1.13.43] - 2026-05-18
|
|
8
22
|
|
|
9
23
|
### Removed
|
|
@@ -14,7 +28,7 @@
|
|
|
14
28
|
|
|
15
29
|
### Added
|
|
16
30
|
|
|
17
|
-
- `efes` rule: новий (поки що порожній) пакет правил для проєктів **github.com/efes-cloud
|
|
31
|
+
- `efes` rule: новий (поки що порожній) пакет правил для проєктів **github.com/efes-cloud/\***. Автодетект у `auto-rules.mjs` через `EFES_REPOSITORY_URL_MARKER` (`https://github.com/efes-cloud/`) — аналогічно до `abie`. Додано `npm/rules/efes/efes.mdc` + `auto.md`, прописано порядок в `AUTO_RULE_ORDER` і покрито тестами в `auto-rules.test.mjs`.
|
|
18
32
|
- `efes-create-env` skill: повʼязано з правилом `efes` через `skills/efes-create-env/auto.md` (`[efes]`) — активується автоматично, коли репозиторій відповідає efes-маркеру. Тести в `auto-skills.test.mjs` фіксують позитивний і негативний випадки.
|
|
19
33
|
|
|
20
34
|
## [1.13.41] - 2026-05-18
|
package/package.json
CHANGED
package/rules/abie/abie.mdc
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Правила для проєктів AbInBev Efes
|
|
3
3
|
alwaysApply: true
|
|
4
|
-
version: '1.
|
|
4
|
+
version: '1.21'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
Правило **abie** для споживачів **@nitra/cursor**: **k8s** (Deployment + **HealthCheckPolicy** у **`hc.yaml`**, overlay **ua** — **nodeSelector**, **HTTPRoute** (будь-який непорожній **`target.name`**, для спільних сервісів **`auth-run-hl`** / **`file-link-hl`** — **`namespace: dev`** у base та patch **`…/backendRefs/…/namespace`** у **ua**)), гілки **dev**, **ua** у **clean-merged-branch**, а також заборона тримати артефакти **Firebase Hosting** у **підкаталогах першого рівня** (безпосередні діти кореня репозиторію; у самому корені ці імена не вимагаються до видалення).
|
|
@@ -140,6 +140,14 @@ KVCMS_URL=http://kvcms-hl.ua-apruv.svc.abie-ua.internal:8080
|
|
|
140
140
|
|
|
141
141
|
Загальне правило про **внутрішній** URL (не публічний домен) для `HASURA_GRAPHQL_ENDPOINT` лишається у **`hasura.mdc`** (для nitra і abie) — `check-hasura.mjs` приймає кластерний DNS-формат `<cluster>.internal`.
|
|
142
142
|
|
|
143
|
+
## `@nitra/abie-docs` у `devDependencies`
|
|
144
|
+
|
|
145
|
+
У кореневому **`package.json`** abie-проєкту в **`devDependencies`** має бути **`@nitra/abie-docs`** — пакет з канонічними контрактами/схемами abie-сервісів (наприклад, шляхи `node_modules/@nitra/abie-docs/...` для імпорту схем). Версію правило не фіксує — лише presence. Додати:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
bun add -d @nitra/abie-docs
|
|
149
|
+
```
|
|
150
|
+
|
|
143
151
|
## Firebase Hosting
|
|
144
152
|
|
|
145
153
|
У **кожному** підкаталозі, що лежить **безпосередньо** в корені репозиторію, не тримати конфіг і кеш **Firebase Hosting**: у таких каталогах не повинно бути **`.firebaserc`**, **`firebase.json`** та каталогу **`.firebase/`** (у **самому** корені репозиторію ці імена перевіркою abie **не** розглядаються; `node_modules` / `.git` зі скану вилучаються).
|
|
@@ -160,5 +168,6 @@ KVCMS_URL=http://kvcms-hl.ua-apruv.svc.abie-ua.internal:8080
|
|
|
160
168
|
- **`health_check_policy/`** → `abie.health_check_policy` — структура HealthCheckPolicy: `apiVersion: networking.gke.io/v1`, `metadata.name`, `spec.default.config.type: HTTP`, `httpHealthCheck.requestPath` починається з `/`, `port: 8080`, `targetRef.kind: Service`, `targetRef.name` має суфікс `-hl`. **Цільові файли:** `…/k8s/.../hc.yaml`.
|
|
161
169
|
- **`base_deployment_preem/`** → `abie.base_deployment_preem` — Deployment у base/ має `spec.template.spec.nodeSelector.preem` зі значенням `true` (boolean або рядок). **Цільові файли:** ресурсні YAML під `…/k8s/.../base/...`.
|
|
162
170
|
- **`clean_merged_ignore_branches/`** → `abie.clean_merged_ignore_branches` — у workflow `.github/workflows/clean-merged-branch.yml` крок з `uses: phpdocker-io/github-actions-delete-abandoned-branches` має `with.ignore_branches`, що містить токени `dev,ua` (case-insensitive). **Цільові файли:** `.github/workflows/clean-merged-branch.yml`.
|
|
171
|
+
- **`package_json_docs/`** → `abie.package_json_docs` — у кореневому `package.json` `devDependencies` має містити `@nitra/abie-docs` (presence-only, версію не фіксуємо). **Цільові файли:** `package.json`.
|
|
163
172
|
|
|
164
173
|
Cross-file логіка (парність HCP↔Deployment у каталозі, обчислений `<deployment.name>-hl` для `targetRef.name`, валідація ua-overlay JSON6902 patches на HTTPRoute, env→cluster DNS, аналіз cross-namespace backendRefs у пакетах) лишається у **`check-abie.mjs`** — Rego не читає файлову систему й не робить cross-document резолюцію.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Перевірка кореневого `package.json` abie-проєкту: у `devDependencies` має бути
|
|
2
|
+
# `@nitra/abie-docs` (контракти/схеми abie-сервісів — наприклад
|
|
3
|
+
# `node_modules/@nitra/abie-docs/...`). Версію не фіксуємо — лише presence.
|
|
4
|
+
#
|
|
5
|
+
# Inverse-presence перевірка — лишається inline у rego (як `@nitra/cspell-dict`
|
|
6
|
+
# у `text.package_json`), бо у template/ зберігаємо позитивні snippet/deny канони,
|
|
7
|
+
# а не одиничний required-ключ.
|
|
8
|
+
package abie.package_json_docs
|
|
9
|
+
|
|
10
|
+
import rego.v1
|
|
11
|
+
|
|
12
|
+
deny contains msg if {
|
|
13
|
+
dev := object.get(input, "devDependencies", {})
|
|
14
|
+
not "@nitra/abie-docs" in object.keys(dev)
|
|
15
|
+
msg := "package.json: devDependencies має містити @nitra/abie-docs — bun add -d @nitra/abie-docs (abie.mdc)"
|
|
16
|
+
}
|
package/rules/efes/efes.mdc
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Правила для проєктів Efes (репозиторії під github.com/efes-cloud)
|
|
3
3
|
alwaysApply: true
|
|
4
|
-
version: '1.
|
|
4
|
+
version: '1.1'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Правило **efes** для споживачів **@nitra/cursor** у репозиторіях під **`github.com/efes-cloud/*`**.
|
|
7
|
+
Правило **efes** для споживачів **@nitra/cursor** у репозиторіях під **`github.com/efes-cloud/*`**.
|
|
8
|
+
|
|
9
|
+
## `@nitra/efes-docs` у `devDependencies`
|
|
10
|
+
|
|
11
|
+
У кореневому **`package.json`** efes-проєкту в **`devDependencies`** має бути **`@nitra/efes-docs`** — пакет з канонічними контрактами/схемами efes-сервісів (зокрема використовується у `graphql.mdc` як `node_modules/@nitra/efes-docs/schema/maya.graphql`). Версію правило не фіксує — лише presence. Додати:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bun add -d @nitra/efes-docs
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Швидкий gate через conftest (Rego)
|
|
18
|
+
|
|
19
|
+
Пер-документні перевірки efes — rego-полісі у **`npm/rules/efes/policy/`** (запускається через **`npx @nitra/cursor check efes`**; синтаксичний lint — через **`bun run lint-rego`**). Деталі шаблону — у **conftest.mdc** / **n-rego.mdc**.
|
|
20
|
+
|
|
21
|
+
Пакети (директорія в **`npm/rules/efes/policy/`** → namespace → що перевіряє):
|
|
22
|
+
|
|
23
|
+
- **`package_json_docs/`** → `efes.package_json_docs` — у кореневому `package.json` `devDependencies` має містити `@nitra/efes-docs` (presence-only, версію не фіксуємо). **Цільові файли:** `package.json`.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Перевірка кореневого `package.json` efes-проєкту: у `devDependencies` має бути
|
|
2
|
+
# `@nitra/efes-docs` (контракти/схеми efes-сервісів — використовується, зокрема,
|
|
3
|
+
# у `graphql.mdc` як `node_modules/@nitra/efes-docs/schema/maya.graphql`). Версію
|
|
4
|
+
# не фіксуємо — лише presence.
|
|
5
|
+
#
|
|
6
|
+
# Inverse-presence перевірка лишається inline у rego (як `@nitra/cspell-dict`
|
|
7
|
+
# у `text.package_json`).
|
|
8
|
+
package efes.package_json_docs
|
|
9
|
+
|
|
10
|
+
import rego.v1
|
|
11
|
+
|
|
12
|
+
deny contains msg if {
|
|
13
|
+
dev := object.get(input, "devDependencies", {})
|
|
14
|
+
not "@nitra/efes-docs" in object.keys(dev)
|
|
15
|
+
msg := "package.json: devDependencies має містити @nitra/efes-docs — bun add -d @nitra/efes-docs (efes.mdc)"
|
|
16
|
+
}
|
package/rules/ga/lint/lint.mjs
CHANGED
|
@@ -81,10 +81,7 @@ const CONFTEST_PREFLIGHT = {
|
|
|
81
81
|
'Без нього не запускається пер-документна валідація через rego-полісі (npm/rules/*/policy/)',
|
|
82
82
|
'у кроці check-ga — `runConftestBatch` завершується hard-fail.'
|
|
83
83
|
].join('\n '),
|
|
84
|
-
install: [
|
|
85
|
-
'macOS: brew install conftest',
|
|
86
|
-
'Universal: https://www.conftest.dev/install/'
|
|
87
|
-
],
|
|
84
|
+
install: ['macOS: brew install conftest', 'Universal: https://www.conftest.dev/install/'],
|
|
88
85
|
successMsg: '✅ conftest знайдено в PATH — check-ga виконає rego-полісі через runConftestBatch'
|
|
89
86
|
}
|
|
90
87
|
|
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
* ув'язування `.avif`-двійників з посиланнями у `.vue`/`.html`.
|
|
4
4
|
*
|
|
5
5
|
* Дії під час `check image-avif`:
|
|
6
|
-
* 1.
|
|
7
|
-
*
|
|
6
|
+
* 1. **Pre-scan**: знайти в `.vue`/`.html` хоча б одне raster-посилання, яке потенційно
|
|
7
|
+
* можна переписати на AVIF-двійник (через `import x from '...png'` або
|
|
8
|
+
* `<img src="...png" />`). Пакети з opt-out `disable-avif: true` пропускаються.
|
|
9
|
+
* Якщо жодного raster-посилання не знайдено → exit 0 одразу (`npx --avif` не запускаємо,
|
|
10
|
+
* rewrite/cleanup-пасс теж пропускаємо — нічого не змінилось би).
|
|
11
|
+
* 2. `npx \@nitra/minify-image --src=. --write --avif` — генерує AVIF-двійники.
|
|
12
|
+
* 3. У кожному workspace-пакеті переписує raster-посилання у `.vue`/`.html` на `.avif`
|
|
8
13
|
* (де AVIF-двійник реально існує на диску). Pakety з `"\@nitra/minify-image": {
|
|
9
14
|
* "disable-avif": true }` у `package.json` пропускаються.
|
|
10
|
-
*
|
|
15
|
+
* 4. Прибирає AVIF-сироти — `<name>.<ext>.avif`, на які не лишилось жодного посилання
|
|
11
16
|
* у `.vue`/`.html` репозиторію, видаляються (умова правила: «AVIF лишається лише
|
|
12
17
|
* там, де заміна вдалася»).
|
|
13
18
|
*
|
|
@@ -69,7 +74,6 @@ const VUE_RASTER_STATIC_SRC_RE = /(?<![:\-_.])\bsrc\s*=\s*['"]([^'"\s]+\.(?:png|
|
|
|
69
74
|
* є сиротами і підлягають видаленню.
|
|
70
75
|
*/
|
|
71
76
|
const VUE_AVIF_REF_RE = /['"]([^'"\s]+\.(?:png|jpe?g|gif)\.avif)['"]/giu
|
|
72
|
-
const RASTER_IMAGE_EXT_RE = /\.(?:png|jpe?g|gif)$/iu
|
|
73
77
|
|
|
74
78
|
/**
|
|
75
79
|
* Чи у `package.json` пакета вимкнено avif-перевірку Vue-імпортів.
|
|
@@ -279,24 +283,51 @@ async function checkVueAvifImports(ignorePaths, usedAvifAbs, stats, pass, fail)
|
|
|
279
283
|
}
|
|
280
284
|
|
|
281
285
|
/**
|
|
282
|
-
*
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
+
* Pre-scan: чи є в `.vue`/`.html` хоча б одне raster-посилання, яке потенційно треба
|
|
287
|
+
* переписати на AVIF-двійник (через `import x from '...png'` або `<img src="...png" />`).
|
|
288
|
+
*
|
|
289
|
+
* Якщо false — весь подальший етап `image-avif` пропускаємо: ні `npx --avif`, ні rewrite,
|
|
290
|
+
* ні cleanup-сиріт не дали б ніяких змін. Сенс — не запускати дорогий `npx @nitra/minify-image`
|
|
291
|
+
* у проєктах, де AVIF не вживається (а опційно і не плануються).
|
|
292
|
+
*
|
|
293
|
+
* Скан робиться тими самими regexp-ами, що й основний rewrite-пасс (`VUE_RASTER_IMPORT_RE`
|
|
294
|
+
* + `VUE_RASTER_STATIC_SRC_RE`), і ходить лише по `.vue`/`.html` у workspace-пакетах, що НЕ
|
|
295
|
+
* мають opt-out `"@nitra/minify-image": { "disable-avif": true }` (інакше їхні шаблони ми
|
|
296
|
+
* все одно не сканували б, тож вони не мають провокувати запуск AVIF-етапу).
|
|
286
297
|
* @param {string[]} ignorePaths абсолютні шляхи каталогів, повністю виключених з обходу
|
|
287
|
-
* @returns {Promise<boolean>} `true`, якщо знайдено принаймні
|
|
298
|
+
* @returns {Promise<boolean>} `true`, якщо знайдено принаймні одне raster-посилання
|
|
288
299
|
*/
|
|
289
|
-
async function
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
+
async function hasAnyVueRasterReference(ignorePaths) {
|
|
301
|
+
const roots = await getMonorepoPackageRootDirs()
|
|
302
|
+
const absRootsByRel = new Map(roots.map(r => [r, join(process.cwd(), r)]))
|
|
303
|
+
for (const root of roots) {
|
|
304
|
+
const pkgPath = join(root, 'package.json')
|
|
305
|
+
if (existsSync(pkgPath)) {
|
|
306
|
+
const pkg = JSON.parse(await readFile(pkgPath, 'utf8'))
|
|
307
|
+
if (packageHasAvifDisabled(pkg)) continue
|
|
308
|
+
}
|
|
309
|
+
const absRoot = absRootsByRel.get(root) ?? join(process.cwd(), root)
|
|
310
|
+
const otherRootsAbs = roots.filter(r => r !== root && r !== '.').map(r => absRootsByRel.get(r) ?? '')
|
|
311
|
+
/** @type {string[]} */
|
|
312
|
+
const targetFiles = []
|
|
313
|
+
await walkDir(
|
|
314
|
+
absRoot,
|
|
315
|
+
absPath => {
|
|
316
|
+
if (!absPath.endsWith('.vue') && !absPath.endsWith('.html')) return
|
|
317
|
+
if (otherRootsAbs.some(other => absPath.startsWith(`${other}/`))) return
|
|
318
|
+
targetFiles.push(absPath)
|
|
319
|
+
},
|
|
320
|
+
ignorePaths
|
|
321
|
+
)
|
|
322
|
+
for (const absPath of targetFiles) {
|
|
323
|
+
const content = await readFile(absPath, 'utf8')
|
|
324
|
+
VUE_RASTER_IMPORT_RE.lastIndex = 0
|
|
325
|
+
if (VUE_RASTER_IMPORT_RE.test(content)) return true
|
|
326
|
+
VUE_RASTER_STATIC_SRC_RE.lastIndex = 0
|
|
327
|
+
if (VUE_RASTER_STATIC_SRC_RE.test(content)) return true
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return false
|
|
300
331
|
}
|
|
301
332
|
|
|
302
333
|
/**
|
|
@@ -381,10 +412,15 @@ export async function check() {
|
|
|
381
412
|
|
|
382
413
|
const ignorePaths = await loadCursorIgnorePaths(process.cwd())
|
|
383
414
|
|
|
384
|
-
if (await
|
|
385
|
-
|
|
415
|
+
if (!(await hasAnyVueRasterReference(ignorePaths))) {
|
|
416
|
+
pass(
|
|
417
|
+
'image-avif: у .vue/.html немає raster-посилань для переписування — AVIF-генерація і cleanup пропущені'
|
|
418
|
+
)
|
|
419
|
+
return reporter.getExitCode()
|
|
386
420
|
}
|
|
387
421
|
|
|
422
|
+
runAvifGeneration()
|
|
423
|
+
|
|
388
424
|
/** @type {Set<string>} */
|
|
389
425
|
const usedAvifAbs = new Set()
|
|
390
426
|
/** @type {RewriteStats} */
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: AVIF-двійники для raster-зображень з ув'язуванням у .vue/.html
|
|
3
|
-
version: '1.
|
|
3
|
+
version: '1.4'
|
|
4
4
|
globs: "**/*.{png,jpg,jpeg,gif,avif,vue,html}"
|
|
5
5
|
alwaysApply: false
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
AVIF-двійники (`<name>.<ext>.avif`) генерує **виключно** `npx @nitra/cursor check image-avif` — у `lint-image` прапорець `--avif` заборонений (це валідує правило `image-compress`). Перевірка робить
|
|
8
|
+
AVIF-двійники (`<name>.<ext>.avif`) генерує **виключно** `npx @nitra/cursor check image-avif` — у `lint-image` прапорець `--avif` заборонений (це валідує правило `image-compress`). Перевірка робить чотири кроки в порядку:
|
|
9
9
|
|
|
10
|
-
1.
|
|
11
|
-
2.
|
|
10
|
+
1. **Pre-scan**: шукає у `.vue`/`.html` хоча б одне raster-посилання, яке потенційно треба переписати на AVIF-двійник (`import x from '...png'` або `<img src="...png" />`). Пакети з opt-out `disable-avif: true` пропускаються. **Якщо жодного raster-посилання не знайдено — `check image-avif` завершується успіхом одразу: ні `npx --avif`, ні rewrite, ні cleanup-сиріт не виконуються** (нічого було б змінювати). Так уникаємо дорогого `npx @nitra/minify-image` у проєктах, де AVIF не вживається.
|
|
11
|
+
2. Запускає `npx @nitra/minify-image --src=. --write --avif` (≥ **3.3.1**) — генерує `<name>.<ext>.avif` поряд з кожним PNG/JPEG/GIF. CLI порівнює sha1 кожного raster-сорсу зі збереженим у `.n-minify-image.tsv` і перезаписує `<source>.avif` при зміні оригіналу.
|
|
12
|
+
3. Сканує `.vue` (а також `.html`) файли в кожному workspace-пакеті (root + workspaces) і автоматично переписує raster-посилання на AVIF-двійник у двох формах:
|
|
12
13
|
- **Імпорт-пов'язані** — `import x from '...png|jpg|jpeg|gif'` (далі `:src="x"` у шаблоні);
|
|
13
14
|
- **Прямі статичні** — `<img src="...png" />` у `<template>` (Vite перетворює такий шлях на asset-імпорт на етапі збірки, тож вимога та сама).
|
|
14
|
-
|
|
15
|
+
4. Видаляє AVIF-сироти: ходить по всіх `<...>.avif` у репозиторії; якщо на двійник не лишилось жодного посилання у `.vue`/`.html` — файл видаляється. **AVIF на диску лишається лише там, де заміна реально відбулась** — тому невикористані оригінали не накопичують `.avif`-«хвости». **Зауваж**: cleanup виконується ЛИШЕ якщо pre-scan на кроці 1 знайшов хоча б одне raster-посилання — інакше осиротілі `.avif` залишаються недоторканими (видаляться вже наступним прогоном, коли в `.vue`/`.html` зʼявиться raster для конвертації).
|
|
15
16
|
|
|
16
17
|
```vue title="App.vue (після check image-avif)"
|
|
17
18
|
<script setup>
|
package/rules/text/lint/lint.mjs
CHANGED
|
@@ -51,13 +51,10 @@ const SHELLCHECK_PREFLIGHT = {
|
|
|
51
51
|
/** @type {PreflightDep} */
|
|
52
52
|
const PATCH_PREFLIGHT = {
|
|
53
53
|
bin: 'patch',
|
|
54
|
-
explanation: [
|
|
55
|
-
'
|
|
56
|
-
|
|
57
|
-
install: [
|
|
58
|
-
'macOS: зазвичай уже є в системі',
|
|
59
|
-
'Debian/Ubuntu: sudo apt-get install -y patch'
|
|
60
|
-
],
|
|
54
|
+
explanation: ['Без `patch` не застосуються авто-виправлення shellcheck (`shellcheck -f diff` + `patch -p1`).'].join(
|
|
55
|
+
'\n '
|
|
56
|
+
),
|
|
57
|
+
install: ['macOS: зазвичай уже є в системі', 'Debian/Ubuntu: sudo apt-get install -y patch'],
|
|
61
58
|
successMsg: '✅ patch знайдено в PATH — shellcheck auto-fix працюватиме'
|
|
62
59
|
}
|
|
63
60
|
|