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()"] []] ;