Repository: thomasborgen/hypermedia (language: python)

Issue:
Support `hx-on:event`
keys in python can't have `-` or `:`. And while a user can get around this by doing:

```python
Div(**{"hx-on:click": "thing"}
```

I don't really like that.

Thankfully htmx also supports having `-`s instead of all these colons ref [the doc](https://htmx.org/attributes/hx-on/)

> Finally, in order to make this feature compatible with some templating languages (e.g. [JSX](https://react.dev/learn/writing-markup-with-jsx)) that do not like having a colon (:) in HTML attributes, you may use dashes in the place of colons for both the long form and the shorthand form:

```html
<!-- These two are equivalent -->
<button hx-get="/info" hx-on-htmx-before-request="alert('Making a request!')">
    Get Info!
</button>

<button hx-get="/info" hx-on--before-request="alert('Making a request!')">
    Get Info!
</button>
```

So I think we should just keep to underscores and also allow double underscores. 


```python
Div(hx_on_click="js string")

Div(hx_on_htmx_before_request="alert('Making a request!')")

Div(hx_on__before_request="alert('Making a request!')")
```


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5e54a12..0f8f46d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,10 @@
 
 ## Latest Changes
 
+### Internal
+
+* Document how to add attributes with symbols like dash and period.
+
 ## Version 4.0.0
 
 ### Breaking
diff --git a/README.md b/README.md
index c31682a..0a8f493 100644
--- a/README.md
+++ b/README.md
@@ -73,6 +73,36 @@ base.dump()
 # '<html><body><menu><ul><li>main</li></ul></menu><header>my header</header><div><div>Some content</div></div></body></html>'
 ```
 
+## Symbol attributes
+
+Attributes with dashes, periods etc can be added by spreading a dictionary
+
+```python
+# Alpine.js
+Button(**{"@click": "open = ! open"}).dump()
+# <button @click='open'></button>
+
+# Datastar
+Div(**{"x-transition.duration_500ms": "$show"}).dump()
+# <div x-transition.duration_500ms='$show'></div>
+```
+
+Note: The </> HTMX attributes get special treatment. [The documentation](https://htmx.org/attributes/hx-on/) specifies that all hx attributes can be written with all dashes. Because of that Hypermedia lets users write hx attributes with underscores and Hypermedia changes them to dashes for you.
+
+```python
+
+Div(hx_on_click='alert("Making a request!")')
+# <div hx-on-click='alert("Making a request!")'></div>
+# Which is equivalent to:
+# <div hx-on:click='alert("Making a request!"'></div>
+
+Div(hx_on_htmx_before_request='alert("Making a request!")')
+# <div hx-on-htmx-before-request='alert("Making a request!")'></div>
+
+# shorthand version of above statement
+Div(hx_on__before_request='alert("Making a request!")')
+# <div hx-on--before-request='alert("Making a request!")'></div>
+```
 
 # HTMX
 


Test patch:
diff --git a/tests/models/element/test_attributes.py b/tests/models/element/test_attributes.py
index dfd8d5d..e651255 100644
--- a/tests/models/element/test_attributes.py
+++ b/tests/models/element/test_attributes.py
@@ -41,3 +41,15 @@ def test_htmx_keys_added_with_hyphen() -> None:
     element = TestElement(hx_get="url")
 
     assert element._render_attributes() == " hx-get='url'"
+
+
+def test_custom_attributes() -> None:
+    element = TestElement(**{"data-show.duration_500ms": "$show"})
+    assert element._render_attributes() == " data-show.duration_500ms='$show'"
+
+
+def test_custom_attributes_with_normal_ones() -> None:
+    element = TestElement(test="green", **{"@-.%": "test"}, bob="bob")
+    assert (
+        element._render_attributes() == " test='green' @-.%='test' bob='bob'"
+    )