Repository: Kozea/WeasyPrint
Pull request #1915 (2023-07-16 12:08:35)

Bug Fix: Footnote is appearing on page before its call #1871
Fix:  #1871


Patch:
diff --git a/weasyprint/layout/table.py b/weasyprint/layout/table.py
index 3a740c22..ca9d8d9c 100644
--- a/weasyprint/layout/table.py
+++ b/weasyprint/layout/table.py
@@ -298,6 +298,9 @@ def table_layout(context, table, bottom_space, skip_stack, containing_block,
             # other content on the page.
             if not page_is_empty and context.overflows_page(
                     bottom_space, next_position_y):
+                for descendant in row.descendants():
+                    if descendant.footnote is not None:
+                        context.unlayout_footnote(descendant.footnote)
                 if new_group_children:
                     previous_row = new_group_children[-1]
                     page_break = block_level_page_break(previous_row, row)
@@ -333,6 +336,9 @@ def table_layout(context, table, bottom_space, skip_stack, containing_block,
         if resume_at and not original_page_is_empty and (
                 avoid_page_break(group.style['break_inside'], context) or
                 not new_group_children):
+            for descendant in group.descendants():
+                if descendant.footnote is not None:
+                    context.unlayout_footnote(descendant.footnote)
             return None, None, next_page
 
         group = group.copy_with_children(new_group_children)


Test patch:
diff --git a/tests/layout/test_footnotes.py b/tests/layout/test_footnotes.py
index 6baeabfe..8352eb13 100644
--- a/tests/layout/test_footnotes.py
+++ b/tests/layout/test_footnotes.py
@@ -706,14 +706,12 @@ def test_footnote_max_height():
               }
           }
           div {
-              color: red;
               font-family: weasyprint;
               font-size: 2px;
               line-height: 1;
           }
           div.footnote {
               float: footnote;
-              color: blue;
           }
       </style>
       <div>ab<div class="footnote">c</div><div class="footnote">d</div>
@@ -748,3 +746,100 @@ def test_footnote_max_height():
     footnote_marker3, footnote_content3 = footnote_line3.children
     assert footnote_marker3.children[0].text == '3.'
     assert footnote_content3.text == 'e'
+
+
+def test_footnote_table_aborted_row():
+    page1, page2 = render_pages('''
+      <style>
+        @font-face {src: url(weasyprint.otf); font-family: weasyprint}
+        @page {size: 10px 35px}
+        body {font-family: weasyprint; font-size: 2px}
+        tr {height: 10px}
+        .footnote {float: footnote}
+      </style>
+      <table><tbody>
+        <tr><td>abc</td></tr>
+        <tr><td>abc</td></tr>
+        <tr><td>abc</td></tr>
+        <tr><td>def<div class="footnote">f</div></td></tr>
+      </tbody></table>
+    ''')
+
+    html, = page1.children
+    body, = html.children
+    table_wrapper, = body.children
+    table, = table_wrapper.children
+    tbody, = table.children
+    for tr in tbody.children:
+        td, = tr.children
+        line, = td.children
+        textbox, = line.children
+        assert textbox.text == 'abc'
+
+    html, footnote_area = page2.children
+    body, = html.children
+    table_wrapper, = body.children
+    table, = table_wrapper.children
+    tbody, = table.children
+    tr, = tbody.children
+    td, = tr.children
+    line, = td.children
+    textbox, call = line.children
+    assert textbox.text == 'def'
+    footnote, = footnote_area.children
+    line, = footnote.children
+    marker, textbox = line.children
+    assert textbox.text == 'f'
+
+
+def test_footnote_table_aborted_group():
+    page1, page2 = render_pages('''
+      <style>
+        @font-face {src: url(weasyprint.otf); font-family: weasyprint}
+        @page {size: 10px 35px}
+        body {font-family: weasyprint; font-size: 2px}
+        tr {height: 10px}
+        tbody {break-inside: avoid}
+        .footnote {float: footnote}
+      </style>
+      <table>
+        <tbody>
+          <tr><td>abc</td></tr>
+          <tr><td>abc</td></tr>
+        </tbody>
+        <tbody>
+          <tr><td>def<div class="footnote">f</div></td></tr>
+          <tr><td>ghi</td></tr>
+        </tbody>
+      </table>
+    ''')
+
+    html, = page1.children
+    body, = html.children
+    table_wrapper, = body.children
+    table, = table_wrapper.children
+    tbody, = table.children
+    for tr in tbody.children:
+        td, = tr.children
+        line, = td.children
+        textbox, = line.children
+        assert textbox.text == 'abc'
+
+    html, footnote_area = page2.children
+    body, = html.children
+    table_wrapper, = body.children
+    table, = table_wrapper.children
+    tbody, = table.children
+    tr1, tr2 = tbody.children
+    td, = tr1.children
+    line, = td.children
+    textbox, call = line.children
+    assert textbox.text == 'def'
+    td, = tr2.children
+    line, = td.children
+    textbox, = line.children
+    assert textbox.text == 'ghi'
+    footnote, = footnote_area.children
+    line, = footnote.children
+    marker, textbox = line.children
+    assert textbox.text == 'f'