@itcase/config 1.6.86 → 1.7.1
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/README.md +15 -3
- package/lint-staged/common.js +77 -0
- package/lint-staged/index.js +3 -38
- package/lint-staged/lintStaged.js +5 -0
- package/lint-staged/lintStagedMonorepo.js +7 -0
- package/package.json +11 -12
- package/semantic-release/common.js +20 -12
- package/semantic-release/index.js +6 -0
- package/semantic-release/semanticReleaseApp.js +58 -0
- package/smart-commit/cli.js +4 -11
- package/smart-commit/dancing-banana.js +224 -339
- package/lint-staged-ts/index.js +0 -46
- package/smart-commit/pacman.js +0 -140
package/README.md
CHANGED
|
@@ -23,8 +23,8 @@ npm install --save-dev @itcase/config
|
|
|
23
23
|
- В git только `.husky/config`; обёртки и `_run.sh` создаёт `itcase-config-husky-install` при `npm i`
|
|
24
24
|
|
|
25
25
|
- **Lint-staged** — запуск линтеров для измененных файлов
|
|
26
|
-
- `
|
|
27
|
-
- `
|
|
26
|
+
- `lintStaged` — eslint, stylelint; `tsc --noEmit`, если в staged есть `.ts`/`.tsx`
|
|
27
|
+
- `lintStagedMonorepo` — то же, но typecheck через `npm run typecheck` по workspaces
|
|
28
28
|
- обе конфигурации блокируют коммит, если в `package.json` есть локальные зависимости `file:` / `link:`
|
|
29
29
|
|
|
30
30
|
- **PostCSS** — обработка CSS
|
|
@@ -41,6 +41,18 @@ npm install --save-dev @itcase/config
|
|
|
41
41
|
- `svgr/index.js` — базовая конфигурация
|
|
42
42
|
- `svgr/webpack.js` — интеграция с Webpack
|
|
43
43
|
|
|
44
|
+
## Подключение Lint-staged
|
|
45
|
+
|
|
46
|
+
В корне проекта `lint-staged.config.mjs`:
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
import { lintStaged } from '@itcase/config/lint-staged/index.js'
|
|
50
|
+
|
|
51
|
+
export default lintStaged
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Для монорепозитория с `npm run typecheck` — `lintStagedMonorepo`.
|
|
55
|
+
|
|
44
56
|
## Подключение Commitlint
|
|
45
57
|
|
|
46
58
|
1. Установите зависимости в проекте:
|
|
@@ -149,7 +161,7 @@ CLI ставится в `~/.local/bin`. Логин в Cursor IDE этот CLI н
|
|
|
149
161
|
|
|
150
162
|
Обновление CLI: `agent update`.
|
|
151
163
|
|
|
152
|
-
Пока Agent думает, в терминале крутится pixel-анимация (случайно nyan cat, dancing banana
|
|
164
|
+
Пока Agent думает, в терминале крутится pixel-анимация (случайно nyan cat, dancing banana или упячка) + статус `(Ns)`, а под ними живой лог агента (`log-update`). Пока процесс агента жив, CLI его не убивает по таймауту. Принудительно: `--cat` / `--banana` / `--upyachka`. Для полного лога: `npm run smart-commit -- --verbose --dry-run`.
|
|
153
165
|
|
|
154
166
|
> **Важно:** в npm есть одноимённый пакет `smart-commit`. Используйте `npm run smart-commit` из проекта с `@itcase/config` — bin берётся из `node_modules`. `npx smart-commit` без локальной установки может подтянуть чужой пакет; CLI перед запуском проверяет, что выполняется именно `@itcase/config`.
|
|
155
167
|
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { dirname, join, resolve } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
|
|
5
|
+
const checkNoFileDependencies = join(
|
|
6
|
+
dirname(fileURLToPath(import.meta.url)),
|
|
7
|
+
'checkNoFileDependencies.js',
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
function existingFiles(files) {
|
|
11
|
+
return files.filter((file) => existsSync(file))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function eslintCommand(files) {
|
|
15
|
+
return `npx eslint --fix --color ${files.join(' ')}`
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function stylelintCommand(files) {
|
|
19
|
+
return `npx stylelint --fix --color --formatter verbose ${files.join(' ')}`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function packageJsonCommand(files) {
|
|
23
|
+
// Проверяем, есть ли package.json в корне репозитория
|
|
24
|
+
const rootPackageJson = resolve(process.cwd(), 'package.json')
|
|
25
|
+
const isRoot = files.some((file) => resolve(file) === rootPackageJson)
|
|
26
|
+
if (existsSync(rootPackageJson) && isRoot) {
|
|
27
|
+
// lint-staged автоматически добавляет изменения задач в index
|
|
28
|
+
return 'npm install --package-lock-only'
|
|
29
|
+
}
|
|
30
|
+
return 'true' // Пропускаем, если не найден
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Создает конфигурацию lint-staged с общими правилами.
|
|
35
|
+
* Один glob на JS/TS — typecheck и eslint в одной группе.
|
|
36
|
+
* `tsc` срабатывает только если в staged есть .ts/.tsx, поэтому JS-пакету
|
|
37
|
+
* отдельный конфиг не нужен.
|
|
38
|
+
* @param {Object} [options]
|
|
39
|
+
* @param {string} [options.typecheckCommand] Команда typecheck, если в staged есть .ts/.tsx
|
|
40
|
+
* @returns {Object} Конфигурация lint-staged
|
|
41
|
+
*/
|
|
42
|
+
function createLintStagedConfig({
|
|
43
|
+
typecheckCommand = 'tsc --noEmit --pretty',
|
|
44
|
+
} = {}) {
|
|
45
|
+
return {
|
|
46
|
+
// На любой staged-файл: если в package.json есть file:/link: — exit 1, коммит не пройдёт
|
|
47
|
+
'*': () => `node ${JSON.stringify(checkNoFileDependencies)}`,
|
|
48
|
+
'*.(js|jsx|ts|tsx)': (files) => {
|
|
49
|
+
const existing = existingFiles(files)
|
|
50
|
+
const tsFiles = existing.filter((file) => /\.(ts|tsx)$/.test(file))
|
|
51
|
+
const commands = []
|
|
52
|
+
|
|
53
|
+
if (typecheckCommand && tsFiles.length > 0) {
|
|
54
|
+
commands.push(typecheckCommand)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (existing.length > 0) {
|
|
58
|
+
commands.push(eslintCommand(existing))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return commands.length ? commands : 'true'
|
|
62
|
+
},
|
|
63
|
+
'*.css': (files) => {
|
|
64
|
+
const existing = existingFiles(files)
|
|
65
|
+
if (!existing.length) return 'true'
|
|
66
|
+
return stylelintCommand(existing)
|
|
67
|
+
},
|
|
68
|
+
'*.mdx': (files) => {
|
|
69
|
+
const existing = existingFiles(files)
|
|
70
|
+
if (!existing.length) return 'true'
|
|
71
|
+
return eslintCommand(existing)
|
|
72
|
+
},
|
|
73
|
+
'package.json': packageJsonCommand,
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { createLintStagedConfig }
|
package/lint-staged/index.js
CHANGED
|
@@ -1,39 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
1
|
+
import { lintStaged } from './lintStaged.js'
|
|
2
|
+
import { lintStagedMonorepo } from './lintStagedMonorepo.js'
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
dirname(fileURLToPath(import.meta.url)),
|
|
7
|
-
'checkNoFileDependencies.js',
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
// eslint-disable-next-line import/no-default-export
|
|
11
|
-
export default {
|
|
12
|
-
// На любой staged-файл: если в package.json есть file:/link: — exit 1, коммит не пройдёт
|
|
13
|
-
'*': () => `node ${JSON.stringify(checkNoFileDependencies)}`,
|
|
14
|
-
'*.(js|jsx|ts|tsx)': (files) => {
|
|
15
|
-
const existing = files.filter((file) => existsSync(file))
|
|
16
|
-
if (!existing.length) return 'true'
|
|
17
|
-
return `npx eslint --fix --color ${existing.join(' ')}`
|
|
18
|
-
},
|
|
19
|
-
'*.css': (files) => {
|
|
20
|
-
const existing = files.filter((file) => existsSync(file))
|
|
21
|
-
if (!existing.length) return 'true'
|
|
22
|
-
return `npx stylelint --fix --color --formatter verbose ${existing.join(' ')}`
|
|
23
|
-
},
|
|
24
|
-
'*.mdx': (files) => {
|
|
25
|
-
const existing = files.filter((file) => existsSync(file))
|
|
26
|
-
if (!existing.length) return 'true'
|
|
27
|
-
return `npx eslint --fix --color ${existing.join(' ')}`
|
|
28
|
-
},
|
|
29
|
-
'package.json': (files) => {
|
|
30
|
-
// Проверяем, есть ли package.json в корне репозитория
|
|
31
|
-
const rootPackageJson = resolve(process.cwd(), 'package.json')
|
|
32
|
-
const isRoot = files.some((file) => resolve(file) === rootPackageJson)
|
|
33
|
-
if (existsSync(rootPackageJson) && isRoot) {
|
|
34
|
-
// lint-staged автоматически добавляет изменения задач в index
|
|
35
|
-
return 'npm install --package-lock-only'
|
|
36
|
-
}
|
|
37
|
-
return 'true' // Пропускаем, если не найден
|
|
38
|
-
},
|
|
39
|
-
}
|
|
4
|
+
export { lintStaged, lintStagedMonorepo }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itcase/config",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"author": "ITCase",
|
|
5
5
|
"description": "ITCase Config",
|
|
6
6
|
"engines": {
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
"commitlint",
|
|
29
29
|
"husky-hooks",
|
|
30
30
|
"lint-staged",
|
|
31
|
-
"lint-staged-ts",
|
|
32
31
|
"semantic-release",
|
|
33
32
|
"postcss",
|
|
34
33
|
"smart-commit",
|
|
@@ -40,9 +39,9 @@
|
|
|
40
39
|
"registry": "https://registry.npmjs.org/"
|
|
41
40
|
},
|
|
42
41
|
"dependencies": {
|
|
43
|
-
"@commitlint/cli": "^21.2.
|
|
44
|
-
"@commitlint/config-conventional": "^21.2.
|
|
45
|
-
"@commitlint/cz-commitlint": "^21.2.
|
|
42
|
+
"@commitlint/cli": "^21.2.3",
|
|
43
|
+
"@commitlint/config-conventional": "^21.2.3",
|
|
44
|
+
"@commitlint/cz-commitlint": "^21.2.3",
|
|
46
45
|
"@lehoczky/postcss-fluid": "^1.0.3",
|
|
47
46
|
"@lerna-lite/cli": "^5.6.1",
|
|
48
47
|
"@lerna-lite/exec": "^5.6.1",
|
|
@@ -63,12 +62,12 @@
|
|
|
63
62
|
"@svgr/plugin-jsx": "^8.1.0",
|
|
64
63
|
"@svgr/plugin-svgo": "^8.1.0",
|
|
65
64
|
"@svgr/webpack": "^8.1.0",
|
|
66
|
-
"autoprefixer": "^10.6.
|
|
65
|
+
"autoprefixer": "^10.6.1",
|
|
67
66
|
"chokidar-cli": "^3.0.0",
|
|
68
67
|
"commitizen": "^4.3.2",
|
|
69
68
|
"conventional-changelog-conventionalcommits": "9.3.1",
|
|
70
|
-
"cssnano": "^9.0.
|
|
71
|
-
"cssnano-preset-default": "^9.0.
|
|
69
|
+
"cssnano": "^9.0.5",
|
|
70
|
+
"cssnano-preset-default": "^9.0.5",
|
|
72
71
|
"inquirer": "^14.2.2",
|
|
73
72
|
"log-update": "^8.0.0",
|
|
74
73
|
"postcss": "^8.5.28",
|
|
@@ -79,7 +78,7 @@
|
|
|
79
78
|
"postcss-combine-duplicated-selectors": "^10.0.3",
|
|
80
79
|
"postcss-convert-unit": "^0.1.3",
|
|
81
80
|
"postcss-dark-theme-class": "^2.0.0",
|
|
82
|
-
"postcss-discard-duplicates": "^9.0.
|
|
81
|
+
"postcss-discard-duplicates": "^9.0.3",
|
|
83
82
|
"postcss-each": "^1.1.0",
|
|
84
83
|
"postcss-easings": "^4.0.0",
|
|
85
84
|
"postcss-extend-rule": "^4.0.0",
|
|
@@ -109,15 +108,15 @@
|
|
|
109
108
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
110
109
|
"rollup-preserve-directives": "^1.1.3",
|
|
111
110
|
"semantic-release": "^25.0.9",
|
|
112
|
-
"semantic-release-lerna": "^3.6.
|
|
111
|
+
"semantic-release-lerna": "^3.6.5"
|
|
113
112
|
},
|
|
114
113
|
"devDependencies": {
|
|
115
|
-
"@itcase/lint": "^1.1.
|
|
114
|
+
"@itcase/lint": "^1.1.126",
|
|
116
115
|
"eslint": "9.39.2",
|
|
117
116
|
"husky": "^9.1.7",
|
|
118
117
|
"inquirer": "^14.2.2",
|
|
119
118
|
"lint-staged": "^17.5.1",
|
|
120
|
-
"prettier": "^3.9.
|
|
119
|
+
"prettier": "^3.9.8",
|
|
121
120
|
"storybook": "^10.6.0",
|
|
122
121
|
"stylelint": "^17.15.0",
|
|
123
122
|
"typescript": "^6.0.3"
|
|
@@ -37,6 +37,14 @@ const releaseNotesGeneratorConfig = {
|
|
|
37
37
|
},
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
const defaultGithubOptions = {
|
|
41
|
+
failComment: false,
|
|
42
|
+
failCommentCondition: false,
|
|
43
|
+
failTitle: false,
|
|
44
|
+
releasedLabels: false,
|
|
45
|
+
successComment: false,
|
|
46
|
+
}
|
|
47
|
+
|
|
40
48
|
const commonPlugins = {
|
|
41
49
|
commitAnalyzer: [
|
|
42
50
|
'@semantic-release/commit-analyzer',
|
|
@@ -52,16 +60,7 @@ const commonPlugins = {
|
|
|
52
60
|
releaseNotesGeneratorConfig,
|
|
53
61
|
],
|
|
54
62
|
changelog: ['@semantic-release/changelog', { changelogFile: CHANGELOG_FILE }],
|
|
55
|
-
github: [
|
|
56
|
-
'@semantic-release/github',
|
|
57
|
-
{
|
|
58
|
-
failComment: false,
|
|
59
|
-
failCommentCondition: false,
|
|
60
|
-
failTitle: false,
|
|
61
|
-
releasedLabels: false,
|
|
62
|
-
successComment: false,
|
|
63
|
-
},
|
|
64
|
-
],
|
|
63
|
+
github: ['@semantic-release/github', defaultGithubOptions],
|
|
65
64
|
}
|
|
66
65
|
|
|
67
66
|
/**
|
|
@@ -70,7 +69,9 @@ const commonPlugins = {
|
|
|
70
69
|
* @param {string|string[]} options.branches - Ветки для релиза
|
|
71
70
|
* @param {Object|null} options.npmConfig - Конфигурация для @semantic-release/npm. Если null, плагин не добавляется
|
|
72
71
|
* @param {Object} options.gitConfig - Конфигурация для @semantic-release/git
|
|
73
|
-
* @param {
|
|
72
|
+
* @param {Object} [options.githubConfig] - Доп. опции для @semantic-release/github (например assets)
|
|
73
|
+
* @param {Array} options.additionalPlugins - Дополнительные плагины перед changelog
|
|
74
|
+
* @param {Array} [options.preparePlugins] - Плагины после npm и перед git (prepare-шаг)
|
|
74
75
|
* @param {boolean} options.skipReleaseNotesGenerator - Пропустить @semantic-release/release-notes-generator
|
|
75
76
|
* @returns {Object} Конфигурация semantic-release
|
|
76
77
|
*/
|
|
@@ -78,7 +79,9 @@ function createSemanticReleaseConfig({
|
|
|
78
79
|
branches,
|
|
79
80
|
npmConfig = {},
|
|
80
81
|
gitConfig,
|
|
82
|
+
githubConfig = {},
|
|
81
83
|
additionalPlugins = [],
|
|
84
|
+
preparePlugins = [],
|
|
82
85
|
skipReleaseNotesGenerator = false,
|
|
83
86
|
}) {
|
|
84
87
|
const plugins = [commonPlugins.commitAnalyzer]
|
|
@@ -95,7 +98,12 @@ function createSemanticReleaseConfig({
|
|
|
95
98
|
plugins.push(['@semantic-release/npm', npmConfig])
|
|
96
99
|
}
|
|
97
100
|
|
|
98
|
-
plugins.push(
|
|
101
|
+
plugins.push(...preparePlugins)
|
|
102
|
+
|
|
103
|
+
plugins.push(
|
|
104
|
+
['@semantic-release/git', gitConfig],
|
|
105
|
+
['@semantic-release/github', { ...defaultGithubOptions, ...githubConfig }],
|
|
106
|
+
)
|
|
99
107
|
|
|
100
108
|
return {
|
|
101
109
|
branches,
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createSemanticReleaseApp,
|
|
3
|
+
semanticReleaseApp,
|
|
4
|
+
} from './semanticReleaseApp.js'
|
|
1
5
|
import { semanticReleaseMonorepo } from './semanticReleaseMonorepo.js'
|
|
2
6
|
import { semanticReleasePackage } from './semanticReleasePackage.js'
|
|
3
7
|
import { semanticReleaseProject } from './semanticReleaseProject.js'
|
|
4
8
|
import { semanticReleaseVSMarketplace } from './semanticReleaseVSMarketplace.js'
|
|
5
9
|
|
|
6
10
|
export {
|
|
11
|
+
createSemanticReleaseApp,
|
|
12
|
+
semanticReleaseApp,
|
|
7
13
|
semanticReleaseMonorepo,
|
|
8
14
|
semanticReleasePackage,
|
|
9
15
|
semanticReleaseProject,
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createSemanticReleaseConfig } from './common.js'
|
|
2
|
+
|
|
3
|
+
const DEFAULT_VERSION_ASSETS = [
|
|
4
|
+
'package.json',
|
|
5
|
+
'package-lock.json',
|
|
6
|
+
'CHANGELOG.md',
|
|
7
|
+
'android/app/build.gradle',
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
const DEFAULT_RELEASE_ASSETS = ['builds/*.apk']
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Конфигурация semantic-release для Android app репозиториев.
|
|
14
|
+
*
|
|
15
|
+
* - Не публикует в npm
|
|
16
|
+
* - Коммитит package + Android version-файлы
|
|
17
|
+
* - Прикрепляет к GitHub release APK из `builds/` (если есть; отсутствующие пропускаются)
|
|
18
|
+
*
|
|
19
|
+
* Сборку APK делайте в prepare проекта или отдельным CI job до publish.
|
|
20
|
+
*
|
|
21
|
+
* @param {Object} [options]
|
|
22
|
+
* @param {string|string[]} [options.branches=['master']]
|
|
23
|
+
* @param {string[]} [options.versionAssets] - файлы для @semantic-release/git
|
|
24
|
+
* @param {string[]|Object[]} [options.releaseAssets] - assets для @semantic-release/github
|
|
25
|
+
* @param {Array} [options.preparePlugins] - плагины после npm (например bump Android version + build APK)
|
|
26
|
+
* @param {Object} [options.githubConfig] - доп. опции github-плагина
|
|
27
|
+
* @param {Object} [options.gitConfig] - доп. опции git-плагина (мержатся поверх message/assets)
|
|
28
|
+
*/
|
|
29
|
+
function createSemanticReleaseApp({
|
|
30
|
+
branches = ['master'],
|
|
31
|
+
gitConfig = {},
|
|
32
|
+
githubConfig = {},
|
|
33
|
+
preparePlugins = [],
|
|
34
|
+
releaseAssets = DEFAULT_RELEASE_ASSETS,
|
|
35
|
+
versionAssets = DEFAULT_VERSION_ASSETS,
|
|
36
|
+
} = {}) {
|
|
37
|
+
return createSemanticReleaseConfig({
|
|
38
|
+
branches,
|
|
39
|
+
gitConfig: {
|
|
40
|
+
message:
|
|
41
|
+
'release: publishing new version ${nextRelease.version} [skip ci]',
|
|
42
|
+
assets: versionAssets,
|
|
43
|
+
...gitConfig,
|
|
44
|
+
},
|
|
45
|
+
githubConfig: {
|
|
46
|
+
assets: releaseAssets,
|
|
47
|
+
...githubConfig,
|
|
48
|
+
},
|
|
49
|
+
npmConfig: {
|
|
50
|
+
npmPublish: false,
|
|
51
|
+
},
|
|
52
|
+
preparePlugins,
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const semanticReleaseApp = createSemanticReleaseApp()
|
|
57
|
+
|
|
58
|
+
export { createSemanticReleaseApp, semanticReleaseApp }
|
package/smart-commit/cli.js
CHANGED
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
} from '../commitlint/commitlintCommon.js'
|
|
18
18
|
import { getBananaFrame } from './dancing-banana.js'
|
|
19
19
|
import { getNyanFrame } from './nyan-cat.js'
|
|
20
|
-
import { getPacmanFrame } from './pacman.js'
|
|
21
20
|
import { getUpyachkaFrame } from './upyachka.js'
|
|
22
21
|
|
|
23
22
|
const PACKAGE_NAME = '@itcase/config'
|
|
@@ -40,7 +39,6 @@ const AGENT_LOG_ROWS = 8
|
|
|
40
39
|
const AGENT_LOG_MAX = 160
|
|
41
40
|
const NYAN_FRAME_MS = 90
|
|
42
41
|
const BANANA_FRAME_MS = 100
|
|
43
|
-
const PACMAN_FRAME_MS = 120
|
|
44
42
|
const UPYACHKA_FRAME_MS = 100
|
|
45
43
|
const INDEX_LOCK_RETRIES = 8
|
|
46
44
|
const INDEX_LOCK_WAIT_MS = 250
|
|
@@ -51,15 +49,15 @@ const AGENT_WAIT_STEPS = [
|
|
|
51
49
|
'Waiting for response',
|
|
52
50
|
]
|
|
53
51
|
const HELP = `smart-commit [--dry-run] [--yes|-y] [--type t] [--model id] [--verbose]
|
|
54
|
-
[--cat|--nyan] [--banana] [--upyachka]
|
|
52
|
+
[--cat|--nyan] [--banana] [--upyachka]
|
|
55
53
|
|
|
56
54
|
Cursor Agent → commit messages by SCOPES → [y/N] → git commit
|
|
57
55
|
Run via: npm exec smart-commit (from project with @itcase/config)
|
|
58
56
|
Needs: agent login (or CURSOR_API_KEY) + commitlint.config.* with SCOPES
|
|
59
57
|
Default model: ${DEFAULT_MODEL} (override with --model / SMART_COMMIT_MODEL).
|
|
60
58
|
|
|
61
|
-
Progress sprite is random (nyan cat, banana,
|
|
62
|
-
Force with --cat, --banana,
|
|
59
|
+
Progress sprite is random (nyan cat, banana, or upyachka).
|
|
60
|
+
Force with --cat, --banana, or --upyachka. Agent log is below.
|
|
63
61
|
`
|
|
64
62
|
const AGENT_MISSING = `Cursor Agent CLI not found — smart-commit cannot run.
|
|
65
63
|
|
|
@@ -224,7 +222,6 @@ function parseArgs(argv) {
|
|
|
224
222
|
else if (arg === '--cat' || arg === '--nyan') option.sprite = 'cat'
|
|
225
223
|
else if (arg === '--banana') option.sprite = 'banana'
|
|
226
224
|
else if (arg === '--upyachka') option.sprite = 'upyachka'
|
|
227
|
-
else if (arg === '--pacman') option.sprite = 'pacman'
|
|
228
225
|
else if (arg === '--type') option.type = argv[++i] || ''
|
|
229
226
|
else if (arg === '--model') option.model = argv[++i] || ''
|
|
230
227
|
else if (arg.startsWith('--type=')) option.type = arg.slice(7)
|
|
@@ -235,7 +232,7 @@ function parseArgs(argv) {
|
|
|
235
232
|
}
|
|
236
233
|
|
|
237
234
|
function pickSprite(forced) {
|
|
238
|
-
const sprites = ['cat', 'banana', 'upyachka'
|
|
235
|
+
const sprites = ['cat', 'banana', 'upyachka']
|
|
239
236
|
if (sprites.includes(forced)) return forced
|
|
240
237
|
return sprites[Math.floor(Math.random() * sprites.length)]
|
|
241
238
|
}
|
|
@@ -556,10 +553,6 @@ async function withAgentProgress(context, callback) {
|
|
|
556
553
|
render: (index) => getNyanFrame(index, columns),
|
|
557
554
|
frameMs: NYAN_FRAME_MS,
|
|
558
555
|
},
|
|
559
|
-
pacman: {
|
|
560
|
-
render: (index) => getPacmanFrame(index, columns, spriteRows),
|
|
561
|
-
frameMs: PACMAN_FRAME_MS,
|
|
562
|
-
},
|
|
563
556
|
upyachka: {
|
|
564
557
|
render: (index) => getUpyachkaFrame(index, columns, spriteRows),
|
|
565
558
|
frameMs: UPYACHKA_FRAME_MS,
|
|
@@ -1,380 +1,265 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// Extracted from the classic dancing banana GIF (Trym Stene, 1999).
|
|
2
|
+
// 8 frames, 24×25px — fixed canvas, solid 2-space blocks.
|
|
3
3
|
|
|
4
4
|
const RESET = '\x1b[0m'
|
|
5
|
-
const FRAME_WIDTH =
|
|
6
|
-
const FRAME_HEIGHT =
|
|
5
|
+
const FRAME_WIDTH = 24
|
|
6
|
+
const FRAME_HEIGHT = 25
|
|
7
7
|
|
|
8
8
|
const COLORS = {
|
|
9
9
|
B: 236,
|
|
10
|
-
d:
|
|
10
|
+
d: 136,
|
|
11
|
+
E: 255,
|
|
11
12
|
R: 196,
|
|
12
|
-
W:
|
|
13
|
+
W: 255,
|
|
13
14
|
Y: 226,
|
|
14
|
-
y:
|
|
15
|
+
y: 214,
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
const FRAMES = [
|
|
18
19
|
[
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'
|
|
33
|
-
'
|
|
34
|
-
'
|
|
35
|
-
'
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
'
|
|
40
|
-
'
|
|
41
|
-
'
|
|
42
|
-
'
|
|
43
|
-
'
|
|
44
|
-
'........BWWWB.BYYYYyyBBWBWWWB....',
|
|
45
|
-
'........BWWBB.BYYYyyyBWWBBWWB....',
|
|
46
|
-
'.........BBBWBBYYyyyBBWWBBBB.....',
|
|
47
|
-
'...........BWBYYyyyBBBWBB........',
|
|
48
|
-
'...........BBBByyBBBWBBB.........',
|
|
49
|
-
'..........BBBBBBBBBBBBB..........',
|
|
50
|
-
'.........BBB........BBBB.........',
|
|
51
|
-
'........BWWWBBB...BBBWWWB........',
|
|
52
|
-
'........BWWWWWB...BWWWWWB........',
|
|
53
|
-
'.........BBBBBB...BBBBBB.........',
|
|
20
|
+
'........................',
|
|
21
|
+
'........................',
|
|
22
|
+
'........................',
|
|
23
|
+
'........................',
|
|
24
|
+
'............BB..........',
|
|
25
|
+
'............BBB.........',
|
|
26
|
+
'............dYB.........',
|
|
27
|
+
'............YYYB........',
|
|
28
|
+
'............YYYBB.......',
|
|
29
|
+
'..........BBBBYyB.......',
|
|
30
|
+
'.........BEBEEByy.......',
|
|
31
|
+
'.........BEBEEByy.......',
|
|
32
|
+
'..........BBBBYBy.......',
|
|
33
|
+
'...........BYYBBy.......',
|
|
34
|
+
'............RRRyy.......',
|
|
35
|
+
'............RBByy.......',
|
|
36
|
+
'.......BB..BYYYyB.BB....',
|
|
37
|
+
'......BEB.BBYYYyBBBEB...',
|
|
38
|
+
'......BEE.BYYYyBBBEEB...',
|
|
39
|
+
'.......BBBBYyyyBWBBB....',
|
|
40
|
+
'........BBYYyyBBWB......',
|
|
41
|
+
'.......BBBBBBBBBB.......',
|
|
42
|
+
'.......BB......BB.......',
|
|
43
|
+
'......BWWBB..BBWWB......',
|
|
44
|
+
'.......BBBB..BBBB.......',
|
|
54
45
|
],
|
|
55
46
|
[
|
|
56
|
-
'
|
|
57
|
-
'
|
|
58
|
-
'
|
|
59
|
-
'
|
|
60
|
-
'
|
|
61
|
-
'
|
|
62
|
-
'
|
|
63
|
-
'
|
|
64
|
-
'
|
|
65
|
-
'
|
|
66
|
-
'
|
|
67
|
-
'
|
|
68
|
-
'
|
|
69
|
-
'
|
|
70
|
-
'
|
|
71
|
-
'
|
|
72
|
-
'
|
|
73
|
-
'
|
|
74
|
-
'
|
|
75
|
-
'
|
|
76
|
-
'
|
|
77
|
-
'
|
|
78
|
-
'......
|
|
79
|
-
'......
|
|
80
|
-
'
|
|
81
|
-
'.......BBBBB.BBYYYyyyBBB.BBBBB...',
|
|
82
|
-
'...........BBBBYYyyyBB.BBB.......',
|
|
83
|
-
'.............BYYyyyBB............',
|
|
84
|
-
'............BBByyBBB.............',
|
|
85
|
-
'...........BBBBBBB.BB............',
|
|
86
|
-
'...........B........B............',
|
|
87
|
-
'.........BBBB.......BBBB.........',
|
|
88
|
-
'........BWWWWBB...BBWWWWB........',
|
|
89
|
-
'........BWWWWWB...BWWWWWB........',
|
|
90
|
-
'.........BBBBB.....BBBBB.........',
|
|
47
|
+
'........................',
|
|
48
|
+
'........................',
|
|
49
|
+
'........................',
|
|
50
|
+
'............BB..........',
|
|
51
|
+
'............ddB.........',
|
|
52
|
+
'............dYB.........',
|
|
53
|
+
'............YYYBB.......',
|
|
54
|
+
'............YYYyB.......',
|
|
55
|
+
'..........BBBBYyB.......',
|
|
56
|
+
'.........BBBWWByy.......',
|
|
57
|
+
'.........BEBEEByy.......',
|
|
58
|
+
'...........BYYBBy.......',
|
|
59
|
+
'...........BBBRBy.......',
|
|
60
|
+
'............RRRyy.......',
|
|
61
|
+
'...........BBYYyy.......',
|
|
62
|
+
'.....BB....BYYYyy...BB..',
|
|
63
|
+
'....BEEB..BBYYYyB..BEEB.',
|
|
64
|
+
'....BEEB..BYYYyBB..BEEB.',
|
|
65
|
+
'.....BBBBBBYYyyBB.BBBB..',
|
|
66
|
+
'.........BYYyyB.........',
|
|
67
|
+
'.........BByBBB.........',
|
|
68
|
+
'........B...............',
|
|
69
|
+
'.......BB......BB.......',
|
|
70
|
+
'......BWWBB..BBWWB......',
|
|
71
|
+
'.......BBB....BBB.......',
|
|
91
72
|
],
|
|
92
73
|
[
|
|
93
|
-
'
|
|
94
|
-
'
|
|
95
|
-
'
|
|
96
|
-
'
|
|
97
|
-
'
|
|
98
|
-
'
|
|
99
|
-
'
|
|
100
|
-
'
|
|
101
|
-
'.
|
|
102
|
-
'.
|
|
103
|
-
'.
|
|
104
|
-
'
|
|
105
|
-
'
|
|
106
|
-
'
|
|
107
|
-
'.........
|
|
108
|
-
'
|
|
109
|
-
'
|
|
110
|
-
'
|
|
111
|
-
'
|
|
112
|
-
'
|
|
113
|
-
'
|
|
114
|
-
'
|
|
115
|
-
'
|
|
116
|
-
'
|
|
117
|
-
'
|
|
118
|
-
'.............BBByBB..............',
|
|
119
|
-
'..............BBBBB..............',
|
|
120
|
-
'..............B...B..............',
|
|
121
|
-
'.............BB...BB.............',
|
|
122
|
-
'.............B.....B.............',
|
|
123
|
-
'.............B.....B.............',
|
|
124
|
-
'..........BBBBB...BBBBB..........',
|
|
125
|
-
'........BBWWWWB...BWWWWBB........',
|
|
126
|
-
'........BWWWWBB...BBWWWWB........',
|
|
127
|
-
'........BBBBB.......BBBBB........',
|
|
74
|
+
'............B...........',
|
|
75
|
+
'...........BdB..........',
|
|
76
|
+
'...........BdBB.........',
|
|
77
|
+
'..........BBYyB.........',
|
|
78
|
+
'..........BYYYy.........',
|
|
79
|
+
'.BBB.....BBBBBB......BB.',
|
|
80
|
+
'.WWW.....WBWWBWB....BWWB',
|
|
81
|
+
'.WWB.....WWWWWWB....BBWB',
|
|
82
|
+
'.BBB.....BBBBBBB....BBB.',
|
|
83
|
+
'.....BB..BBBBBRB.BBB....',
|
|
84
|
+
'.......BBBRRRRBB.B......',
|
|
85
|
+
'.........BYBBYYB........',
|
|
86
|
+
'.........BYYYYyB........',
|
|
87
|
+
'.........BYYYYyB........',
|
|
88
|
+
'.........BYYYYy.........',
|
|
89
|
+
'.........BYYYyy.........',
|
|
90
|
+
'.........BYYyyB.........',
|
|
91
|
+
'.........BYYyBB.........',
|
|
92
|
+
'.........BBBBB..........',
|
|
93
|
+
'..........B..B..........',
|
|
94
|
+
'.........BB..BB.........',
|
|
95
|
+
'.........B....B.........',
|
|
96
|
+
'.......BBBB..BBBB.......',
|
|
97
|
+
'......BWWWB..BWWWB......',
|
|
98
|
+
'......BBB......BBB......',
|
|
128
99
|
],
|
|
129
100
|
[
|
|
130
|
-
'
|
|
131
|
-
'
|
|
132
|
-
'
|
|
133
|
-
'
|
|
134
|
-
'
|
|
135
|
-
'
|
|
136
|
-
'
|
|
137
|
-
'
|
|
138
|
-
'
|
|
139
|
-
'
|
|
140
|
-
'
|
|
141
|
-
'
|
|
142
|
-
'..
|
|
143
|
-
'.
|
|
144
|
-
'
|
|
145
|
-
'
|
|
146
|
-
'
|
|
147
|
-
'
|
|
148
|
-
'
|
|
149
|
-
'
|
|
150
|
-
'..........
|
|
151
|
-
'
|
|
152
|
-
'
|
|
153
|
-
'
|
|
154
|
-
'
|
|
155
|
-
'............BByyYYB..............',
|
|
156
|
-
'.............BByBBB..............',
|
|
157
|
-
'.............BBBBBB..............',
|
|
158
|
-
'.............B....B..............',
|
|
159
|
-
'............BB....BB.............',
|
|
160
|
-
'............B......B.............',
|
|
161
|
-
'..........BBB......BBBB..........',
|
|
162
|
-
'........BBWWWBB...BBWWWBB........',
|
|
163
|
-
'........BWWWWWB...BWWWWWB........',
|
|
164
|
-
'........BBBBBB.....BBBBBB........',
|
|
101
|
+
'........................',
|
|
102
|
+
'..........BB............',
|
|
103
|
+
'.........Bdd............',
|
|
104
|
+
'.........Bdd............',
|
|
105
|
+
'.........yYYB...........',
|
|
106
|
+
'........ByYYB...........',
|
|
107
|
+
'........BBBYBB..........',
|
|
108
|
+
'.......BBWWBWWB.........',
|
|
109
|
+
'.......BBBWBBWB.........',
|
|
110
|
+
'.WWB...ByBBYBB...BWW....',
|
|
111
|
+
'.EEE...BBYYYYB...EEE....',
|
|
112
|
+
'.BBB...ByRRRRB...BBB....',
|
|
113
|
+
'....B..ByBRRBB..B.......',
|
|
114
|
+
'....BB.ByYBBYB.BB.......',
|
|
115
|
+
'.......BBYYYYB..........',
|
|
116
|
+
'........BYYYYB..........',
|
|
117
|
+
'........ByYYYB..........',
|
|
118
|
+
'.........yyYYB..........',
|
|
119
|
+
'.........ByyYB..........',
|
|
120
|
+
'.........BBBBB..........',
|
|
121
|
+
'.........B...B..........',
|
|
122
|
+
'..............B.........',
|
|
123
|
+
'.......BB.....BBB.......',
|
|
124
|
+
'......BWWBB..BBWWB......',
|
|
125
|
+
'......BBBB....BBBB......',
|
|
165
126
|
],
|
|
166
127
|
[
|
|
167
|
-
'
|
|
168
|
-
'
|
|
169
|
-
'
|
|
170
|
-
'
|
|
171
|
-
'
|
|
172
|
-
'
|
|
173
|
-
'
|
|
174
|
-
'
|
|
175
|
-
'
|
|
176
|
-
'
|
|
177
|
-
'
|
|
178
|
-
'
|
|
179
|
-
'..........
|
|
180
|
-
'
|
|
181
|
-
'
|
|
182
|
-
'
|
|
183
|
-
'
|
|
184
|
-
'
|
|
185
|
-
'
|
|
186
|
-
'
|
|
187
|
-
'
|
|
188
|
-
'
|
|
189
|
-
'
|
|
190
|
-
'
|
|
191
|
-
'
|
|
192
|
-
'....BWWWBWBByyYYYYB.BWWWB........',
|
|
193
|
-
'....BWWBBWWByyyYYYB.BBWWB........',
|
|
194
|
-
'.....BBBBWWBByyyYYBB.BBB.........',
|
|
195
|
-
'........BBWBBByyyYYB.B...........',
|
|
196
|
-
'.........BBBWBBByyBBBB...........',
|
|
197
|
-
'..........BBBBBBBBBBBBB..........',
|
|
198
|
-
'.........BBBB........BBB.........',
|
|
199
|
-
'........BWWWBBB...BBBWWWB........',
|
|
200
|
-
'........BWWWWWB...BWWWWWB........',
|
|
201
|
-
'.........BBBBBB...BBBBBB.........',
|
|
128
|
+
'........................',
|
|
129
|
+
'........................',
|
|
130
|
+
'........................',
|
|
131
|
+
'........................',
|
|
132
|
+
'..........BB............',
|
|
133
|
+
'.........BBB............',
|
|
134
|
+
'.........BYd............',
|
|
135
|
+
'........BYYY............',
|
|
136
|
+
'.......BBYYY............',
|
|
137
|
+
'.......ByYBBBB..........',
|
|
138
|
+
'.......yyBEEBEB.........',
|
|
139
|
+
'.......yyBEEBEB.........',
|
|
140
|
+
'.......yBYBBBB..........',
|
|
141
|
+
'.......yBBYYB...........',
|
|
142
|
+
'.......yyRRR............',
|
|
143
|
+
'.......yyBBR............',
|
|
144
|
+
'....BB.ByYYYB..BB.......',
|
|
145
|
+
'...BEBBByYYYBB.BEB......',
|
|
146
|
+
'...BEEBBByYYYB.EEB......',
|
|
147
|
+
'....BBBWByyyYBBBB.......',
|
|
148
|
+
'......BWBByyYYBB........',
|
|
149
|
+
'.......BBBBBBBBBB.......',
|
|
150
|
+
'.......BB......BB.......',
|
|
151
|
+
'......BWWBB..BBWWB......',
|
|
152
|
+
'.......BBBB..BBBB.......',
|
|
202
153
|
],
|
|
203
154
|
[
|
|
204
|
-
'
|
|
205
|
-
'
|
|
206
|
-
'
|
|
207
|
-
'
|
|
208
|
-
'
|
|
209
|
-
'
|
|
210
|
-
'
|
|
211
|
-
'............
|
|
212
|
-
'
|
|
213
|
-
'
|
|
214
|
-
'
|
|
215
|
-
'
|
|
216
|
-
'
|
|
217
|
-
'
|
|
218
|
-
'
|
|
219
|
-
'
|
|
220
|
-
'
|
|
221
|
-
'
|
|
222
|
-
'
|
|
223
|
-
'.........
|
|
224
|
-
'.........
|
|
225
|
-
'
|
|
226
|
-
'
|
|
227
|
-
'..
|
|
228
|
-
'
|
|
229
|
-
'...BBBBB.BBByyyYYYBB.BBBBB.......',
|
|
230
|
-
'.......BBB.BByyyYYBBBB...........',
|
|
231
|
-
'............BByyyYYB.............',
|
|
232
|
-
'.............BBByyBBB............',
|
|
233
|
-
'............BB.BBBBBBB...........',
|
|
234
|
-
'............B........B...........',
|
|
235
|
-
'.........BBBB.......BBBB.........',
|
|
236
|
-
'........BWWWWBB...BBWWWWB........',
|
|
237
|
-
'........BWWWWWB...BWWWWWB........',
|
|
238
|
-
'.........BBBBB.....BBBBB.........',
|
|
155
|
+
'........................',
|
|
156
|
+
'........................',
|
|
157
|
+
'........................',
|
|
158
|
+
'..........BB............',
|
|
159
|
+
'.........Bdd............',
|
|
160
|
+
'.........BYd............',
|
|
161
|
+
'.......BBYYY............',
|
|
162
|
+
'.......ByYYY............',
|
|
163
|
+
'.......ByYBBBB..........',
|
|
164
|
+
'.......yyBWWBBB.........',
|
|
165
|
+
'.......yyBEEBEB.........',
|
|
166
|
+
'.......yBBYYB...........',
|
|
167
|
+
'.......yBRBBB...........',
|
|
168
|
+
'.......yyRRR............',
|
|
169
|
+
'.......yyYYBB...........',
|
|
170
|
+
'..BB...yyYYYB....BB.....',
|
|
171
|
+
'.BEEB..ByYYYBB..BEEB....',
|
|
172
|
+
'.BEEB..BByYYYB..BEEB....',
|
|
173
|
+
'..BBBB.BByyYYBBBBBB.....',
|
|
174
|
+
'.........ByyYYB.........',
|
|
175
|
+
'.........BBByBB.........',
|
|
176
|
+
'...............B........',
|
|
177
|
+
'.......BB......BB.......',
|
|
178
|
+
'......BWWBB..BBWWB......',
|
|
179
|
+
'.......BBB....BBB.......',
|
|
239
180
|
],
|
|
240
181
|
[
|
|
241
|
-
'
|
|
242
|
-
'
|
|
243
|
-
'
|
|
244
|
-
'
|
|
245
|
-
'
|
|
246
|
-
'
|
|
247
|
-
'
|
|
248
|
-
'.
|
|
249
|
-
'
|
|
250
|
-
'
|
|
251
|
-
'
|
|
252
|
-
'
|
|
253
|
-
'
|
|
254
|
-
'
|
|
255
|
-
'
|
|
256
|
-
'.........
|
|
257
|
-
'
|
|
258
|
-
'
|
|
259
|
-
'
|
|
260
|
-
'
|
|
261
|
-
'
|
|
262
|
-
'
|
|
263
|
-
'
|
|
264
|
-
'
|
|
265
|
-
'
|
|
266
|
-
'..............BByBBB.............',
|
|
267
|
-
'..............BBBBB..............',
|
|
268
|
-
'..............B...B..............',
|
|
269
|
-
'.............BB...BB.............',
|
|
270
|
-
'.............B.....B.............',
|
|
271
|
-
'.............B.....B.............',
|
|
272
|
-
'..........BBBBB...BBBBB..........',
|
|
273
|
-
'........BBWWWWB...BWWWWBB........',
|
|
274
|
-
'........BWWWWBB...BBWWWWB........',
|
|
275
|
-
'........BBBBB.......BBBBB........',
|
|
182
|
+
'...........B............',
|
|
183
|
+
'..........BdB...........',
|
|
184
|
+
'.........BBdB...........',
|
|
185
|
+
'.........ByYBB..........',
|
|
186
|
+
'.........yYYYB..........',
|
|
187
|
+
'.BB......BBBBBB.....BBB.',
|
|
188
|
+
'BWWB....BWBWWBW.....WWW.',
|
|
189
|
+
'BWBB....BWWWWWW.....BWW.',
|
|
190
|
+
'.BBB....BBBBBBB.....BBB.',
|
|
191
|
+
'....BBB.BRBBBBB..BB.....',
|
|
192
|
+
'......B.BBRRRRBBB.......',
|
|
193
|
+
'........BYYBBYB.........',
|
|
194
|
+
'........ByYYYYB.........',
|
|
195
|
+
'........ByYYYYB.........',
|
|
196
|
+
'.........yYYYYB.........',
|
|
197
|
+
'.........yyYYYB.........',
|
|
198
|
+
'.........ByyYYB.........',
|
|
199
|
+
'.........BByYYB.........',
|
|
200
|
+
'..........BBBBB.........',
|
|
201
|
+
'..........B..B..........',
|
|
202
|
+
'.........BB..BB.........',
|
|
203
|
+
'.........B....B.........',
|
|
204
|
+
'.......BBBB..BBBB.......',
|
|
205
|
+
'......BWWWB..BWWWB......',
|
|
206
|
+
'......BBB......BBB......',
|
|
276
207
|
],
|
|
277
208
|
[
|
|
278
|
-
'
|
|
279
|
-
'
|
|
280
|
-
'
|
|
281
|
-
'
|
|
282
|
-
'
|
|
283
|
-
'
|
|
284
|
-
'
|
|
285
|
-
'
|
|
286
|
-
'
|
|
287
|
-
'
|
|
288
|
-
'
|
|
289
|
-
'
|
|
290
|
-
'
|
|
291
|
-
'
|
|
292
|
-
'
|
|
293
|
-
'
|
|
294
|
-
'
|
|
295
|
-
'.........
|
|
296
|
-
'..........
|
|
297
|
-
'
|
|
298
|
-
'
|
|
299
|
-
'..............
|
|
300
|
-
'
|
|
301
|
-
'
|
|
302
|
-
'
|
|
303
|
-
'..............BYYyyBB............',
|
|
304
|
-
'..............BBByBB.............',
|
|
305
|
-
'..............BBBBBB.............',
|
|
306
|
-
'..............B....B.............',
|
|
307
|
-
'.............BB....BB............',
|
|
308
|
-
'.............B......B............',
|
|
309
|
-
'..........BBBB......BBB..........',
|
|
310
|
-
'........BBWWWBB...BBWWWBB........',
|
|
311
|
-
'........BWWWWWB...BWWWWWB........',
|
|
312
|
-
'........BBBBBB.....BBBBBB........',
|
|
209
|
+
'........................',
|
|
210
|
+
'............BB..........',
|
|
211
|
+
'............ddB.........',
|
|
212
|
+
'............ddB.........',
|
|
213
|
+
'...........BYYy.........',
|
|
214
|
+
'...........BYYyB........',
|
|
215
|
+
'..........BBYBBB........',
|
|
216
|
+
'.........BWWBWWBB.......',
|
|
217
|
+
'.........BWBBWBBB.......',
|
|
218
|
+
'....WWB...BBYBByB...BWW.',
|
|
219
|
+
'....EEE...BYYYYBB...EEE.',
|
|
220
|
+
'....BBB...BRRRRyB...BBB.',
|
|
221
|
+
'.......B..BBRRByB..B....',
|
|
222
|
+
'.......BB.BYBBYyB.BB....',
|
|
223
|
+
'..........BYYYYBB.......',
|
|
224
|
+
'..........BYYYYB........',
|
|
225
|
+
'..........BYYYyB........',
|
|
226
|
+
'..........BYYyy.........',
|
|
227
|
+
'..........BYyyB.........',
|
|
228
|
+
'..........BBBBB.........',
|
|
229
|
+
'..........B...B.........',
|
|
230
|
+
'.........B..............',
|
|
231
|
+
'.......BBB.....BB.......',
|
|
232
|
+
'......BWWBB..BBWWB......',
|
|
233
|
+
'......BBBB....BBBB......',
|
|
313
234
|
],
|
|
314
235
|
]
|
|
315
236
|
|
|
316
|
-
function
|
|
317
|
-
if (srcSize <= maxSize) {
|
|
318
|
-
return Array.from({ length: srcSize }, (_, i) => i)
|
|
319
|
-
}
|
|
320
|
-
return Array.from({ length: maxSize }, (_, i) =>
|
|
321
|
-
Math.round((i * (srcSize - 1)) / (maxSize - 1)),
|
|
322
|
-
)
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
function cellScale(terminalColumns, terminalRows) {
|
|
326
|
-
const maxCols = Math.max(8, Math.floor((terminalColumns - 1) / 2))
|
|
327
|
-
const maxRows = Math.max(8, (terminalRows || 24) - 2)
|
|
328
|
-
return Math.max(
|
|
329
|
-
1,
|
|
330
|
-
Math.min(
|
|
331
|
-
Math.floor(maxCols / FRAME_WIDTH),
|
|
332
|
-
Math.floor(maxRows / FRAME_HEIGHT),
|
|
333
|
-
),
|
|
334
|
-
)
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
function renderRow(row, colIndexes, scale) {
|
|
237
|
+
function renderRow(row) {
|
|
338
238
|
const padded = row.padEnd(FRAME_WIDTH, '.').slice(0, FRAME_WIDTH)
|
|
339
239
|
let line = ''
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
last = -1
|
|
348
|
-
}
|
|
349
|
-
line += ' '
|
|
350
|
-
continue
|
|
351
|
-
}
|
|
352
|
-
if (code !== last) {
|
|
353
|
-
line += `\x1b[48;5;${code}m`
|
|
354
|
-
last = code
|
|
355
|
-
}
|
|
240
|
+
for (const cell of padded) {
|
|
241
|
+
if (cell === '.') {
|
|
242
|
+
line += ' '
|
|
243
|
+
continue
|
|
244
|
+
}
|
|
245
|
+
const code = COLORS[cell]
|
|
246
|
+
if (code === undefined) {
|
|
356
247
|
line += ' '
|
|
248
|
+
continue
|
|
357
249
|
}
|
|
250
|
+
const bold = cell === 'E' ? '\x1b[1m' : ''
|
|
251
|
+
line += `${bold}\x1b[48;5;${code}m ${RESET}`
|
|
358
252
|
}
|
|
359
|
-
if (last !== -1) line += RESET
|
|
360
253
|
return line
|
|
361
254
|
}
|
|
362
255
|
|
|
363
|
-
export function getBananaFrame(index
|
|
364
|
-
const scale = cellScale(terminalColumns, terminalRows)
|
|
365
|
-
const maxCols = Math.max(8, Math.floor((terminalColumns - 1) / (2 * scale)))
|
|
366
|
-
const maxRows = Math.max(8, Math.floor(((terminalRows || 24) - 2) / scale))
|
|
367
|
-
const colIndexes = pickIndexes(FRAME_WIDTH, maxCols)
|
|
368
|
-
const rowIndexes = pickIndexes(FRAME_HEIGHT, maxRows)
|
|
256
|
+
export function getBananaFrame(index) {
|
|
369
257
|
const frame = FRAMES[index % FRAMES.length]
|
|
370
|
-
const lines =
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
for (let s = 0; s < scale; s += 1) {
|
|
374
|
-
lines.push(rendered)
|
|
375
|
-
}
|
|
258
|
+
const lines = frame.map(renderRow)
|
|
259
|
+
while (lines.length < FRAME_HEIGHT) {
|
|
260
|
+
lines.push(' '.repeat(FRAME_WIDTH * 2))
|
|
376
261
|
}
|
|
377
|
-
return lines.join('\n')
|
|
262
|
+
return lines.slice(0, FRAME_HEIGHT).join('\n')
|
|
378
263
|
}
|
|
379
264
|
|
|
380
265
|
export function getBananaFrameCount() {
|
package/lint-staged-ts/index.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs'
|
|
2
|
-
import { dirname, join, resolve } from 'node:path'
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
4
|
-
|
|
5
|
-
const checkNoFileDependencies = join(
|
|
6
|
-
dirname(fileURLToPath(import.meta.url)),
|
|
7
|
-
'../lint-staged/checkNoFileDependencies.js',
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
// eslint-disable-next-line import/no-default-export
|
|
11
|
-
export default {
|
|
12
|
-
// На любой staged-файл: если в package.json есть file:/link: — exit 1, коммит не пройдёт
|
|
13
|
-
'*': () => `node ${JSON.stringify(checkNoFileDependencies)}`,
|
|
14
|
-
'*.(ts|tsx)': (files) => {
|
|
15
|
-
const existing = files.filter((file) => existsSync(file))
|
|
16
|
-
const tsFiles = existing.filter((file) => /\.(ts|tsx)$/.test(file))
|
|
17
|
-
const commands = []
|
|
18
|
-
if (tsFiles.length > 0) {
|
|
19
|
-
commands.push('tsc --noEmit --pretty')
|
|
20
|
-
}
|
|
21
|
-
if (existing.length > 0) {
|
|
22
|
-
commands.push(`npx eslint --fix ${existing.join(' ')}`)
|
|
23
|
-
}
|
|
24
|
-
return commands.length ? commands : 'true'
|
|
25
|
-
},
|
|
26
|
-
'*.css': (files) => {
|
|
27
|
-
const existing = files.filter((file) => existsSync(file))
|
|
28
|
-
if (!existing.length) return 'true'
|
|
29
|
-
return `npx stylelint --fix --color --formatter verbose ${existing.join(' ')}`
|
|
30
|
-
},
|
|
31
|
-
'*.mdx': (files) => {
|
|
32
|
-
const existing = files.filter((file) => existsSync(file))
|
|
33
|
-
if (!existing.length) return 'true'
|
|
34
|
-
return `npx eslint --fix ${existing.join(' ')}`
|
|
35
|
-
},
|
|
36
|
-
'package.json': (files) => {
|
|
37
|
-
// Проверяем, есть ли package.json в корне репозитория
|
|
38
|
-
const rootPackageJson = resolve(process.cwd(), 'package.json')
|
|
39
|
-
const isRoot = files.some((file) => resolve(file) === rootPackageJson)
|
|
40
|
-
if (existsSync(rootPackageJson) && isRoot) {
|
|
41
|
-
// lint-staged автоматически добавляет изменения задач в index
|
|
42
|
-
return 'npm install --package-lock-only'
|
|
43
|
-
}
|
|
44
|
-
return 'true' // Пропускаем, если не найден
|
|
45
|
-
},
|
|
46
|
-
}
|
package/smart-commit/pacman.js
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
// High-resolution terminal sprites reconstructed from the supplied reference.
|
|
2
|
-
// Two vertical source pixels share one terminal cell via half-block glyphs.
|
|
3
|
-
|
|
4
|
-
const RESET = '\x1b[0m'
|
|
5
|
-
const FRAME_WIDTH = 80
|
|
6
|
-
const FRAME_HEIGHT = 16
|
|
7
|
-
const FRAME_COUNT = 82
|
|
8
|
-
const SPRITE_WIDTH = 14
|
|
9
|
-
const SPRITE_HEIGHT = 16
|
|
10
|
-
const COLORS = { B: 33, C: 51, O: 208, P: 218, R: 196, W: 231, Y: 226 }
|
|
11
|
-
|
|
12
|
-
const GHOST = [
|
|
13
|
-
'................',
|
|
14
|
-
'......XXXX......',
|
|
15
|
-
'....XXXXXXXX....',
|
|
16
|
-
'...XXXXXXXXXX...',
|
|
17
|
-
'..XXXXXXXXXXXX..',
|
|
18
|
-
'..XWWXXXXWWWXXX.',
|
|
19
|
-
'..WWWWXXWWWWXX..',
|
|
20
|
-
'..BBWWXXBBWWXX..',
|
|
21
|
-
'.XBBWWXXBBWWXXX.',
|
|
22
|
-
'.XXWWXXXXWWXXXX.',
|
|
23
|
-
'.XXXXXXXXXXXXXX.',
|
|
24
|
-
'.XXXXXXXXXXXXXX.',
|
|
25
|
-
'.XXXXXXXXXXXXXX.',
|
|
26
|
-
'.XXXXXXXXXXXXXX.',
|
|
27
|
-
'.XXXXXXXXXXXXXX.',
|
|
28
|
-
'.XX.XXX..XXX.XX.',
|
|
29
|
-
'.X...XX..XX...X.',
|
|
30
|
-
'................',
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
const PACMAN_CLOSED = [
|
|
34
|
-
'................',
|
|
35
|
-
'.....YYYYYY.....',
|
|
36
|
-
'...YYYYYYYYYY...',
|
|
37
|
-
'..YYYYYYYYYYYY..',
|
|
38
|
-
'.YYYYYYYYYYYYYY.',
|
|
39
|
-
'YYYYYYYYYYYYYYYY',
|
|
40
|
-
'YYYYYYYYYYYYYYYY',
|
|
41
|
-
'YYYYYYYYYYYYYYYY',
|
|
42
|
-
'YYYYYYYYYYYYYYYY',
|
|
43
|
-
'YYYYYYYYYYYYYYYY',
|
|
44
|
-
'YYYYYYYYYYYYYYYY',
|
|
45
|
-
'YYYYYYYYYYYYYYYY',
|
|
46
|
-
'YYYYYYYYYYYYYYYY',
|
|
47
|
-
'.YYYYYYYYYYYYYY.',
|
|
48
|
-
'..YYYYYYYYYYYY..',
|
|
49
|
-
'...YYYYYYYYYY...',
|
|
50
|
-
'.....YYYYYY.....',
|
|
51
|
-
'................',
|
|
52
|
-
]
|
|
53
|
-
|
|
54
|
-
const PACMAN_OPEN = [
|
|
55
|
-
'................',
|
|
56
|
-
'.....YYYYYY.....',
|
|
57
|
-
'...YYYYYYYYYY...',
|
|
58
|
-
'..YYYYYYYYYYYY..',
|
|
59
|
-
'.YYYYYYYYYYYYYY.',
|
|
60
|
-
'YYYYYYYYYYYYYYYY',
|
|
61
|
-
'..YYYYYYYYYYYYYY',
|
|
62
|
-
'....YYYYYYYYYYYY',
|
|
63
|
-
'......YYYYYYYYYY',
|
|
64
|
-
'........YYYYYYYY',
|
|
65
|
-
'......YYYYYYYYYY',
|
|
66
|
-
'....YYYYYYYYYYYY',
|
|
67
|
-
'..YYYYYYYYYYYYYY',
|
|
68
|
-
'.YYYYYYYYYYYYYY.',
|
|
69
|
-
'..YYYYYYYYYYYY..',
|
|
70
|
-
'...YYYYYYYYYY...',
|
|
71
|
-
'.....YYYYYY.....',
|
|
72
|
-
'................',
|
|
73
|
-
]
|
|
74
|
-
|
|
75
|
-
function drawSprite(canvas, sprite, left, color) {
|
|
76
|
-
const columns = pickIndexes(sprite[0].length, SPRITE_WIDTH)
|
|
77
|
-
const rows = pickIndexes(sprite.length, SPRITE_HEIGHT)
|
|
78
|
-
for (let y = 0; y < rows.length; y++) {
|
|
79
|
-
for (let x = 0; x < columns.length; x++) {
|
|
80
|
-
const cell = sprite[rows[y]][columns[x]]
|
|
81
|
-
const targetX = left + x
|
|
82
|
-
if (cell === '.' || targetX < 0 || targetX >= FRAME_WIDTH) continue
|
|
83
|
-
canvas[y][targetX] = cell === 'X' ? color : cell
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function buildFrame(index) {
|
|
89
|
-
const canvas = Array.from({ length: FRAME_HEIGHT }, () =>
|
|
90
|
-
Array(FRAME_WIDTH).fill('.'),
|
|
91
|
-
)
|
|
92
|
-
const pacmanLeft = FRAME_WIDTH - 7 - index * 2
|
|
93
|
-
const pacman = Math.floor(index / 2) % 2 ? PACMAN_CLOSED : PACMAN_OPEN
|
|
94
|
-
drawSprite(canvas, pacman, pacmanLeft, 'Y')
|
|
95
|
-
|
|
96
|
-
for (const [ghostIndex, color] of ['R', 'C', 'P', 'O'].entries()) {
|
|
97
|
-
drawSprite(canvas, GHOST, pacmanLeft + 20 + ghostIndex * 18, color)
|
|
98
|
-
}
|
|
99
|
-
return canvas
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function pickIndexes(srcSize, maxSize) {
|
|
103
|
-
if (srcSize <= maxSize) {
|
|
104
|
-
return Array.from({ length: srcSize }, (_, index) => index)
|
|
105
|
-
}
|
|
106
|
-
return Array.from({ length: maxSize }, (_, index) =>
|
|
107
|
-
Math.round((index * (srcSize - 1)) / (maxSize - 1)),
|
|
108
|
-
)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function paint(top, bottom) {
|
|
112
|
-
const topColor = COLORS[top]
|
|
113
|
-
const bottomColor = COLORS[bottom]
|
|
114
|
-
if (topColor === undefined && bottomColor === undefined) return ' '
|
|
115
|
-
if (topColor === bottomColor) return `\x1b[48;5;${topColor}m \x1b[0m`
|
|
116
|
-
if (topColor === undefined) return `\x1b[38;5;${bottomColor}m▄\x1b[0m`
|
|
117
|
-
if (bottomColor === undefined) return `\x1b[38;5;${topColor}m▀\x1b[0m`
|
|
118
|
-
return `\x1b[38;5;${topColor};48;5;${bottomColor}m▀\x1b[0m`
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function getPacmanFrame(index, terminalColumns = 80, terminalRows = 24) {
|
|
122
|
-
const frame = buildFrame(index % FRAME_COUNT)
|
|
123
|
-
const maxColumns = Math.max(16, (terminalColumns || 80) - 1)
|
|
124
|
-
const maxLogicalRows = Math.max(4, ((terminalRows || 24) - 2) * 2)
|
|
125
|
-
const columns = pickIndexes(FRAME_WIDTH, maxColumns)
|
|
126
|
-
const rowCount = Math.min(FRAME_HEIGHT, maxLogicalRows)
|
|
127
|
-
const rows = pickIndexes(FRAME_HEIGHT, rowCount - (rowCount % 2))
|
|
128
|
-
const lines = []
|
|
129
|
-
|
|
130
|
-
for (let index = 0; index < rows.length; index += 2) {
|
|
131
|
-
const top = frame[rows[index]]
|
|
132
|
-
const bottom = frame[rows[index + 1]]
|
|
133
|
-
lines.push(columns.map((x) => paint(top[x], bottom[x])).join('') + RESET)
|
|
134
|
-
}
|
|
135
|
-
return lines.join('\n')
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export function getPacmanFrameCount() {
|
|
139
|
-
return FRAME_COUNT
|
|
140
|
-
}
|