diff --git a/_test/options.txt b/_test/options.txt
index 433c49f..3137b65 100644
--- a/_test/options.txt
+++ b/_test/options.txt
@@ -68,3 +68,11 @@
//- - - - - - - - -//
Test ## {class=0#.}
//= = = = = = = = = = = = = = = = = = = = = = = =//
+
+
+7: short handed ids can contain hyphens ("-"), underscores ("_"), colons (":"), and periods (".")
+//- - - - - - - - -//
+# Test ## {#id-foo_bar:baz.qux .foobar}
+//- - - - - - - - -//
+Test
+//= = = = = = = = = = = = = = = = = = = = = = = =//
diff --git a/parser/attribute.go b/parser/attribute.go
index 4c7cc24..f86c836 100644
--- a/parser/attribute.go
+++ b/parser/attribute.go
@@ -89,7 +89,11 @@ func parseAttribute(reader text.Reader) (Attribute, bool) {
reader.Advance(1)
line, _ := reader.PeekLine()
i := 0
- for ; i < len(line) && !util.IsSpace(line[i]) && (!util.IsPunct(line[i]) || line[i] == '_' || line[i] == '-'); i++ {
+ // HTML5 allows any kind of characters as id, but XHTML restricts characters for id.
+ // CommonMark is basically defined for XHTML(even though it is legacy).
+ // So we restrict id characters.
+ for ; i < len(line) && !util.IsSpace(line[i]) &&
+ (!util.IsPunct(line[i]) || line[i] == '_' || line[i] == '-' || line[i] == ':' || line[i] == '.'); i++ {
}
name := attrNameClass
if c == '#' {