Repository: pelme/htpy

Issue:
Discard whitespace between shorthand id/class names
if one introduces some extra whitespace in the id/class shorthand, the whitespace is not properly stripped:

```
>>> print(h.span('#a .b .c'))
<span id="a " class="b  c"></span>
```

we should just get rid of the extra spaces.

Discussion:

Solution patch:
diff --git a/docs/changelog.md b/docs/changelog.md
index fc84367..4987ecc 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,5 +1,10 @@
 # Changelog
 
+## Next (minor)
+- Strip whitespace around id and class values in CSS selector. Fixes
+[issue #97](https://github.com/pelme/htpy/issues/97). See [PR #100](https://github.com/pelme/htpy/pull/100).
+Thanks to [William Jackson](https://github.com/williamjacksn).
+
 ## 25.3.0 - 2025-03-16
 - Add `fragment` for explicitly grouping a collection of nodes. [Read the Usage docs for more details](usage.md#fragments) Fixes
 [issue #82](https://github.com/pelme/htpy/issues/82).
diff --git a/htpy/__init__.py b/htpy/__init__.py
index 9b8af80..11ff589 100644
--- a/htpy/__init__.py
+++ b/htpy/__init__.py
@@ -60,8 +60,8 @@ def _id_class_names_from_css_str(x: t.Any) -> Mapping[str, Attribute]:
         raise ValueError("id/class strings must start with # or .")
 
     parts = x.split(".")
-    ids = [part.removeprefix("#") for part in parts if part.startswith("#")]
-    classes = [part for part in parts if not part.startswith("#") if part]
+    ids = [part.removeprefix("#").strip() for part in parts if part.startswith("#")]
+    classes = [part.strip() for part in parts if not part.startswith("#") if part]
 
     assert len(ids) in (0, 1)
 


Test patch:
diff --git a/tests/test_attributes.py b/tests/test_attributes.py
index 4b6b410..6e158bf 100644
--- a/tests/test_attributes.py
+++ b/tests/test_attributes.py
@@ -161,6 +161,21 @@ def test_id_class_only_classes(render: RenderFixture) -> None:
     assert render(result) == ['<div class="foo bar">', "</div>"]
 
 
+def test_id_class_spaces_only_id(render: RenderFixture) -> None:
+    result = div("#a ")
+    assert render(result) == ['<div id="a">', "</div>"]
+
+
+def test_id_class_spaces_only_classes(render: RenderFixture) -> None:
+    result = div(".a ")
+    assert render(result) == ['<div class="a">', "</div>"]
+
+
+def test_id_class_spaces(render: RenderFixture) -> None:
+    result = div("#a .a ")
+    assert render(result) == ['<div id="a" class="a">', "</div>"]
+
+
 def test_id_class_wrong_order() -> None:
     with pytest.raises(ValueError, match="id \\(#\\) must be specified before classes \\(\\.\\)"):
         div(".myclass#myid")