1+ /**
2+ * Preprocessor for scene text.
3+ *
4+ * Use two-pass to generate a new scene text that concats multiline sequences
5+ * into a single line and add placeholder lines to preserve the original number
6+ * of lines.
7+ *
8+ * @param sceneText The original scene text
9+ * @returns The processed scene text
10+ */
11+ export function sceneTextPreProcess ( sceneText : string ) : string {
12+ let lines = sceneText . replaceAll ( '\r' , '' ) . split ( '\n' ) ;
13+
14+ lines = sceneTextPreProcessPassOne ( lines ) ;
15+ lines = sceneTextPreProcessPassTwo ( lines ) ;
16+
17+ return lines . join ( '\n' ) ;
18+ }
19+
20+ /**
21+ * Pass one.
22+ *
23+ * Add escape character to all lines that should be multiline.
24+ *
25+ * @param lines The original lines
26+ * @returns The processed lines
27+ */
28+ function sceneTextPreProcessPassOne ( lines : string [ ] ) : string [ ] {
29+ const processedLines : string [ ] = [ ] ;
30+ let lastLineIsMultiline = false ;
31+ let thisLineIsMultiline = false ;
32+
33+ for ( const line of lines ) {
34+ thisLineIsMultiline = false ;
35+
36+ if ( canBeMultiline ( line ) ) {
37+ thisLineIsMultiline = true ;
38+ }
39+
40+ if ( shouldNotBeMultiline ( line , lastLineIsMultiline ) ) {
41+ thisLineIsMultiline = false ;
42+ }
43+
44+ if ( thisLineIsMultiline ) {
45+ processedLines [ processedLines . length - 1 ] += '\\' ;
46+ }
47+
48+ processedLines . push ( line ) ;
49+
50+ lastLineIsMultiline = thisLineIsMultiline ;
51+ }
52+
53+ return processedLines ;
54+ }
55+
56+ function canBeMultiline ( line : string ) : boolean {
57+ if ( ! line . startsWith ( ' ' ) ) {
58+ return false ;
59+ }
60+
61+ const trimmedLine = line . trimStart ( ) ;
62+ return trimmedLine . startsWith ( '|' ) || trimmedLine . startsWith ( '-' ) ;
63+ }
64+
65+ /**
66+ * Logic to check if a line should not be multiline.
67+ *
68+ * @param line The line to check
69+ * @returns If the line should not be multiline
70+ */
71+ function shouldNotBeMultiline ( line : string , lastLineIsMultiline : boolean ) : boolean {
72+ if ( ! lastLineIsMultiline && isEmptyLine ( line ) ) {
73+ return true ;
74+ }
75+
76+ // Custom logic: if the line contains -concat, it should not be multiline
77+ if ( line . indexOf ( '-concat' ) !== - 1 ) {
78+ return true ;
79+ }
80+
81+ return false ;
82+ }
83+
84+ function isEmptyLine ( line : string ) : boolean {
85+ return line . trim ( ) === '' ;
86+ }
87+
88+
89+ /**
90+ * Pass two.
91+ *
92+ * Traverse the lines to
93+ * - remove escape characters
94+ * - add placeholder lines to preserve the original number of lines.
95+ *
96+ * @param lines The lines in pass one
97+ * @returns The processed lines
98+ */
99+ function sceneTextPreProcessPassTwo ( lines : string [ ] ) : string [ ] {
100+ const processedLines : string [ ] = [ ] ;
101+ let currentMultilineContent = "" ;
102+ let placeHolderLines : string [ ] = [ ] ;
103+
104+ function concat ( line : string ) {
105+ let trimmed = line . trim ( ) ;
106+ if ( trimmed . startsWith ( '-' ) ) {
107+ trimmed = " " + trimmed ;
108+ }
109+ currentMultilineContent = currentMultilineContent + trimmed ;
110+ placeHolderLines . push ( placeholderLine ( line ) ) ;
111+ }
112+
113+ for ( const line of lines ) {
114+ console . log ( line ) ;
115+ if ( line . endsWith ( '\\' ) ) {
116+ const trueLine = line . slice ( 0 , - 1 ) ;
117+
118+ if ( currentMultilineContent === "" ) {
119+ // first line
120+ currentMultilineContent = trueLine ;
121+ } else {
122+ // middle line
123+ concat ( trueLine ) ;
124+ }
125+ continue ;
126+ }
127+
128+ if ( currentMultilineContent !== "" ) {
129+ // end line
130+ concat ( line ) ;
131+ processedLines . push ( currentMultilineContent ) ;
132+ processedLines . push ( ...placeHolderLines ) ;
133+
134+ placeHolderLines = [ ] ;
135+ currentMultilineContent = "" ;
136+ continue ;
137+ }
138+
139+ processedLines . push ( line ) ;
140+ }
141+
142+ return processedLines ;
143+ }
144+
145+ /**
146+ * Placeholder Line. Adding this line preserves the original number of lines
147+ * in the scene text, so that it can be compatible with the graphical editor.
148+ *
149+ * @param content The original content on this line
150+ * @returns The placeholder line
151+ */
152+ function placeholderLine ( content = "" ) {
153+ return ";_WEBGAL_LINE_BREAK_" + content ;
154+ }
155+
156+ // export function sceneTextPreProcess(sceneText: string): string {
157+ // const lines = sceneText.replaceAll('\r', '').split('\n');
158+ // const processedLines: string[] = [];
159+ // let lastNonMultilineIndex = -1;
160+ // let isInMultilineSequence = false;
161+
162+ // function isMultiline(line: string): boolean {
163+ // if (!line.startsWith(' ')) return false;
164+ // const trimmedLine = line.trimStart();
165+ // return trimmedLine.startsWith('|') || trimmedLine.startsWith('-');
166+ // }
167+
168+ // for (let i = 0; i < lines.length; i++) {
169+ // const line = lines[i];
170+
171+ // if (line.trim() === '') {
172+ // // Empty line handling
173+ // if (isInMultilineSequence) {
174+ // // Check if the next line is a multiline line
175+
176+ // let isStillInMulti = false;
177+ // for (let j = i + 1; j < lines.length; j++) {
178+ // const lookForwardLine = lines[j] || '';
179+ // // 遇到正常语句了,直接中断
180+ // if (lookForwardLine.trim() !== '' && !isMultiline(lookForwardLine)) {
181+ // isStillInMulti = false;
182+ // break;
183+ // }
184+ // // 必须找到后面接的是参数,并且中间没有遇到任何正常语句才行
185+ // if (lookForwardLine.trim() !== '' && isMultiline(lookForwardLine)) {
186+ // isStillInMulti = true;
187+ // break;
188+ // }
189+ // }
190+ // if (isStillInMulti) {
191+ // // Still within a multiline sequence
192+ // processedLines.push(';_WEBGAL_LINE_BREAK_');
193+ // } else {
194+ // // End of multiline sequence
195+ // isInMultilineSequence = false;
196+ // processedLines.push(line);
197+ // }
198+ // } else {
199+ // // Preserve empty lines outside of multiline sequences
200+ // processedLines.push(line);
201+ // }
202+ // } else if (isMultiline(line)) {
203+ // // Multiline statement handling
204+ // if (lastNonMultilineIndex >= 0) {
205+ // // Concatenate to the previous non-multiline statement
206+ // const trimedLine = line.trimStart();
207+ // const addBlank = trimedLine.startsWith('-') ? ' ' : '';
208+ // processedLines[lastNonMultilineIndex] += addBlank + trimedLine;
209+ // }
210+
211+ // // Add the special comment line
212+ // processedLines.push(';_WEBGAL_LINE_BREAK_' + line);
213+ // isInMultilineSequence = true;
214+ // } else {
215+ // // Non-multiline statement handling
216+ // processedLines.push(line);
217+ // lastNonMultilineIndex = processedLines.length - 1;
218+ // isInMultilineSequence = false;
219+ // }
220+ // }
221+
222+ // return processedLines.join('\n');
223+ // }
0 commit comments