feat(text-cleaner): collapse preview on run + full hidden-char audit

Two small UX fixes on the Clean Text page:

1. The input preview is now wrapped in an ``st.expander`` whose
   default-expanded state is ``not has_result``. Clicking the
   "Clean Text" primary button stashes the result and calls
   ``st.rerun()`` so the next pass sees the result in session state
   and the expander folds — the Results section becomes the primary
   visual focus. User can re-expand manually to re-inspect the source.

2. The Examples (changes audit) table's Before/After columns were
   calling ``visualize_hidden_html`` WITHOUT ``mark_outer_whitespace``,
   so leading/trailing whitespace — which is exactly what the cleaner
   most often removes — was invisible. Pass ``mark_outer_whitespace=True``
   to match the input-preview rendering. Column-name cell now mirrors
   that flag too.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-16 20:43:52 +00:00
parent 502a72cd46
commit ca14ce2952

View File

@@ -101,7 +101,11 @@ except Exception as e:
)
st.stop()
st.subheader(f"Preview: {uploaded.name}")
# Collapse the input preview once the user has clicked Clean Text so
# the Results section below is the primary visual focus. The user can
# re-expand the expander to re-inspect the source rows.
_has_result = st.session_state.get("textclean_result") is not None
with st.expander(f"Preview: {uploaded.name}", expanded=not _has_result):
st.caption(f"{len(df)} rows, {len(df.columns)} columns")
preview_show_hidden = st.toggle(
"Show hidden characters in preview",
@@ -211,6 +215,11 @@ if st.button("Clean Text", type="primary", use_container_width=True):
st.stop()
st.session_state["textclean_result"] = result
st.session_state["textclean_input_name"] = uploaded.name
# Force a second rerun so the preview-section expander above sees
# the new result on its NEXT script pass and collapses itself.
# Without this the preview stays expanded until the user touches
# any other widget.
st.rerun()
result = st.session_state.get("textclean_result")
if result is None:
@@ -252,15 +261,19 @@ if result.cells_changed:
if show_hidden:
# Inject the badge CSS once, then render an HTML table so the
# invisibles in old/new are actually visible to the user.
# ``mark_outer_whitespace=True`` matches the input preview's
# rendering so leading/trailing spaces show up as badges in the
# Before/After columns — without it, the examples table missed
# exactly the whitespace the cleaner is removing.
st.markdown(hidden_char_css(), unsafe_allow_html=True)
rows_html = []
for _, row in examples.iterrows():
rows_html.append(
"<tr>"
f"<td>{row['row']}</td>"
f"<td><code>{visualize_hidden_html(str(row['column']))}</code></td>"
f"<td>{visualize_hidden_html(str(row['old']))}</td>"
f"<td>{visualize_hidden_html(str(row['new']))}</td>"
f"<td><code>{visualize_hidden_html(str(row['column']), mark_outer_whitespace=True)}</code></td>"
f"<td>{visualize_hidden_html(str(row['old']), mark_outer_whitespace=True)}</td>"
f"<td>{visualize_hidden_html(str(row['new']), mark_outer_whitespace=True)}</td>"
f"<td><code>{row['ops_applied']}</code></td>"
"</tr>"
)