11import SceneParser from "../src/index" ;
22import { ADD_NEXT_ARG_LIST , SCRIPT_CONFIG } from "../src/config/scriptConfig" ;
33import { expect , test } from "vitest" ;
4- import { commandType , ISentence } from "../src/interface/sceneInterface" ;
4+ import { commandType , IAsset , ISentence } from "../src/interface/sceneInterface" ;
55import * as fsp from 'fs/promises' ;
66import { fileType } from "../src/interface/assets" ;
77
@@ -223,6 +223,39 @@ test("say statement applies asset setter to vocal named argument", async () => {
223223 } ) ;
224224} ) ;
225225
226+ test ( "scene assets are deduplicated by type and url" , async ( ) => {
227+ let prefetchedAssets : IAsset [ ] = [ ] ;
228+ const parser = new SceneParser ( ( assetList ) => {
229+ prefetchedAssets = assetList ;
230+ } , ( fileName , assetType ) => {
231+ return fileName ;
232+ } , ADD_NEXT_ARG_LIST , SCRIPT_CONFIG ) ;
233+
234+ const result = parser . parse ( `changeBg:shared.webp;
235+ changeFigure:shared.webp;
236+ changeBg:shared.webp;` , 'test' , 'test' ) ;
237+
238+ expect ( result . assetsList ) . toEqual ( [
239+ { name : "shared.webp" , url : 'shared.webp' , type : fileType . background , lineNumber : 0 } ,
240+ { name : "shared.webp" , url : 'shared.webp' , type : fileType . figure , lineNumber : 1 } ,
241+ ] ) ;
242+ expect ( prefetchedAssets ) . toEqual ( result . assetsList ) ;
243+ } ) ;
244+
245+ test ( "scene assets skip entries with empty urls" , async ( ) => {
246+ const parser = new SceneParser ( ( assetList ) => {
247+ } , ( fileName , assetType ) => {
248+ if ( assetType === fileType . vocal ) {
249+ return '' ;
250+ }
251+ return fileName ;
252+ } , ADD_NEXT_ARG_LIST , SCRIPT_CONFIG ) ;
253+
254+ const result = parser . parse ( `say:123 -vocal=missing.mp3;` , 'test' , 'test' ) ;
255+
256+ expect ( result . assetsList ) . toEqual ( [ ] ) ;
257+ } ) ;
258+
226259test ( "wait command" , async ( ) => {
227260 const parser = new SceneParser ( ( assetList ) => {
228261 } , ( fileName , assetType ) => {
@@ -326,6 +359,25 @@ test("escaped semicolon is preserved in content and inline comment is preserved"
326359 expect ( result . sentenceList ) . toContainEqual ( expectSentenceItem ) ;
327360} ) ;
328361
362+ test ( "inline comment preserves following semicolons" , async ( ) => {
363+ const parser = new SceneParser ( ( assetList ) => {
364+ } , ( fileName , assetType ) => {
365+ return fileName ;
366+ } , ADD_NEXT_ARG_LIST , SCRIPT_CONFIG ) ;
367+
368+ const result = parser . parse ( `say:123; first; second; third` , 'test' , 'test' ) ;
369+ const expectSentenceItem : ISentence = {
370+ command : commandType . say ,
371+ commandRaw : "say" ,
372+ content : "123" ,
373+ args : [ ] ,
374+ sentenceAssets : [ ] ,
375+ subScene : [ ] ,
376+ inlineComment : "first; second; third"
377+ } ;
378+ expect ( result . sentenceList ) . toContainEqual ( expectSentenceItem ) ;
379+ } ) ;
380+
329381test ( "comment-only line keeps comment in content" , async ( ) => {
330382 const parser = new SceneParser ( ( assetList ) => {
331383 } , ( fileName , assetType ) => {
@@ -344,3 +396,22 @@ test("comment-only line keeps comment in content", async () => {
344396 } ;
345397 expect ( result . sentenceList ) . toContainEqual ( expectSentenceItem ) ;
346398} ) ;
399+
400+ test ( "comment-only line preserves following semicolons" , async ( ) => {
401+ const parser = new SceneParser ( ( assetList ) => {
402+ } , ( fileName , assetType ) => {
403+ return fileName ;
404+ } , ADD_NEXT_ARG_LIST , SCRIPT_CONFIG ) ;
405+
406+ const result = parser . parse ( `; first; second; third` , 'test' , 'test' ) ;
407+ const expectSentenceItem : ISentence = {
408+ command : commandType . comment ,
409+ commandRaw : "comment" ,
410+ content : "first; second; third" ,
411+ args : [ { key : 'next' , value : true } ] ,
412+ sentenceAssets : [ ] ,
413+ subScene : [ ] ,
414+ inlineComment : ""
415+ } ;
416+ expect ( result . sentenceList ) . toContainEqual ( expectSentenceItem ) ;
417+ } ) ;
0 commit comments