Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions packtools/sps/formats/pdf/pipeline/docx.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ def docx_second_footer_pipe(docx, footer_data, paragraph_style_name='SCL Footer'

docx_renderer.text.add_field_run(para, "PAGE \\* MERGEFORMAT")

para.add_run(f" | VOL. {footer_data['volume']} ({footer_data['issue']}) {footer_data['year']}: {footer_data['location_label']}")
para.add_run(f" | {_format_vol_issue_year(footer_data)}")

def docx_page_vol_issue_year_pipe(docx, footer_data, paragraph_style_name='SCL Footer'):
"""
Expand All @@ -416,7 +416,7 @@ def docx_page_vol_issue_year_pipe(docx, footer_data, paragraph_style_name='SCL F

para.style = docx.styles[paragraph_style_name]
docx_renderer.text.add_field_run(para, "PAGE \\* MERGEFORMAT")
para.add_run(f" | VOL. {footer_data['volume']} ({footer_data['issue']}) {footer_data['year']}: {footer_data['location_label']}")
para.add_run(f" | {_format_vol_issue_year(footer_data)}")

def docx_body_pipe(docx, body_data):
"""
Expand Down Expand Up @@ -501,7 +501,7 @@ def docx_supplementary_material_pipe(docx, footer_data, supplementary_data, sect

# No PAGE field is added here: supplementary material has its own
# pagination, independent of the article body, so no leading " | " either.
para.add_run(f"VOL. {footer_data['volume']} ({footer_data['issue']}) {footer_data['year']}: {footer_data['location_label']}")
para.add_run(_format_vol_issue_year(footer_data))

docx_renderer.section.setup_section_columns(section, 1, pdf_enum.TWO_COLUMNS_SPACING)

Expand All @@ -518,6 +518,20 @@ def docx_supplementary_material_pipe(docx, footer_data, supplementary_data, sect
# Private helpers
# -----------------

def _format_vol_issue_year(footer_data):
"""
Format 'VOL. {volume} ({issue}) {year}: {location}', dropping the VOL.
segment or the issue parentheses when that value is missing from the
XML front matter (e.g. ahead-of-print articles carry no issue).
"""
parts = []
if footer_data['volume']:
parts.append(f"VOL. {footer_data['volume']}")
if footer_data['issue']:
parts.append(f"({footer_data['issue']})")
parts.append(f"{footer_data['year']}: {footer_data['location_label']}")
return ' '.join(parts)

def _format_journal_title_two_lines(journal_title_text):
"""
Break a journal title into at most two lines for the masthead: the first
Expand Down
49 changes: 49 additions & 0 deletions tests/sps/formats/pdf/pipeline/test_docx.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,17 @@ def test_uses_elocation_id_when_fpage_is_absent(self):
self.assertIn('VOL. 33 (3) 2024: e282794', para.text)
self.assertNotIn(': -', para.text)

def test_omits_issue_parentheses_when_issue_is_absent(self):
docx = _docx_with_layout_styles()
footer_data = {'volume': '86', 'issue': '', 'year': '2026',
'fpage': '', 'lpage': '', 'location_label': 'e301043'}
docx_pipe.docx_second_footer_pipe(docx, footer_data)

footer = docx_renderer.section.get_second_footer(docx)
para = footer.paragraphs[0]
self.assertIn('VOL. 86 2026: e301043', para.text)
self.assertNotIn('()', para.text)


class TestDocxPageVolIssueYearPipe(unittest.TestCase):

Expand All @@ -252,6 +263,17 @@ def test_uses_elocation_id_when_fpage_is_absent(self):
self.assertIn('VOL. 33 (3) 2024: e282794', para.text)
self.assertNotIn(': -', para.text)

def test_omits_issue_parentheses_when_issue_is_absent(self):
docx = _docx_with_layout_styles()
footer_data = {'volume': '86', 'issue': '', 'year': '2026',
'fpage': '', 'lpage': '', 'location_label': 'e301043'}
docx_pipe.docx_page_vol_issue_year_pipe(docx, footer_data)

footer = docx_renderer.section.get_first_page_footer(docx)
para = footer.paragraphs[-1]
self.assertIn('VOL. 86 2026: e301043', para.text)
self.assertNotIn('()', para.text)


class TestDocxBodyPipe(unittest.TestCase):
# TODO
Expand Down Expand Up @@ -294,6 +316,33 @@ def test_uses_elocation_id_when_fpage_is_absent(self):
para = footer.paragraphs[-1]
self.assertEqual(para.text, 'VOL. 33 (3) 2024: e282794')

def test_omits_issue_parentheses_when_issue_is_absent(self):
docx = _docx_with_layout_styles()
footer_data = {'volume': '86', 'issue': '', 'year': '2026',
'fpage': '', 'lpage': '', 'location_label': 'e301043'}
docx_pipe.docx_supplementary_material_pipe(
docx, footer_data, {'title': 'Supplementary Material', 'elements': []}
)

footer = docx.sections[-1].footer
para = footer.paragraphs[-1]
self.assertEqual(para.text, 'VOL. 86 2026: e301043')


class TestFormatVolIssueYear(unittest.TestCase):

def test_keeps_both_when_present(self):
footer_data = {'volume': '10', 'issue': '2', 'year': '2023', 'location_label': '123-130'}
self.assertEqual(docx_pipe._format_vol_issue_year(footer_data), 'VOL. 10 (2) 2023: 123-130')

def test_omits_issue_parentheses_when_issue_is_absent(self):
footer_data = {'volume': '86', 'issue': '', 'year': '2026', 'location_label': 'e301043'}
self.assertEqual(docx_pipe._format_vol_issue_year(footer_data), 'VOL. 86 2026: e301043')

def test_omits_vol_label_when_volume_is_absent(self):
footer_data = {'volume': '', 'issue': '67', 'year': '2023', 'location_label': 'e236720'}
self.assertEqual(docx_pipe._format_vol_issue_year(footer_data), '(67) 2023: e236720')


class TestBodyColumnConfiguration(unittest.TestCase):
"""
Expand Down