webgal-parser 4.5.13 → 4.5.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,28 @@
1
+ # WebGAL Parser Changelog
2
+
3
+ ## [4.5.13] - 2025-07-05
4
+
5
+ ### Fixed
6
+ - Fixed interface consistency between `webgal-parser` and main WebGAL project
7
+ - Added missing trailing comma in `commandType` enum to match WebGAL main project
8
+ - Updated `ISceneData` interface to use `ISceneEntry` instead of `sceneEntry` for better type consistency
9
+
10
+ ### Added
11
+ - Added `ISceneEntry` interface as compatibility alias for `sceneEntry`
12
+ - Added comprehensive test cases for new animation parameters:
13
+ - `wait` command testing
14
+ - `changeFigure` with `duration`, `enter`, `exit` parameters
15
+ - `changeBg` with animation and transform parameters
16
+
17
+ ### Improved
18
+ - Enhanced type safety and consistency with main WebGAL project
19
+ - Better test coverage for animation-related features
20
+ - Improved interface documentation
21
+
22
+ ### Technical Notes
23
+ - The parser already supports all animation parameters (`duration`, `enter`, `exit`, `transform`) through its generic argument parsing system
24
+ - No changes to core parsing logic were needed - the parser was already compatible with the latest WebGAL features
25
+ - This update focuses on interface consistency and test coverage improvements
26
+
27
+ ## [4.5.12] - Previous Version
28
+ - Previous stable release with `wait` command support
@@ -38,6 +38,7 @@ var commandType;
38
38
  commandType[commandType["getUserInput"] = 31] = "getUserInput";
39
39
  commandType[commandType["applyStyle"] = 32] = "applyStyle";
40
40
  commandType[commandType["wait"] = 33] = "wait";
41
+ commandType[commandType["callSteam"] = 34] = "callSteam";
41
42
  })(commandType || (commandType = {}));
42
43
 
43
44
  const SCRIPT_CONFIG = [
@@ -78,6 +79,7 @@ const SCRIPT_CONFIG = [
78
79
  { scriptString: 'getUserInput', scriptType: commandType.getUserInput },
79
80
  { scriptString: 'applyStyle', scriptType: commandType.applyStyle },
80
81
  { scriptString: 'wait', scriptType: commandType.wait },
82
+ { scriptString: 'callSteam', scriptType: commandType.callSteam },
81
83
  ];
82
84
  const ADD_NEXT_ARG_LIST = [
83
85
  commandType.bgm,
@@ -93,6 +95,7 @@ const ADD_NEXT_ARG_LIST = [
93
95
  commandType.playEffect,
94
96
  commandType.setTransition,
95
97
  commandType.applyStyle,
98
+ commandType.callSteam,
96
99
  ];
97
100
 
98
101
  /**
@@ -128,10 +131,10 @@ function argsParser(argsRaw, assetSetter) {
128
131
  });
129
132
  rawArgsList.forEach((e) => {
130
133
  const equalSignIndex = e.indexOf('=');
131
- let argName = e.slice(0, equalSignIndex);
132
- let argValue = e.slice(equalSignIndex + 1);
134
+ let argName = e.slice(0, equalSignIndex).trim();
135
+ let argValue = e.slice(equalSignIndex + 1).trim();
133
136
  if (equalSignIndex < 0) {
134
- argName = e;
137
+ argName = e.trim();
135
138
  argValue = undefined;
136
139
  }
137
140
  // 判断是不是语音参数
@@ -447,14 +450,16 @@ const scriptParser = (sentenceRaw, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG
447
450
  let commandRaw;
448
451
  // 正式开始解析
449
452
  // 去分号
450
- let newSentenceRaw = sentenceRaw.split(/(?<!\\);/)[0];
453
+ const commentSplit = sentenceRaw.split(/(?<!\\);/);
454
+ let newSentenceRaw = commentSplit[0];
451
455
  newSentenceRaw = newSentenceRaw.replaceAll('\\;', ';');
452
- if (newSentenceRaw === '') {
456
+ const sentenceComment = commentSplit[1] ?? '';
457
+ if (newSentenceRaw.trim() === '') {
453
458
  // 注释提前返回
454
459
  return {
455
460
  command: commandType.comment,
456
461
  commandRaw: 'comment',
457
- content: sentenceRaw.split(';')[1] ?? '',
462
+ content: sentenceComment.trim(),
458
463
  args: [{ key: 'next', value: true }],
459
464
  sentenceAssets: [],
460
465
  subScene: [], // 语句携带的子场景
@@ -1771,7 +1776,7 @@ var uniqWith_1 = uniqWith;
1771
1776
  * @return {IScene} 解析后的场景
1772
1777
  */
1773
1778
  const sceneParser = (rawScene, sceneName, sceneUrl, assetsPrefetcher, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP) => {
1774
- const rawSentenceList = rawScene.split('\n'); // 原始句子列表
1779
+ const rawSentenceList = rawScene.replaceAll('\r', '').split('\n'); // 原始句子列表
1775
1780
  // 去分号留到后面去做了,现在注释要单独处理
1776
1781
  const rawSentenceListWithoutEmpty = rawSentenceList;
1777
1782
  // .map((sentence) => sentence.split(";")[0])
@@ -7,3 +7,9 @@ export interface sceneEntry {
7
7
  sceneUrl: string;
8
8
  continueLine: number;
9
9
  }
10
+ /**
11
+ * 场景栈条目接口 (兼容性别名)
12
+ * @interface ISceneEntry
13
+ */
14
+ export interface ISceneEntry extends sceneEntry {
15
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * 语句类型
3
3
  */
4
- import { sceneEntry } from './runtimeInterface';
4
+ import { ISceneEntry } from './runtimeInterface';
5
5
  import { fileType } from './assets';
6
6
  export declare enum commandType {
7
7
  say = 0,
@@ -37,7 +37,8 @@ export declare enum commandType {
37
37
  setTransition = 30,
38
38
  getUserInput = 31,
39
39
  applyStyle = 32,
40
- wait = 33
40
+ wait = 33,
41
+ callSteam = 34
41
42
  }
42
43
  /**
43
44
  * 单个参数接口
@@ -86,7 +87,7 @@ export interface IScene {
86
87
  */
87
88
  export interface ISceneData {
88
89
  currentSentenceId: number;
89
- sceneStack: Array<sceneEntry>;
90
+ sceneStack: Array<ISceneEntry>;
90
91
  currentScene: IScene;
91
92
  }
92
93
  /**
package/build/es/index.js CHANGED
@@ -34,6 +34,7 @@ var commandType;
34
34
  commandType[commandType["getUserInput"] = 31] = "getUserInput";
35
35
  commandType[commandType["applyStyle"] = 32] = "applyStyle";
36
36
  commandType[commandType["wait"] = 33] = "wait";
37
+ commandType[commandType["callSteam"] = 34] = "callSteam";
37
38
  })(commandType || (commandType = {}));
38
39
 
39
40
  const SCRIPT_CONFIG = [
@@ -74,6 +75,7 @@ const SCRIPT_CONFIG = [
74
75
  { scriptString: 'getUserInput', scriptType: commandType.getUserInput },
75
76
  { scriptString: 'applyStyle', scriptType: commandType.applyStyle },
76
77
  { scriptString: 'wait', scriptType: commandType.wait },
78
+ { scriptString: 'callSteam', scriptType: commandType.callSteam },
77
79
  ];
78
80
  const ADD_NEXT_ARG_LIST = [
79
81
  commandType.bgm,
@@ -89,6 +91,7 @@ const ADD_NEXT_ARG_LIST = [
89
91
  commandType.playEffect,
90
92
  commandType.setTransition,
91
93
  commandType.applyStyle,
94
+ commandType.callSteam,
92
95
  ];
93
96
 
94
97
  /**
@@ -124,10 +127,10 @@ function argsParser(argsRaw, assetSetter) {
124
127
  });
125
128
  rawArgsList.forEach((e) => {
126
129
  const equalSignIndex = e.indexOf('=');
127
- let argName = e.slice(0, equalSignIndex);
128
- let argValue = e.slice(equalSignIndex + 1);
130
+ let argName = e.slice(0, equalSignIndex).trim();
131
+ let argValue = e.slice(equalSignIndex + 1).trim();
129
132
  if (equalSignIndex < 0) {
130
- argName = e;
133
+ argName = e.trim();
131
134
  argValue = undefined;
132
135
  }
133
136
  // 判断是不是语音参数
@@ -443,14 +446,16 @@ const scriptParser = (sentenceRaw, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG
443
446
  let commandRaw;
444
447
  // 正式开始解析
445
448
  // 去分号
446
- let newSentenceRaw = sentenceRaw.split(/(?<!\\);/)[0];
449
+ const commentSplit = sentenceRaw.split(/(?<!\\);/);
450
+ let newSentenceRaw = commentSplit[0];
447
451
  newSentenceRaw = newSentenceRaw.replaceAll('\\;', ';');
448
- if (newSentenceRaw === '') {
452
+ const sentenceComment = commentSplit[1] ?? '';
453
+ if (newSentenceRaw.trim() === '') {
449
454
  // 注释提前返回
450
455
  return {
451
456
  command: commandType.comment,
452
457
  commandRaw: 'comment',
453
- content: sentenceRaw.split(';')[1] ?? '',
458
+ content: sentenceComment.trim(),
454
459
  args: [{ key: 'next', value: true }],
455
460
  sentenceAssets: [],
456
461
  subScene: [], // 语句携带的子场景
@@ -1767,7 +1772,7 @@ var uniqWith_1 = uniqWith;
1767
1772
  * @return {IScene} 解析后的场景
1768
1773
  */
1769
1774
  const sceneParser = (rawScene, sceneName, sceneUrl, assetsPrefetcher, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP) => {
1770
- const rawSentenceList = rawScene.split('\n'); // 原始句子列表
1775
+ const rawSentenceList = rawScene.replaceAll('\r', '').split('\n'); // 原始句子列表
1771
1776
  // 去分号留到后面去做了,现在注释要单独处理
1772
1777
  const rawSentenceListWithoutEmpty = rawSentenceList;
1773
1778
  // .map((sentence) => sentence.split(";")[0])
@@ -7,3 +7,9 @@ export interface sceneEntry {
7
7
  sceneUrl: string;
8
8
  continueLine: number;
9
9
  }
10
+ /**
11
+ * 场景栈条目接口 (兼容性别名)
12
+ * @interface ISceneEntry
13
+ */
14
+ export interface ISceneEntry extends sceneEntry {
15
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * 语句类型
3
3
  */
4
- import { sceneEntry } from './runtimeInterface';
4
+ import { ISceneEntry } from './runtimeInterface';
5
5
  import { fileType } from './assets';
6
6
  export declare enum commandType {
7
7
  say = 0,
@@ -37,7 +37,8 @@ export declare enum commandType {
37
37
  setTransition = 30,
38
38
  getUserInput = 31,
39
39
  applyStyle = 32,
40
- wait = 33
40
+ wait = 33,
41
+ callSteam = 34
41
42
  }
42
43
  /**
43
44
  * 单个参数接口
@@ -86,7 +87,7 @@ export interface IScene {
86
87
  */
87
88
  export interface ISceneData {
88
89
  currentSentenceId: number;
89
- sceneStack: Array<sceneEntry>;
90
+ sceneStack: Array<ISceneEntry>;
90
91
  currentScene: IScene;
91
92
  }
92
93
  /**
@@ -7,3 +7,9 @@ export interface sceneEntry {
7
7
  sceneUrl: string;
8
8
  continueLine: number;
9
9
  }
10
+ /**
11
+ * 场景栈条目接口 (兼容性别名)
12
+ * @interface ISceneEntry
13
+ */
14
+ export interface ISceneEntry extends sceneEntry {
15
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * 语句类型
3
3
  */
4
- import { sceneEntry } from './runtimeInterface';
4
+ import { ISceneEntry } from './runtimeInterface';
5
5
  import { fileType } from './assets';
6
6
  export declare enum commandType {
7
7
  say = 0,
@@ -37,7 +37,8 @@ export declare enum commandType {
37
37
  setTransition = 30,
38
38
  getUserInput = 31,
39
39
  applyStyle = 32,
40
- wait = 33
40
+ wait = 33,
41
+ callSteam = 34
41
42
  }
42
43
  /**
43
44
  * 单个参数接口
@@ -86,7 +87,7 @@ export interface IScene {
86
87
  */
87
88
  export interface ISceneData {
88
89
  currentSentenceId: number;
89
- sceneStack: Array<sceneEntry>;
90
+ sceneStack: Array<ISceneEntry>;
90
91
  currentScene: IScene;
91
92
  }
92
93
  /**
@@ -37,6 +37,7 @@ var webgalParser = (function (exports) {
37
37
  commandType[commandType["getUserInput"] = 31] = "getUserInput";
38
38
  commandType[commandType["applyStyle"] = 32] = "applyStyle";
39
39
  commandType[commandType["wait"] = 33] = "wait";
40
+ commandType[commandType["callSteam"] = 34] = "callSteam";
40
41
  })(commandType || (commandType = {}));
41
42
 
42
43
  const SCRIPT_CONFIG = [
@@ -77,6 +78,7 @@ var webgalParser = (function (exports) {
77
78
  { scriptString: 'getUserInput', scriptType: commandType.getUserInput },
78
79
  { scriptString: 'applyStyle', scriptType: commandType.applyStyle },
79
80
  { scriptString: 'wait', scriptType: commandType.wait },
81
+ { scriptString: 'callSteam', scriptType: commandType.callSteam },
80
82
  ];
81
83
  const ADD_NEXT_ARG_LIST = [
82
84
  commandType.bgm,
@@ -92,6 +94,7 @@ var webgalParser = (function (exports) {
92
94
  commandType.playEffect,
93
95
  commandType.setTransition,
94
96
  commandType.applyStyle,
97
+ commandType.callSteam,
95
98
  ];
96
99
 
97
100
  /**
@@ -127,10 +130,10 @@ var webgalParser = (function (exports) {
127
130
  });
128
131
  rawArgsList.forEach((e) => {
129
132
  const equalSignIndex = e.indexOf('=');
130
- let argName = e.slice(0, equalSignIndex);
131
- let argValue = e.slice(equalSignIndex + 1);
133
+ let argName = e.slice(0, equalSignIndex).trim();
134
+ let argValue = e.slice(equalSignIndex + 1).trim();
132
135
  if (equalSignIndex < 0) {
133
- argName = e;
136
+ argName = e.trim();
134
137
  argValue = undefined;
135
138
  }
136
139
  // 判断是不是语音参数
@@ -446,14 +449,16 @@ var webgalParser = (function (exports) {
446
449
  let commandRaw;
447
450
  // 正式开始解析
448
451
  // 去分号
449
- let newSentenceRaw = sentenceRaw.split(/(?<!\\);/)[0];
452
+ const commentSplit = sentenceRaw.split(/(?<!\\);/);
453
+ let newSentenceRaw = commentSplit[0];
450
454
  newSentenceRaw = newSentenceRaw.replaceAll('\\;', ';');
451
- if (newSentenceRaw === '') {
455
+ const sentenceComment = commentSplit[1] ?? '';
456
+ if (newSentenceRaw.trim() === '') {
452
457
  // 注释提前返回
453
458
  return {
454
459
  command: commandType.comment,
455
460
  commandRaw: 'comment',
456
- content: sentenceRaw.split(';')[1] ?? '',
461
+ content: sentenceComment.trim(),
457
462
  args: [{ key: 'next', value: true }],
458
463
  sentenceAssets: [],
459
464
  subScene: [], // 语句携带的子场景
@@ -1770,7 +1775,7 @@ var webgalParser = (function (exports) {
1770
1775
  * @return {IScene} 解析后的场景
1771
1776
  */
1772
1777
  const sceneParser = (rawScene, sceneName, sceneUrl, assetsPrefetcher, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP) => {
1773
- const rawSentenceList = rawScene.split('\n'); // 原始句子列表
1778
+ const rawSentenceList = rawScene.replaceAll('\r', '').split('\n'); // 原始句子列表
1774
1779
  // 去分号留到后面去做了,现在注释要单独处理
1775
1780
  const rawSentenceListWithoutEmpty = rawSentenceList;
1776
1781
  // .map((sentence) => sentence.split(";")[0])
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "webgal-parser",
3
- "version": "4.5.13",
3
+ "version": "4.5.17",
4
4
  "description": "WebGAL script parser",
5
5
  "scripts": {
6
6
  "test": "vitest",
7
7
  "coverage": "vitest run --coverage",
8
8
  "build": "rimraf -rf ./build && rollup --config",
9
+ "prepublishOnly": "npm run build",
9
10
  "build-ci": "rollup --config",
10
11
  "debug": "tsx test/debug.ts",
11
12
  "debug-scss-parser": "tsx test/debugCssParser.ts",
@@ -38,6 +38,7 @@ export const SCRIPT_CONFIG = [
38
38
  { scriptString: 'getUserInput', scriptType: commandType.getUserInput },
39
39
  { scriptString: 'applyStyle', scriptType: commandType.applyStyle },
40
40
  { scriptString: 'wait', scriptType: commandType.wait },
41
+ { scriptString: 'callSteam', scriptType: commandType.callSteam },
41
42
  ];
42
43
  export const ADD_NEXT_ARG_LIST = [
43
44
  commandType.bgm,
@@ -53,6 +54,7 @@ export const ADD_NEXT_ARG_LIST = [
53
54
  commandType.playEffect,
54
55
  commandType.setTransition,
55
56
  commandType.applyStyle,
57
+ commandType.callSteam,
56
58
  ];
57
59
 
58
60
  export type ConfigMap = Map<string, ConfigItem>;
@@ -7,3 +7,9 @@ export interface sceneEntry {
7
7
  sceneUrl: string; // 场景url
8
8
  continueLine: number; // 继续原场景的行号
9
9
  }
10
+
11
+ /**
12
+ * 场景栈条目接口 (兼容性别名)
13
+ * @interface ISceneEntry
14
+ */
15
+ export interface ISceneEntry extends sceneEntry {}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * 语句类型
3
3
  */
4
- import { sceneEntry } from './runtimeInterface';
4
+ import { sceneEntry, ISceneEntry } from './runtimeInterface';
5
5
  import { fileType } from './assets';
6
6
 
7
7
  export enum commandType {
@@ -38,7 +38,8 @@ export enum commandType {
38
38
  setTransition,
39
39
  getUserInput,
40
40
  applyStyle,
41
- wait
41
+ wait,
42
+ callSteam, // 调用Steam功能
42
43
  }
43
44
 
44
45
  /**
@@ -92,7 +93,7 @@ export interface IScene {
92
93
  */
93
94
  export interface ISceneData {
94
95
  currentSentenceId: number; // 当前语句ID
95
- sceneStack: Array<sceneEntry>; // 场景栈
96
+ sceneStack: Array<ISceneEntry>; // 场景栈
96
97
  currentScene: IScene; // 当前场景数据
97
98
  }
98
99
 
@@ -29,7 +29,7 @@ export const sceneParser = (
29
29
  ADD_NEXT_ARG_LIST: commandType[],
30
30
  SCRIPT_CONFIG_MAP: ConfigMap,
31
31
  ): IScene => {
32
- const rawSentenceList = rawScene.split('\n'); // 原始句子列表
32
+ const rawSentenceList = rawScene.replaceAll('\r', '').split('\n'); // 原始句子列表
33
33
 
34
34
  // 去分号留到后面去做了,现在注释要单独处理
35
35
  const rawSentenceListWithoutEmpty = rawSentenceList;
@@ -23,10 +23,10 @@ export function argsParser(
23
23
  });
24
24
  rawArgsList.forEach((e) => {
25
25
  const equalSignIndex = e.indexOf('=');
26
- let argName = e.slice(0, equalSignIndex);
27
- let argValue: string | undefined = e.slice(equalSignIndex + 1);
26
+ let argName = e.slice(0, equalSignIndex).trim();
27
+ let argValue: string | undefined = e.slice(equalSignIndex + 1).trim();
28
28
  if (equalSignIndex < 0) {
29
- argName = e;
29
+ argName = e.trim();
30
30
  argValue = undefined;
31
31
  }
32
32
  // 判断是不是语音参数
@@ -36,14 +36,16 @@ export const scriptParser = (
36
36
  // 正式开始解析
37
37
 
38
38
  // 去分号
39
- let newSentenceRaw = sentenceRaw.split(/(?<!\\);/)[0];
39
+ const commentSplit = sentenceRaw.split(/(?<!\\);/);
40
+ let newSentenceRaw = commentSplit[0];
40
41
  newSentenceRaw = newSentenceRaw.replaceAll('\\;',';');
41
- if (newSentenceRaw === '') {
42
+ const sentenceComment = commentSplit[1] ?? '';
43
+ if (newSentenceRaw.trim() === '') {
42
44
  // 注释提前返回
43
45
  return {
44
46
  command: commandType.comment, // 语句类型
45
47
  commandRaw: 'comment', // 命令原始内容,方便调试
46
- content: sentenceRaw.split(';')[1] ?? '', // 语句内容
48
+ content: sentenceComment.trim(), // 语句内容
47
49
  args: [{ key: 'next', value: true }], // 参数列表
48
50
  sentenceAssets: [], // 语句携带的资源列表
49
51
  subScene: [], // 语句携带的子场景