webtalekit-alpha 0.2.11 → 0.2.14
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 +231 -87
- package/package.json +12 -2
- package/parser/checker.js +184 -0
- package/parser/checker.test.ts +491 -0
- package/parser/cli.js +34 -2
- package/parser/parser.js +25 -18
- package/src/core/defaultUIHandler.js +309 -0
- package/src/core/defaultUIHandler.js.map +1 -0
- package/src/core/drawer.js +65 -49
- package/src/core/drawer.js.map +1 -1
- package/src/core/index.js +418 -179
- package/src/core/scenarioManager.js +33 -12
- package/src/core/scenarioManager.js.map +1 -1
- package/src/resource/soundObject.js +4 -2
- package/src/resource/soundObject.js.map +1 -1
- package/src/utils/eventBus.js +88 -0
- package/src/utils/eventBus.js.map +1 -0
- package/src/utils/fallbackTemplate.js +13 -0
- package/src/utils/fallbackTemplate.js.map +1 -0
- package/src/utils/logger.js +45 -1
- package/src/utils/logger.js.map +1 -1
- package/src/utils/store.js +5 -0
- package/src/utils/store.js.map +1 -1
package/README.md
CHANGED
|
@@ -1,50 +1,84 @@
|
|
|
1
1
|
# webTaleKit
|
|
2
2
|
|
|
3
|
-

|
|
4
|
+
|
|
5
|
+
**[English](README_EN.md) | 日本語**
|
|
4
6
|
|
|
5
7
|
## 目次
|
|
6
8
|
|
|
7
|
-
- 概要
|
|
8
|
-
- デモ
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
9
|
+
- [概要](#概要)
|
|
10
|
+
- [デモ](#デモ)
|
|
11
|
+
- [ドキュメント](#ドキュメント)
|
|
12
|
+
- [環境構築手順](#環境構築手順)
|
|
13
|
+
- [動作確認手順](#動作確認手順)
|
|
14
|
+
- [Quick Start(デモゲームを弄ってみよう)](#quick-startデモゲームを弄ってみよう)
|
|
15
|
+
- [開発コマンド](#開発コマンド)
|
|
16
|
+
- [シナリオ検証API](#シナリオ検証api)
|
|
17
|
+
- [現在の状況](#現在の状況)
|
|
18
|
+
- [ロードマップ](#ロードマップ実装予定)
|
|
19
|
+
- [できること](#アルファ版01x-02xでできること)
|
|
20
|
+
- [制限事項](#アルファ版01x-02xの制限事項)
|
|
15
21
|
|
|
16
22
|
## 概要
|
|
17
23
|
|
|
18
|
-
TypeScript(JavaScript) ベースのビジュアルノベルゲームエンジンです。
|
|
19
|
-
UIをHTML・CSS・JavaScriptで柔軟に作成でき、シナリオをマークアップ言語とJavaScriptで制御できます。
|
|
20
|
-
|
|
21
|
-
VS Codeの拡張機能を用いたGUIエディタやREST API呼び出しによる生成AI連携の追加を提供予定です。
|
|
24
|
+
TypeScript(JavaScript) ベースのビジュアルノベルゲームエンジンです。
|
|
25
|
+
UIをHTML・CSS・JavaScriptで柔軟に作成でき、シナリオをマークアップ言語とJavaScriptで制御できます。
|
|
26
|
+
自動スケーリング機能で、様々なウィンドウサイズに対応します。
|
|
27
|
+
VS Codeの拡張機能を用いたGUIエディタやREST API呼び出しによる生成AI連携の追加を提供予定です。
|
|
28
|
+
|
|
29
|
+
### 特徴
|
|
30
|
+
|
|
31
|
+
- 🎮 **柔軟なUI作成**: HTML・CSS・JavaScriptで自由にUIをデザイン
|
|
32
|
+
- 📝 **直感的なシナリオ記述**: マークアップ言語とJavaScriptでシナリオを制御
|
|
33
|
+
- 🔄 **自動スケーリング**: 様々なウィンドウサイズに自動対応
|
|
34
|
+
- 🎨 **豊富な画像処理**: フィルター・アニメーション機能を搭載
|
|
35
|
+
- 🔊 **サウンド対応**: BGM・SE・ボイス再生に対応
|
|
36
|
+
- 🛠️ **TypeScript対応**: TypeScriptでの開発をサポート
|
|
37
|
+
- 🤖 **AI連携**: REST API呼び出しによる生成AI連携(予定)
|
|
22
38
|
|
|
23
39
|
## デモ
|
|
24
40
|
|
|
25
|
-
Firefoxでも、Chromeでも、Edge
|
|
41
|
+
Firefoxでも、Chromeでも、Edgeでも、好きなブラウザを使いたまえ・・・!
|
|
26
42
|
<https://test-game-chi.vercel.app/>
|
|
27
|
-

|
|
44
|
+
|
|
45
|
+
## ドキュメント
|
|
46
|
+
|
|
47
|
+
📖 **オンラインドキュメント**: <https://endohizumi.github.io/webTaleKit/>
|
|
28
48
|
|
|
29
49
|
## 環境構築手順
|
|
30
50
|
|
|
31
|
-
1.
|
|
51
|
+
1. Git が必要です。
|
|
52
|
+
- **インストール確認:** `git --version` でバージョンが表示されれば OK
|
|
53
|
+
- Windowsの場合は、Git公式サイト (<https://git-scm.com/>) からインストールしてください。
|
|
54
|
+
- Macの場合は、`brew install git` を実行してインストールしてください。
|
|
55
|
+
- Linuxの場合は、以下のコマンドを実行してインストールしてください。
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
sudo apt-get update
|
|
59
|
+
sudo apt-get install git
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
2. Node.js(20以降)が必要です。(nvm等お好みの方法がある場合は、そちらでも構いません)
|
|
63
|
+
- **インストール確認:** `node --version` でv20以上のバージョンが表示されれば OK
|
|
32
64
|
- Windowsの場合は、Node.js公式サイト (<https://nodejs.org/>) からインストールしてください。
|
|
33
65
|
- Macの場合は、`brew install node` を実行してインストールしてください。
|
|
34
66
|
- Linuxの場合は、以下のコマンドを実行して、インストールしてください。
|
|
35
67
|
|
|
36
68
|
```bash
|
|
37
|
-
|
|
38
|
-
|
|
69
|
+
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
|
|
70
|
+
sudo apt-get install -y nodejs
|
|
39
71
|
```
|
|
40
72
|
|
|
41
|
-
|
|
73
|
+
3. 以下のコマンドを実行してください
|
|
42
74
|
|
|
43
75
|
``` bash
|
|
44
76
|
npm create tale-game your-game-title
|
|
77
|
+
cd your-game-title
|
|
78
|
+
npm run play
|
|
45
79
|
```
|
|
46
80
|
|
|
47
|
-
|
|
81
|
+
デモゲームが起動すれば、構築は完了です。
|
|
48
82
|
|
|
49
83
|
## 動作確認手順
|
|
50
84
|
|
|
@@ -52,82 +86,172 @@ Firefoxでも、Chromeでも、Edgeでも、好きなブラウザを使いたま
|
|
|
52
86
|
|
|
53
87
|
```bash
|
|
54
88
|
git clone https://github.com/EndoHizumi/testGame.git
|
|
89
|
+
cd testGame
|
|
55
90
|
npm install
|
|
56
91
|
npm run play
|
|
57
92
|
```
|
|
58
93
|
|
|
59
|
-
## Quick Start
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
-
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
94
|
+
## Quick Start(デモゲームを弄ってみよう)
|
|
95
|
+
|
|
96
|
+
このセクションでは、プログラミングの知識がなくても簡単にゲームをカスタマイズできる方法を説明します。
|
|
97
|
+
|
|
98
|
+
### 画像を差し替える(簡単なカスタマイズ)
|
|
99
|
+
|
|
100
|
+
**手順:** 既存の画像ファイルを新しい画像で置き換える(ファイル名は同じにしてください)
|
|
101
|
+
|
|
102
|
+
#### キャラクターや背景を変える
|
|
103
|
+
|
|
104
|
+
- **キャラを変える場合**
|
|
105
|
+
- `./src/resource/chara/guide.png` を新しいキャラ画像で上書きしてください(ファイル名は `guide.png` のまま)
|
|
106
|
+
- **背景画像を変える**
|
|
107
|
+
- `./src/resource/background/title_bg.png` を新しい背景画像で上書きしてください(ファイル名は `title_bg.png` のまま)
|
|
108
|
+
- **BGMを変える**
|
|
109
|
+
- `./src/resource/bgm/title_theme.mp3` を新しい音楽ファイルで上書きしてください(ファイル名は `title_theme.mp3` のまま)
|
|
110
|
+
|
|
111
|
+
#### ボタンの見た目を変える
|
|
112
|
+
|
|
113
|
+
- **選択肢の画像を変える**
|
|
114
|
+
- `./src/resource/system/systemPicture/02_button/button.png`(通常時) - ファイル名は `button.png` のまま上書き
|
|
115
|
+
- `./src/resource/system/systemPicture/02_button/button2.png`(マウスを乗せた時) - ファイル名は `button2.png` のまま上書き
|
|
116
|
+
- `./src/resource/system/systemPicture/02_button/button3.png`(クリック時) - ファイル名は `button3.png` のまま上書き
|
|
117
|
+
|
|
118
|
+
**パス表記について:**
|
|
119
|
+
|
|
120
|
+
- `./` は「現在のプロジェクトフォルダから」という意味です
|
|
121
|
+
- パス区切り文字は `/` (スラッシュ) を使用しています
|
|
122
|
+
- **Windowsをお使いの方:** `\` (バックスラッシュ) でも動作しますが、上記の `/` 形式を推奨します
|
|
123
|
+
|
|
124
|
+
### シナリオファイルを編集する(テキストの変更)
|
|
125
|
+
|
|
126
|
+
シナリオファイル(`.scene`ファイル)をテキストエディタで開いて、以下の方法で内容を変更できます:
|
|
127
|
+
|
|
128
|
+
#### 基本的な要素の追加
|
|
129
|
+
|
|
130
|
+
- **キャラを増やす**
|
|
131
|
+
1. `./src/resource/character` フォルダに新しいキャラ画像を保存
|
|
132
|
+
2. シナリオファイルで `<show src="キャラ画像のファイル名"></show>` を記述
|
|
133
|
+
- **セリフを増やす**
|
|
134
|
+
- `<say name="キャラの名前">ここにセリフを入力</say>` を記述
|
|
135
|
+
- **地の文(ナレーション)を増やす**
|
|
136
|
+
- `<text>ここに地の文を入力</text>` を記述
|
|
137
|
+
|
|
138
|
+
**初心者の方へ:** まずは既存のテキストを変更することから始めることをお勧めします。
|
|
139
|
+
|
|
140
|
+
#### 選択肢を追加・変更する
|
|
141
|
+
|
|
142
|
+
選択肢はプレイヤーがゲームの進行を選ぶ重要な要素です。シナリオファイル内の `<choice>` タグを編集することで変更できます。
|
|
143
|
+
|
|
144
|
+
**基本的な選択肢の書き方:**
|
|
145
|
+
|
|
146
|
+
``` html
|
|
147
|
+
<item label='選択肢の文言'>
|
|
148
|
+
<text>選択後に表示される文章</text>
|
|
149
|
+
</item>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**実用的な例:**
|
|
153
|
+
|
|
154
|
+
```html
|
|
155
|
+
<choice prompt="ゲームを始めますか?">
|
|
156
|
+
<item label="はい">
|
|
157
|
+
<jump index="5" />
|
|
158
|
+
</item>
|
|
159
|
+
<item label="いいえ">
|
|
160
|
+
<jump index="16" />
|
|
161
|
+
</item>
|
|
162
|
+
<item label='ちょっと待ってくれ'>
|
|
163
|
+
<text>承知しました。</text>
|
|
164
|
+
<jump index="1" />
|
|
165
|
+
</item>
|
|
166
|
+
</choice>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## 開発コマンド
|
|
170
|
+
|
|
171
|
+
### ビルドと開発
|
|
172
|
+
|
|
173
|
+
- `npm run build` - TypeScriptをJavaScriptにコンパイルし、配布ファイルを準備
|
|
174
|
+
- `npm run dev` - プロジェクトをビルドし、exampleフォルダで開発サーバーを起動
|
|
175
|
+
- `npm run lint` - ESLintでコード品質をチェック
|
|
176
|
+
- `npm run test` - Jestでテストを実行
|
|
177
|
+
|
|
178
|
+
### CLIツール
|
|
179
|
+
|
|
180
|
+
- `wtc` - WebTaleScriptパーサーCLI (`parser/cli.js` から利用可能)
|
|
181
|
+
- 使用方法: `wtc <scene-file> [output-directory]` で `.scene` ファイルを `.js/.ts` ファイルに変換
|
|
182
|
+
|
|
183
|
+
### ドキュメント
|
|
184
|
+
|
|
185
|
+
- `npm run docs:dev` - VitePressドキュメントサーバーを起動
|
|
186
|
+
- `npm run docs:build` - ドキュメントをビルド
|
|
187
|
+
- `npm run docs:preview` - ビルドしたドキュメントをプレビュー
|
|
188
|
+
|
|
189
|
+
## シナリオ検証API
|
|
190
|
+
|
|
191
|
+
WebTaleKit には、シナリオ配列を検証しつつ、HTML風の文字列を非破壊でサニタイズできる公開APIがあります。
|
|
192
|
+
|
|
193
|
+
- `validateScenarioObjects` - 検証結果とサニタイズ済みシナリオを返します
|
|
194
|
+
- `formatValidationOutput` - エラーと警告を表示用文字列へ整形します
|
|
195
|
+
- `createScenarioValidationError` - 検証結果から Error を生成します
|
|
196
|
+
- `assertScenarioValidation` - エラーがある場合に例外を送出します
|
|
197
|
+
- `reportScenarioValidation` - logger 経由で警告とエラーを出力します
|
|
198
|
+
|
|
199
|
+
これらのAPIは、エンジン実行時に自動で強制適用されません。シナリオの読み込み時、エディタ連携時、独自ビルド処理時などに、利用者が必要に応じて呼び出す想定です。
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
import {
|
|
203
|
+
assertScenarioValidation,
|
|
204
|
+
reportScenarioValidation,
|
|
205
|
+
validateScenarioObjects,
|
|
206
|
+
} from './src/utils/validateScenario'
|
|
207
|
+
|
|
208
|
+
const result = validateScenarioObjects(scenarioObjects, commandList)
|
|
209
|
+
|
|
210
|
+
await reportScenarioValidation(result, 'Scene import')
|
|
211
|
+
assertScenarioValidation(result, 'Scene import')
|
|
212
|
+
|
|
213
|
+
const safeScenario = result.sanitizedScenario
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
`sanitizedScenario` は元の入力配列を破壊せずに返されます。`sanitized` が `true` の場合は、HTML風の文字列がエスケープされています。
|
|
110
217
|
|
|
111
218
|
## 現在の状況
|
|
112
219
|
|
|
113
|
-
webTaleKitは、現在アルファ版です。
|
|
220
|
+
webTaleKitは、現在アルファ版です。
|
|
114
221
|
|
|
115
222
|
開発進捗は、[@endo_hizumi](https://x.com/endo_hizumi) で行っております。
|
|
116
223
|
実装予定の項目については、こちらの[Trello](https://trello.com/b/qYNGh7MY)からも確認できます。
|
|
117
224
|
|
|
118
|
-
デモをプレイした感想・WebTaleKit
|
|
225
|
+
デモをプレイした感想・WebTaleKitを使って気になったことなど、意見・感想はこちらで受け付けています!
|
|
119
226
|
[https://forms.gle/uejQwvwAb99wcJht7](https://forms.gle/uejQwvwAb99wcJht7)
|
|
120
227
|
|
|
121
228
|
検索Hashtag: #webTalekit
|
|
122
229
|
|
|
230
|
+
## ロードマップ(実装予定)
|
|
231
|
+
|
|
232
|
+
| バージョン | コードネーム | codeName | 内容
|
|
233
|
+
| :--- | :--- | :--- | :---
|
|
234
|
+
| 0.1.0 | 初音| HATUNE | 初期リリース
|
|
235
|
+
| 0.2.0 | 礎 | ISHIZUE | 基本機能アップデート<br>0.2.12〜<br>ダイアログ表示タグの追加<br>engineConfig反映バグの修正<br>未定義タグがある場合、undefineを呼び出すバグの修正<br>文字列以外を囲むとこける問題の修正<br>リンク切れでこける問題の修正<br>メッセージウィンドウオーバーフローの修正<br>if属性の実装<br>for属性の実装<br>既読管理の追加
|
|
236
|
+
| 0.3.0 | 舞踊 | BUYO | トランジション・アニメーション関連のアップデート<br>テキストスピードの調整タグの追加<br>テキスト表示フォントサイズの変更<br>Webフォントのサポート(フォント変更設定の追加)<br>動画再生のサポート<br>子要素でフィルター・アニメーション設定
|
|
237
|
+
| 0.4.0 | 狭間 | HAZAMA | Vue.jsやReact、SvelteなどのUIフレームワークとの連携追加のアップデート
|
|
238
|
+
| 0.5.0 | 操手 | AYATURI | ゲームパッドのサポート追加<br>キーコンフィグの追加<br>VOICEBOX APIの対応<br>npm run recの追加
|
|
239
|
+
| 0.6.0 | 絡繰 | KARAKURI | wtsLinterの追加<br>VSCodeとの連携追加<br>wst2htmlの追加<br>プラグイン機能の追加<br>クロスプラットホームへのビルド追加
|
|
240
|
+
| 0.7.0 | 綴り | TUDURI | GUIエディタの追加
|
|
241
|
+
| 0.8.0 | 迅雷 | JINRAI | パフォーマンスアップデート
|
|
242
|
+
| 0.9.0 | 出島 | DEJIMA | KAGタグコンバータの追加
|
|
243
|
+
| 1.0.0 | 暁月 | AKATUKI | メジャーアップデート
|
|
244
|
+
|
|
123
245
|
## アルファ版(0.1.x-0.2.x)で、できること
|
|
124
246
|
|
|
125
247
|
### テキスト表示
|
|
248
|
+
|
|
126
249
|
- 地の文の表示
|
|
127
250
|
- キャラクターのセリフの表示・ボイスの再生
|
|
128
251
|
- 定義した変数の表示
|
|
129
252
|
|
|
130
253
|
### キャラクター・画像操作
|
|
254
|
+
|
|
131
255
|
- キャラクターの画像の表示・位置変更・アニメーション
|
|
132
256
|
- その他の画像の画像の表示・位置変更・アニメーション
|
|
133
257
|
- キャラクターの複数表示・位置変更・アニメーション
|
|
@@ -135,6 +259,7 @@ webTaleKitは、現在アルファ版です。
|
|
|
135
259
|
- 背景画像の表示・変更
|
|
136
260
|
|
|
137
261
|
### 画像処理
|
|
262
|
+
|
|
138
263
|
- 画像のフィルター操作
|
|
139
264
|
- モノクロ化
|
|
140
265
|
- セピア化
|
|
@@ -142,6 +267,7 @@ webTaleKitは、現在アルファ版です。
|
|
|
142
267
|
- サイズの変更
|
|
143
268
|
|
|
144
269
|
### ユーザーインタラクション
|
|
270
|
+
|
|
145
271
|
- 選択肢の表示
|
|
146
272
|
- 選択肢の画像の変更
|
|
147
273
|
- 通常時
|
|
@@ -151,53 +277,64 @@ webTaleKitは、現在アルファ版です。
|
|
|
151
277
|
- Enterキーで全文表示
|
|
152
278
|
|
|
153
279
|
### シナリオ制御
|
|
280
|
+
|
|
154
281
|
- 表示する文章・画像の条件分岐
|
|
155
282
|
- セリフのジャンプ
|
|
156
|
-
-
|
|
283
|
+
- シナリオ(シーン)の切り替え
|
|
157
284
|
|
|
158
285
|
### 音声
|
|
286
|
+
|
|
159
287
|
- BGMの再生・停止
|
|
160
288
|
- SEの再生・停止
|
|
161
289
|
|
|
290
|
+
### セーブ&ロード
|
|
291
|
+
|
|
292
|
+
- セーブ機能
|
|
293
|
+
- ロード機能
|
|
294
|
+
|
|
162
295
|
### システム設定・UI
|
|
296
|
+
|
|
163
297
|
- HTMLで作った画面の表示
|
|
164
298
|
- 解像度の設定変更
|
|
165
299
|
|
|
166
300
|
### プログラミング連携
|
|
301
|
+
|
|
167
302
|
- JavaScript連携
|
|
168
303
|
- メソッドの呼び出し
|
|
169
304
|
- 式の実行
|
|
170
305
|
- 変数の定義・値の変更
|
|
171
306
|
- JavaScript側での背景画像の変更
|
|
172
307
|
- TypeScript連携
|
|
173
|
-
- REST API
|
|
308
|
+
- REST API呼び出し(レスポンスの表示)
|
|
174
309
|
|
|
175
|
-
##
|
|
310
|
+
## アルファ版(0.1.x-0.2.x)の制限事項
|
|
176
311
|
|
|
177
312
|
### ビルド・プラットフォーム
|
|
313
|
+
|
|
178
314
|
- Desktopアプリケーションへのビルド
|
|
179
315
|
- Android(iOS)向けのビルド
|
|
180
316
|
|
|
181
317
|
### ユーザーインターフェース (UI)
|
|
318
|
+
|
|
182
319
|
- 画面各種のボタン
|
|
183
320
|
- セーブファイルの一覧の取得
|
|
184
321
|
|
|
185
322
|
### キャラクター操作
|
|
323
|
+
|
|
186
324
|
- sayタグの以下の機能
|
|
187
325
|
- キャラが表示されていないときは、表示する
|
|
188
326
|
|
|
189
|
-
### セーブ&ロード
|
|
190
|
-
- セーブ&ロード機能
|
|
191
|
-
|
|
192
327
|
### 視覚効果
|
|
328
|
+
|
|
193
329
|
- showタグ / hideタグの以下の機能
|
|
194
330
|
- 子要素でフィルター指定
|
|
195
331
|
- 子要素でアニメーション指定
|
|
196
332
|
- スラッシュで区切ってリソース種類を指定
|
|
197
|
-
- quake
|
|
198
|
-
- mask
|
|
333
|
+
- quakeタグ(画面を揺らす)
|
|
334
|
+
- maskタグ(画面の暗転)
|
|
199
335
|
|
|
200
336
|
### 音声
|
|
337
|
+
|
|
201
338
|
- soundタグの以下の機能
|
|
202
339
|
- pause
|
|
203
340
|
- setVolume
|
|
@@ -207,19 +344,26 @@ webTaleKitは、現在アルファ版です。
|
|
|
207
344
|
- seエイリアス
|
|
208
345
|
|
|
209
346
|
### リソース管理
|
|
210
|
-
|
|
347
|
+
|
|
211
348
|
- JavaScriptでのリソースの動的定義
|
|
212
349
|
|
|
213
350
|
### 設定・最適化
|
|
351
|
+
|
|
214
352
|
- ゲーム設定ファイルの反映
|
|
215
353
|
- 画面用HTMLのcss・jsのインライン化・minify化
|
|
216
354
|
|
|
217
|
-
##
|
|
355
|
+
## ライセンス
|
|
356
|
+
|
|
357
|
+
MIT License
|
|
358
|
+
|
|
359
|
+
## クレジット
|
|
360
|
+
|
|
361
|
+
### アイコン素材
|
|
218
362
|
|
|
219
363
|
- <https://www.silhouette-illust.com/>
|
|
220
364
|
|
|
221
|
-
|
|
365
|
+
### カラーコード
|
|
222
366
|
|
|
223
|
-
青: #3178C6 (TypeScript
|
|
224
|
-
緑: #02a889 (WebTaleKit Green)
|
|
225
|
-
白: #f8f8f8 (White Smoke)
|
|
367
|
+
- 青: #3178C6 (TypeScript Blue)
|
|
368
|
+
- 緑: #02a889 (WebTaleKit Green)
|
|
369
|
+
- 白: #f8f8f8 (White Smoke)
|
package/package.json
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webtalekit-alpha",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.14",
|
|
4
4
|
"description": "Web知識でノベルゲーを作ることを目指したやつ",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"lint": "eslint . --ext .ts --ext .js",
|
|
8
8
|
"test": "jest",
|
|
9
|
-
"
|
|
9
|
+
"setup": "npm install && cd example && npm install",
|
|
10
|
+
"dev": "npm run build && cd example && npm run dev",
|
|
11
|
+
"api": "node server/api.js",
|
|
12
|
+
"build": "rimraf ./dist/ && tsc && cp -r package.json README.md engineConfig.json parser/ dist/ && cp src/core/index.js dist/src/core/",
|
|
13
|
+
"docs:dev": "vitepress dev docs",
|
|
14
|
+
"docs:build": "vitepress build docs",
|
|
15
|
+
"docs:preview": "vitepress preview docs"
|
|
10
16
|
},
|
|
11
17
|
"bin": {
|
|
12
18
|
"wtc": "parser/cli.js"
|
|
@@ -14,6 +20,9 @@
|
|
|
14
20
|
"author": "EndoHizumi",
|
|
15
21
|
"license": "MIT",
|
|
16
22
|
"dependencies": {
|
|
23
|
+
"express": "^5.2.1",
|
|
24
|
+
"gsap": "^3.14.2",
|
|
25
|
+
"html-inline": "^1.2.0",
|
|
17
26
|
"html-minifier": "^4.0.0",
|
|
18
27
|
"html-to-json-parser": "^2.0.1",
|
|
19
28
|
"rimraf": "^6.0.1",
|
|
@@ -42,6 +51,7 @@
|
|
|
42
51
|
"ts-loader": "^9.5.1",
|
|
43
52
|
"ts-node": "^10.9.2",
|
|
44
53
|
"typescript": "^5.4.2",
|
|
54
|
+
"vitepress": "^1.6.4",
|
|
45
55
|
"webpack": "^5.90.3",
|
|
46
56
|
"webpack-cli": "^5.1.4",
|
|
47
57
|
"webpack-dev-server": "^5.0.2"
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* トップレベルコマンドの一覧 (core/index.js の Core.commandList から抽出)。
|
|
5
|
+
* HTTP サブタグはこれらのコマンドいずれかの子要素として使用できる。
|
|
6
|
+
*/
|
|
7
|
+
const TOP_LEVEL_COMMANDS = [
|
|
8
|
+
'text', 'choice', 'show', 'newpage', 'hide', 'jump', 'sound', 'say',
|
|
9
|
+
'if', 'call', 'moveto', 'route', 'wait', 'dialog', 'save', 'load',
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 各ノードタイプが配置できる親タイプを定義する。
|
|
14
|
+
* キー: 子ノードタイプ、値: 許可された親タイプの配列
|
|
15
|
+
*/
|
|
16
|
+
const ALLOWED_PARENTS = {
|
|
17
|
+
// choice 構造
|
|
18
|
+
item: ['choice'],
|
|
19
|
+
// dialog 構造
|
|
20
|
+
prompt: ['dialog'],
|
|
21
|
+
actions: ['dialog'],
|
|
22
|
+
action: ['actions'],
|
|
23
|
+
// if 構造
|
|
24
|
+
else: ['if'],
|
|
25
|
+
// then は <if> の子要素としても、トップレベルコマンドの HTTP レスポンスの子要素としても使用できる
|
|
26
|
+
then: ['if', ...TOP_LEVEL_COMMANDS],
|
|
27
|
+
// インラインテキスト装飾タグ (drawer.ts の createDecoratedElement と textHandler から)
|
|
28
|
+
color: ['text', 'say'],
|
|
29
|
+
ruby: ['text', 'say'],
|
|
30
|
+
b: ['text', 'say'],
|
|
31
|
+
i: ['text', 'say'],
|
|
32
|
+
br: ['text', 'say'],
|
|
33
|
+
// HTTP サブタグ (httpHandler から) — トップレベルコマンドの子要素として有効
|
|
34
|
+
header: TOP_LEVEL_COMMANDS,
|
|
35
|
+
data: TOP_LEVEL_COMMANDS,
|
|
36
|
+
error: TOP_LEVEL_COMMANDS,
|
|
37
|
+
progress: TOP_LEVEL_COMMANDS,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* すべてのノードタイプに共通して有効な属性。
|
|
42
|
+
* - type: タグタイプ自体
|
|
43
|
+
* - content: 子ノードの配列
|
|
44
|
+
* - if: 条件付き実行 (core/index.js の runScenario)
|
|
45
|
+
* - get/post/put/delete: HTTP メソッド属性 (core/index.js の httpHandler)
|
|
46
|
+
*/
|
|
47
|
+
const GLOBAL_ATTRIBUTES = new Set(['type', 'content', 'if', 'get', 'post', 'put', 'delete'])
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* ノードタイプごとの既知の属性セット (GLOBAL_ATTRIBUTES を除く)。
|
|
51
|
+
* このセットに含まれない属性は unknown_attribute 警告を生成する。
|
|
52
|
+
* このマップにないノードタイプは属性チェックをスキップする
|
|
53
|
+
* (<header> や <data> の子要素のような自由形式の子要素に対応)。
|
|
54
|
+
*/
|
|
55
|
+
const KNOWN_ATTRIBUTES = {
|
|
56
|
+
// トップレベルコマンド (core/index.js のハンドラ実装から取得)
|
|
57
|
+
text: new Set(['name', 'speed', 'time']),
|
|
58
|
+
say: new Set(['name', 'speed', 'voice']),
|
|
59
|
+
choice: new Set(['prompt', 'position']),
|
|
60
|
+
show: new Set(['src', 'name', 'mode', 'x', 'y', 'width', 'height', 'pos', 'look', 'entry', 'sepia', 'mono', 'blur', 'opacity', 'transition', 'duration']),
|
|
61
|
+
hide: new Set(['name', 'mode', 'transition', 'duration']),
|
|
62
|
+
moveto: new Set(['name', 'x', 'y', 'duration']),
|
|
63
|
+
sound: new Set(['src', 'name', 'mode', 'play', 'loop', 'stop', 'pause']),
|
|
64
|
+
jump: new Set(['index', 'sub']),
|
|
65
|
+
if: new Set(['condition']),
|
|
66
|
+
call: new Set(['method']),
|
|
67
|
+
route: new Set(['to']),
|
|
68
|
+
wait: new Set(['wait', 'time']),
|
|
69
|
+
newpage: new Set([]),
|
|
70
|
+
dialog: new Set(['name', 'template']),
|
|
71
|
+
save: new Set(['slot', 'name', 'message']),
|
|
72
|
+
load: new Set(['slot', 'message']),
|
|
73
|
+
// サブノード
|
|
74
|
+
item: new Set(['label', 'id', 'default', 'hover', 'select', 'color', 'position']),
|
|
75
|
+
action: new Set(['id', 'label', 'value']),
|
|
76
|
+
then: new Set([]),
|
|
77
|
+
else: new Set([]),
|
|
78
|
+
prompt: new Set([]),
|
|
79
|
+
actions: new Set([]),
|
|
80
|
+
// インラインテキスト装飾 (drawer.ts の createDecoratedElement から)
|
|
81
|
+
color: new Set(['value']),
|
|
82
|
+
ruby: new Set(['text']),
|
|
83
|
+
b: new Set([]),
|
|
84
|
+
i: new Set([]),
|
|
85
|
+
br: new Set([]),
|
|
86
|
+
// HTTP サブタグ (header/data の子要素は自由形式のキーを使用するため、チェックしない)
|
|
87
|
+
header: new Set([]),
|
|
88
|
+
data: new Set([]),
|
|
89
|
+
error: new Set([]),
|
|
90
|
+
progress: new Set([]),
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 親子関係が不正な場合のエラーメッセージを生成する。
|
|
95
|
+
* @param {string} nodeType - 誤った位置に配置されたノードのタイプ
|
|
96
|
+
* @param {string|null} parentType - 実際の親タイプ。ルートの場合は null
|
|
97
|
+
* @param {string[]} allowedParents - 許可された親タイプの配列
|
|
98
|
+
* @returns {string}
|
|
99
|
+
*/
|
|
100
|
+
const buildInvalidParentMessage = (nodeType, parentType, allowedParents) => {
|
|
101
|
+
const allowed = allowedParents.map((p) => `<${p}>`).join(' or ')
|
|
102
|
+
const actual = parentType ? `<${parentType}>` : 'scenario root'
|
|
103
|
+
return `<${nodeType}> must be inside ${allowed}, but found inside ${actual}`
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* 未知の属性 (エンジンに無視される属性) の警告メッセージを生成する。
|
|
108
|
+
* @param {string} nodeType
|
|
109
|
+
* @param {string} attrName
|
|
110
|
+
* @returns {string}
|
|
111
|
+
*/
|
|
112
|
+
const buildUnknownAttributeMessage = (nodeType, attrName) => {
|
|
113
|
+
return `<${nodeType}> has unknown attribute "${attrName}" which will be ignored`
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* エンジンで認識されない属性をノード単位でチェックする。
|
|
118
|
+
* 該当する属性ごとに unknown_attribute 警告を結果配列に追加する。
|
|
119
|
+
* @param {Object} node
|
|
120
|
+
* @param {Array} results - 結果オブジェクトを蓄積する配列
|
|
121
|
+
*/
|
|
122
|
+
const checkAttributes = (node, results) => {
|
|
123
|
+
const nodeType = node.type
|
|
124
|
+
if (!nodeType) return
|
|
125
|
+
const knownForType = KNOWN_ATTRIBUTES[nodeType]
|
|
126
|
+
if (knownForType === undefined) return // 未知のノードタイプはスキップ
|
|
127
|
+
for (const key of Object.keys(node)) {
|
|
128
|
+
if (GLOBAL_ATTRIBUTES.has(key)) continue
|
|
129
|
+
if (knownForType.has(key)) continue
|
|
130
|
+
results.push({
|
|
131
|
+
type: 'unknown_attribute',
|
|
132
|
+
node: nodeType,
|
|
133
|
+
attribute: key,
|
|
134
|
+
message: buildUnknownAttributeMessage(nodeType, key),
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* ノードの親子関係の違反と未知の属性を再帰的にチェックする。
|
|
141
|
+
* @param {Array} nodes - パース済みシナリオノードの配列
|
|
142
|
+
* @param {string|null} parentType - 親ノードのタイプ。ルートの場合は null
|
|
143
|
+
* @param {Array} results - 結果オブジェクトを蓄積する配列
|
|
144
|
+
*/
|
|
145
|
+
const checkNodes = (nodes, parentType, results) => {
|
|
146
|
+
if (!Array.isArray(nodes)) return
|
|
147
|
+
for (const node of nodes) {
|
|
148
|
+
if (typeof node !== 'object' || node === null) continue
|
|
149
|
+
const nodeType = node.type
|
|
150
|
+
if (!nodeType) continue
|
|
151
|
+
|
|
152
|
+
const allowedParents = ALLOWED_PARENTS[nodeType]
|
|
153
|
+
if (allowedParents && !allowedParents.includes(parentType)) {
|
|
154
|
+
results.push({
|
|
155
|
+
type: 'invalid_parent',
|
|
156
|
+
node: nodeType,
|
|
157
|
+
parent: parentType,
|
|
158
|
+
message: buildInvalidParentMessage(nodeType, parentType, allowedParents),
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
checkAttributes(node, results)
|
|
163
|
+
|
|
164
|
+
if (Array.isArray(node.content)) {
|
|
165
|
+
checkNodes(node.content, nodeType, results)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* パース済みシナリオ配列の構文エラーと属性警告をチェックする。
|
|
172
|
+
* 結果オブジェクトの配列を返す:
|
|
173
|
+
* - type 'invalid_parent': 構造エラー (不正な親子関係)
|
|
174
|
+
* - type 'unknown_attribute': 警告 (エンジンが読み取らない属性)
|
|
175
|
+
* @param {Array} scenario - パース・フラット化されたシナリオ配列
|
|
176
|
+
* @returns {Array}
|
|
177
|
+
*/
|
|
178
|
+
const check = (scenario) => {
|
|
179
|
+
const results = []
|
|
180
|
+
checkNodes(scenario, null, results)
|
|
181
|
+
return results
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
module.exports = { check, ALLOWED_PARENTS, KNOWN_ATTRIBUTES, GLOBAL_ATTRIBUTES }
|