diff --git a/pycaption/base.py b/pycaption/base.py index 0b3c27f1..b3559a20 100644 --- a/pycaption/base.py +++ b/pycaption/base.py @@ -425,6 +425,23 @@ def remove_empty_captions(self): out_captions.append(caption) self.set_captions(lang, out_captions) + def remove_styling(self): + """ + Removes structured styling from all captions in all languages. + + Unlike ``strip_html_tags`` (which only removes literal markup found + in TEXT node content), this removes styling that readers store + structurally: ``CaptionNode.STYLE`` nodes and the per-caption + ``style`` attribute. Writers generate style tags (e.g. ```` in + WebVTT) from these at write time, so this is what actually prevents + formats like SCC from producing styled output. + """ + for lang in self.get_languages(): + captions = self.get_captions(lang) + for caption in captions: + caption.style = {} + caption.nodes = [node for node in caption.nodes if node.type_ != CaptionNode.STYLE] + def remove_layout_info(self): """ Removes layout info from all captions and nodes in all languages. diff --git a/tests/test_base.py b/tests/test_base.py index 5d7cba23..c20a7e75 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -1,6 +1,6 @@ import pytest -from pycaption.base import CaptionList, Caption +from pycaption.base import CaptionList, Caption, CaptionNode, CaptionSet class TestCaption: @@ -56,3 +56,39 @@ def test_add_two_caption_lists(self): with pytest.raises(ValueError): newcaps = self.caps + CaptionList([4], layout_info="Other Layout") + + +class TestCaptionSetRemoveStyling: + def setup_method(self): + nodes = [ + CaptionNode.create_style(True, {"italics": True}), + CaptionNode.create_text("hello"), + CaptionNode.create_style(False, {"italics": True}), + CaptionNode.create_break(), + CaptionNode.create_text("world"), + ] + self.caption = Caption(0, 1000, nodes, style={"italics": True}) + self.caption_set = CaptionSet({"en": CaptionList([self.caption])}) + + def test_removes_style_nodes(self): + self.caption_set.remove_styling() + + node_types = [node.type_ for node in self.caption.nodes] + assert CaptionNode.STYLE not in node_types + + def test_clears_caption_style_attribute(self): + self.caption_set.remove_styling() + + assert self.caption.style == {} + + def test_preserves_text_and_break_nodes(self): + self.caption_set.remove_styling() + + remaining = [ + (node.type_, node.content) for node in self.caption.nodes + ] + assert remaining == [ + (CaptionNode.TEXT, "hello"), + (CaptionNode.BREAK, None), + (CaptionNode.TEXT, "world"), + ]