@nitra/cursor 12.13.0 → 12.14.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [12.14.0] - 2026-06-26
4
+
5
+ ### Changed
6
+
7
+ - Заміна picomatch на ignore для обробки glob-ів у docgen та resolve-target-files
8
+
3
9
  ## [12.13.0] - 2026-06-26
4
10
 
5
11
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitra/cursor",
3
- "version": "12.13.0",
3
+ "version": "12.14.0",
4
4
  "description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
5
5
  "keywords": [
6
6
  "cli",
@@ -55,6 +55,7 @@
55
55
  "dependencies": {
56
56
  "@7n/mt": "^0.5.1",
57
57
  "globby": "^16.0.0",
58
+ "ignore": "^7.0.5",
58
59
  "oxc-parser": "^0.137.0",
59
60
  "picomatch": "^4.0.4",
60
61
  "smol-toml": "^1.7.0",
@@ -1,5 +1,5 @@
1
1
  /** @see ./docs/docgen-ignore.md */
2
- import picomatch from 'picomatch'
2
+ import ignore from 'ignore'
3
3
 
4
4
  /** Базовий список glob-ів для `docgen` ignore. */
5
5
  export const DOCGEN_IGNORE_GLOBS = Object.freeze([
@@ -22,7 +22,7 @@ export const DOCGEN_IGNORE_GLOBS = Object.freeze([
22
22
  'npm/rules/k8s/js/manifests.mjs'
23
23
  ])
24
24
 
25
- const IGNORE_MATCHERS = DOCGEN_IGNORE_GLOBS.map(glob => picomatch(glob, { dot: true }))
25
+ const ig = ignore().add(DOCGEN_IGNORE_GLOBS)
26
26
 
27
27
  /**
28
28
  * Нормалізує відносний шлях до posix-формату для glob-matching.
@@ -36,7 +36,7 @@ function toPosixRelPath(relPath) {
36
36
  /**
37
37
  * Перевіряє, чи шлях має бути пропущений `docgen`.
38
38
  * Для `kind = 'dir'` це працює і на піддерево каталогу, тож glob на кшталт
39
- * `**\\/demo/**` спрацьовує на `demo/x` під час рекурсивного обходу.
39
+ * `**\/demo/**` спрацьовує на `demo/x` під час рекурсивного обходу.
40
40
  * @param {string} relPath відносний шлях від кореня проєкту
41
41
  * @param {'path'|'dir'} [kind] тип перевірки (за замовчуванням `'path'`)
42
42
  * @returns {boolean} `true`, якщо шлях ігнорується
@@ -47,7 +47,8 @@ export function isDocgenIgnored(relPath, kind = 'path') {
47
47
  }
48
48
  const posixRelPath = toPosixRelPath(relPath)
49
49
  if (kind === 'dir') {
50
- return IGNORE_MATCHERS.some(match => match(posixRelPath) || match(`${posixRelPath}/__docgen__`))
50
+ // `**/demo/**` не матчить `demo` напряму — перевіряємо фіктивний файл всередині
51
+ return ig.ignores(posixRelPath) || ig.ignores(`${posixRelPath}/__docgen__`)
51
52
  }
52
- return IGNORE_MATCHERS.some(match => match(posixRelPath))
53
+ return ig.ignores(posixRelPath)
53
54
  }
@@ -3,7 +3,7 @@ type: JS Module
3
3
  title: docgen-ignore.mjs
4
4
  resource: npm/rules/doc-files/js/docgen-ignore.mjs
5
5
  docgen:
6
- crc: c17cd785
6
+ crc: 00687334
7
7
  score: 100
8
8
  ---
9
9
 
@@ -3,7 +3,7 @@ type: JS Module
3
3
  title: resolve-target-files.mjs
4
4
  resource: npm/scripts/lib/resolve-target-files.mjs
5
5
  docgen:
6
- crc: a3b361d9
6
+ crc: 4d3546e6
7
7
  ---
8
8
 
9
9
  Цей файл відповідає за перевірку наявності файлів, що відповідають певним правилам, вказаним у файлах `policy/<name>/target.json`. Він створює список файлів для подальшого використання, використовуючи або конкретні відносні шляхи, або обхід каталогу з використанням шаблонів та ігнорування файлів. Це забезпечує узгодженість та контроль над файлами, які потрібно обробити, відповідно до заданих політик.
@@ -16,7 +16,7 @@ docgen:
16
16
  4. **Завантаження ігнорування:** Завантажує список абсолютних шляхів, які слід ігнорувати, з конфігурації `.n-cursor.json:ignore`.
17
17
  5. **Кешування обходу:** Використовує кеш обходу дерева (Map) для запобігання повторному обходу одного й того ж набору ігнорування. Якщо обхід вже виконано для заданого набору ігнорування, повертає результат з кешу.
18
18
  6. **Обхід дерева:** Якщо обхід не кешований або кеш порожній, виконує обхід дерева файлів від заданого кореня, використовуючи `walkDir`. Під час обходу генерує відносні шляхи файлів від кореня.
19
- 7. **Фільтрація за масками:** Для кожного відносного шляху файлу застосовує маски `walkGlob` за допомогою `picomatch`. Фільтрує файли, які відповідають маскам, та виключає ті, що відповідають негативним маскам.
19
+ 7. **Фільтрація за масками:** Для кожного відносного шляху файлу застосовує маски `walkGlob` за допомогою `ignore`. Фільтрує файли, які відповідають маскам, та виключає ті, що відповідають негативним маскам.
20
20
  8. **Збіг з ігноруванням:** Перевіряє, чи файл не входить до списку ігнорування.
21
21
  9. **Збіг шляху:** Перетворює відносні шляхи файлів у абсолютні шляхи, додавши корень.
22
22
  10. **Повернення результатів:** Повертає масив абсолют
@@ -29,7 +29,7 @@ resolveTargetFiles — Знаходить файли, що вказані в `ta
29
29
 
30
30
  - **Контракт на поліси:** Зчитуються лише файли з репозиторію.
31
31
  - **`single`:** Якщо `existsSync`, повертається список файлів, що відповідають `single`. Інакше, повертається порожній список.
32
- - **`walkGlob`:** Використовується picomatch для обробки glob-шаблонів відносно шляхів, отриманих з обходу `walkDir` від `root`.
32
+ - **`walkGlob`:** Використовується ignore для обробки glob-шаблонів відносно шляхів, отриманих з обходу `walkDir` від `root`.
33
33
  - **Ігнорування:** Підтримується ігнорування файлів за допомогою `.n-cursor.json:ignore` та кешування шляхів ігнорування у `walkCache`.
34
34
  - **Кешування:** Результати обходу кешуються для повторного використання при однаковому наборі ігнорувань.
35
35
  - **Path-traversal:** При розв'язанні шляхів у формі `single` виникає помилка.
@@ -4,7 +4,7 @@
4
4
  * Дві форми у `target.json:files`:
5
5
  * - `{ "single": "<rel>" }` — конкретний відносний шлях. Якщо `existsSync(root/single)` → `[single]`;
6
6
  * інакше `[]` (caller сам вирішує fail vs silent skip за `required`).
7
- * - `{ "walkGlob": <glob | glob[]> }` — picomatch проти posix-відносних шляхів, отриманих обходом
7
+ * - `{ "walkGlob": <glob | glob[]> }` — `ignore` проти posix-відносних шляхів, отриманих обходом
8
8
  * `walkDir` від `root` із загальними skip-ами та `.n-cursor.json:ignore`. Обхід кешований у
9
9
  * `walkCache` (Map ключ — підпис ignorePaths) — повторні таргети з тим самим набором ignore
10
10
  * перевикористовують список без нового readdir.
@@ -15,7 +15,7 @@
15
15
  import { existsSync } from 'node:fs'
16
16
  import { isAbsolute, join, normalize, relative, sep } from 'node:path'
17
17
 
18
- import picomatch from 'picomatch'
18
+ import ignore from 'ignore'
19
19
 
20
20
  import { loadCursorIgnorePaths } from './load-cursor-config.mjs'
21
21
  import { walkDir } from '../utils/walkDir.mjs'
@@ -96,14 +96,8 @@ export async function resolveTargetFiles(filesSpec, root, walkCache) {
96
96
  const ignorePaths = await loadCursorIgnorePaths(root)
97
97
  const all = await getAllFilesCached(root, ignorePaths, walkCache)
98
98
  const globs = Array.isArray(filesSpec.walkGlob) ? filesSpec.walkGlob : [filesSpec.walkGlob]
99
- // picomatch у масиві трактує `!neg` як ОКРЕМИЙ позитивний матчер «не-neg» (some-OR логіка),
100
- // тож наївне `picomatch(['pos','!neg'])` повертає true майже на всьому. Розділяємо вручну:
101
- // позитиви join-имо через picomatch(...), негативні фільтруємо окремим isExcluded.
102
- const positives = globs.filter(g => !g.startsWith('!'))
103
- const negatives = globs.filter(g => g.startsWith('!')).map(g => g.slice(1))
104
- const isMatch = positives.length > 0 ? picomatch(positives, { dot: false }) : () => false
105
- const isExcluded = negatives.length > 0 ? picomatch(negatives, { dot: false }) : () => false
106
- return all.filter(rel => isMatch(rel) && !isExcluded(rel)).map(rel => join(root, rel))
99
+ const ig = ignore().add(globs)
100
+ return all.filter(rel => ig.ignores(rel)).map(rel => join(root, rel))
107
101
  }
108
102
  throw new Error(`target.json: files має містити single або walkGlob (отримано: ${JSON.stringify(filesSpec)})`)
109
103
  }