@itcase/config 1.7.0 → 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 CHANGED
@@ -161,7 +161,7 @@ CLI ставится в `~/.local/bin`. Логин в Cursor IDE этот CLI н
161
161
 
162
162
  Обновление CLI: `agent update`.
163
163
 
164
- Пока Agent думает, в терминале крутится pixel-анимация (случайно nyan cat, dancing banana, упячка или Pac-Man) + статус `(Ns)`, а под ними живой лог агента (`log-update`). Пока процесс агента жив, CLI его не убивает по таймауту. Принудительно: `--cat` / `--banana` / `--upyachka` / `--pacman`. Для полного лога: `npm run smart-commit -- --verbose --dry-run`.
164
+ Пока Agent думает, в терминале крутится pixel-анимация (случайно nyan cat, dancing banana или упячка) + статус `(Ns)`, а под ними живой лог агента (`log-update`). Пока процесс агента жив, CLI его не убивает по таймауту. Принудительно: `--cat` / `--banana` / `--upyachka`. Для полного лога: `npm run smart-commit -- --verbose --dry-run`.
165
165
 
166
166
  > **Важно:** в npm есть одноимённый пакет `smart-commit`. Используйте `npm run smart-commit` из проекта с `@itcase/config` — bin берётся из `node_modules`. `npx smart-commit` без локальной установки может подтянуть чужой пакет; CLI перед запуском проверяет, что выполняется именно `@itcase/config`.
167
167
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itcase/config",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "author": "ITCase",
5
5
  "description": "ITCase Config",
6
6
  "engines": {
@@ -39,9 +39,9 @@
39
39
  "registry": "https://registry.npmjs.org/"
40
40
  },
41
41
  "dependencies": {
42
- "@commitlint/cli": "^21.2.2",
43
- "@commitlint/config-conventional": "^21.2.2",
44
- "@commitlint/cz-commitlint": "^21.2.2",
42
+ "@commitlint/cli": "^21.2.3",
43
+ "@commitlint/config-conventional": "^21.2.3",
44
+ "@commitlint/cz-commitlint": "^21.2.3",
45
45
  "@lehoczky/postcss-fluid": "^1.0.3",
46
46
  "@lerna-lite/cli": "^5.6.1",
47
47
  "@lerna-lite/exec": "^5.6.1",
@@ -62,12 +62,12 @@
62
62
  "@svgr/plugin-jsx": "^8.1.0",
63
63
  "@svgr/plugin-svgo": "^8.1.0",
64
64
  "@svgr/webpack": "^8.1.0",
65
- "autoprefixer": "^10.6.0",
65
+ "autoprefixer": "^10.6.1",
66
66
  "chokidar-cli": "^3.0.0",
67
67
  "commitizen": "^4.3.2",
68
68
  "conventional-changelog-conventionalcommits": "9.3.1",
69
- "cssnano": "^9.0.4",
70
- "cssnano-preset-default": "^9.0.4",
69
+ "cssnano": "^9.0.5",
70
+ "cssnano-preset-default": "^9.0.5",
71
71
  "inquirer": "^14.2.2",
72
72
  "log-update": "^8.0.0",
73
73
  "postcss": "^8.5.28",
@@ -78,7 +78,7 @@
78
78
  "postcss-combine-duplicated-selectors": "^10.0.3",
79
79
  "postcss-convert-unit": "^0.1.3",
80
80
  "postcss-dark-theme-class": "^2.0.0",
81
- "postcss-discard-duplicates": "^9.0.2",
81
+ "postcss-discard-duplicates": "^9.0.3",
82
82
  "postcss-each": "^1.1.0",
83
83
  "postcss-easings": "^4.0.0",
84
84
  "postcss-extend-rule": "^4.0.0",
@@ -108,15 +108,15 @@
108
108
  "rollup-plugin-peer-deps-external": "^2.2.4",
109
109
  "rollup-preserve-directives": "^1.1.3",
110
110
  "semantic-release": "^25.0.9",
111
- "semantic-release-lerna": "^3.6.4"
111
+ "semantic-release-lerna": "^3.6.5"
112
112
  },
113
113
  "devDependencies": {
114
- "@itcase/lint": "^1.1.125",
114
+ "@itcase/lint": "^1.1.126",
115
115
  "eslint": "9.39.2",
116
116
  "husky": "^9.1.7",
117
117
  "inquirer": "^14.2.2",
118
118
  "lint-staged": "^17.5.1",
119
- "prettier": "^3.9.6",
119
+ "prettier": "^3.9.8",
120
120
  "storybook": "^10.6.0",
121
121
  "stylelint": "^17.15.0",
122
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 {Array} options.additionalPlugins - Дополнительные плагины для добавления перед changelog и git
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(['@semantic-release/git', gitConfig], commonPlugins.github)
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 }
@@ -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] [--pacman]
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, upyachka, or Pac-Man).
62
- Force with --cat, --banana, --upyachka, or --pacman. Agent log is below.
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', 'pacman']
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
- // Native pixels from the classic dancing banana GIF (Trym Stene, 1999).
2
- // 33×35px, 8 frames — 2-space cells, integer scale to the terminal.
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 = 33
6
- const FRAME_HEIGHT = 35
5
+ const FRAME_WIDTH = 24
6
+ const FRAME_HEIGHT = 25
7
7
 
8
8
  const COLORS = {
9
9
  B: 236,
10
- d: 142,
10
+ d: 136,
11
+ E: 255,
11
12
  R: 196,
12
- W: 231,
13
+ W: 255,
13
14
  Y: 226,
14
- y: 184,
15
+ y: 214,
15
16
  }
16
17
 
17
18
  const FRAMES = [
18
19
  [
19
- '.................................',
20
- '.................................',
21
- '.................................',
22
- '.................................',
23
- '.................................',
24
- '.................................',
25
- '.................BB..............',
26
- '................BBBB.............',
27
- '................BddB.............',
28
- '................BdYBB............',
29
- '................BYYYBB...........',
30
- '................BYYYyBB..........',
31
- '................BYYYyyB..........',
32
- '..............BBBBBYYyBB.........',
33
- '.............BWBWWWBYyyB.........',
34
- '.............BBBBWWBYyyB.........',
35
- '.............BWBWWWBYyyB.........',
36
- '..............BBBBBYYByB.........',
37
- '...............BYYYBBByB.........',
38
- '...............BBBBRRByB.........',
39
- '................BRRRByyB.........',
40
- '................BRBBYyyB.........',
41
- '...............BBBYYYyyB.........',
42
- '.........BBB...BYYYYyyBB.BBB.....',
43
- '........BWWBB.BBYYYYyyBWBBWWB....',
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
- '.................BB..............',
61
- '................BBBB.............',
62
- '................BddB.............',
63
- '................BdYBB............',
64
- '................BYYYBB...........',
65
- '................BYYYyBB..........',
66
- '................BYYYyyB..........',
67
- '..............BBBBBYYyBB.........',
68
- '.............BWBWWWBYyyB.........',
69
- '.............BBBBWWBYyyB.........',
70
- '.............BWBWWWBYyyB.........',
71
- '..............BBBBBYYByB.........',
72
- '...............BYYYBBByB.........',
73
- '...............BBBBRRByB.........',
74
- '................BRRRByyB.........',
75
- '................BRBBYyyB.........',
76
- '...............BBBYYYyyB.........',
77
- '.......BBB.....BYYYYYyyB...BBB...',
78
- '......BWWBB....BYYYYyyBB..BBWWB..',
79
- '......BWWWB...BBYYYYyyB...BWWWB..',
80
- '......BWWBB...BYYYYyyBB...BBWWB..',
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
- '................BB...............',
94
- '...............BddB..............',
95
- '...............BddB..............',
96
- '...............BydBB.............',
97
- '..............BBYYyB.............',
98
- '..............BYYYyBB............',
99
- '..............BYYYYyB............',
100
- '..BBB........BBBYBBBB........BBB.',
101
- '.BWWBB......BWWWBWWWBB......BBWWB',
102
- '.BWWWB......BWBWBWBWBB......BWWWB',
103
- '.BWWBB......BWWWBWWWBB......BBWWB',
104
- '..BBBB.......BBBYBBByB......BBBB.',
105
- '.....BBB.....BYYYYYdBB....BBB....',
106
- '.......BBB...BBBBBBRBB..BBB......',
107
- '.........BBB.BRRRRRByB.BB........',
108
- '...........BBBBRRRBYyBBB.........',
109
- '.............BYBBBYYyB...........',
110
- '.............BYYYYYyyB...........',
111
- '.............BYYYYYyyB...........',
112
- '.............BYYYYYyBB...........',
113
- '.............BYYYYYyB............',
114
- '.............BYYYYyyB............',
115
- '.............BYYYYyBB............',
116
- '.............BYYYyyB.............',
117
- '.............BYYyyBB.............',
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
- '..............BB.................',
133
- '.............BddB................',
134
- '.............BddB................',
135
- '............BBdyB................',
136
- '............ByYYBB...............',
137
- '...........BByYYYB...............',
138
- '...........ByYYYYB...............',
139
- '...........BBBBYBBB..............',
140
- '..........BBWWWBWWWB.............',
141
- '..........BBWBWBWBWB.............',
142
- '..BB......BBWWWBWWWB....BBB......',
143
- '.BWWBB....ByBBBYBBB....BBWWB.....',
144
- '.BWWWB....BBdYYYYYB....BWWWB.....',
145
- '.BWWBB....BBRBBBBBB....BBWWB.....',
146
- '..BBBB....ByBRRRRRB....BBBB......',
147
- '.....BB...ByYBRRRBB...BB.........',
148
- '......BB..ByYYBBBYB..BB..........',
149
- '.......BBBByyYYYYYBBBB...........',
150
- '..........BByYYYYYB..............',
151
- '...........ByYYYYYB..............',
152
- '...........ByyYYYYB..............',
153
- '...........BByYYYYB..............',
154
- '............ByyYYYB..............',
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
- '..............BB.................',
174
- '.............BBBB................',
175
- '.............BddB................',
176
- '............BBYdB................',
177
- '...........BBYYYB................',
178
- '..........BByYYYB................',
179
- '..........ByyYYYB................',
180
- '.........BByYYBBBBB..............',
181
- '.........ByyYBWWWBWB.............',
182
- '.........ByyYBWWBBBB.............',
183
- '.........ByyYBWWWBWB.............',
184
- '.........ByBYYBBBBB..............',
185
- '.........ByBBBYYYB...............',
186
- '.........ByBRRBBBB...............',
187
- '.........ByyBRRRB................',
188
- '.........ByyYBBRB................',
189
- '.........ByyYYYBBB...............',
190
- '.....BBB.BByyYYYYB...BBB.........',
191
- '....BWWBBWByyYYYYBB.BBWWB........',
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
- '..............BB.................',
209
- '.............BBBB................',
210
- '.............BddB................',
211
- '............BBYdB................',
212
- '...........BBYYYB................',
213
- '..........BByYYYB................',
214
- '..........ByyYYYB................',
215
- '.........BByYYBBBBB..............',
216
- '.........ByyYBWWWBWB.............',
217
- '.........ByyYBWWBBBB.............',
218
- '.........ByyYBWWWBWB.............',
219
- '.........ByBYYBBBBB..............',
220
- '.........ByBBBYYYB...............',
221
- '.........ByBRRBBBB...............',
222
- '.........ByyBRRRB................',
223
- '.........ByyYBBRB................',
224
- '.........ByyYYYBBB...............',
225
- '...BBB...ByyYYYYYB.....BBB.......',
226
- '..BWWBB..BByyYYYYB....BBWWB......',
227
- '..BWWWB...ByyYYYYBB...BWWWB......',
228
- '..BWWBB...BByyYYYYB...BBWWB......',
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
- '...............BB................',
242
- '..............BddB...............',
243
- '..............BddB...............',
244
- '.............BBdyB...............',
245
- '.............ByYYBB..............',
246
- '............BByYYYB..............',
247
- '............ByYYYYB..............',
248
- '.BBB........BBBBYBBB........BBB..',
249
- 'BWWBB......BBWWWBWWWB......BBWWB.',
250
- 'BWWWB......BBWBWBWBWB......BWWWB.',
251
- 'BWWBB......BBWWWBWWWB......BBWWB.',
252
- '.BBBB......ByBBBYBBB.......BBBB..',
253
- '....BBB....BBdYYYYYB.....BBB.....',
254
- '......BBB..BBRBBBBBB...BBB.......',
255
- '........BB.ByBRRRRRB.BBB.........',
256
- '.........BBByYBRRRBBBB...........',
257
- '...........ByYYBBBYB.............',
258
- '...........ByyYYYYYB.............',
259
- '...........ByyYYYYYB.............',
260
- '...........BByYYYYYB.............',
261
- '............ByYYYYYB.............',
262
- '............ByyYYYYB.............',
263
- '............BByYYYYB.............',
264
- '.............ByyYYYB.............',
265
- '.............BByyYYB.............',
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
- '.................BB..............',
281
- '................BddB.............',
282
- '................BddB.............',
283
- '................BydBB............',
284
- '...............BBYYyB............',
285
- '...............BYYYyBB...........',
286
- '...............BYYYYyB...........',
287
- '..............BBBYBBBB...........',
288
- '.............BWWWBWWWBB..........',
289
- '.............BWBWBWBWBB..........',
290
- '......BBB....BWWWBWWWBB.....BBB..',
291
- '.....BWWBB....BBBYBBByB....BBWWB.',
292
- '.....BWWWB....BYYYYYdBB....BWWWB.',
293
- '.....BWWBB....BBBBBBRBB....BBWWB.',
294
- '......BBBB....BRRRRRByB....BBBB..',
295
- '.........BB...BBRRRBYyB...BB.....',
296
- '..........BB..BYBBBYYyB..BB......',
297
- '...........BBBBYYYYYyyBBBB.......',
298
- '..............BYYYYYyBB..........',
299
- '..............BYYYYYyB...........',
300
- '..............BYYYYyyB...........',
301
- '..............BYYYYyBB...........',
302
- '..............BYYYyyB............',
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 pickIndexes(srcSize, maxSize) {
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
- let last = -1
341
- for (const x of colIndexes) {
342
- const code = padded[x] === '.' ? undefined : COLORS[padded[x]]
343
- for (let s = 0; s < scale; s += 1) {
344
- if (code === undefined) {
345
- if (last !== -1) {
346
- line += RESET
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, terminalColumns = 80, terminalRows = 24) {
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
- for (const y of rowIndexes) {
372
- const rendered = renderRow(frame[y], colIndexes, scale)
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() {
@@ -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
- }