#!/usr/bin/env python3 """ Generate test EPUB for subscript and superscript rendering verification. """ import zipfile from pathlib import Path OUTPUT_DIR = Path(__file__).parent.parent / "test" / "epubs" OUTPUT_DIR.mkdir(parents=True, exist_ok=True) def create_epub(filename, title, chapters): """Create an EPUB file with given chapters.""" with zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED) as epub: # mimetype (uncompressed, first file) epub.writestr('mimetype', 'application/epub+zip', compress_type=zipfile.ZIP_STORED) # META-INF/container.xml epub.writestr('META-INF/container.xml', ''' ''') # Build spine and manifest manifest_items = [] spine_items = [] for i, (chapter_title, content) in enumerate(chapters): chapter_id = f'chapter{i}' manifest_items.append(f'') spine_items.append(f'') epub.writestr(f'OEBPS/{chapter_id}.xhtml', content) # Write stylesheet epub.writestr('OEBPS/style.css', '''.super { vertical-align: super; } .sub { vertical-align: sub; } ''') manifest_items.append('') # content.opf epub.writestr('OEBPS/content.opf', f''' {title} CrossPoint Test Generator en test-supsub-001 {''.join(manifest_items)} {''.join(spine_items)} ''') # toc.ncx nav_points = [] for i, (chapter_title, _) in enumerate(chapters): nav_points.append(f''' {chapter_title} ''') epub.writestr('OEBPS/toc.ncx', f''' {title} {''.join(nav_points)} ''') def make_chapter(title, content): """Create XHTML chapter content.""" return f''' {title}

{title}

{content} ''' if __name__ == '__main__': print("Creating subscript/superscript test EPUB...") chapters = [ ("Introduction", make_chapter("Subscript and Superscript Tests", """

This EPUB tests subscript and superscript rendering.

Features tested:

  • Basic superscript (exponents, footnotes)
  • Basic subscript (chemical formulas, sequences)
  • Mixed sup and sub in same paragraph
  • Ordinal numbers
  • Nested with bold and italic
  • Long runs of sup/sub text
""")), ("Basic Superscript", make_chapter("Basic Superscript", """

Mathematical Formulas

E = mc2 is Einstein's mass-energy equivalence.

The area of a circle is πr2.

210 = 1024.

xn + yn = zn

Footnote References

This is a sentence with a footnote1 reference.

Multiple footnotes2 can appear3 in one paragraph.

""")), ("Basic Subscript", make_chapter("Basic Subscript", """

Chemical Formulas

Water is H2O.

Carbon dioxide is CO2.

Glucose: C6H12O6.

Sulfuric acid: H2SO4.

Mathematical Sequences

The sequence a1, a2, a3, ..., an.

Matrix element Aij where i is row and j is column.

""")), ("Mixed Sup and Sub", make_chapter("Mixed Superscript and Subscript", """

Chemistry and Physics

The pH of water is 7, meaning [H3O+] = 10-7 mol/L.

Speed of light: c = 2.998 × 108 m/s.

Avogadro's number: 6.022 × 1023 mol-1.

Complex Formulas

Isotope notation: 235U92 (uranium-235).

Electron configuration: 1s2 2s2 2p6.

""")), ("Ordinals and Dates", make_chapter("Ordinal Numbers", """

Ordinal Suffixes

On the 1st of January, the 2nd quarter begins on the 3rd month.

The 4th through 20th days of the month.

The 21st, 22nd, 23rd, and 24th hours.

Historical Dates

The 19th century saw rapid industrialization.

World War II ended on May 8th, 1945.

""")), ("Nested Styles", make_chapter("Nested with Bold and Italic", """

Bold Superscript

Bold superscript: x2 + y2 = r2.

Bold base with superscript: E = mc2.

Italic Subscript

Italic subscript: Hn represents the n-th harmonic.

Italic base with subscript: a1, a2, a3.

Combined Styles

Bold text with H2O and E = mc2 inside.

Italic text with CO2 and xn inside.

""")), ("Long Runs", make_chapter("Long Superscript and Subscript Runs", """

Extended Superscript

This wordhas a rather long superscript attached to it continuing normally.

Polynomial: x10 + x9 + x8 + x7 + x6 + x5 + x4 + x3 + x2 + x + 1.

Extended Subscript

This wordhas a rather long subscript attached to it continuing normally.

Sequence: a1, a2, a3, a4, a5, a6, a7, a8, a9, a10.

Alternating

Mixed: x2y1 + x3y2 + x4y3 = 0.

""")), ("Edge Cases", make_chapter("Edge Cases and Stress Tests", """

Empty and Whitespace

Empty superscript: xy should show xy.

Whitespace: x y should show x y.

Nested Sup/Sub (Not Standard)

Nested attempt: xyz (may not render correctly).

Unicode in Sup/Sub

Greek letters: α2 + β2 = γ2.

Symbols: H2O → H+ + OH.

Line Breaking

Long text with superscript at the end of a line to test wrapping behavior when the superscript might need to wrap to the next line1 and continue here.

""")), ("CSS Style Tests", make_chapter("CSS Style Tests", """

CSS Classes

This tests superscript via CSS class (.super): E = mc2.

This tests subscript via CSS class (.sub): Water is H2O.

CSS Inline Styles

This tests superscript via inline style: E = mc2.

This tests subscript via inline style: Water is H2O.

Comparison Side-by-Side

Tag `sup`: E = mc2

Class `super`: E = mc2

Inline `super`: E = mc2


Tag `sub`: H2O

Class `sub`: H2O

Inline `sub`: H2O

Mixed and Nested in CSS

CSS Class mixed: [H3O+] = 10-7 mol/L.

CSS Inline mixed: [H3O+] = 10-7 mol/L.

Bold text with class H2O and E = mc2 inside.

Italic text with inline H2O and E = mc2 inside.

""")), ] output_file = OUTPUT_DIR / 'test_supsub.epub' create_epub(output_file, 'Subscript and Superscript Tests', chapters) print(f"Created: {output_file}")