diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 17d8c79994dbe..895c21e79886f 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -448,7 +448,7 @@ Other - :meth:`Index.where` behavior now mirrors :meth:`Index.putmask` behavior, i.e. ``index.where(mask, other)`` matches ``index.putmask(~mask, other)`` (:issue:`39412`) - Bug in :func:`pandas.testing.assert_series_equal`, :func:`pandas.testing.assert_frame_equal`, :func:`pandas.testing.assert_index_equal` and :func:`pandas.testing.assert_extension_array_equal` incorrectly raising when an attribute has an unrecognized NA type (:issue:`39461`) - Bug in :class:`Styler` where ``subset`` arg in methods raised an error for some valid multiindex slices (:issue:`33562`) -- +- :class:`Styler` rendered HTML output minor alterations to support w3 good code standard (:issue:`39626`) - .. --------------------------------------------------------------------------- diff --git a/pandas/io/formats/templates/html.tpl b/pandas/io/formats/templates/html.tpl index 97bfda9af089d..b315c57a65cdf 100644 --- a/pandas/io/formats/templates/html.tpl +++ b/pandas/io/formats/templates/html.tpl @@ -1,70 +1,70 @@ {# Update the template_structure.html document too #} {%- block before_style -%}{%- endblock before_style -%} {% block style %} - -{%- endblock style %} -{%- block before_table %}{% endblock before_table %} -{%- block table %} - -{%- block caption %} -{%- if caption -%} - -{%- endif -%} -{%- endblock caption %} -{%- block thead %} - - {%- block before_head_rows %}{% endblock %} - {%- for r in head %} - {%- block head_tr scoped %} +{% endblock style %} +{% block before_table %}{% endblock before_table %} +{% block table %} +
{{caption}}
+{% block caption %} +{% if caption %} + +{% endif %} +{% endblock caption %} +{% block thead %} + +{% block before_head_rows %}{% endblock %} +{% for r in head %} +{% block head_tr scoped %} - {%- for c in r %} - {%- if c.is_visible != False %} - <{{ c.type }} class="{{c.class}}" {{ c.attributes|join(" ") }}>{{c.value}} - {%- endif %} - {%- endfor %} +{% for c in r %} +{% if c.is_visible != False %} + <{{c.type}} class="{{c.class}}" {{c.attributes|join(" ")}}>{{c.value}} +{% endif %} +{% endfor %} - {%- endblock head_tr %} - {%- endfor %} - {%- block after_head_rows %}{% endblock %} - -{%- endblock thead %} -{%- block tbody %} - - {% block before_rows %}{% endblock before_rows %} - {% for r in body %} - {% block tr scoped %} +{% endblock head_tr %} +{% endfor %} +{% block after_head_rows %}{% endblock %} + +{% endblock thead %} +{% block tbody %} + +{% block before_rows %}{% endblock before_rows %} +{% for r in body %} +{% block tr scoped %} - {% for c in r %} - {% if c.is_visible != False %} - <{{ c.type }} {% if c.id is defined -%} id="T_{{ uuid }}{{ c.id }}" {%- endif %} class="{{ c.class }}" {{ c.attributes|join(" ") }}>{{ c.display_value }} - {% endif %} - {%- endfor %} +{% for c in r %} +{% if c.is_visible != False %} + <{{c.type}} {% if c.id is defined -%} id="T_{{uuid}}{{c.id}}" {%- endif %} class="{{c.class}}" {{c.attributes|join(" ")}}>{{c.display_value}} +{% endif %} +{% endfor %} - {% endblock tr %} - {%- endfor %} - {%- block after_rows %}{%- endblock after_rows %} - -{%- endblock tbody %} +{% endblock tr %} +{% endfor %} +{% block after_rows %}{% endblock after_rows %} + +{% endblock tbody %}
{{caption}}
-{%- endblock table %} -{%- block after_table %}{% endblock after_table %} +{% endblock table %} +{% block after_table %}{% endblock after_table %} diff --git a/pandas/tests/io/formats/test_style.py b/pandas/tests/io/formats/test_style.py index d2c5b5b9d0b2c..0bd0c5bd87761 100644 --- a/pandas/tests/io/formats/test_style.py +++ b/pandas/tests/io/formats/test_style.py @@ -140,8 +140,8 @@ def test_multiple_render(self): s = Styler(self.df, uuid_len=0).applymap(lambda x: "color: red;", subset=["A"]) s.render() # do 2 renders to ensure css styles not duplicated assert ( - '" in s.render() + '" in s.render() ) def test_render_empty_dfs(self): @@ -1794,11 +1794,11 @@ def test_column_and_row_styling(self): df = DataFrame(data=[[0, 1], [1, 2]], columns=["A", "B"]) s = Styler(df, uuid_len=0) s = s.set_table_styles({"A": [{"selector": "", "props": [("color", "blue")]}]}) - assert "#T__ .col0 {\n color: blue;\n }" in s.render() + assert "#T__ .col0 {\n color: blue;\n}" in s.render() s = s.set_table_styles( {0: [{"selector": "", "props": [("color", "blue")]}]}, axis=1 ) - assert "#T__ .row0 {\n color: blue;\n }" in s.render() + assert "#T__ .row0 {\n color: blue;\n}" in s.render() def test_colspan_w3(self): # GH 36223 @@ -1855,12 +1855,12 @@ def test_tooltip_render(self, ttips): s = Styler(df, uuid_len=0).set_tooltips(ttips).render() # test tooltip table level class - assert "#T__ .pd-t {\n visibility: hidden;\n" in s + assert "#T__ .pd-t {\n visibility: hidden;\n" in s # test 'Min' tooltip added assert ( - "#T__ #T__row0_col0:hover .pd-t {\n visibility: visible;\n } " - + ' #T__ #T__row0_col0 .pd-t::after {\n content: "Min";\n }' + "#T__ #T__row0_col0:hover .pd-t {\n visibility: visible;\n}\n" + + '#T__ #T__row0_col0 .pd-t::after {\n content: "Min";\n}' in s ) assert ( @@ -1871,8 +1871,8 @@ def test_tooltip_render(self, ttips): # test 'Max' tooltip added assert ( - "#T__ #T__row0_col1:hover .pd-t {\n visibility: visible;\n } " - + ' #T__ #T__row0_col1 .pd-t::after {\n content: "Max";\n }' + "#T__ #T__row0_col1:hover .pd-t {\n visibility: visible;\n}\n" + + '#T__ #T__row0_col1 .pd-t::after {\n content: "Max";\n}' in s ) assert ( @@ -1892,16 +1892,16 @@ def test_tooltip_reindex(self): index=[0, 2], ) s = Styler(df, uuid_len=0).set_tooltips(DataFrame(ttips)).render() - assert '#T__ #T__row0_col0 .pd-t::after {\n content: "Mi";\n }' in s - assert '#T__ #T__row0_col2 .pd-t::after {\n content: "Ma";\n }' in s - assert '#T__ #T__row2_col0 .pd-t::after {\n content: "Mu";\n }' in s - assert '#T__ #T__row2_col2 .pd-t::after {\n content: "Mo";\n }' in s + assert '#T__ #T__row0_col0 .pd-t::after {\n content: "Mi";\n}' in s + assert '#T__ #T__row0_col2 .pd-t::after {\n content: "Ma";\n}' in s + assert '#T__ #T__row2_col0 .pd-t::after {\n content: "Mu";\n}' in s + assert '#T__ #T__row2_col2 .pd-t::after {\n content: "Mo";\n}' in s def test_tooltip_ignored(self): # GH 21266 df = DataFrame(data=[[0, 1], [2, 3]]) s = Styler(df).set_tooltips_class("pd-t").render() # no set_tooltips() - assert '' in s + assert '' in s assert '' not in s def test_tooltip_class(self): @@ -1913,11 +1913,8 @@ def test_tooltip_class(self): .set_tooltips_class(name="other-class", properties=[("color", "green")]) .render() ) - assert "#T__ .other-class {\n color: green;\n" in s - assert ( - '#T__ #T__row0_col0 .other-class::after {\n content: "tooltip";\n' - in s - ) + assert "#T__ .other-class {\n color: green;\n" in s + assert '#T__ #T__row0_col0 .other-class::after {\n content: "tooltip";\n' in s # GH 39563 s = ( @@ -1926,10 +1923,50 @@ def test_tooltip_class(self): .set_tooltips_class(name="other-class", properties="color:green;color:red;") .render() ) - assert ( - "#T__ .other-class {\n color: green;\n color: red;\n " - in s + assert "#T__ .other-class {\n color: green;\n color: red;\n}" in s + + def test_w3_html_format(self): + s = ( + Styler( + DataFrame([[2.61], [2.69]], index=["a", "b"], columns=["A"]), + uuid_len=0, + ) + .set_table_styles([{"selector": "th", "props": "att2:v2;"}]) + .applymap(lambda x: "att1:v1;") + .set_table_attributes('class="my-cls1" style="attr3:v3;"') + .set_td_classes(DataFrame(["my-cls2"], index=["a"], columns=["A"])) + .format("{:.1f}") + .set_caption("A comprehensive test") ) + expected = """ + + + + + + + + + + + + + + + + + + +
A comprehensive test
A
a2.6
b2.7
+""" + assert expected == s.render() @td.skip_if_no_mpl