From 0f47396b0912ad2dec47e9d3976ce847d1c479b9 Mon Sep 17 00:00:00 2001 From: Kevin DARNE Date: Tue, 14 Nov 2023 14:53:36 +1100 Subject: [PATCH 1/4] Issue #854 Fix image (uml) captions with emphasis Signed-off-by: Kevin DARNE --- sphinxcontrib/confluencebuilder/storage/translator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinxcontrib/confluencebuilder/storage/translator.py b/sphinxcontrib/confluencebuilder/storage/translator.py index d8f749fe..af9b25be 100644 --- a/sphinxcontrib/confluencebuilder/storage/translator.py +++ b/sphinxcontrib/confluencebuilder/storage/translator.py @@ -1865,7 +1865,7 @@ def _visit_image(self, node, opts): self.body.append(self._start_tag(node, 'ac:caption')) next_sibling._skip_caption = True for child in next_sibling.children: - child.walk(self) + child.walkabout(self) self.body.append(self._end_tag(node)) self.body.append(self._end_ac_image(node)) From 8608b269e9ea6c4f0f3b9623cd2620e6590346bf Mon Sep 17 00:00:00 2001 From: James Knight Date: Sat, 18 Nov 2023 09:52:25 -0500 Subject: [PATCH 2/4] tests: introduce `setup_editor` decorator Provides a decorator to allow a unit test to be easily configured to use a v2 editor. Signed-off-by: James Knight --- tests/lib/testcase.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/lib/testcase.py b/tests/lib/testcase.py index 43dee649..c3f8923c 100644 --- a/tests/lib/testcase.py +++ b/tests/lib/testcase.py @@ -34,6 +34,7 @@ def test_storage_example(self): super().__init__(*args, **kwargs) self.builder = DEFAULT_BUILDER + self.target_editor = None @classmethod def setUpClass(cls): @@ -61,6 +62,8 @@ def build(self, *args, **kwargs): new_kwargs = dict(kwargs) new_kwargs.setdefault('builder', self.builder) new_kwargs.setdefault('config', self.config) + if self.target_editor: + new_kwargs['config']['confluence_editor'] = self.target_editor return build_sphinx(*args, **new_kwargs) @@ -76,6 +79,8 @@ def prepare(self, *args, **kwargs): new_kwargs = dict(kwargs) new_kwargs.setdefault('builder', self.builder) new_kwargs.setdefault('config', self.config) + if self.target_editor: + new_kwargs['config']['confluence_editor'] = self.target_editor return prepare_sphinx(*args, **new_kwargs) @@ -100,3 +105,25 @@ def _wrapper(self, *args, **kwargs): return func(self, *args, **kwargs) return _wrapper return _decorator + + +def setup_editor(editor): + """ + prepare a confluence unit test for a specific editor configuration + + A utility "decorator" to help setup editor options for a unit test. This + avoids the need to explicitly configure an editor directly in the + configuration for a unit test testing against a dataset. + + Args: + editor: the editor to use + """ + + def _decorator(func): + @wraps(func) + def _wrapper(self, *args, **kwargs): + self.target_editor = editor + + return func(self, *args, **kwargs) + return _wrapper + return _decorator From 58bc3cb1c2f98360dc1a2d5dc80e691bf80b770c Mon Sep 17 00:00:00 2001 From: James Knight Date: Sat, 18 Nov 2023 09:52:45 -0500 Subject: [PATCH 3/4] tests: add markup checks for figure captions Adding some unit tests to verify the processing non-simple text for captions (i.e. additional markup for text). Previous implementations had caption data malformed, and these checks should help prevent this from happening again. Signed-off-by: James Knight --- .../datasets/rst/figure-caption/index.rst | 12 ++++ tests/unit-tests/test_rst_figure.py | 58 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 tests/unit-tests/datasets/rst/figure-caption/index.rst diff --git a/tests/unit-tests/datasets/rst/figure-caption/index.rst b/tests/unit-tests/datasets/rst/figure-caption/index.rst new file mode 100644 index 00000000..0722bdd5 --- /dev/null +++ b/tests/unit-tests/datasets/rst/figure-caption/index.rst @@ -0,0 +1,12 @@ +.. https://docutils.sourceforge.io/docs/ref/rst/directives.html#figure + +figure +------ + +.. figure with caption + +.. figure:: ../../../assets/image03.png + + **caption** with *markup* + + legend diff --git a/tests/unit-tests/test_rst_figure.py b/tests/unit-tests/test_rst_figure.py index 0eeb10b6..a1924ce3 100644 --- a/tests/unit-tests/test_rst_figure.py +++ b/tests/unit-tests/test_rst_figure.py @@ -5,6 +5,7 @@ from tests.lib.parse import parse from tests.lib.testcase import ConfluenceTestCase from tests.lib.testcase import setup_builder +from tests.lib.testcase import setup_editor import os @@ -166,3 +167,60 @@ def test_storage_rst_figure_defaults(self): self.assertIsNotNone(next_tag) self.assertTrue(next_tag.has_attr('style')) self.assertTrue('clear: both' in next_tag['style']) + + @setup_builder('confluence') + def test_storage_rst_figure_caption_default(self): + dataset = os.path.join(self.datasets, 'rst', 'figure-caption') + out_dir = self.build(dataset) + + with parse('index', out_dir) as data: + figures = data.find_all('p', recursive=False) + self.assertEqual(len(figures), 1) + + # ########################################################## + # single figure with caption + # ########################################################## + figure = figures.pop(0) + + image = figure.find('ac:image', recursive=False) + self.assertIsNotNone(image) + + caption = figure.find('p', recursive=False) + self.assertIsNotNone(caption) + + markup1 = caption.find('strong', recursive=False) + self.assertIsNotNone(markup1) + self.assertIsNotNone(markup1.text, 'caption') + + markup2 = caption.find('em', recursive=False) + self.assertIsNotNone(markup2) + self.assertIsNotNone(markup2.text, 'markup') + + @setup_builder('confluence') + @setup_editor('v2') + def test_storage_rst_figure_caption_v2(self): + dataset = os.path.join(self.datasets, 'rst', 'figure-caption') + out_dir = self.build(dataset) + + with parse('index', out_dir) as data: + figures = data.find_all('p', recursive=False) + self.assertEqual(len(figures), 1) + + # ########################################################## + # single figure with caption + # ########################################################## + figure = figures.pop(0) + + image = figure.find('ac:image', recursive=False) + self.assertIsNotNone(image) + + caption = image.find('ac:caption', recursive=False) + self.assertIsNotNone(caption) + + markup1 = caption.find('strong', recursive=False) + self.assertIsNotNone(markup1) + self.assertIsNotNone(markup1.text, 'caption') + + markup2 = caption.find('em', recursive=False) + self.assertIsNotNone(markup2) + self.assertIsNotNone(markup2.text, 'markup') From 5d1604c7455669c64b743e952187f1604db3794f Mon Sep 17 00:00:00 2001 From: James Knight Date: Sat, 18 Nov 2023 10:13:55 -0500 Subject: [PATCH 4/4] tests: always clone configuration to support decorator config overrides When decorators are used to alter the test case's configuration, this is applied to a base configuration prepared for the entire test class. This could then result in some unit tests changing other unit test's configuration, depending on how the unit test order is run. To prevent unexpected configuration changes, always clone the base configuration when running a prepare/build invoke. Signed-off-by: James Knight --- tests/lib/testcase.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/lib/testcase.py b/tests/lib/testcase.py index c3f8923c..8845a01a 100644 --- a/tests/lib/testcase.py +++ b/tests/lib/testcase.py @@ -61,7 +61,7 @@ def build(self, *args, **kwargs): new_kwargs = dict(kwargs) new_kwargs.setdefault('builder', self.builder) - new_kwargs.setdefault('config', self.config) + new_kwargs.setdefault('config', self.config.clone()) if self.target_editor: new_kwargs['config']['confluence_editor'] = self.target_editor @@ -78,7 +78,7 @@ def prepare(self, *args, **kwargs): new_kwargs = dict(kwargs) new_kwargs.setdefault('builder', self.builder) - new_kwargs.setdefault('config', self.config) + new_kwargs.setdefault('config', self.config.clone()) if self.target_editor: new_kwargs['config']['confluence_editor'] = self.target_editor