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
3 changes: 2 additions & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ Release History

**Fixes**

- None
- Fixes `#73 <https://github.com/dfop02/html4docx/issues/73>`_: Error parsing styles with spaces. | `dfop02 <https://github.com/dfop02>`_
- Fixes `#71 <https://github.com/dfop02/html4docx/issues/71>`_: Error applying color to table cells. | `vvalchev <https://github.com/vvalchev>`_

**New Features**

Expand Down
2 changes: 2 additions & 0 deletions html4docx/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,5 @@ def default_borders():
re.compile(r'page-break-after\s*:\s*always\s*(?:!important)?\s*(?:;|$)'),
re.compile(r'break-after\s*:\s*page\s*(?:!important)?\s*(?:;|$)'),
)

RGB_SPACES_REGEX = re.compile(r'(rgba?\()([^)]+)(\))', re.IGNORECASE)
33 changes: 28 additions & 5 deletions html4docx/h4d.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,21 @@ def check_unit_keywords(value: str) -> str:
lower_val = value.lower()
return keywords.get(lower_val, value)

def normalize_rgb_spaces(value: str) -> str:
"""
Removes spaces inside rgb()/rgba() so it can be safely split.
Example:
rgb(222, 222, 222) -> rgb(222,222,222)
"""

def _replace(match):
prefix, content, suffix = match.groups()
# remove spaces only inside the function
content = content.replace(' ', '')
return f"{prefix}{content}{suffix}"

return constants.RGB_SPACES_REGEX.sub(_replace, value)

@lru_cache(maxsize=None)
def border_unit_converter(unit_value: str):
"""Convert multiple units to pt that is used on Word table cell border"""
Expand Down Expand Up @@ -360,10 +375,16 @@ def parse_border_value(value: str):
Parses a border value like:
'1px solid #000000', 'solid 1px red', or '#000000 medium dashed' in any order.
"""
parts = value.split()
value = value.strip()

# Return all default if there is only empty value
if not value or value == '':
return default_size, default_style, default_color

parts = normalize_rgb_spaces(value).split()

# Return all default if there is only 'none' or empty
if (len(parts) == 1 and parts[0] == 'none') or (not value or value.strip() == ''):
# Return all default if there is only 'none' value
if len(parts) == 1 and parts[0].lower() == 'none':
return default_size, default_style, default_color

size = None
Expand Down Expand Up @@ -1061,7 +1082,8 @@ def add_styles_to_table_cell(self, styles, doc_cell, cell_row):
"""Styles that must be applied specifically in a _Cell object"""
# Set background color
if 'background-color' in styles:
self.set_cell_background(doc_cell, styles['background-color'])
color = utils.parse_color(styles['background-color'], return_hex=True)
self.set_cell_background(doc_cell, color)

# Set width (approximate, since DOCX uses different units)
if 'width' in styles:
Expand Down Expand Up @@ -1741,7 +1763,8 @@ def handle_comment(self, data):

# Style: Green color to mimic HTML comment styling
dark_ish_green = "#008000"
run.font.color.rgb = utils.parse_color(dark_ish_green)
dark_ish_green_color = utils.parse_color(dark_ish_green)
run.font.color.rgb = RGBColor(*dark_ish_green_color)
run.italic = True # makes it feel more like a comment

def ignore_nested_tables(self, tables_soup):
Expand Down
10 changes: 5 additions & 5 deletions tests/assets/htmls/tables3.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,26 @@
width="641">
<tbody>
<tr style="height:23.75pt;">
<td style="background-color:#3749EF;border-bottom-color:#d95b48;border-left-color:red;border-right-color:darkred;border-style:solid;border-top-color:#d95b48;border-width:1.0pt;height:23.75pt;padding:0in;width:258.35px;"
<td style="background-color:rgb(55, 73, 239);border-bottom-color:#d95b48;border-left-color:red;border-right-color:darkred;border-style:solid;border-top-color:#d95b48;border-width:1.0pt;height:23.75pt;padding:0in;width:258.35px;"
width="344">
<p style="text-align:center;"><span style="color:white;"><strong>CATEGORY</strong></span></p>
</td>
<td style="background-color:#33b32e;border-bottom:1.5px solid
#fac32a;border-left-style:none;border-right:1em solid #fac32a;border-top:1.0pt solid
#fac32a;height:23.75pt;padding:0in;width:222.2pt;" width="296">
rgba(250, 195, 42, 1);border-left-style:none;border-right:1em solid #fac32a;border-top:1.0pt solid
rgb(250, 195, 42);height:23.75pt;padding:0in;width:222.2pt;" width="296">
<p style="margin-left:.7pt;text-align:center;"><span
style="color:white;"><strong>OBSERVATIONS/COMMENTS</strong></span></p>
</td>
</tr>
<tr style="height:15.5pt;">
<td style="background-color:#BFBFBF;border-bottom-style:solid;border-color:#30e667;border-left-style:solid;border-right-style:solid;border-top-style:none;border-width:0.2cm;height:15.5pt;padding:0in;width:258.35in;"
<td style="background-color:#BFBFBF;color:rgba(222, 222, 0, 0);border-bottom-style:solid;border-color:#30e667;border-left-style:solid;border-right-style:solid;border-top-style:none;border-width:0.2cm;height:15.5pt;padding:0in;width:258.35in;"
width="344"><strong>NETHERLANDS COURTS</strong></td>
<td style="background-color:#2eaab3;border-bottom:2px solid
#d948cf;border-left-style:none;border-right:0.2cm solid
#d948cf;border-top-style:none;height:15.5pt;padding:0in;width:6cm;" width="296">&nbsp;</td>
</tr>
<tr>
<td style="background-color:#99fffa;border-bottom-style:solid;border-color:#eaaaa7;border-style:solid;border-width:20%;height:2rem;padding:0in;width:258.35pt;"
<td style="background-color:#99fffa;color:rgba(222, 222, 0, 0);border-bottom-style:solid;border-color:#eaaaa7;border-style:solid;border-width:20%;height:2rem;padding:0in;width:258.35pt;"
width="344"><strong>GERMANY COURTS</strong></td>
<td style="background-color:#2eaab3;border-bottom:0.6em dashed
#acc4aa;border-left-style:none;border-right:0.4rem dotted
Expand Down
1 change: 0 additions & 1 deletion tests/test_h4d.py
Original file line number Diff line number Diff line change
Expand Up @@ -1781,7 +1781,6 @@ def test_html_comment_rendering(self):
expected_comment == text for text in paragraph_texts
), f"Expected comment '{expected_comment}' to appear in the document, but it was not found."

# (Optional) Check styling if needed: green color or italic
comment_paragraph = next(
(p for p in document.paragraphs if p.text.strip() == expected_comment),
None
Expand Down
Loading