mirror of
https://github.com/c-cube/tiny_httpd.git
synced 2025-12-06 19:25:32 -05:00
improve html combinators, add if_ flag
This commit is contained in:
parent
5c1a7310ee
commit
b88c8bbda1
2 changed files with 81 additions and 38 deletions
|
|
@ -6,10 +6,10 @@ include Tiny_httpd_html_
|
||||||
@param top if true, add DOCTYPE at the beginning. The top element should then
|
@param top if true, add DOCTYPE at the beginning. The top element should then
|
||||||
be a "html" tag. *)
|
be a "html" tag. *)
|
||||||
let to_string ?(top=false) (self:elt) : string =
|
let to_string ?(top=false) (self:elt) : string =
|
||||||
let buf = Buffer.create 256 in
|
let out = Out.create () in
|
||||||
if top then Printf.bprintf buf "<!DOCTYPE html>\n";
|
if top then Out.add_string out "<!DOCTYPE html>\n";
|
||||||
self buf;
|
self out;
|
||||||
Buffer.contents buf
|
Out.to_string out
|
||||||
|
|
||||||
let to_string_top = to_string ~top:true
|
let to_string_top = to_string ~top:true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -278,34 +278,74 @@ let attrs = [
|
||||||
]
|
]
|
||||||
|
|
||||||
let prelude = {|
|
let prelude = {|
|
||||||
type attribute = string * string
|
(** Output for HTML combinators.
|
||||||
type elt = Buffer.t -> unit
|
|
||||||
type void = attribute list -> elt
|
|
||||||
type nary = attribute list -> elt list -> elt
|
|
||||||
type nary' = attribute list -> (Buffer.t -> unit) -> elt
|
|
||||||
|
|
||||||
let str_escape (buf:Buffer.t) (s:string) : unit =
|
This output type is used to produce a string reasonably efficiently from
|
||||||
|
a tree of combinators. *)
|
||||||
|
module Out : sig
|
||||||
|
type t
|
||||||
|
val create : unit -> t
|
||||||
|
val clear : t -> unit
|
||||||
|
val add_char : t -> char -> unit
|
||||||
|
val add_string : t -> string -> unit
|
||||||
|
val to_string : t -> string
|
||||||
|
end = struct
|
||||||
|
include Buffer
|
||||||
|
let create () = Buffer.create 256
|
||||||
|
let to_string = contents
|
||||||
|
end
|
||||||
|
|
||||||
|
type attribute = string * string
|
||||||
|
(** An attribute, i.e. a key/value pair *)
|
||||||
|
|
||||||
|
type elt = Out.t -> unit
|
||||||
|
(** A html element. It is represented by its output function, so we
|
||||||
|
can directly print it. *)
|
||||||
|
|
||||||
|
type void = ?if_:bool -> attribute list -> elt
|
||||||
|
(** Element without children. *)
|
||||||
|
|
||||||
|
type nary = ?if_:bool -> attribute list -> elt list -> elt
|
||||||
|
(** Element with children, represented as a list.
|
||||||
|
@param if_ if false, do not print anything (default true) *)
|
||||||
|
|
||||||
|
type nary' = ?if_:bool -> attribute list -> (Out.t -> unit) -> elt
|
||||||
|
(** Element with children, represented as a continuation.
|
||||||
|
@param if_ if false, do not print anything (default true) *)
|
||||||
|
|
||||||
|
(** Escape string so it can be safely embedded in HTML text. *)
|
||||||
|
let str_escape (out:Out.t) (s:string) : unit =
|
||||||
String.iter (function
|
String.iter (function
|
||||||
| '<' -> Buffer.add_string buf "<"
|
| '<' -> Out.add_string out "<"
|
||||||
| '>' -> Buffer.add_string buf ">"
|
| '>' -> Out.add_string out ">"
|
||||||
| '&' -> Buffer.add_string buf "&"
|
| '&' -> Out.add_string out "&"
|
||||||
| '"' -> Buffer.add_string buf """
|
| '"' -> Out.add_string out """
|
||||||
| '\'' -> Buffer.add_string buf "'"
|
| '\'' -> Out.add_string out "'"
|
||||||
| c -> Buffer.add_char buf c)
|
| c -> Out.add_char out c)
|
||||||
s
|
s
|
||||||
|
|
||||||
(** Print the value part of an attribute *)
|
(** Print the value part of an attribute *)
|
||||||
let attr_escape buf (s:string) =
|
let attr_escape (out:Out.t) (s:string) =
|
||||||
Buffer.add_char buf '"';
|
Out.add_char out '"';
|
||||||
str_escape buf s;
|
str_escape out s;
|
||||||
Buffer.add_char buf '"'
|
Out.add_char out '"'
|
||||||
|
|
||||||
|
(** Output a list of attributes. *)
|
||||||
|
let write_attrs (out:Out.t ) (l:attribute list) : unit =
|
||||||
|
List.iter
|
||||||
|
(fun (k,v) ->
|
||||||
|
Out.add_char out ' ';
|
||||||
|
Out.add_string out k;
|
||||||
|
Out.add_char out '=';
|
||||||
|
attr_escape out v)
|
||||||
|
l
|
||||||
|
|
||||||
(** Emit a string value, which will be escaped. *)
|
(** Emit a string value, which will be escaped. *)
|
||||||
let txt (txt:string) : elt = fun buf -> str_escape buf txt
|
let txt (txt:string) : elt = fun out -> str_escape out txt
|
||||||
|
|
||||||
(** Emit raw HTML. Caution, this can lead to injection vulnerabilities,
|
(** Emit raw HTML. Caution, this can lead to injection vulnerabilities,
|
||||||
never use with text that comes from untrusted users. *)
|
never use with text that comes from untrusted users. *)
|
||||||
let raw_html (s:string) : elt = fun buf -> Buffer.add_string buf s
|
let raw_html (s:string) : elt = fun out -> Out.add_string out s
|
||||||
|}
|
|}
|
||||||
|
|
||||||
let oname = function
|
let oname = function
|
||||||
|
|
@ -324,10 +364,11 @@ let emit_void name =
|
||||||
let oname = oname name in
|
let oname = oname name in
|
||||||
pf "(** tag %S, see {{:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/%s} mdn} *)\n"
|
pf "(** tag %S, see {{:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/%s} mdn} *)\n"
|
||||||
name name;
|
name name;
|
||||||
pf "let %s : void = fun attrs buf ->\n" oname;
|
pf "let %s : void = fun ?(if_=true) attrs out ->\n" oname;
|
||||||
pf " Buffer.add_string buf \"<%s\";\n" name;
|
pf " if if_ then (\n";
|
||||||
pf " List.iter (fun (k,v) -> Printf.bprintf buf \" %%s=%%a\" k attr_escape v) attrs;\n";
|
pf " Out.add_string out \"<%s\";\n" name;
|
||||||
pf " Buffer.add_string buf \"/>\"";
|
pf " write_attrs out attrs;\n";
|
||||||
|
pf " Out.add_string out \"/>\")";
|
||||||
pf "\n\n";
|
pf "\n\n";
|
||||||
()
|
()
|
||||||
|
|
||||||
|
|
@ -336,24 +377,26 @@ let emit_normal name =
|
||||||
|
|
||||||
pf "(** tag %S, see {{:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/%s} mdn} *)\n"
|
pf "(** tag %S, see {{:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/%s} mdn} *)\n"
|
||||||
name name;
|
name name;
|
||||||
pf "let %s : nary = fun attrs sub buf ->\n" oname;
|
pf "let %s : nary = fun ?(if_=true) attrs sub out ->\n" oname;
|
||||||
pf " Buffer.add_string buf \"<%s\";\n" name;
|
pf " if if_ then (\n";
|
||||||
pf " List.iter (fun (k,v) -> Printf.bprintf buf \" %%s=%%a\" k attr_escape v) attrs;\n";
|
pf " Out.add_string out \"<%s\";\n" name;
|
||||||
pf " Buffer.add_string buf \">\\n\";\n";
|
pf " write_attrs out attrs;\n";
|
||||||
pf " List.iter (fun sub -> sub buf; Buffer.add_char buf '\\n') sub;\n";
|
pf " Out.add_string out \">\\n\";\n";
|
||||||
pf " Buffer.add_string buf \"</%s>\\n\"" name;
|
pf " List.iter (fun sub -> sub out; Out.add_char out '\\n') sub;\n";
|
||||||
|
pf " Out.add_string out \"</%s>\\n\")" name;
|
||||||
pf "\n\n";
|
pf "\n\n";
|
||||||
|
|
||||||
(* block version *)
|
(* block version *)
|
||||||
let oname = oname ^ "'" in
|
let oname = oname ^ "'" in
|
||||||
pf "(** tag %S, see {{:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/%s} mdn} *)\n"
|
pf "(** tag %S, see {{:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/%s} mdn} *)\n"
|
||||||
name name;
|
name name;
|
||||||
pf "let %s : nary' = fun attrs f buf ->\n" oname;
|
pf "let %s : nary' = fun ?(if_=true) attrs f out ->\n" oname;
|
||||||
pf " Buffer.add_string buf \"<%s\";\n" name;
|
pf " if if_ then (\n";
|
||||||
pf " List.iter (fun (k,v) -> Printf.bprintf buf \" %%s=%%a\" k attr_escape v) attrs;\n";
|
pf " Out.add_string out \"<%s\";\n" name;
|
||||||
pf " Buffer.add_string buf \">\\n\";\n";
|
pf " write_attrs out attrs;\n";
|
||||||
pf " f buf;\n";
|
pf " Out.add_string out \">\\n\";\n";
|
||||||
pf " Buffer.add_string buf \"</%s>\\n\"" name;
|
pf " f out;\n";
|
||||||
|
pf " Out.add_string out \"</%s>\\n\")" name;
|
||||||
pf "\n\n";
|
pf "\n\n";
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue