diff --git a/CHANGELOG.md b/CHANGELOG.md index f7a768c95..de0f49290 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,18 +24,20 @@ This can also be enabled programmatically with `warnings.simplefilter('default', * feature to identify the Unicode script of the input text and break it into fragments when different scripts are used, improving text shaping results * [`FPDF.image()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image): now handles `keep_aspect_ratio` in combination with an enum value provided to `x` * file names are mentioned in errors when `fpdf2` fails to parse a SVG image -* * feature to adjust spacing before lists via the `HTML2FPDF.list_vertical_margin` attribute +* [`FPDF.write_html()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.write_html): spacing before lists can now be adjusted via the `HTML2FPDF.list_vertical_margin` attribute ### Fixed +* [`FPDF.local_context()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.local_context) used to leak styling during page breaks, when rendering `footer()` & `header()` * [`fpdf.drawing.DeviceCMYK`](https://py-pdf.github.io/fpdf2/fpdf/drawing.html#fpdf.drawing.DeviceCMYK) objects can now be passed to [`FPDF.set_draw_color()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_draw_color), [`FPDF.set_fill_color()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_fill_color) and [`FPDF.set_text_color()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_text_color) without raising a `ValueError`: [documentation](https://py-pdf.github.io/fpdf2/Text.html#text-formatting). +* [`FPDF.write_html()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.write_html): fixing rendering of `
, remove one initial nl. - ) + # nothing written yet to, remove one initial nl: + self._pre_started = False self.follows_trailing_space = False # The last write has ended with a space. self.follows_heading = False # We don't want extra space below a heading. self.href = "" @@ -464,11 +461,7 @@ def _end_paragraph(self): self.align = "" if self._paragraph: self._column.end_paragraph() - our_context = ( - self.pdf._pop_local_stack() # pylint: disable=protected-access - ) self._column.render() - self.pdf._push_local_stack(our_context) # pylint: disable=protected-access self._paragraph = None self.follows_trailing_space = True @@ -530,15 +523,12 @@ def handle_data(self, data): elif self._pre_formatted: # pre blocks # If we want to mimick the exact HTML semantics about newlines at the # beginning and end of the block, then this needs some more thought. - s_nl = data.startswith("\n") and self._pre_started + if data.startswith("\n") and self._pre_started: + if data.endswith("\n"): + data = data[1:-1] + else: + data = data[1:] self._pre_started = False - e_nl = data.endswith("\n") - if s_nl and e_nl: - data = data[1:-1] - elif s_nl: - data = data[1:] - # elif e_nl: - # data = data[:-1] self._write_data(data) else: data = _WS_SUB_PAT.sub(" ", data) @@ -650,7 +640,13 @@ def handle_starttag(self, tag, attrs): size=tag_style.size_pt or self.font_size, ) if tag == "hr": - self.pdf.add_page(same=True) + self.pdf.line( + x1=self.pdf.l_margin, + y1=self.pdf.y, + x2=self.pdf.l_margin + self.pdf.epw, + y2=self.pdf.y, + ) + self._write_paragraph("\n") if tag == "code": self.style_stack.append( FontFace( @@ -667,6 +663,7 @@ def handle_starttag(self, tag, attrs): size=tag_style.size_pt or self.font_size, ) if tag == "pre": + self._end_paragraph() self.style_stack.append( FontFace( family=self.font_family, @@ -682,8 +679,8 @@ def handle_starttag(self, tag, attrs): size=tag_style.size_pt or self.font_size, ) self._pre_formatted = True - self._new_paragraph() self._pre_started = True + self._new_paragraph() if tag == "blockquote": tag_style = self.tag_styles[tag] if tag_style.color: @@ -928,12 +925,12 @@ def handle_endtag(self, tag): self.set_font(font_face.family, font_face.size_pt) self.set_text_color(*font_face.color.colors255) if tag == "pre": - self._end_paragraph() font_face = self.style_stack.pop() self.set_font(font_face.family, font_face.size_pt) self.set_text_color(*font_face.color.colors255) self._pre_formatted = False self._pre_started = False + self._end_paragraph() if tag == "blockquote": self._end_paragraph() self.set_text_color(*self.font_color) @@ -991,10 +988,6 @@ def feed(self, data): while self._tags_stack and self._tags_stack[-1] in self.HTML_UNCLOSED_TAGS: self._tags_stack.pop() self._end_paragraph() # render the final chunk of text and clean up our local context. - self.pdf._pop_local_stack() # pylint: disable=protected-access - if self._prev_font[0]: # restore previously defined font settings - self.emphasis = self._prev_font[2] - self.set_font(self._prev_font[0], size=self._prev_font[1], set_default=True) if self._tags_stack and self.warn_on_tags_not_matching: LOGGER.warning("Missing HTML end tag for <%s>", self._tags_stack[-1]) diff --git a/fpdf/text_region.py b/fpdf/text_region.py index 4c8dc3f8d..2b1a02e0b 100644 --- a/fpdf/text_region.py +++ b/fpdf/text_region.py @@ -718,7 +718,7 @@ def render(self): _first_page_top = max(self.pdf.t_margin, self.pdf.y) self._render_page_lines(text_lines, _first_page_top, page_bottom) while text_lines: - self.pdf.add_page(same=True) + self.pdf._perform_page_break() self._cur_column = 0 self._render_page_lines(text_lines, self.pdf.y, page_bottom) diff --git a/scripts/compare-changed-pdfs.py b/scripts/compare-changed-pdfs.py index 1b165a6a5..ebd48462b 100755 --- a/scripts/compare-changed-pdfs.py +++ b/scripts/compare-changed-pdfs.py @@ -3,9 +3,9 @@ # Generate a HTML page that makes it easy to visually compare all PDF files # that are modified in the current branch, compared to the master branch. -# USAGE: ./compare-changed-pdfs.py +# USAGE: ./compare-changed-pdfs.py [test_subdir_path] -import webbrowser +import sys, webbrowser from functools import partial from http.server import HTTPServer, SimpleHTTPRequestHandler from os import makedirs, scandir @@ -30,15 +30,18 @@ def scantree_dirs(path): yield from scantree_dirs(entry.path) +target_dir = sys.argv[1] if len(sys.argv) > 1 else "test" +print(f"Processing all PDF reference files in {target_dir}") + stdout = check_output("git diff --name-status master", shell=True) changed_pdf_files = [ line[1:].strip() for line in stdout.decode("utf-8").splitlines() - if line.startswith("M\ttest/") + if line.startswith(f"M\t{target_dir}") ] TMP_DIR.mkdir(exist_ok=True) -for dir in scantree_dirs(REPO_DIR / "test"): +for dir in scantree_dirs(REPO_DIR / target_dir): (TMP_DIR / dir).mkdir(exist_ok=True) for changed_pdf_file in changed_pdf_files: command = f"git show master:{changed_pdf_file} > {TMP_DIR}/{changed_pdf_file}" diff --git a/test/embed_file_all_optionals.pdf b/test/embed_file_all_optionals.pdf index 2331560eb..7059b51b3 100644 Binary files a/test/embed_file_all_optionals.pdf and b/test/embed_file_all_optionals.pdf differ diff --git a/test/embed_file_self.pdf b/test/embed_file_self.pdf index b6f888bc3..fc65a79f2 100644 Binary files a/test/embed_file_self.pdf and b/test/embed_file_self.pdf differ diff --git a/test/file_attachment_annotation.pdf b/test/file_attachment_annotation.pdf index ff5d89099..3db222d90 100644 Binary files a/test/file_attachment_annotation.pdf and b/test/file_attachment_annotation.pdf differ diff --git a/test/html/html_align_paragraph.pdf b/test/html/html_align_paragraph.pdf index 09ed3b811..65bb70a85 100644 Binary files a/test/html/html_align_paragraph.pdf and b/test/html/html_align_paragraph.pdf differ diff --git a/test/html/html_blockquote_color.pdf b/test/html/html_blockquote_color.pdf index a2b22f554..03d4149e2 100644 Binary files a/test/html/html_blockquote_color.pdf and b/test/html/html_blockquote_color.pdf differ diff --git a/test/html/html_blockquote_indent.pdf b/test/html/html_blockquote_indent.pdf index 45099424b..c63968eb9 100644 Binary files a/test/html/html_blockquote_indent.pdf and b/test/html/html_blockquote_indent.pdf differ diff --git a/test/html/html_bold_italic_underline.pdf b/test/html/html_bold_italic_underline.pdf index 7a705e4a1..a4968f5b8 100644 Binary files a/test/html/html_bold_italic_underline.pdf and b/test/html/html_bold_italic_underline.pdf differ diff --git a/test/html/html_custom_heading_sizes.pdf b/test/html/html_custom_heading_sizes.pdf index a4ae2c520..298a62dc7 100644 Binary files a/test/html/html_custom_heading_sizes.pdf and b/test/html/html_custom_heading_sizes.pdf differ diff --git a/test/html/html_custom_line_height.pdf b/test/html/html_custom_line_height.pdf index 916327fe7..54a126a78 100644 Binary files a/test/html/html_custom_line_height.pdf and b/test/html/html_custom_line_height.pdf differ diff --git a/test/html/html_custom_pre_code_font.pdf b/test/html/html_custom_pre_code_font.pdf index 1b10ec102..789557ddc 100644 Binary files a/test/html/html_custom_pre_code_font.pdf and b/test/html/html_custom_pre_code_font.pdf differ diff --git a/test/html/html_customize_ul.pdf b/test/html/html_customize_ul.pdf index e97a5cbdc..d85f8d525 100644 Binary files a/test/html/html_customize_ul.pdf and b/test/html/html_customize_ul.pdf differ diff --git a/test/html/html_description.pdf b/test/html/html_description.pdf index 548a87db2..516d99de7 100644 Binary files a/test/html/html_description.pdf and b/test/html/html_description.pdf differ diff --git a/test/html/html_features.pdf b/test/html/html_features.pdf index e36c8a5e0..c19c4e2a1 100644 Binary files a/test/html/html_features.pdf and b/test/html/html_features.pdf differ diff --git a/test/html/html_font_color_name.pdf b/test/html/html_font_color_name.pdf index 0738d8c4c..f9ac07e6e 100644 Binary files a/test/html/html_font_color_name.pdf and b/test/html/html_font_color_name.pdf differ diff --git a/test/html/html_format_within_p.pdf b/test/html/html_format_within_p.pdf index 29e600e68..eebcf3eff 100644 Binary files a/test/html/html_format_within_p.pdf and b/test/html/html_format_within_p.pdf differ diff --git a/test/html/html_heading_color_attribute.pdf b/test/html/html_heading_color_attribute.pdf index b755c0051..3652b9308 100644 Binary files a/test/html/html_heading_color_attribute.pdf and b/test/html/html_heading_color_attribute.pdf differ diff --git a/test/html/html_heading_hebrew.pdf b/test/html/html_heading_hebrew.pdf index 803c93f39..8316b6768 100644 Binary files a/test/html/html_heading_hebrew.pdf and b/test/html/html_heading_hebrew.pdf differ diff --git a/test/html/html_headings_color.pdf b/test/html/html_headings_color.pdf index 683eb64e4..93e10d853 100644 Binary files a/test/html/html_headings_color.pdf and b/test/html/html_headings_color.pdf differ diff --git a/test/html/html_headings_line_height.pdf b/test/html/html_headings_line_height.pdf index 8c82e9d04..d99aa7ea4 100644 Binary files a/test/html/html_headings_line_height.pdf and b/test/html/html_headings_line_height.pdf differ diff --git a/test/html/html_images.pdf b/test/html/html_images.pdf index 20e7f4ea6..72909f3ad 100644 Binary files a/test/html/html_images.pdf and b/test/html/html_images.pdf differ diff --git a/test/html/html_img_not_overlapping.pdf b/test/html/html_img_not_overlapping.pdf index d65c643d9..2218bcd13 100644 Binary files a/test/html/html_img_not_overlapping.pdf and b/test/html/html_img_not_overlapping.pdf differ diff --git a/test/html/html_li_prefix_color.pdf b/test/html/html_li_prefix_color.pdf index 5baa1800b..7750b6ff9 100644 Binary files a/test/html/html_li_prefix_color.pdf and b/test/html/html_li_prefix_color.pdf differ diff --git a/test/html/html_li_tag_indent.pdf b/test/html/html_li_tag_indent.pdf index e7f84ff0f..68ed219ad 100644 Binary files a/test/html/html_li_tag_indent.pdf and b/test/html/html_li_tag_indent.pdf differ diff --git a/test/html/html_link_color.pdf b/test/html/html_link_color.pdf index 751b65e0c..d11bf1bb2 100644 Binary files a/test/html/html_link_color.pdf and b/test/html/html_link_color.pdf differ diff --git a/test/html/html_list_vertical_margin.pdf b/test/html/html_list_vertical_margin.pdf index 00304ff24..380f5f1cd 100644 Binary files a/test/html/html_list_vertical_margin.pdf and b/test/html/html_list_vertical_margin.pdf differ diff --git a/test/html/html_ln_outside_p.pdf b/test/html/html_ln_outside_p.pdf index 0ccbb593d..a552e647d 100644 Binary files a/test/html/html_ln_outside_p.pdf and b/test/html/html_ln_outside_p.pdf differ diff --git a/test/html/html_long_list_entries.pdf b/test/html/html_long_list_entries.pdf index e82f70ca7..dd2063ba2 100644 Binary files a/test/html/html_long_list_entries.pdf and b/test/html/html_long_list_entries.pdf differ diff --git a/test/html/html_long_ol_bullets.pdf b/test/html/html_long_ol_bullets.pdf index d8173b393..a7e28d720 100644 Binary files a/test/html/html_long_ol_bullets.pdf and b/test/html/html_long_ol_bullets.pdf differ diff --git a/test/html/html_measurement_units.pdf b/test/html/html_measurement_units.pdf index de9849542..21a0e5f18 100644 Binary files a/test/html/html_measurement_units.pdf and b/test/html/html_measurement_units.pdf differ diff --git a/test/html/html_ol_start_and_type.pdf b/test/html/html_ol_start_and_type.pdf index d786793a9..2496bfbd1 100644 Binary files a/test/html/html_ol_start_and_type.pdf and b/test/html/html_ol_start_and_type.pdf differ diff --git a/test/html/html_ol_ul_line_height.pdf b/test/html/html_ol_ul_line_height.pdf index ae2ae26f8..c2f95f593 100644 Binary files a/test/html/html_ol_ul_line_height.pdf and b/test/html/html_ol_ul_line_height.pdf differ diff --git a/test/html/html_preserve_initial_text_color.pdf b/test/html/html_preserve_initial_text_color.pdf index 7e7be5c77..cb135d753 100644 Binary files a/test/html/html_preserve_initial_text_color.pdf and b/test/html/html_preserve_initial_text_color.pdf differ diff --git a/test/html/html_superscript.pdf b/test/html/html_superscript.pdf index bd1f0b2f7..f29e0f9a5 100644 Binary files a/test/html/html_superscript.pdf and b/test/html/html_superscript.pdf differ diff --git a/test/html/html_table_honoring_align.pdf b/test/html/html_table_honoring_align.pdf index 08396b28f..4e3777210 100644 Binary files a/test/html/html_table_honoring_align.pdf and b/test/html/html_table_honoring_align.pdf differ diff --git a/test/html/html_table_line_separators.pdf b/test/html/html_table_line_separators.pdf index bdfbff3f1..a3723e07b 100644 Binary files a/test/html/html_table_line_separators.pdf and b/test/html/html_table_line_separators.pdf differ diff --git a/test/html/html_table_simple.pdf b/test/html/html_table_simple.pdf index edfad2bc9..d26e6f263 100644 Binary files a/test/html/html_table_simple.pdf and b/test/html/html_table_simple.pdf differ diff --git a/test/html/html_table_th_inside_tr_issue_137.pdf b/test/html/html_table_th_inside_tr_issue_137.pdf index 0952510e3..18510970d 100644 Binary files a/test/html/html_table_th_inside_tr_issue_137.pdf and b/test/html/html_table_th_inside_tr_issue_137.pdf differ diff --git a/test/html/html_table_with_bgcolor.pdf b/test/html/html_table_with_bgcolor.pdf index ab085490a..9f9793207 100644 Binary files a/test/html/html_table_with_bgcolor.pdf and b/test/html/html_table_with_bgcolor.pdf differ diff --git a/test/html/html_table_with_border.pdf b/test/html/html_table_with_border.pdf index 8e8b306e9..7a156a2b8 100644 Binary files a/test/html/html_table_with_border.pdf and b/test/html/html_table_with_border.pdf differ diff --git a/test/html/html_table_with_data_that_contains_entity_names.pdf b/test/html/html_table_with_data_that_contains_entity_names.pdf index 4397aecf3..a28b2ab26 100644 Binary files a/test/html/html_table_with_data_that_contains_entity_names.pdf and b/test/html/html_table_with_data_that_contains_entity_names.pdf differ diff --git a/test/html/html_table_with_empty_cell_contents.pdf b/test/html/html_table_with_empty_cell_contents.pdf index 27f586687..37a5d3efc 100644 Binary files a/test/html/html_table_with_empty_cell_contents.pdf and b/test/html/html_table_with_empty_cell_contents.pdf differ diff --git a/test/html/html_table_with_font_tags_used_to_set_text_color.pdf b/test/html/html_table_with_font_tags_used_to_set_text_color.pdf index 7e09d60a8..36a61ff0f 100644 Binary files a/test/html/html_table_with_font_tags_used_to_set_text_color.pdf and b/test/html/html_table_with_font_tags_used_to_set_text_color.pdf differ diff --git a/test/html/html_table_with_img.pdf b/test/html/html_table_with_img.pdf index 230135ad7..03b3c9369 100644 Binary files a/test/html/html_table_with_img.pdf and b/test/html/html_table_with_img.pdf differ diff --git a/test/html/html_table_with_img_without_explicit_dimensions.pdf b/test/html/html_table_with_img_without_explicit_dimensions.pdf index 230135ad7..03b3c9369 100644 Binary files a/test/html/html_table_with_img_without_explicit_dimensions.pdf and b/test/html/html_table_with_img_without_explicit_dimensions.pdf differ diff --git a/test/html/html_table_with_imgs_captions_and_colspan.pdf b/test/html/html_table_with_imgs_captions_and_colspan.pdf index 6231defb6..a95dc3100 100644 Binary files a/test/html/html_table_with_imgs_captions_and_colspan.pdf and b/test/html/html_table_with_imgs_captions_and_colspan.pdf differ diff --git a/test/html/html_table_with_multi_lines_text.pdf b/test/html/html_table_with_multi_lines_text.pdf index b50ba5d66..2a5e55cbd 100644 Binary files a/test/html/html_table_with_multi_lines_text.pdf and b/test/html/html_table_with_multi_lines_text.pdf differ diff --git a/test/html/html_table_with_multiline_cells_and_split_over_page.pdf b/test/html/html_table_with_multiline_cells_and_split_over_page.pdf index 1b894eb53..317979244 100644 Binary files a/test/html/html_table_with_multiline_cells_and_split_over_page.pdf and b/test/html/html_table_with_multiline_cells_and_split_over_page.pdf differ diff --git a/test/html/html_table_with_only_tds.pdf b/test/html/html_table_with_only_tds.pdf index 7e04a4f9b..87ed1dbc6 100644 Binary files a/test/html/html_table_with_only_tds.pdf and b/test/html/html_table_with_only_tds.pdf differ diff --git a/test/html/html_table_with_width_and_align.pdf b/test/html/html_table_with_width_and_align.pdf index ffe932e55..e3f284da3 100644 Binary files a/test/html/html_table_with_width_and_align.pdf and b/test/html/html_table_with_width_and_align.pdf differ diff --git a/test/html/html_ul_type.pdf b/test/html/html_ul_type.pdf index fdb16ada2..0421be0f7 100644 Binary files a/test/html/html_ul_type.pdf and b/test/html/html_ul_type.pdf differ diff --git a/test/html/html_unorthodox_headings_hierarchy.pdf b/test/html/html_unorthodox_headings_hierarchy.pdf index 643c5e733..b9a4f26c8 100644 Binary files a/test/html/html_unorthodox_headings_hierarchy.pdf and b/test/html/html_unorthodox_headings_hierarchy.pdf differ diff --git a/test/html/html_whitespace_handling.pdf b/test/html/html_whitespace_handling.pdf index 21f87eff6..f676cd5b1 100644 Binary files a/test/html/html_whitespace_handling.pdf and b/test/html/html_whitespace_handling.pdf differ diff --git a/test/html/issue_156.pdf b/test/html/issue_156.pdf index b838c5ef8..c8d9ce685 100644 Binary files a/test/html/issue_156.pdf and b/test/html/issue_156.pdf differ diff --git a/test/html/test_html.py b/test/html/test_html.py index dbb0c22bb..cdbc13af1 100644 --- a/test/html/test_html.py +++ b/test/html/test_html.py @@ -53,10 +53,11 @@ def test_html_features(tmp_path): pdf.write_html("h4
") pdf.write_html("h5
") pdf.write_html("h6
") - pdf.write_html("
") - pdf.write_html("
") - pdf.write_html("
") - pdf.write_html("
") + pdf.write_html("Rendering <hr>:
") + pdf.write_html("
") + # Now inserting
tags until a page jump is triggered: + for _ in range(25): + pdf.write_html("
") pdf.write_html("i am preformatted text.") pdf.write_html("hello blockquote") pdf.write_html("
Testing paragraph blocks
that span multiple lines.
- Testing tabs and spaces
- and break tags.
+ Testing tabs and spaces
+
and break tags.
Testing code blocks with tabs and spaces.
Testing code blocks with tabs and spaces.
+Testing pre blocks that span multiple lines @@ -444,8 +446,8 @@ def test_html_whitespace_handling(tmp_path): # Issue 547
Testing unicode nbsp \u00a0\u00a0\u00a0\u00a0,
-and html nbsp .
- \u00a0 Testing leading nbsp
+and html nbsp .
+
\u00a0 Testing leading nbsp