webgal-parser 4.6.2 → 4.6.3-beta.2
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 +18 -0
- package/build/cjs/index.cjs +157 -163
- package/build/cjs/index.d.ts +2 -2
- package/build/cjs/interface/runtimeInterface.d.ts +2 -0
- package/build/cjs/interface/sceneInterface.d.ts +11 -1
- package/build/cjs/sceneTextPreProcessor.d.ts +10 -0
- package/build/es/index.d.ts +2 -2
- package/build/es/index.js +156 -164
- package/build/es/interface/runtimeInterface.d.ts +2 -0
- package/build/es/interface/sceneInterface.d.ts +11 -1
- package/build/es/sceneTextPreProcessor.d.ts +10 -0
- package/build/types/index.d.ts +2 -2
- package/build/types/interface/runtimeInterface.d.ts +2 -0
- package/build/types/interface/sceneInterface.d.ts +11 -1
- package/build/types/sceneTextPreProcessor.d.ts +10 -0
- package/build/umd/index.global.js +157 -163
- package/package.json +1 -1
- package/src/config/scriptConfig.ts +1 -0
- package/src/index.ts +6 -2
- package/src/interface/runtimeInterface.ts +2 -0
- package/src/interface/sceneInterface.ts +10 -0
- package/src/sceneParser.ts +36 -1
- package/src/sceneTextPreProcessor.ts +39 -88
- package/src/scriptParser/argsParser.ts +1 -1
- package/src/scriptParser/scriptParser.ts +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# WebGAL Parser Changelog
|
|
2
2
|
|
|
3
|
+
## [4.6.3-beta.2] - 2026-07-31
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- `sceneTextPreProcess`:折叠序列的首行是空行时(例如空行后面紧跟一条续行),整条序列会被静默丢弃,导致预处理后行数变少。这会击穿「解析后语句 index == 文件行号」,进而让存档进度错位。改用 `null` 哨兵区分「不在折叠序列中」与「首行内容为空串」
|
|
7
|
+
|
|
8
|
+
## [4.6.3-beta.1] - 2026-07-31
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- 正式启用多行语句支持:`sceneParser` 现在会先经过 `sceneTextPreProcess`,把以空白开头且首字符为 `-` 或 `|` 的续行折叠进上一条语句
|
|
12
|
+
- `ISentence` 新增行范围字段 `startLine` / `endLine`(0-based,含首尾)与 `isLineBreakHolder`,供图形编辑器按行范围整体替换语句
|
|
13
|
+
- 导出 `WEBGAL_LINE_BREAK_MARK` 与 `isLineBreakPlaceholder`
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- `sceneTextPreProcess`:移除逐行 `console.log`;场景首行不再被误判为续行;场景末行以 `\` 结尾时不再丢失整段累积内容
|
|
17
|
+
|
|
18
|
+
### Technical Notes
|
|
19
|
+
- 续行会被替换成 `;_WEBGAL_LINE_BREAK_` 占位注释行,**预处理前后行数严格一致**。因此「解析后语句 index == 文件行号」这一不变量继续成立,引擎的存读档、Backlog、场景栈、已读记录(都存语句 index)无需改动,旧存档也不会错位
|
|
20
|
+
|
|
3
21
|
## [4.5.13] - 2025-07-05
|
|
4
22
|
|
|
5
23
|
### Fixed
|
package/build/cjs/index.cjs
CHANGED
|
@@ -39,6 +39,7 @@ var commandType;
|
|
|
39
39
|
commandType[commandType["applyStyle"] = 32] = "applyStyle";
|
|
40
40
|
commandType[commandType["wait"] = 33] = "wait";
|
|
41
41
|
commandType[commandType["callSteam"] = 34] = "callSteam";
|
|
42
|
+
commandType[commandType["return"] = 35] = "return";
|
|
42
43
|
})(commandType || (commandType = {}));
|
|
43
44
|
|
|
44
45
|
const SCRIPT_CONFIG = [
|
|
@@ -80,6 +81,7 @@ const SCRIPT_CONFIG = [
|
|
|
80
81
|
{ scriptString: 'applyStyle', scriptType: commandType.applyStyle },
|
|
81
82
|
{ scriptString: 'wait', scriptType: commandType.wait },
|
|
82
83
|
{ scriptString: 'callSteam', scriptType: commandType.callSteam },
|
|
84
|
+
{ scriptString: 'return', scriptType: commandType.return },
|
|
83
85
|
];
|
|
84
86
|
const ADD_NEXT_ARG_LIST = [
|
|
85
87
|
commandType.bgm,
|
|
@@ -138,7 +140,7 @@ function argsParser(argsRaw, assetSetter) {
|
|
|
138
140
|
argValue = undefined;
|
|
139
141
|
}
|
|
140
142
|
// 判断是不是语音参数
|
|
141
|
-
if (argName.toLowerCase().match(/.ogg|.mp3|.wav/)) {
|
|
143
|
+
if (argName.toLowerCase().match(/.ogg|.mp3|.wav|.opus/)) {
|
|
142
144
|
returnArrayList.push({
|
|
143
145
|
key: 'vocal',
|
|
144
146
|
value: assetSetter(e, fileType.vocal),
|
|
@@ -463,7 +465,10 @@ const scriptParser = (sentenceRaw, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG
|
|
|
463
465
|
args: [{ key: 'next', value: true }],
|
|
464
466
|
sentenceAssets: [],
|
|
465
467
|
subScene: [],
|
|
466
|
-
inlineComment: '',
|
|
468
|
+
inlineComment: '',
|
|
469
|
+
startLine: lineNumber,
|
|
470
|
+
endLine: lineNumber,
|
|
471
|
+
isLineBreakHolder: false,
|
|
467
472
|
};
|
|
468
473
|
}
|
|
469
474
|
// 截取命令
|
|
@@ -514,92 +519,14 @@ const scriptParser = (sentenceRaw, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG
|
|
|
514
519
|
args: args,
|
|
515
520
|
sentenceAssets: sentenceAssets,
|
|
516
521
|
subScene: subScene,
|
|
517
|
-
inlineComment: sentenceComment.trim(),
|
|
522
|
+
inlineComment: sentenceComment.trim(),
|
|
523
|
+
// 单行语句的行范围就是自己,多行语句的 endLine 由 sceneParser 回填
|
|
524
|
+
startLine: lineNumber,
|
|
525
|
+
endLine: lineNumber,
|
|
526
|
+
isLineBreakHolder: false,
|
|
518
527
|
};
|
|
519
528
|
};
|
|
520
529
|
|
|
521
|
-
/**
|
|
522
|
-
* 场景解析器
|
|
523
|
-
* @param rawScene 原始场景
|
|
524
|
-
* @param sceneName 场景名称
|
|
525
|
-
* @param sceneUrl 场景url
|
|
526
|
-
* @param assetsPrefetcher
|
|
527
|
-
* @param assetSetter
|
|
528
|
-
* @param ADD_NEXT_ARG_LIST
|
|
529
|
-
* @param SCRIPT_CONFIG_MAP
|
|
530
|
-
* @return {IScene} 解析后的场景
|
|
531
|
-
*/
|
|
532
|
-
const sceneParser = (rawScene, sceneName, sceneUrl, assetsPrefetcher, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP) => {
|
|
533
|
-
const rawSentenceList = rawScene.replaceAll('\r', '').split('\n'); // 原始句子列表
|
|
534
|
-
// 去分号留到后面去做了,现在注释要单独处理
|
|
535
|
-
const rawSentenceListWithoutEmpty = rawSentenceList;
|
|
536
|
-
// .map((sentence) => sentence.split(";")[0])
|
|
537
|
-
// .filter((sentence) => sentence.trim() !== "");
|
|
538
|
-
let assetsList = []; // 场景资源列表
|
|
539
|
-
let subSceneList = []; // 子场景列表
|
|
540
|
-
const sentenceList = rawSentenceListWithoutEmpty.map((sentence, index) => {
|
|
541
|
-
const returnSentence = scriptParser(sentence, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, index);
|
|
542
|
-
// 在这里解析出语句可能携带的资源和场景,合并到 assetsList 和 subSceneList
|
|
543
|
-
assetsList = [...assetsList, ...returnSentence.sentenceAssets];
|
|
544
|
-
subSceneList = [...subSceneList, ...returnSentence.subScene];
|
|
545
|
-
return returnSentence;
|
|
546
|
-
});
|
|
547
|
-
// 开始资源的预加载
|
|
548
|
-
assetsList = deduplicateAssets(assetsList);
|
|
549
|
-
assetsPrefetcher(assetsList);
|
|
550
|
-
return {
|
|
551
|
-
sceneName: sceneName,
|
|
552
|
-
sceneUrl: sceneUrl,
|
|
553
|
-
sentenceList: sentenceList,
|
|
554
|
-
assetsList: assetsList,
|
|
555
|
-
subSceneList: subSceneList, // 子场景列表
|
|
556
|
-
};
|
|
557
|
-
};
|
|
558
|
-
const deduplicateAssets = (assetsList) => {
|
|
559
|
-
const seenAssets = new Set();
|
|
560
|
-
return assetsList.filter((asset) => {
|
|
561
|
-
if (!asset || typeof asset.url !== 'string' || asset.url === '') {
|
|
562
|
-
return false;
|
|
563
|
-
}
|
|
564
|
-
const assetKey = `${asset.type}:${asset.url}`;
|
|
565
|
-
if (seenAssets.has(assetKey)) {
|
|
566
|
-
return false;
|
|
567
|
-
}
|
|
568
|
-
seenAssets.add(assetKey);
|
|
569
|
-
return true;
|
|
570
|
-
});
|
|
571
|
-
};
|
|
572
|
-
|
|
573
|
-
function scss2cssinjsParser(scssString) {
|
|
574
|
-
const [classNameStyles, others] = parseCSS(scssString);
|
|
575
|
-
return {
|
|
576
|
-
classNameStyles,
|
|
577
|
-
others,
|
|
578
|
-
};
|
|
579
|
-
}
|
|
580
|
-
/**
|
|
581
|
-
* GPT 4 写的,临时用,以后要重构!!!
|
|
582
|
-
* TODO:用人类智能重构,要是用着一直没问题,也不是不可以 trust AI
|
|
583
|
-
* @param css
|
|
584
|
-
*/
|
|
585
|
-
function parseCSS(css) {
|
|
586
|
-
const result = {};
|
|
587
|
-
let specialRules = '';
|
|
588
|
-
let matches;
|
|
589
|
-
// 使用非贪婪匹配,尝试正确处理任意层次的嵌套
|
|
590
|
-
const classRegex = /\.([^{\s]+)\s*{((?:[^{}]*|{[^}]*})*)}/g;
|
|
591
|
-
const specialRegex = /(@[^{]+{\s*(?:[^{}]*{[^}]*}[^{}]*)+\s*})/g;
|
|
592
|
-
while ((matches = classRegex.exec(css)) !== null) {
|
|
593
|
-
const key = matches[1];
|
|
594
|
-
const value = matches[2].trim().replace(/\s*;\s*/g, ';\n');
|
|
595
|
-
result[key] = value;
|
|
596
|
-
}
|
|
597
|
-
while ((matches = specialRegex.exec(css)) !== null) {
|
|
598
|
-
specialRules += matches[1].trim() + '\n';
|
|
599
|
-
}
|
|
600
|
-
return [result, specialRules.trim()];
|
|
601
|
-
}
|
|
602
|
-
|
|
603
530
|
/**
|
|
604
531
|
* Preprocessor for scene text.
|
|
605
532
|
*
|
|
@@ -629,13 +556,11 @@ function sceneTextPreProcessPassOne(lines) {
|
|
|
629
556
|
let lastLineIsMultiline = false;
|
|
630
557
|
let thisLineIsMultiline = false;
|
|
631
558
|
for (const line of lines) {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
thisLineIsMultiline = false;
|
|
638
|
-
}
|
|
559
|
+
// 续行需要接到上一行,所以场景的第一行永远不会是续行。
|
|
560
|
+
thisLineIsMultiline =
|
|
561
|
+
processedLines.length > 0 &&
|
|
562
|
+
canBeMultiline(line) &&
|
|
563
|
+
!shouldNotBeMultiline(line, lastLineIsMultiline);
|
|
639
564
|
if (thisLineIsMultiline) {
|
|
640
565
|
processedLines[processedLines.length - 1] += '\\';
|
|
641
566
|
}
|
|
@@ -682,7 +607,10 @@ function isEmptyLine(line) {
|
|
|
682
607
|
*/
|
|
683
608
|
function sceneTextPreProcessPassTwo(lines) {
|
|
684
609
|
const processedLines = [];
|
|
685
|
-
|
|
610
|
+
// null 表示当前不在多行序列里。这里不能用空串来判断:
|
|
611
|
+
// 序列的首行本身可能就是空行(比如空行后面紧跟着一条续行),
|
|
612
|
+
// 那样整条序列会被静默丢弃,破坏「预处理前后行数一致」这个前提。
|
|
613
|
+
let currentMultilineContent = null;
|
|
686
614
|
let placeHolderLines = [];
|
|
687
615
|
function concat(line) {
|
|
688
616
|
let trimmed = line.trim();
|
|
@@ -692,11 +620,16 @@ function sceneTextPreProcessPassTwo(lines) {
|
|
|
692
620
|
currentMultilineContent = currentMultilineContent + trimmed;
|
|
693
621
|
placeHolderLines.push(placeholderLine(line));
|
|
694
622
|
}
|
|
623
|
+
/** 把折叠好的整条语句连同补齐行数的占位行一起输出 */
|
|
624
|
+
function flushMultiline() {
|
|
625
|
+
processedLines.push(currentMultilineContent, ...placeHolderLines);
|
|
626
|
+
placeHolderLines = [];
|
|
627
|
+
currentMultilineContent = null;
|
|
628
|
+
}
|
|
695
629
|
for (const line of lines) {
|
|
696
|
-
console.log(line);
|
|
697
630
|
if (line.endsWith('\\')) {
|
|
698
631
|
const trueLine = line.slice(0, -1);
|
|
699
|
-
if (currentMultilineContent ===
|
|
632
|
+
if (currentMultilineContent === null) {
|
|
700
633
|
// first line
|
|
701
634
|
currentMultilineContent = trueLine;
|
|
702
635
|
}
|
|
@@ -706,19 +639,32 @@ function sceneTextPreProcessPassTwo(lines) {
|
|
|
706
639
|
}
|
|
707
640
|
continue;
|
|
708
641
|
}
|
|
709
|
-
if (currentMultilineContent !==
|
|
642
|
+
if (currentMultilineContent !== null) {
|
|
710
643
|
// end line
|
|
711
644
|
concat(line);
|
|
712
|
-
|
|
713
|
-
processedLines.push(...placeHolderLines);
|
|
714
|
-
placeHolderLines = [];
|
|
715
|
-
currentMultilineContent = "";
|
|
645
|
+
flushMultiline();
|
|
716
646
|
continue;
|
|
717
647
|
}
|
|
718
648
|
processedLines.push(line);
|
|
719
649
|
}
|
|
650
|
+
// 场景末行仍以 \ 结尾时循环里没有机会收尾,在这里把累积的内容补出去。
|
|
651
|
+
if (currentMultilineContent !== null) {
|
|
652
|
+
flushMultiline();
|
|
653
|
+
}
|
|
720
654
|
return processedLines;
|
|
721
655
|
}
|
|
656
|
+
/**
|
|
657
|
+
* 占位行的前缀。占位行本身是一条注释,引擎会空跑掉;
|
|
658
|
+
* 它的作用是让预处理后的行数与原始场景一致,从而保持
|
|
659
|
+
* 「解析后语句 index == 文件行号」这一不变量。
|
|
660
|
+
*/
|
|
661
|
+
const WEBGAL_LINE_BREAK_MARK = ';_WEBGAL_LINE_BREAK_';
|
|
662
|
+
/**
|
|
663
|
+
* 判断预处理后的某一行是否是占位行,即它是上一条多行语句折叠掉的续行。
|
|
664
|
+
*/
|
|
665
|
+
function isLineBreakPlaceholder(processedLine) {
|
|
666
|
+
return processedLine.startsWith(WEBGAL_LINE_BREAK_MARK);
|
|
667
|
+
}
|
|
722
668
|
/**
|
|
723
669
|
* Placeholder Line. Adding this line preserves the original number of lines
|
|
724
670
|
* in the scene text, so that it can be compatible with the graphical editor.
|
|
@@ -727,70 +673,116 @@ function sceneTextPreProcessPassTwo(lines) {
|
|
|
727
673
|
* @returns The placeholder line
|
|
728
674
|
*/
|
|
729
675
|
function placeholderLine(content = "") {
|
|
730
|
-
return
|
|
676
|
+
return WEBGAL_LINE_BREAK_MARK + content;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* 场景解析器
|
|
681
|
+
* @param rawScene 原始场景
|
|
682
|
+
* @param sceneName 场景名称
|
|
683
|
+
* @param sceneUrl 场景url
|
|
684
|
+
* @param assetsPrefetcher
|
|
685
|
+
* @param assetSetter
|
|
686
|
+
* @param ADD_NEXT_ARG_LIST
|
|
687
|
+
* @param SCRIPT_CONFIG_MAP
|
|
688
|
+
* @return {IScene} 解析后的场景
|
|
689
|
+
*/
|
|
690
|
+
const sceneParser = (rawScene, sceneName, sceneUrl, assetsPrefetcher, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP) => {
|
|
691
|
+
// 预处理把多行语句折叠进它的首行,并用占位行补齐被折叠掉的行,
|
|
692
|
+
// 因此这里的行数与原始场景严格一致,「语句 index == 文件行号」始终成立。
|
|
693
|
+
const rawSentenceList = sceneTextPreProcess(rawScene).split('\n'); // 原始句子列表
|
|
694
|
+
// 去分号留到后面去做了,现在注释要单独处理
|
|
695
|
+
const rawSentenceListWithoutEmpty = rawSentenceList;
|
|
696
|
+
// .map((sentence) => sentence.split(";")[0])
|
|
697
|
+
// .filter((sentence) => sentence.trim() !== "");
|
|
698
|
+
let assetsList = []; // 场景资源列表
|
|
699
|
+
let subSceneList = []; // 子场景列表
|
|
700
|
+
const sentenceList = rawSentenceListWithoutEmpty.map((sentence, index) => {
|
|
701
|
+
const returnSentence = scriptParser(sentence, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, index);
|
|
702
|
+
// 在这里解析出语句可能携带的资源和场景,合并到 assetsList 和 subSceneList
|
|
703
|
+
assetsList = [...assetsList, ...returnSentence.sentenceAssets];
|
|
704
|
+
subSceneList = [...subSceneList, ...returnSentence.subScene];
|
|
705
|
+
return returnSentence;
|
|
706
|
+
});
|
|
707
|
+
markMultilineRanges(sentenceList, rawSentenceList);
|
|
708
|
+
// 开始资源的预加载
|
|
709
|
+
assetsList = deduplicateAssets(assetsList);
|
|
710
|
+
assetsPrefetcher(assetsList);
|
|
711
|
+
return {
|
|
712
|
+
sceneName: sceneName,
|
|
713
|
+
sceneUrl: sceneUrl,
|
|
714
|
+
sentenceList: sentenceList,
|
|
715
|
+
assetsList: assetsList,
|
|
716
|
+
subSceneList: subSceneList, // 子场景列表
|
|
717
|
+
};
|
|
718
|
+
};
|
|
719
|
+
/**
|
|
720
|
+
* 回填多行语句的行范围。
|
|
721
|
+
*
|
|
722
|
+
* 预处理后,一条多行语句的完整内容都落在它的首行,紧跟其后的若干占位行
|
|
723
|
+
* 就是被折叠掉的续行。这里把占位行标记出来,并把首行语句的 endLine
|
|
724
|
+
* 推到最后一条续行,图形编辑器据此按整个行范围替换语句。
|
|
725
|
+
*
|
|
726
|
+
* @param sentenceList 解析后的语句列表
|
|
727
|
+
* @param processedLines 预处理后的行,与 sentenceList 一一对应
|
|
728
|
+
*/
|
|
729
|
+
const markMultilineRanges = (sentenceList, processedLines) => {
|
|
730
|
+
let headIndex = -1; // 最近一条非占位语句的下标,即当前多行语句的首行
|
|
731
|
+
for (let index = 0; index < sentenceList.length; index++) {
|
|
732
|
+
if (!isLineBreakPlaceholder(processedLines[index])) {
|
|
733
|
+
headIndex = index;
|
|
734
|
+
continue;
|
|
735
|
+
}
|
|
736
|
+
sentenceList[index].isLineBreakHolder = true;
|
|
737
|
+
if (headIndex >= 0) {
|
|
738
|
+
sentenceList[headIndex].endLine = index;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
const deduplicateAssets = (assetsList) => {
|
|
743
|
+
const seenAssets = new Set();
|
|
744
|
+
return assetsList.filter((asset) => {
|
|
745
|
+
if (!asset || typeof asset.url !== 'string' || asset.url === '') {
|
|
746
|
+
return false;
|
|
747
|
+
}
|
|
748
|
+
const assetKey = `${asset.type}:${asset.url}`;
|
|
749
|
+
if (seenAssets.has(assetKey)) {
|
|
750
|
+
return false;
|
|
751
|
+
}
|
|
752
|
+
seenAssets.add(assetKey);
|
|
753
|
+
return true;
|
|
754
|
+
});
|
|
755
|
+
};
|
|
756
|
+
|
|
757
|
+
function scss2cssinjsParser(scssString) {
|
|
758
|
+
const [classNameStyles, others] = parseCSS(scssString);
|
|
759
|
+
return {
|
|
760
|
+
classNameStyles,
|
|
761
|
+
others,
|
|
762
|
+
};
|
|
731
763
|
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
//
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
// break;
|
|
755
|
-
// }
|
|
756
|
-
// // 必须找到后面接的是参数,并且中间没有遇到任何正常语句才行
|
|
757
|
-
// if (lookForwardLine.trim() !== '' && isMultiline(lookForwardLine)) {
|
|
758
|
-
// isStillInMulti = true;
|
|
759
|
-
// break;
|
|
760
|
-
// }
|
|
761
|
-
// }
|
|
762
|
-
// if (isStillInMulti) {
|
|
763
|
-
// // Still within a multiline sequence
|
|
764
|
-
// processedLines.push(';_WEBGAL_LINE_BREAK_');
|
|
765
|
-
// } else {
|
|
766
|
-
// // End of multiline sequence
|
|
767
|
-
// isInMultilineSequence = false;
|
|
768
|
-
// processedLines.push(line);
|
|
769
|
-
// }
|
|
770
|
-
// } else {
|
|
771
|
-
// // Preserve empty lines outside of multiline sequences
|
|
772
|
-
// processedLines.push(line);
|
|
773
|
-
// }
|
|
774
|
-
// } else if (isMultiline(line)) {
|
|
775
|
-
// // Multiline statement handling
|
|
776
|
-
// if (lastNonMultilineIndex >= 0) {
|
|
777
|
-
// // Concatenate to the previous non-multiline statement
|
|
778
|
-
// const trimedLine = line.trimStart();
|
|
779
|
-
// const addBlank = trimedLine.startsWith('-') ? ' ' : '';
|
|
780
|
-
// processedLines[lastNonMultilineIndex] += addBlank + trimedLine;
|
|
781
|
-
// }
|
|
782
|
-
// // Add the special comment line
|
|
783
|
-
// processedLines.push(';_WEBGAL_LINE_BREAK_' + line);
|
|
784
|
-
// isInMultilineSequence = true;
|
|
785
|
-
// } else {
|
|
786
|
-
// // Non-multiline statement handling
|
|
787
|
-
// processedLines.push(line);
|
|
788
|
-
// lastNonMultilineIndex = processedLines.length - 1;
|
|
789
|
-
// isInMultilineSequence = false;
|
|
790
|
-
// }
|
|
791
|
-
// }
|
|
792
|
-
// return processedLines.join('\n');
|
|
793
|
-
// }
|
|
764
|
+
/**
|
|
765
|
+
* GPT 4 写的,临时用,以后要重构!!!
|
|
766
|
+
* TODO:用人类智能重构,要是用着一直没问题,也不是不可以 trust AI
|
|
767
|
+
* @param css
|
|
768
|
+
*/
|
|
769
|
+
function parseCSS(css) {
|
|
770
|
+
const result = {};
|
|
771
|
+
let specialRules = '';
|
|
772
|
+
let matches;
|
|
773
|
+
// 使用非贪婪匹配,尝试正确处理任意层次的嵌套
|
|
774
|
+
const classRegex = /\.([^{\s]+)\s*{((?:[^{}]*|{[^}]*})*)}/g;
|
|
775
|
+
const specialRegex = /(@[^{]+{\s*(?:[^{}]*{[^}]*}[^{}]*)+\s*})/g;
|
|
776
|
+
while ((matches = classRegex.exec(css)) !== null) {
|
|
777
|
+
const key = matches[1];
|
|
778
|
+
const value = matches[2].trim().replace(/\s*;\s*/g, ';\n');
|
|
779
|
+
result[key] = value;
|
|
780
|
+
}
|
|
781
|
+
while ((matches = specialRegex.exec(css)) !== null) {
|
|
782
|
+
specialRules += matches[1].trim() + '\n';
|
|
783
|
+
}
|
|
784
|
+
return [result, specialRules.trim()];
|
|
785
|
+
}
|
|
794
786
|
|
|
795
787
|
class SceneParser {
|
|
796
788
|
assetsPrefetcher;
|
|
@@ -837,5 +829,7 @@ class SceneParser {
|
|
|
837
829
|
|
|
838
830
|
exports.ADD_NEXT_ARG_LIST = ADD_NEXT_ARG_LIST;
|
|
839
831
|
exports.SCRIPT_CONFIG = SCRIPT_CONFIG;
|
|
832
|
+
exports.WEBGAL_LINE_BREAK_MARK = WEBGAL_LINE_BREAK_MARK;
|
|
840
833
|
exports.default = SceneParser;
|
|
834
|
+
exports.isLineBreakPlaceholder = isLineBreakPlaceholder;
|
|
841
835
|
exports.sceneTextPreProcess = sceneTextPreProcess;
|
package/build/cjs/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { WebgalConfig } from './configParser/configParser';
|
|
|
3
3
|
import { fileType } from './interface/assets';
|
|
4
4
|
import { IAsset } from './interface/sceneInterface';
|
|
5
5
|
import { IWebGALStyleObj } from "./styleParser";
|
|
6
|
-
import { sceneTextPreProcess } from "./sceneTextPreProcessor";
|
|
6
|
+
import { isLineBreakPlaceholder, sceneTextPreProcess, WEBGAL_LINE_BREAK_MARK } from "./sceneTextPreProcessor";
|
|
7
7
|
export default class SceneParser {
|
|
8
8
|
private readonly assetsPrefetcher;
|
|
9
9
|
private readonly assetSetter;
|
|
@@ -23,4 +23,4 @@ export default class SceneParser {
|
|
|
23
23
|
parseScssToWebgalStyleObj(scssString: string): IWebGALStyleObj;
|
|
24
24
|
}
|
|
25
25
|
export { ADD_NEXT_ARG_LIST, SCRIPT_CONFIG };
|
|
26
|
-
export { sceneTextPreProcess };
|
|
26
|
+
export { sceneTextPreProcess, isLineBreakPlaceholder, WEBGAL_LINE_BREAK_MARK };
|
|
@@ -38,7 +38,8 @@ export declare enum commandType {
|
|
|
38
38
|
getUserInput = 31,
|
|
39
39
|
applyStyle = 32,
|
|
40
40
|
wait = 33,
|
|
41
|
-
callSteam = 34
|
|
41
|
+
callSteam = 34,
|
|
42
|
+
return = 35
|
|
42
43
|
}
|
|
43
44
|
/**
|
|
44
45
|
* 单个参数接口
|
|
@@ -70,6 +71,15 @@ export interface ISentence {
|
|
|
70
71
|
sentenceAssets: Array<IAsset>;
|
|
71
72
|
subScene: Array<string>;
|
|
72
73
|
inlineComment: string;
|
|
74
|
+
/**
|
|
75
|
+
* 本语句在原始场景文件中占据的行范围(0-based,含首尾)。
|
|
76
|
+
* 单行语句 startLine === endLine;多行语句 endLine 指向最后一条续行。
|
|
77
|
+
* 图形编辑器据此做「只替换被编辑语句所占的行」。
|
|
78
|
+
*/
|
|
79
|
+
startLine: number;
|
|
80
|
+
endLine: number;
|
|
81
|
+
/** 本条是多行语句被折叠掉的续行占位,仅用于补齐行数,不应展示给用户 */
|
|
82
|
+
isLineBreakHolder: boolean;
|
|
73
83
|
}
|
|
74
84
|
/**
|
|
75
85
|
* 场景接口
|
|
@@ -9,3 +9,13 @@
|
|
|
9
9
|
* @returns The processed scene text
|
|
10
10
|
*/
|
|
11
11
|
export declare function sceneTextPreProcess(sceneText: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* 占位行的前缀。占位行本身是一条注释,引擎会空跑掉;
|
|
14
|
+
* 它的作用是让预处理后的行数与原始场景一致,从而保持
|
|
15
|
+
* 「解析后语句 index == 文件行号」这一不变量。
|
|
16
|
+
*/
|
|
17
|
+
export declare const WEBGAL_LINE_BREAK_MARK = ";_WEBGAL_LINE_BREAK_";
|
|
18
|
+
/**
|
|
19
|
+
* 判断预处理后的某一行是否是占位行,即它是上一条多行语句折叠掉的续行。
|
|
20
|
+
*/
|
|
21
|
+
export declare function isLineBreakPlaceholder(processedLine: string): boolean;
|
package/build/es/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { WebgalConfig } from './configParser/configParser';
|
|
|
3
3
|
import { fileType } from './interface/assets';
|
|
4
4
|
import { IAsset } from './interface/sceneInterface';
|
|
5
5
|
import { IWebGALStyleObj } from "./styleParser";
|
|
6
|
-
import { sceneTextPreProcess } from "./sceneTextPreProcessor";
|
|
6
|
+
import { isLineBreakPlaceholder, sceneTextPreProcess, WEBGAL_LINE_BREAK_MARK } from "./sceneTextPreProcessor";
|
|
7
7
|
export default class SceneParser {
|
|
8
8
|
private readonly assetsPrefetcher;
|
|
9
9
|
private readonly assetSetter;
|
|
@@ -23,4 +23,4 @@ export default class SceneParser {
|
|
|
23
23
|
parseScssToWebgalStyleObj(scssString: string): IWebGALStyleObj;
|
|
24
24
|
}
|
|
25
25
|
export { ADD_NEXT_ARG_LIST, SCRIPT_CONFIG };
|
|
26
|
-
export { sceneTextPreProcess };
|
|
26
|
+
export { sceneTextPreProcess, isLineBreakPlaceholder, WEBGAL_LINE_BREAK_MARK };
|