diff --git a/CHANGES.md b/CHANGES.md
index 74ecef559..7da69b8f2 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,6 +2,10 @@
* Add support for the clip-path presentation attribute
(#333 by Martin @MBodin Bodin)
+* Add support for Microdata attributes
+ (#343 by toastal)
+* Add support for to be in flow content
+ (#343 by toastal)
# 4.6.0
diff --git a/lib/html_f.ml b/lib/html_f.ml
index 4e1484f99..4adbfaed2 100644
--- a/lib/html_f.ml
+++ b/lib/html_f.ml
@@ -70,6 +70,8 @@ struct
let uri_attrib a s = Xml.uri_attrib a s
+ let uris_attrib a ss = Xml.uris_attrib a ss
+
let space_sep_attrib = Xml.space_sep_attrib
let comma_sep_attrib = Xml.comma_sep_attrib
@@ -500,6 +502,18 @@ struct
let a_aria name = space_sep_attrib ("aria-" ^ name)
+ (* Microdata *)
+
+ let a_itemid = uri_attrib "itemid"
+
+ let a_itemprop = string_attrib "itemprop"
+
+ let a_itemref = space_sep_attrib "itemref"
+
+ let a_itemscope = constant_attrib "itemscope"
+
+ let a_itemtype = uris_attrib "itemtype"
+
type 'a elt = Xml.elt
type ('a, 'b) nullary = ?a: (('a attrib) list) -> unit -> 'b elt
@@ -817,6 +831,9 @@ struct
let meta = terminal "meta"
+ let meta_itemprop itemprop ?(a = []) () =
+ Xml.leaf ~a: ((a_itemprop itemprop) :: a) "meta"
+
let style ?(a = []) elts = Xml.node ~a "style" elts
let link ~rel ~href ?(a = []) () =
@@ -858,6 +875,8 @@ struct
let uri_attrib a s = Xml.uri_attrib a s
+ let uris_attrib a ss = Xml.uris_attrib a ss
+
let space_sep_attrib = Xml.space_sep_attrib
let comma_sep_attrib = Xml.comma_sep_attrib
diff --git a/lib/html_sigs.mli b/lib/html_sigs.mli
index 1cf169c8f..2bc94102c 100644
--- a/lib/html_sigs.mli
+++ b/lib/html_sigs.mli
@@ -694,6 +694,24 @@ module type T = sig
@see List of WAI-ARIA attributes
*)
+ (** {3 Microdata support} *)
+
+ (** {{: https://html.spec.whatwg.org/multipage/microdata.html} Microdata} is
+ a specification written by the W3C, defining a set of additional HTML
+ attributes that can be applied to elements to annotate content with
+ specific machine-readable labels using schemas.
+ *)
+
+ val a_itemid : Xml.uri wrap -> [> | `ItemID ] attrib
+
+ val a_itemprop : string wrap -> [> | `ItemProp ] attrib
+
+ val a_itemref : idrefs wrap -> [> | `ItemRef ] attrib
+
+ val a_itemscope : unit -> [> | `ItemScope ] attrib
+
+ val a_itemtype : Xml.uri list wrap -> [> | `ItemType ] attrib
+
(** {2:elements Elements} *)
val txt : string wrap -> [> | txt] elt
@@ -1079,6 +1097,10 @@ module type T = sig
val meta : ([< | meta_attrib], [> | meta]) nullary
+ val meta_itemprop :
+ string wrap ->
+ ([< | meta_attrib], [> | meta_with_itemprop]) nullary
+
(** {3 Style Sheets} *)
val style :
@@ -1169,7 +1191,10 @@ module type T = sig
(** Same, for URI attribute *)
val uri_attrib : string -> uri wrap -> 'a attrib
- (** Same, for a space separated list of values *)
+ (** Same, for a space-separated list of URI attributes *)
+ val uris_attrib : string -> uri list wrap -> 'a attrib
+
+ (** Same, for a space-separated list of values *)
val space_sep_attrib : string -> string list wrap -> 'a attrib
(** Same, for a comma separated list of values *)
diff --git a/lib/html_types.mli b/lib/html_types.mli
index 7ccd3d3cc..8e6ec1207 100644
--- a/lib/html_types.mli
+++ b/lib/html_types.mli
@@ -380,8 +380,19 @@ type aria =
| `Aria
]
+(** {2 Microdata} *)
+
+type microdata =
+ [
+ | `ItemID
+ | `ItemProp
+ | `ItemRef
+ | `ItemScope
+ | `ItemType
+ ]
+
(** Common attributes *)
-type common = [ | core | i18n | events | aria ]
+type common = [ | core | i18n | events | aria | microdata ]
(** {1 Categories of HTML elements}
@@ -571,6 +582,7 @@ type core_phrasing =
| `Img | `Img_interactive
| `Picture
| `PCDATA
+ | `Meta_with_itemprop
]
type core_phrasing_without_noscript =
@@ -611,6 +623,7 @@ type core_phrasing_without_noscript =
| `B
| `Abbr
| `PCDATA
+ | `Meta_with_itemprop
]
type core_phrasing_without_interactive =
[
@@ -646,6 +659,7 @@ type core_phrasing_without_interactive =
| `B
| `Abbr
| `PCDATA
+ | `Meta_with_itemprop
]
type core_phrasing_without_media =
@@ -686,6 +700,7 @@ type core_phrasing_without_media =
| `B
| `Abbr
| `PCDATA
+ | `Meta_with_itemprop
]
type phrasing_without_noscript =
@@ -722,9 +737,10 @@ type (+'a, +'b) between_phrasing_and_phrasing_without_interactive =
phrasing,
phrasing_without_media) transparent
> `Abbr `B `Bdo `Br `Canvas `Cite `Code `Command
- `Datalist `Del `Dfn `Em `I `Img `Picture `Ins `Kbd `Map `Mark `Meter
- `Noscript `Object `PCDATA `Progress `Q `Ruby `Samp `Script
- `Small `Span `Strong `Sub `Sup `Svg `Template `Time `U `Var `Wbr ] as 'a)
+ `Datalist `Del `Dfn `Em `I `Img `Picture `Ins `Kbd `Map `Mark
+ `Meta_with_itemprop `Meter `Noscript `Object `PCDATA `Progress `Q `Ruby
+ `Samp `Script `Small `Span `Strong `Sub `Sup `Svg `Template `Time `U
+ `Var `Wbr ] as 'a)
(** Phrasing without the interactive markups *)
type phrasing_without_dfn =
@@ -761,6 +777,7 @@ type phrasing_without_dfn =
| `B
| `Abbr
| `PCDATA
+ | `Meta_with_itemprop
| (phrasing_without_interactive, phrasing_without_noscript,
phrasing_without_dfn, phrasing_without_media) transparent
]
@@ -799,6 +816,7 @@ type phrasing_without_label =
| `B
| `Abbr
| `PCDATA
+ | `Meta_with_itemprop
| (phrasing_without_interactive, phrasing_without_noscript,
phrasing_without_label, phrasing_without_media) transparent
]
@@ -840,6 +858,7 @@ type phrasing_without_progress =
| `B
| `Abbr
| `PCDATA
+ | `Meta_with_itemprop
| (phrasing_without_interactive, phrasing_without_noscript,
phrasing_without_progress, phrasing_without_media) transparent
]
@@ -878,6 +897,7 @@ type phrasing_without_time =
| `B
| `Abbr
| `PCDATA
+ | `Meta_with_itemprop
| (phrasing_without_interactive, phrasing_without_noscript,
phrasing_without_time, phrasing_without_media) transparent
]
@@ -919,6 +939,7 @@ type phrasing_without_meter =
| `B
| `Abbr
| `PCDATA
+ | `Meta_with_itemprop
| (phrasing_without_interactive, phrasing_without_noscript,
phrasing_without_meter, phrasing_without_media) transparent
]
@@ -2276,6 +2297,8 @@ type noscript_attrib = [ | common ]
(* NAME: meta, KIND: nullary, TYPE: [= common | `Http_equiv | `Name | `Content | `Charset ], [=`Meta], ARG: notag, ATTRIB: OUT: [=`Meta] *)
type meta = [ | `Meta ]
+type meta_with_itemprop = [ | `Meta_with_itemprop ]
+
type meta_content = notag
type meta_content_fun = notag
diff --git a/syntax/reflect/reflect.ml b/syntax/reflect/reflect.ml
index dafd1975b..7274105be 100644
--- a/syntax/reflect/reflect.ml
+++ b/syntax/reflect/reflect.ml
@@ -174,6 +174,7 @@ let rec to_attribute_parser lang name ~loc = function
| [[%type: shape]] ->
[%expr variant]
+ | [[%type: Xml.uri list]]
| [[%type: nmtokens]]
| [[%type: idrefs]]
| [[%type: charsets]]
diff --git a/test/test_ppx.ml b/test/test_ppx.ml
index b521aada4..6de07ee8f 100644
--- a/test/test_ppx.ml
+++ b/test/test_ppx.ml
@@ -303,6 +303,26 @@ let attribs = "ppx attribs", HtmlTests.make Html.[
[[%html ""]],
[div ~a:[a_aria "hidden" ["true"]] []] ;
+ "microdata attributes",
+ [[%html "- Name
- Turnout Lantern Kit
- Purpose
- For retrofitting 2 C Track turnouts.
"]],
+ [dl
+ ~a: [
+ a_itemscope ();
+ a_itemtype ["https://md.example.com/track"; "https://md.example.com/lighting"];
+ ]
+ [
+ dt [txt "Name"];
+ dd ~a: [a_itemprop "name"] [txt "Turnout Lantern Kit"];
+ dt [txt "Purpose"];
+ dd
+ [
+ txt "For retrofitting 2 ";
+ span ~a: [a_itemprop "track-type"] [txt "C"];
+ txt " Track turnouts.";
+ meta_itemprop "scale" ~a: [a_content "HO"] ();
+ ]
+ ]];
+
"touch events",
[[%html ""]],
[div ~a:[a_ontouchstart "alert()"] []] ;