Skip to content
Merged
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
35 changes: 15 additions & 20 deletions save_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,23 +186,17 @@ def _highlight_context_html(context: str, terms: Iterable[str]) -> str:
if not terms_list:
return html.escape(raw)

# Paleta de cores para cada termo (cores distintas e acessíveis)
# Soft pastel palette (light, readable; distinct per term). Dark text is applied
# via the .highlight CSS class so these backgrounds stay legible in both themes.
color_palette = [
"#fff59d", # Pale yellow
"#ffcc80", # Orange
"#f48fb1", # Pink
"#90caf9", # Light blue
"#a5d6a7", # Light green
"#ce93d8", # Light purple
"#ffab91", # Light red-orange
"#b0bec5", # Light blue-gray
"#ffe082", # Amber
"#c5e1a5", # Light lime
"#b39ddb", # Light indigo
"#ef9a9a", # Light red
"#81c784", # Green
"#64b5f6", # Blue
"#ffb74d", # Deep orange
"#fff3b0", # pale yellow
"#d8f3dc", # pale green
"#dbeafe", # pale blue
"#fde2e4", # pale pink
"#f3e8ff", # pale lavender
"#ffe5d9", # pale peach
"#e0f2fe", # pale cyan
"#fef9c3", # light cream
]

# Mapear cada termo para uma cor
Expand Down Expand Up @@ -513,12 +507,12 @@ def save_results(
*{box-sizing:border-box}
:root{
--bg:#ffffff; --panel:#f7f7f9; --text:#111827; --muted:#58606b;
--border:#e5e7eb; --accent:#16a34a; --hi:#fff59d;
--border:#e5e7eb; --accent:#16a34a; --hi:#fff3b0; --hi-text:#111827;
}
@media (prefers-color-scheme: dark){
:root{
--bg:#0b0c10; --panel:#111827; --text:#e5e7eb; --muted:#9aa4b2;
--border:#2a2f3a; --accent:#22c55e; --hi:#4b5563;
--border:#2a2f3a; --accent:#22c55e; --hi:#fef9c3; --hi-text:#111827;
}
}
html,body{height:100%}
Expand Down Expand Up @@ -552,8 +546,9 @@ def save_results(
}

.highlight{
padding:0 2px; border-radius:3px; font-weight:600;
text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 2px;
padding:0 2px; border-radius:3px;
color:var(--hi-text); /* dark text keeps pastels readable */
border-bottom:1px solid rgba(0,0,0,0.15); /* subtle, not aggressive */
}
/* Cor padrão (fallback) - será sobrescrita por inline styles quando especificado */
.highlight:not([style*="background-color"]) {
Expand Down
64 changes: 64 additions & 0 deletions tests/test_html_highlight.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Tests for the HTML search-term highlight styling (soft pastel palette).

These verify presentation only: markup is still produced, term text is preserved,
and the colours come from the soft pastel palette (no saturated legacy colours).
They do not touch match-finding, counts, or ranking.
"""

from __future__ import annotations

import re
import sys
import unittest
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))

import save_results # noqa: E402

# Soft pastel palette (must match save_results._highlight_context_html).
PASTEL = {
"#fff3b0", "#d8f3dc", "#dbeafe", "#fde2e4",
"#f3e8ff", "#ffe5d9", "#e0f2fe", "#fef9c3",
}
# Saturated colours that must no longer appear anywhere in the output styling.
LEGACY_SATURATED = {
"#fff59d", "#ffcc80", "#f48fb1", "#90caf9", "#a5d6a7", "#ce93d8",
"#ffab91", "#b0bec5", "#ffe082", "#c5e1a5", "#b39ddb", "#ef9a9a",
"#81c784", "#64b5f6", "#ffb74d",
}

_HEX = re.compile(r"background-color:\s*(#[0-9a-fA-F]{6})")


class TestHtmlHighlight(unittest.TestCase):
def test_highlight_markup_present_and_term_preserved(self):
out = save_results._highlight_context_html("the quick brown fox", ["quick"])
self.assertIn('class="highlight"', out)
# The matched term text is preserved verbatim.
self.assertIn("quick", out)
self.assertIn("brown fox", out) # non-matched text intact

def test_highlight_colours_are_soft_pastels(self):
out = save_results._highlight_context_html("alpha beta gamma", ["beta"])
colours = set(m.lower() for m in _HEX.findall(out))
self.assertTrue(colours, "expected at least one highlight background colour")
self.assertTrue(colours <= PASTEL, f"non-pastel colours used: {colours - PASTEL}")
self.assertFalse(colours & LEGACY_SATURATED, "legacy saturated colour present")

def test_multiple_terms_keep_distinct_colours(self):
out = save_results._highlight_context_html("one two three four", ["one", "two"])
colours = [c.lower() for c in _HEX.findall(out)]
self.assertGreaterEqual(len(set(colours)), 2, "terms should be visually distinct")
self.assertTrue(set(colours) <= PASTEL)

def test_no_legacy_saturated_colours_in_source(self):
src = (ROOT / "save_results.py").read_text(encoding="utf-8")
lower = src.lower()
for colour in LEGACY_SATURATED:
self.assertNotIn(colour, lower, f"legacy saturated colour still in source: {colour}")


if __name__ == "__main__":
unittest.main()
Loading