From 91a284f44a3c4626c5e20941da32c2be935b1703 Mon Sep 17 00:00:00 2001 From: Muhammad Haris Date: Tue, 11 Aug 2020 15:19:53 -0400 Subject: [PATCH] feat(text): Render bold/italics/underline on SimpleTextDisplayer (#2779) Related to #2648, #2357, and #2776 --- lib/text/simple_text_displayer.js | 28 +++++++++++++-- test/text/simple_text_displayer_unit.js | 48 +++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/lib/text/simple_text_displayer.js b/lib/text/simple_text_displayer.js index 2b60527f03..25a5b4cee6 100644 --- a/lib/text/simple_text_displayer.js +++ b/lib/text/simple_text_displayer.js @@ -82,8 +82,30 @@ shaka.text.SimpleTextDisplayer = class { // Flatten nested cue payloads recursively. If a cue has nested cues, // their contents should be combined and replace the payload of the parent. const flattenPayload = (cue) => { - // TODO: If we want to support bold, italic, underline here, we would - // insert markup into the payload. + // Handle styles (currently bold/italics/underline). + // TODO add support for color rendering. + const openStyleTags = []; + const bold = cue.fontWeight >= shaka.text.Cue.fontWeight.BOLD; + const italics = cue.fontStyle == shaka.text.Cue.fontStyle.ITALIC; + const underline = cue.textDecoration.includes( + shaka.text.Cue.textDecoration.UNDERLINE); + if (bold) { + openStyleTags.push('b'); + } + if (italics) { + openStyleTags.push('i'); + } + if (underline) { + openStyleTags.push('u'); + } + + // Prefix opens tags, suffix closes tags in reverse order of opening. + const prefixStyleTags = openStyleTags.reduce((acc, tag) => { + return `${acc}<${tag}>`; + }, ''); + const suffixStyleTags = openStyleTags.reduceRight((acc, tag) => { + return `${acc}`; + }, ''); if (cue.spacer) { // This is a vertical spacer, so insert a newline. @@ -92,7 +114,7 @@ shaka.text.SimpleTextDisplayer = class { return cue.nestedCues.map(flattenPayload).join(''); } else { // This is a real cue. - return cue.payload; + return prefixStyleTags + cue.payload + suffixStyleTags; } }; diff --git a/test/text/simple_text_displayer_unit.js b/test/text/simple_text_displayer_unit.js index 3ed4fd8460..4e66043511 100644 --- a/test/text/simple_text_displayer_unit.js +++ b/test/text/simple_text_displayer_unit.js @@ -95,6 +95,54 @@ describe('SimpleTextDisplayer', () => { [shakaCue]); }); + it('creates style tags for cues with underline/italics/bold', () => { + const shakaCue = new shaka.text.Cue(10, 20, ''); + + // First cue is underlined and italicized. + const nestedCue1 = new shaka.text.Cue(10, 20, 'Test1'); + nestedCue1.fontStyle = shaka.text.Cue.fontStyle.ITALIC; + nestedCue1.textDecoration.push(shaka.text.Cue.textDecoration.UNDERLINE); + + // Second cue is italicized and bolded. + const nestedCue2 = new shaka.text.Cue(10, 20, 'Test2'); + nestedCue2.fontStyle = shaka.text.Cue.fontStyle.ITALIC; + nestedCue2.fontWeight = shaka.text.Cue.fontWeight.BOLD; + + // Third cue has no bold, italics, or underline. + const nestedCue3 = new shaka.text.Cue(10, 20, 'Test3'); + + // Fourth cue is only underlined. + const nestedCue4 = new shaka.text.Cue(10, 20, 'Test4'); + nestedCue4.textDecoration.push(shaka.text.Cue.textDecoration.UNDERLINE); + + const expectedText = + 'Test1Test2Test3Test4'; + shakaCue.nestedCues = [nestedCue1, nestedCue2, nestedCue3, nestedCue4]; + verifyHelper( + [ + {startTime: 10, endTime: 20, text: expectedText}, + ], + [shakaCue]); + }); + + it('adds linebreaks when a linebreak cue is seen', () => { + const shakaCue = new shaka.text.Cue(10, 20, ''); + const nestedCue1 = new shaka.text.Cue(10, 20, 'Test1'); + + // Second cue is a linebreak cue. + const nestedCue2 = new shaka.text.Cue(10, 20, ''); + nestedCue2.spacer = true; + + const nestedCue3 = new shaka.text.Cue(10, 20, 'Test2'); + + shakaCue.nestedCues = [nestedCue1, nestedCue2, nestedCue3]; + verifyHelper( + [ + {startTime: 10, endTime: 20, text: 'Test1\nTest2'}, + ], + [shakaCue]); + }); + it('skips duplicate cues', () => { const cue1 = new shaka.text.Cue(10, 20, 'Test'); displayer.append([cue1]);