koikatu.js 0.1.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/README.ja.md +138 -0
- package/README.md +141 -0
- package/dist/index.cjs +541 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +94 -0
- package/dist/index.d.ts +94 -0
- package/dist/index.js +498 -0
- package/dist/index.js.map +1 -0
- package/package.json +45 -0
package/README.ja.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# koikatu.js
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/koikatu.js)
|
|
4
|
+
|
|
5
|
+
Koikatu / Honeycome キャラクターカードのパーサーライブラリ。PNG 末尾に付加されたバイナリペイロードを解析し、キャラクターデータを JavaScript オブジェクトとして取得できる。
|
|
6
|
+
|
|
7
|
+
ブラウザ・Node.js 両対応。ESM / CJS デュアルフォーマット。
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install koikatu.js
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { parseCard, parseCardSummary, isCard } from 'koikatu.js';
|
|
19
|
+
|
|
20
|
+
// ファイルがキャラクターカードか判定
|
|
21
|
+
const buf = await fetch('card.png').then(r => r.arrayBuffer());
|
|
22
|
+
if (isCard(buf)) {
|
|
23
|
+
console.log('Character card detected');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// カード全体をパース
|
|
27
|
+
const card = parseCard(buf);
|
|
28
|
+
console.log(card.header.header); // "【KoiKatuChara】"
|
|
29
|
+
console.log(card.blockIndex); // [{ name: "Custom", ... }, ...]
|
|
30
|
+
console.log(card.blocks['Parameter']); // { lastname: "白峰", firstname: "一乃", ... }
|
|
31
|
+
|
|
32
|
+
// サマリーのみ取得
|
|
33
|
+
const summary = parseCardSummary(buf);
|
|
34
|
+
console.log(summary.product); // "koikatu"
|
|
35
|
+
console.log(summary.name); // "白峰 一乃"
|
|
36
|
+
console.log(summary.birthday); // { month: 5, day: 12 }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### PNG を含まないペイロードの場合
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
const card = parseCard(rawPayload, { containsPng: false });
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## API
|
|
46
|
+
|
|
47
|
+
### `parseCard(input, options?): Card`
|
|
48
|
+
|
|
49
|
+
カードをフルパースし、ヘッダー・全ブロック・ブロックインデックスを返す。
|
|
50
|
+
|
|
51
|
+
### `parseCardSummary(input, options?): CardSummary`
|
|
52
|
+
|
|
53
|
+
カードをパースし、product / name / birthday / sex 等の正規化されたサマリーを返す。
|
|
54
|
+
|
|
55
|
+
### `parseHeader(input, options?): CardHeader`
|
|
56
|
+
|
|
57
|
+
ヘッダー部分のみを軽量にパースする。
|
|
58
|
+
|
|
59
|
+
### `isCard(input): boolean`
|
|
60
|
+
|
|
61
|
+
入力がキャラクターカードかどうかを判定する。
|
|
62
|
+
|
|
63
|
+
### `scanPngIend(input): number`
|
|
64
|
+
|
|
65
|
+
PNG の IEND チャンク末尾のオフセットを返す。
|
|
66
|
+
|
|
67
|
+
### Options
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
type ParseOptions = {
|
|
71
|
+
containsPng?: boolean; // default: true - 入力に PNG が含まれるか
|
|
72
|
+
strict?: boolean; // default: false - 不明ヘッダーや壊れたブロックでエラーを投げるか
|
|
73
|
+
decodeBlocks?: boolean; // default: true - ブロックを MessagePack デコードするか
|
|
74
|
+
};
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Supported Games
|
|
78
|
+
|
|
79
|
+
| Game | Header |
|
|
80
|
+
|------|--------|
|
|
81
|
+
| Koikatu | `【KoiKatuChara】` |
|
|
82
|
+
| Koikatu Sunshine | `【KoiKatuCharaSun】` |
|
|
83
|
+
| EmotionCreators | `【Emocre】` |
|
|
84
|
+
| Honeycome | `【HCChara】` |
|
|
85
|
+
| Honeycome Party | `【HCPChara】` |
|
|
86
|
+
| DigitalCraft | `【DCChara】` |
|
|
87
|
+
| SummerVacation | `【SVChara】` |
|
|
88
|
+
| Aicomi | `【ACChara】` |
|
|
89
|
+
|
|
90
|
+
## Types
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
type Card = {
|
|
94
|
+
header: CardHeader;
|
|
95
|
+
blocks: Record<string, any>;
|
|
96
|
+
blockIndex: BlockInfo[];
|
|
97
|
+
rawBlockBytes?: Record<string, Uint8Array>;
|
|
98
|
+
errors?: ParseError[];
|
|
99
|
+
unsupportedHeader?: boolean;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
type CardSummary = {
|
|
103
|
+
header: CardHeader;
|
|
104
|
+
product: 'koikatu' | 'honeycome' | 'unknown';
|
|
105
|
+
name?: string;
|
|
106
|
+
birthday?: { month?: number; day?: number };
|
|
107
|
+
sex?: number;
|
|
108
|
+
hasKKEx?: boolean;
|
|
109
|
+
blocks: string[];
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
type CardHeader = {
|
|
113
|
+
productNo: number;
|
|
114
|
+
header: string;
|
|
115
|
+
version: string;
|
|
116
|
+
faceImage?: Uint8Array;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
type BlockInfo = {
|
|
120
|
+
name: string;
|
|
121
|
+
version: string;
|
|
122
|
+
pos: number;
|
|
123
|
+
size: number;
|
|
124
|
+
};
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Development
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
make install # 依存関係インストール
|
|
131
|
+
make build # ビルド
|
|
132
|
+
make test # テスト実行
|
|
133
|
+
make clean # dist/ を削除
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
MIT
|
package/README.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# koikatu.js
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/koikatu.js)
|
|
4
|
+
|
|
5
|
+
Parser library for Koikatu / Honeycome character cards. Extracts character data from the binary payload appended after the PNG IEND chunk.
|
|
6
|
+
|
|
7
|
+
Works in both browser and Node.js. Dual ESM / CJS output.
|
|
8
|
+
|
|
9
|
+
[日本語版 README](./README.ja.md)
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install koikatu.js
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { parseCard, parseCardSummary, isCard } from 'koikatu.js';
|
|
21
|
+
|
|
22
|
+
// Check if a file is a character card
|
|
23
|
+
const buf = await fetch('card.png').then(r => r.arrayBuffer());
|
|
24
|
+
if (isCard(buf)) {
|
|
25
|
+
console.log('Character card detected');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Full parse
|
|
29
|
+
const card = parseCard(buf);
|
|
30
|
+
console.log(card.header.header); // "【KoiKatuChara】"
|
|
31
|
+
console.log(card.blockIndex); // [{ name: "Custom", ... }, ...]
|
|
32
|
+
console.log(card.blocks['Parameter']); // { lastname: "白峰", firstname: "一乃", ... }
|
|
33
|
+
|
|
34
|
+
// Summary only
|
|
35
|
+
const summary = parseCardSummary(buf);
|
|
36
|
+
console.log(summary.product); // "koikatu"
|
|
37
|
+
console.log(summary.name); // "白峰 一乃"
|
|
38
|
+
console.log(summary.birthday); // { month: 5, day: 12 }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Raw payload without PNG
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
const card = parseCard(rawPayload, { containsPng: false });
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## API
|
|
48
|
+
|
|
49
|
+
### `parseCard(input, options?): Card`
|
|
50
|
+
|
|
51
|
+
Fully parses a card and returns the header, all decoded blocks, and the block index.
|
|
52
|
+
|
|
53
|
+
### `parseCardSummary(input, options?): CardSummary`
|
|
54
|
+
|
|
55
|
+
Parses a card and returns a normalized summary including product, name, birthday, and sex.
|
|
56
|
+
|
|
57
|
+
### `parseHeader(input, options?): CardHeader`
|
|
58
|
+
|
|
59
|
+
Lightweight parse of the header only.
|
|
60
|
+
|
|
61
|
+
### `isCard(input): boolean`
|
|
62
|
+
|
|
63
|
+
Returns whether the input is a character card.
|
|
64
|
+
|
|
65
|
+
### `scanPngIend(input): number`
|
|
66
|
+
|
|
67
|
+
Returns the byte offset immediately after the PNG IEND chunk.
|
|
68
|
+
|
|
69
|
+
### Options
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
type ParseOptions = {
|
|
73
|
+
containsPng?: boolean; // default: true - whether the input contains a PNG image
|
|
74
|
+
strict?: boolean; // default: false - throw on unknown headers or corrupted blocks
|
|
75
|
+
decodeBlocks?: boolean; // default: true - decode blocks via MessagePack
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Supported Games
|
|
80
|
+
|
|
81
|
+
| Game | Header |
|
|
82
|
+
|------|--------|
|
|
83
|
+
| Koikatu | `【KoiKatuChara】` |
|
|
84
|
+
| Koikatu Sunshine | `【KoiKatuCharaSun】` |
|
|
85
|
+
| EmotionCreators | `【Emocre】` |
|
|
86
|
+
| Honeycome | `【HCChara】` |
|
|
87
|
+
| Honeycome Party | `【HCPChara】` |
|
|
88
|
+
| DigitalCraft | `【DCChara】` |
|
|
89
|
+
| SummerVacation | `【SVChara】` |
|
|
90
|
+
| Aicomi | `【ACChara】` |
|
|
91
|
+
|
|
92
|
+
## Types
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
type Card = {
|
|
96
|
+
header: CardHeader;
|
|
97
|
+
blocks: Record<string, any>;
|
|
98
|
+
blockIndex: BlockInfo[];
|
|
99
|
+
rawBlockBytes?: Record<string, Uint8Array>;
|
|
100
|
+
errors?: ParseError[];
|
|
101
|
+
unsupportedHeader?: boolean;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
type CardSummary = {
|
|
105
|
+
header: CardHeader;
|
|
106
|
+
product: 'koikatu' | 'honeycome' | 'unknown';
|
|
107
|
+
name?: string;
|
|
108
|
+
birthday?: { month?: number; day?: number };
|
|
109
|
+
sex?: number;
|
|
110
|
+
hasKKEx?: boolean;
|
|
111
|
+
blocks: string[];
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
type CardHeader = {
|
|
115
|
+
productNo: number;
|
|
116
|
+
header: string;
|
|
117
|
+
version: string;
|
|
118
|
+
faceImage?: Uint8Array;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
type BlockInfo = {
|
|
122
|
+
name: string;
|
|
123
|
+
version: string;
|
|
124
|
+
pos: number;
|
|
125
|
+
size: number;
|
|
126
|
+
};
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Development
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
make install # Install dependencies
|
|
133
|
+
make build # Build with tsup
|
|
134
|
+
make test # Run tests
|
|
135
|
+
make check # Build + test
|
|
136
|
+
make clean # Remove dist/
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## License
|
|
140
|
+
|
|
141
|
+
MIT
|