From ffbfcf9e629b47780c7d5058e11e2b5b0ae18903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=B7=F0=90=91=91=F0=90=91=B4=F0=90=91=95=F0=90=91=91?= =?UTF-8?q?=F0=90=91=A9=F0=90=91=A4?= Date: Sun, 22 Jun 2025 01:00:27 +0700 Subject: [PATCH 1/5] Expose Xml.uris_attrib --- lib/html_f.ml | 4 ++++ lib/html_sigs.mli | 5 ++++- syntax/reflect/reflect.ml | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/html_f.ml b/lib/html_f.ml index 4e1484f99..ac922b5a9 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 @@ -858,6 +860,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..f012d2ece 100644 --- a/lib/html_sigs.mli +++ b/lib/html_sigs.mli @@ -1169,7 +1169,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/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]] From 1ed27453ab8ddb937af2a230c9a2fc04552ec7b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=B7=F0=90=91=91=F0=90=91=B4=F0=90=91=95=F0=90=91=91?= =?UTF-8?q?=F0=90=91=A9=F0=90=91=A4?= Date: Tue, 13 May 2025 15:34:24 +0700 Subject: [PATCH 2/5] Add support for Microdata See: https://html.spec.whatwg.org/multipage/microdata.html --- lib/html_f.ml | 12 ++++++++++++ lib/html_sigs.mli | 18 ++++++++++++++++++ lib/html_types.mli | 13 ++++++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/html_f.ml b/lib/html_f.ml index ac922b5a9..f0555ecb5 100644 --- a/lib/html_f.ml +++ b/lib/html_f.ml @@ -502,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 diff --git a/lib/html_sigs.mli b/lib/html_sigs.mli index f012d2ece..8895f7701 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 diff --git a/lib/html_types.mli b/lib/html_types.mli index 7ccd3d3cc..e9583d2f2 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} From fc1eaca598975ea3ded5cdf04b880f63c6688de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=B7=F0=90=91=91=F0=90=91=B4=F0=90=91=95=F0=90=91=91?= =?UTF-8?q?=F0=90=91=A9=F0=90=91=A4?= Date: Sat, 21 Jun 2025 23:43:43 +0700 Subject: [PATCH 3/5] Add `Meta_with_itemprop to follow spec --- lib/html_f.ml | 3 +++ lib/html_sigs.mli | 4 ++++ lib/html_types.mli | 18 +++++++++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/html_f.ml b/lib/html_f.ml index f0555ecb5..4adbfaed2 100644 --- a/lib/html_f.ml +++ b/lib/html_f.ml @@ -831,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 = []) () = diff --git a/lib/html_sigs.mli b/lib/html_sigs.mli index 8895f7701..2bc94102c 100644 --- a/lib/html_sigs.mli +++ b/lib/html_sigs.mli @@ -1097,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 : diff --git a/lib/html_types.mli b/lib/html_types.mli index e9583d2f2..8e6ec1207 100644 --- a/lib/html_types.mli +++ b/lib/html_types.mli @@ -582,6 +582,7 @@ type core_phrasing = | `Img | `Img_interactive | `Picture | `PCDATA + | `Meta_with_itemprop ] type core_phrasing_without_noscript = @@ -622,6 +623,7 @@ type core_phrasing_without_noscript = | `B | `Abbr | `PCDATA + | `Meta_with_itemprop ] type core_phrasing_without_interactive = [ @@ -657,6 +659,7 @@ type core_phrasing_without_interactive = | `B | `Abbr | `PCDATA + | `Meta_with_itemprop ] type core_phrasing_without_media = @@ -697,6 +700,7 @@ type core_phrasing_without_media = | `B | `Abbr | `PCDATA + | `Meta_with_itemprop ] type phrasing_without_noscript = @@ -733,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 = @@ -772,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 ] @@ -810,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 ] @@ -851,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 ] @@ -889,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 ] @@ -930,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 ] @@ -2287,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 From 56626375a3a1edc29bb67a57c812198d1568dc7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=B7=F0=90=91=91=F0=90=91=B4=F0=90=91=95=F0=90=91=91?= =?UTF-8?q?=F0=90=91=A9=F0=90=91=A4?= Date: Tue, 13 May 2025 19:21:41 +0700 Subject: [PATCH 4/5] Add Microdata test --- test/test_ppx.ml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) 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()"] []] ; From 10a94aa6ac7e3e945e287170ba8405ff6636857d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=B7=F0=90=91=91=F0=90=91=B4=F0=90=91=95=F0=90=91=91?= =?UTF-8?q?=F0=90=91=A9=F0=90=91=A4?= Date: Tue, 13 May 2025 19:35:52 +0700 Subject: [PATCH 5/5] Microdata changelog entry --- CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) 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