@@ -2,6 +2,26 @@ import webvtt from "node-webvtt";
22import { ILoader } from "./_types" ;
33import { createLoader } from "./_utils" ;
44
5+ const UNSUPPORTED_BLOCK_REGEX = / ^ (?: S T Y L E | R E G I O N ) \s * $ / ;
6+
7+ function isUnsupportedBlock ( block : string ) : boolean {
8+ const firstLine = block . trimStart ( ) . split ( "\n" , 1 ) [ 0 ] ;
9+ return UNSUPPORTED_BLOCK_REGEX . test ( firstLine ) ;
10+ }
11+
12+ // node-webvtt doesn't handle STYLE/REGION blocks — strip them before parsing
13+ function stripUnsupportedBlocks ( input : string ) : string {
14+ return input
15+ . replace ( / \r \n / g, "\n" )
16+ . split ( "\n\n" )
17+ . filter ( ( part ) => ! isUnsupportedBlock ( part ) )
18+ . join ( "\n\n" ) ;
19+ }
20+
21+ function getUnsupportedBlocks ( input : string ) : string [ ] {
22+ return input . replace ( / \r \n / g, "\n" ) . split ( "\n\n" ) . filter ( isUnsupportedBlock ) ;
23+ }
24+
525export default function createVttLoader ( ) : ILoader <
626 string ,
727 Record < string , any >
@@ -11,7 +31,7 @@ export default function createVttLoader(): ILoader<
1131 if ( ! input ) {
1232 return "" ; // if VTT file does not exist yet we can not parse it - return empty string
1333 }
14- const vtt = webvtt . parse ( input ) ?. cues ;
34+ const vtt = webvtt . parse ( stripUnsupportedBlocks ( input ) ) ?. cues ;
1535 if ( Object . keys ( vtt ) . length === 0 ) {
1636 return { } ;
1737 } else {
@@ -22,27 +42,40 @@ export default function createVttLoader(): ILoader<
2242 } , { } ) ;
2343 }
2444 } ,
25- async push ( locale , payload ) {
26- const output = Object . entries ( payload ) . map ( ( [ key , text ] ) => {
27- const [ id , timeRange , identifier ] = key . split ( "#" ) ;
28- const [ startTime , endTime ] = timeRange . split ( "-" ) ;
29-
30- return {
31- end : Number ( endTime ) ,
32- identifier : identifier ,
33- start : Number ( startTime ) ,
34- styles : "" ,
35- text : text ,
36- } ;
37- } ) ;
45+ async push ( locale , payload , originalInput ) {
46+ const output = Object . entries ( payload ) . reduce (
47+ ( cues : any [ ] , [ key , text ] ) => {
48+ if ( ! text ) return cues ;
49+
50+ const [ , timeRange , identifier ] = key . split ( "#" ) ;
51+ const [ startTime , endTime ] = timeRange . split ( "-" ) ;
52+
53+ cues . push ( {
54+ end : Number ( endTime ) ,
55+ identifier,
56+ start : Number ( startTime ) ,
57+ styles : "" ,
58+ text,
59+ } ) ;
60+ return cues ;
61+ } ,
62+ [ ] ,
63+ ) ;
3864
3965 const input = {
4066 valid : true ,
4167 strict : true ,
4268 cues : output ,
4369 } ;
4470
45- return webvtt . compile ( input ) ;
71+ const compiled = webvtt . compile ( input ) ;
72+
73+ // Re-insert STYLE/REGION blocks after the WEBVTT header
74+ const blocks = getUnsupportedBlocks ( originalInput ?? "" ) ;
75+ if ( blocks . length === 0 ) return compiled ;
76+
77+ const [ header , ...rest ] = compiled . split ( "\n\n" ) ;
78+ return [ header , ...blocks , ...rest ] . join ( "\n\n" ) ;
4679 } ,
4780 } ) ;
4881}
0 commit comments