diff --git a/lib/text/vtt_text_parser.js b/lib/text/vtt_text_parser.js
index 6d8e2cbf25..c13cd9e56a 100644
--- a/lib/text/vtt_text_parser.js
+++ b/lib/text/vtt_text_parser.js
@@ -221,96 +221,113 @@ shaka.text.VttTextParser = class {
return;
}
- if (!text[1].includes('::cue')) {
- return;
- }
- let styleSelector = 'global';
- // Look for what is within parentisesis. For example:
- // :: cue (b) {
, what we are looking for is b
- const selector = text[1].match(/\((.*)\)/);
- if (selector) {
- styleSelector = selector.pop();
+ /** @type {!Array.>} */
+ const styleBlocks = [];
+ let lastBlockIndex = -1;
+ for (let i = 1; i < text.length; i++) {
+ if (text[i].includes('::cue')) {
+ styleBlocks.push([]);
+ lastBlockIndex = styleBlocks.length - 1;
+ }
+ if (lastBlockIndex == -1) {
+ continue;
+ }
+ styleBlocks[lastBlockIndex].push(text[i]);
+ if (text[i].includes('}')) {
+ lastBlockIndex = -1;
+ }
}
- // We start at 2 to avoid '::cue' and end earlier to avoid '}'
- let propertyLines = text.slice(2, -1);
- if (text[1].includes('}')) {
- const payload = /\{(.*?)\}/.exec(text[1]);
- if (payload) {
- propertyLines = payload[1].split(';');
+ for (const styleBlock of styleBlocks) {
+ let styleSelector = 'global';
+ // Look for what is within parentheses. For example:
+ // :: cue (b) {
, what we are looking for is b
+ const selector = styleBlock[0].match(/\((.*)\)/);
+ if (selector) {
+ styleSelector = selector.pop();
}
- }
- const cue = new shaka.text.Cue(0, 0, '');
- let validStyle = false;
- for (let i = 0; i < propertyLines.length; i++) {
- // We look for CSS properties. As a general rule they are separated by
- // :
. Eg: color: red;
- const lineParts = /^\s*([^:]+):\s*(.*)/.exec(propertyLines[i]);
- if (lineParts) {
- const name = lineParts[1].trim();
- const value = lineParts[2].trim().replace(';', '');
- switch (name) {
- case 'background-color':
- validStyle = true;
- cue.backgroundColor = value;
- break;
- case 'color':
- validStyle = true;
- cue.color = value;
- break;
- case 'font-family':
- validStyle = true;
- cue.fontFamily = value;
- break;
- case 'font-size':
- validStyle = true;
- cue.fontSize = value;
- break;
- case 'font-weight':
- if (parseInt(value, 10) >= 700) {
+ // We start at 1 to avoid '::cue' and end earlier to avoid '}'
+ let propertyLines = styleBlock.slice(1, -1);
+ if (styleBlock[0].includes('}')) {
+ const payload = /\{(.*?)\}/.exec(styleBlock[0]);
+ if (payload) {
+ propertyLines = payload[1].split(';');
+ }
+ }
+
+ const cue = new shaka.text.Cue(0, 0, '');
+ let validStyle = false;
+ for (let i = 0; i < propertyLines.length; i++) {
+ // We look for CSS properties. As a general rule they are separated by
+ // :
. Eg: color: red;
+ const lineParts = /^\s*([^:]+):\s*(.*)/.exec(propertyLines[i]);
+ if (lineParts) {
+ const name = lineParts[1].trim();
+ const value = lineParts[2].trim().replace(';', '');
+ switch (name) {
+ case 'background-color':
+ case 'background':
validStyle = true;
- cue.fontWeight = shaka.text.Cue.fontWeight.BOLD;
- }
- break;
- case 'font-style':
- switch (value) {
- case 'normal':
- validStyle = true;
- cue.fontStyle = shaka.text.Cue.fontStyle.NORMAL;
- break;
- case 'italic':
- validStyle = true;
- cue.fontStyle = shaka.text.Cue.fontStyle.ITALIC;
- break;
- case 'oblique':
+ cue.backgroundColor = value;
+ break;
+ case 'color':
+ validStyle = true;
+ cue.color = value;
+ break;
+ case 'font-family':
+ validStyle = true;
+ cue.fontFamily = value;
+ break;
+ case 'font-size':
+ validStyle = true;
+ cue.fontSize = value;
+ break;
+ case 'font-weight':
+ if (parseInt(value, 10) >= 700 || value == 'bold') {
validStyle = true;
- cue.fontStyle = shaka.text.Cue.fontStyle.OBLIQUE;
- break;
- }
- break;
- case 'opacity':
- validStyle = true;
- cue.opacity = parseFloat(value);
- break;
- case 'text-shadow':
- validStyle = true;
- cue.textShadow = value;
- break;
- case 'white-space':
- validStyle = true;
- cue.wrapLine = value != 'noWrap';
- break;
- default:
- shaka.log.warning('VTT parser encountered an unsupported style: ',
- lineParts);
- break;
+ cue.fontWeight = shaka.text.Cue.fontWeight.BOLD;
+ }
+ break;
+ case 'font-style':
+ switch (value) {
+ case 'normal':
+ validStyle = true;
+ cue.fontStyle = shaka.text.Cue.fontStyle.NORMAL;
+ break;
+ case 'italic':
+ validStyle = true;
+ cue.fontStyle = shaka.text.Cue.fontStyle.ITALIC;
+ break;
+ case 'oblique':
+ validStyle = true;
+ cue.fontStyle = shaka.text.Cue.fontStyle.OBLIQUE;
+ break;
+ }
+ break;
+ case 'opacity':
+ validStyle = true;
+ cue.opacity = parseFloat(value);
+ break;
+ case 'text-shadow':
+ validStyle = true;
+ cue.textShadow = value;
+ break;
+ case 'white-space':
+ validStyle = true;
+ cue.wrapLine = value != 'noWrap';
+ break;
+ default:
+ shaka.log.warning('VTT parser encountered an unsupported style: ',
+ lineParts);
+ break;
+ }
}
}
- }
- if (validStyle) {
- styles.set(styleSelector, cue);
+ if (validStyle) {
+ styles.set(styleSelector, cue);
+ }
}
}
@@ -674,6 +691,11 @@ shaka.text.VttTextParser = class {
if (styleTag.startsWith('.voice-')) {
const voice = styleTag.split('-').pop();
styleTag = `v[voice="${voice}"]`;
+ // The specification allows to have quotes and not, so we check to
+ // see which one is being used.
+ if (!styles.has(styleTag)) {
+ styleTag = `v[voice=${voice}]`;
+ }
}
if (styles.has(styleTag)) {
VttTextParser.mergeStyle_(nestedCue, styles.get(styleTag));
diff --git a/test/text/vtt_text_parser_unit.js b/test/text/vtt_text_parser_unit.js
index 6c02656ab5..836590be17 100644
--- a/test/text/vtt_text_parser_unit.js
+++ b/test/text/vtt_text_parser_unit.js
@@ -1099,7 +1099,7 @@ describe('VttTextParser', () => {
startTime: 40,
endTime: 50,
payload: 'Test',
- color: 'cyan',
+ color: 'red',
},
{
startTime: 40,
@@ -1111,11 +1111,13 @@ describe('VttTextParser', () => {
},
],
'WEBVTT\n\n' +
- 'STYLE\n::cue(v[voice="Shaka"]) { color: cyan; }\n\n' +
+ 'STYLE\n' +
+ '::cue(v[voice="Shaka"]) { color: cyan; }\n' +
+ '::cue(v[voice=ShakaBis]) { color: red; }\n\n' +
'00:00:20.000 --> 00:00:40.000\n' +
'Test\n\n' +
'00:00:40.000 --> 00:00:50.000\n' +
- 'Test2',
+ 'Test2',
{periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
});