Skip to content

Commit 2f99cf3

Browse files
committed
Merge pull request #125 from ocsigen/fix-eliom-275
Add unit arg for constant attributes.
2 parents f1f67e1 + 18def31 commit 2f99cf3

File tree

6 files changed

+99
-33
lines changed

6 files changed

+99
-33
lines changed

lib/html_f.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ struct
7979

8080
let bool_attrib = user_attrib C.string_of_bool
8181

82-
let constant_attrib a =
82+
let constant_attrib a () =
8383
string_attrib a (W.return a)
8484

8585
let linktypes_attrib name x =

lib/html_sigs.mli

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -250,15 +250,15 @@ module type T = sig
250250

251251
(** {3 Other attributes} *)
252252

253-
val a_autocomplete : bool wrap -> [> | `Autocomplete] attrib
253+
val a_autocomplete : (bool[@onoff]) wrap -> [> | `Autocomplete] attrib
254254

255-
val a_async : [> | `Async] attrib
255+
val a_async : unit -> [> | `Async] attrib
256256

257-
val a_autofocus : [> | `Autofocus] attrib
257+
val a_autofocus : unit -> [> | `Autofocus] attrib
258258

259-
val a_autoplay : [> | `Autoplay] attrib
259+
val a_autoplay : unit -> [> | `Autoplay] attrib
260260

261-
val a_muted : [> | `Muted] attrib
261+
val a_muted : unit -> [> | `Muted] attrib
262262

263263
val a_crossorigin :
264264
[< | `Anonymous | `Use_credentials ] wrap -> [> | `Crossorigin ] attrib
@@ -271,7 +271,7 @@ module type T = sig
271271

272272
val a_contextmenu : idref wrap -> [> | `Contextmenu] attrib
273273

274-
val a_controls : [> | `Controls] attrib
274+
val a_controls : unit -> [> | `Controls] attrib
275275

276276
val a_dir : [< | `Rtl | `Ltr] wrap -> [> | `Dir] attrib
277277

@@ -283,23 +283,23 @@ module type T = sig
283283

284284
val a_formenctype : contenttype wrap -> [> | `Formenctype] attrib
285285

286-
val a_formnovalidate : [> | `Formnovalidate] attrib
286+
val a_formnovalidate : unit -> [> | `Formnovalidate] attrib
287287

288288
val a_formtarget : text wrap -> [> | `Formtarget] attrib
289289

290-
val a_hidden : [> | `Hidden] attrib
290+
val a_hidden : unit -> [> | `Hidden] attrib
291291

292292
val a_high : float_number wrap -> [> | `High] attrib
293293

294294
val a_icon : Xml.uri wrap -> [> | `Icon] attrib
295295

296-
val a_ismap : [> | `Ismap] attrib
296+
val a_ismap : unit -> [> | `Ismap] attrib
297297

298298
val a_keytype : text wrap -> [> | `Keytype] attrib
299299

300300
val a_list : idref wrap -> [> | `List] attrib
301301

302-
val a_loop : [> | `Loop] attrib
302+
val a_loop : unit -> [> | `Loop] attrib
303303

304304
val a_low : float_number wrap -> [> | `High] attrib
305305

@@ -321,9 +321,9 @@ module type T = sig
321321
[> `Inputmode] attrib
322322
(** @see <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes> Input HTML documentation. *)
323323

324-
val a_novalidate : [> | `Novalidate] attrib
324+
val a_novalidate : unit -> [> | `Novalidate] attrib
325325

326-
val a_open : [> | `Open] attrib
326+
val a_open : unit -> [> | `Open] attrib
327327

328328
val a_optimum : float_number wrap -> [> | `Optimum] attrib
329329

@@ -335,21 +335,21 @@ module type T = sig
335335

336336
val a_preload : [< | `None | `Metadata | `Audio] wrap -> [> | `Preload] attrib
337337

338-
val a_pubdate : [> | `Pubdate] attrib
338+
val a_pubdate : unit -> [> | `Pubdate] attrib
339339

340340
val a_radiogroup : text wrap -> [> | `Radiogroup] attrib
341341

342-
val a_required : [> | `Required] attrib
342+
val a_required : unit -> [> | `Required] attrib
343343

344-
val a_reversed : [> | `Reversed] attrib
344+
val a_reversed : unit -> [> | `Reversed] attrib
345345

346346
val a_sandbox : [< | sandbox_token ] list wrap -> [> | `Sandbox] attrib
347347

348348
val a_spellcheck : bool wrap -> [> | `Spellcheck] attrib
349349

350-
val a_scoped : [> | `Scoped] attrib
350+
val a_scoped : unit -> [> | `Scoped] attrib
351351

352-
val a_seamless : [> | `Seamless] attrib
352+
val a_seamless : unit -> [> | `Seamless] attrib
353353

354354
val a_sizes : (number * number) list option wrap -> [> | `Sizes] attrib
355355

@@ -444,7 +444,7 @@ module type T = sig
444444
(** This attribute specifies a form processing agent. User agent
445445
behavior for a value other than an HTTP URI is undefined. *)
446446

447-
val a_checked : [> | `Checked] attrib
447+
val a_checked : unit -> [> | `Checked] attrib
448448
(** When the [type] attribute has the value ["radio"] or
449449
["checkbox"], this boolean attribute specifies that the
450450
button is on. User agents must ignore this attribute for
@@ -485,7 +485,7 @@ module type T = sig
485485
[@@ocaml.deprecated "Use a_method"]
486486
(** @deprecated Use a_method *)
487487

488-
val a_multiple : [> | `Multiple] attrib
488+
val a_multiple : unit -> [> | `Multiple] attrib
489489

490490
val a_name : text wrap -> [> | `Name] attrib
491491
(** This attribute assigns the control name. *)
@@ -497,7 +497,7 @@ module type T = sig
497497
the contents of the control when the contents extend beyond
498498
the visible area. *)
499499

500-
val a_selected : [> | `Selected] attrib
500+
val a_selected : unit -> [> | `Selected] attrib
501501
(** When set, this boolean attribute specifies that
502502
this option is pre-selected. *)
503503

@@ -545,9 +545,9 @@ module type T = sig
545545
val a_float_value : float_number wrap -> [> | `Float_Value] attrib
546546
[@@reflect.attribute "value" ["progress"; "meter"]]
547547

548-
val a_disabled : [> | `Disabled] attrib
548+
val a_disabled : unit -> [> | `Disabled] attrib
549549

550-
val a_readonly : [> | `ReadOnly] attrib
550+
val a_readonly : unit -> [> | `ReadOnly] attrib
551551
val a_button_type :
552552
[< | `Button | `Submit | `Reset] wrap -> [> | `Button_Type] attrib
553553
[@@reflect.attribute "type" ["button"]]
@@ -618,7 +618,7 @@ module type T = sig
618618

619619
val a_http_equiv : text wrap -> [> | `Http_equiv] attrib
620620

621-
val a_defer :[> | `Defer] attrib
621+
val a_defer : unit -> [> | `Defer] attrib
622622

623623
val a_media : mediadesc wrap -> [> | `Media] attrib
624624

ppx/ppx_attribute_value.ml

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,9 @@ let float_exp loc s =
142142
with Failure "float_of_string" ->
143143
None
144144

145-
145+
let bool_exp loc b =
146+
let s = if b then "true" else "false" in
147+
Exp.construct ~loc (Location.mkloc (Longident.Lident s) loc) None
146148

147149
(* Numeric. *)
148150

@@ -172,14 +174,31 @@ let char ?separated_by:_ ?default:_ loc name s =
172174

173175
Some (Exp.constant ~loc (Const_char c))
174176

177+
let onoff ?separated_by:_ ?default:_ loc name s =
178+
let b = match s with
179+
| "" | "on" -> true
180+
| "off" -> false
181+
| _ ->
182+
Ppx_common.error loc {|Value of %s must be "on", "" or "off"|} name
183+
in
184+
Some (bool_exp loc b)
185+
175186
let bool ?separated_by:_ ?default:_ loc name s =
176-
begin
177-
try bool_of_string s |> ignore
178-
with Invalid_argument "bool_of_string" ->
179-
Ppx_common.error loc "Value of %s must be \"true\" or \"false\"" name
180-
end;
187+
let b = match s with
188+
| "" | "true" -> true
189+
| "false" -> false
190+
| _ ->
191+
Ppx_common.error loc {|Value of %s must be "true", "" or "false"|} name
192+
in
193+
Some (bool_exp loc b)
181194

182-
Some (Exp.construct ~loc (Location.mkloc (Longident.parse s) loc) None)
195+
let unit ?separated_by:_ ?default:_ loc name s =
196+
if s = "" || s = name then
197+
Some (Ast_convenience.(with_default_loc loc unit))
198+
else
199+
Ppx_common.error loc
200+
{|Value of %s must be %s or "".|}
201+
name name
183202

184203
let int ?separated_by ?default loc name s =
185204
match int_exp loc s with

ppx/ppx_attribute_value.mli

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,15 @@ val char : parser
9494
a parse tree for [c]. *)
9595

9696
val bool : parser
97-
(** [bool _ _ s] produces a parse tree for the boolean [true] if [s = "true"]
98-
and [false] if [s = "false"]. *)
97+
(** [bool _ _ s] produces a parse tree for the boolean [true]
98+
if [s = "true"] or [""] and [false] if [s = "false"]. *)
99+
100+
val onoff : parser
101+
(** [onoff _ _ s] produces a parse tree for the boolean [true]
102+
if [s = "on"] or [""] and [false] if [s = "off"]. *)
103+
104+
val unit : parser
105+
(** [unit _ name s] produces a parse tree for [()]. It fails if [name <> s]. *)
99106

100107
val int : parser
101108
(** [int _ _ s] produces a parse tree for [int_of_string s]. *)

ppx/ppx_reflect.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,10 @@ let rec to_attribute_parser name = function
9696
[%expr wrap [%e to_attribute_parser name [ty]]]
9797

9898
| [[%type: character]] -> [%expr char]
99+
| [[%type: bool] as ty]
100+
when AC.has_attr "onoff" ty.ptyp_attributes -> [%expr onoff]
99101
| [[%type: bool]] -> [%expr bool]
102+
| [[%type: unit]] -> [%expr nowrap unit]
100103

101104
| [[%type: number]]
102105
| [[%type: pixels]]

test/test_ppx.ml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,42 @@ let basics = "ppx basics", tyxml_tests Html.[
6464

6565
]
6666

67+
let attribs = "ppx attribs", tyxml_tests Html.[
68+
69+
"unit absent",
70+
[[%html "<div hidden></div>"]],
71+
[div ~a:[a_hidden ()] []] ;
72+
73+
"unit present",
74+
[[%html "<div hidden=hidden></div>"]],
75+
[div ~a:[a_hidden ()] []] ;
76+
77+
"bool default",
78+
[[%html "<div draggable></div>"]],
79+
[div ~a:[a_draggable true] []] ;
80+
81+
"bool true",
82+
[[%html "<div draggable=true></div>"]],
83+
[div ~a:[a_draggable true] []] ;
84+
85+
"bool false",
86+
[[%html "<div draggable=false></div>"]],
87+
[div ~a:[a_draggable false] []] ;
88+
89+
"onoff default",
90+
[[%html "<form autocomplete></form>"]],
91+
[form ~a:[a_autocomplete true] []] ;
92+
93+
"bool true",
94+
[[%html "<form autocomplete=on></form>"]],
95+
[form ~a:[a_autocomplete true] []] ;
96+
97+
"bool false",
98+
[[%html "<form autocomplete=off></form>"]],
99+
[form ~a:[a_autocomplete false] []] ;
100+
101+
]
102+
67103
let ns_nesting = "namespace nesting" , tyxml_tests Html.[
68104

69105
"html/svg",
@@ -122,6 +158,7 @@ let antiquot = "ppx antiquot", tyxml_tests Html.[
122158

123159
let tests = [
124160
basics ;
161+
attribs ;
125162
ns_nesting ;
126163
antiquot ;
127164
]

0 commit comments

Comments
 (0)