diff --git a/electron/src/shared/utils/importStory.js b/electron/src/shared/utils/importStory.js index 2186d892a..e15a3f695 100644 --- a/electron/src/shared/utils/importStory.js +++ b/electron/src/shared/utils/importStory.js @@ -83,7 +83,11 @@ function captionBlocks(text, webvtt) { if (!lines.length) return false; const first = lines[0]; if (/^WEBVTT(?:[ \t]|$)/.test(first)) return false; - return !isWebVttMetadata(first); + if (!isWebVttMetadata(first)) return true; + // WebVTT's block parser gives a timing line in position two precedence + // over the identifier, so `STYLE`/`REGION`/`NOTE` can name a real cue. + // https://www.w3.org/TR/webvtt1/#file-parsing — mirrors parse_srt. + return lines.length > 1 && isTimingLine(lines[1]); }); } diff --git a/electron/src/shared/utils/importStory.test.js b/electron/src/shared/utils/importStory.test.js index b5d8c89e7..18a08bebe 100644 --- a/electron/src/shared/utils/importStory.test.js +++ b/electron/src/shared/utils/importStory.test.js @@ -109,11 +109,20 @@ describe('parseSrt', () => { '00:00:01.000 --> 00:00:02.000\nSpoken text\n'; expect(parseSrt(vtt)).toBe('Spoken text'); }); - it('never treats a NOTE block as a cue even when it contains a valid timing line', () => { - const vtt = - 'WEBVTT\n\nNOTE\n00:00:01.000 --> 00:00:02.000\nprivate note\n\n' + - '00:00:03.000 --> 00:00:04.000\nSpoken text\n'; - expect(parseSrt(vtt)).toBe('Spoken text'); + it('lets a timing line in position two outrank a metadata identifier', () => { + for (const identifier of ['STYLE', 'REGION', 'NOTE', 'NOTE identifier']) { + expect(parseSrt(`WEBVTT\n\n${identifier}\n00:01.000 --> 00:02.000\nSpoken text\n`)).toBe( + 'Spoken text', + ); + } + }); + it('keeps a cue whose identifier is STYLE or REGION in a mixed file', () => { + for (const identifier of ['intro', 'STYLE', 'REGION']) { + const vtt = + `WEBVTT\n\n${identifier}\n00:00:01.000 --> 00:00:02.000\nHello world.\n\n` + + 'next\n00:00:03.000 --> 00:00:04.000\nStill here.\n'; + expect(parseSrt(vtt)).toBe('Hello world.\nStill here.'); + } }); it('keeps NOTE when it is the spoken dialogue', () => { expect(