1. Kakadu
  2. ukraine

Commits

Kakadu  committed a363ec2

created buggy compilation example

  • Participants
  • Parent commits 508e51b
  • Branches deps_bug_example

Comments (0)

Files changed (10)

File Makefile

View file
  • Ignore whitespace
 
 CLIENT_LIBS := ${addprefix -package ,${CLIENT_PACKAGES}}
 CLIENT_INC  := ${addprefix -package ,${CLIENT_PACKAGES}}
-CLIENT_FILES += wikicreole.ml
+#CLIENT_FILES += wikicreole.ml
 CLIENT_OBJS := $(filter %.eliom %.ml, $(CLIENT_FILES))
 CLIENT_OBJS := $(patsubst %.eliom,${ELIOM_CLIENT_DIR}/%.cmo, ${CLIENT_OBJS})
 CLIENT_OBJS := $(patsubst %.ml,${ELIOM_CLIENT_DIR}/%.cmo, ${CLIENT_OBJS})

File editevent.eliom

  • Ignore whitespace
-(* Service handler for adding new events.
- * TODO: refactor code to allow editing of events
- *)
-open Printf
-open Types
-
-{shared{
-open Eliom_content.Html5
-open Eliom_content.Html5.F
-type datetime_str = string deriving (Json)
-let add_event_date_input_id = "add_event_date_input"
-let add_event_time_input_id = "add_event_time_input"
-}}
-
-{client{
-open Printf
-open Helpers
-open ClientHelpers
-open Ojquery
-}}
-
-let dummy_service' =
-  Eliom_service.Http.post_coservice  ~fallback:Ukraine_services.view_event_service
-    ~post_params:Eliom_parameter.(string "title"**string "image" ** string "lenta_text" ** string "lenta_url")
-    ()
-
-let update_event_rpc
-  : (eventId_t*string*string*string*datetime_str, unit) Eliom_pervasives.server_function
-  = server_function Json.t<eventId_t*string*string*string*datetime_str>
-    (fun (eventId,title,text,link,datetime_str) ->
-       Events_db.update ~text ~link ~title ~datetime_str ~eventId)
-
-let handler userId (eventId: int64) () : _ Lwt.t =
-  lwt curevent = Events_db.get_by_id eventId in
-
-  let open Eliom_content.Html5.D in
-  let form = post_form ~service:dummy_service' (fun (title,(image,(lenta_text,lenta_url))) ->
-    let title_input = string_input ~a:[a_placeholder "title"; a_class ["add_node_line_input"]]
-        ~name:title ~input_type:`Text ()
-        ~value:curevent.Event.title
-    in
-    let lenta_input = string_input ~a:[a_placeholder "url"; a_class ["add_node_line_input"]]
-        ~name:lenta_url ~input_type:`Url ()
-        ~value:(Helpers.Option.get curevent.Event.link ~default:"")
-    in
-    let text_input = textarea ~a:[a_placeholder "text"; a_class ["edit_event_text_input"]]
-        ~name:lenta_text ()
-        ~value: curevent.Event.text
-    in
-    let date_input = string_input ~name:lenta_text ~input_type:`Text ()
-        ~a:[ a_placeholder "date"; a_class ["datepicker";"add_node_date_input"]
-           ; a_id add_event_date_input_id ]
-        ~value:(string_of_date curevent.Event.datetime)
-    in
-    let time_input = string_input ~name:lenta_text ~input_type:`Text ()
-        ~a:[ a_placeholder "time"; a_class ["timepicker";"add_node_time_input"]
-           ; a_id add_event_time_input_id ]
-        ~value:(string_of_time curevent.Event.datetime)
-    in
-    let submit_clicked = {Dom_html.mouseEvent Js.t -> unit { fun _event ->
-      Dom.preventDefault _event;
-      (* TODO: we need to check that date is >parentDate and  < nextDate *)
-      let title    = (To_dom.of_input %title_input)##value |>  Js.to_string in
-      let text     = (To_dom.of_textarea %text_input)##value |> Js.to_string in (*
-      let image    = (To_dom.of_input %image_input)##value |> Js.to_string in *)
-      let link     = (To_dom.of_input %lenta_input)##value |> Js.to_string in
-      let datetime = sprintf "%s %s"
-         ( (To_dom.of_input %date_input)##value |> Js.to_string )
-         ( (To_dom.of_input %time_input)##value |> Js.to_string )
-      in
-      Lwt.ignore_result begin
-      lwt () = %update_event_rpc (%eventId, title, text, link, datetime) in
-      Eliom_client.exit_to ~service: %Ukraine_services.view_event_service %eventId ();
-      Lwt.return ()
-      end
-    }} in
-
-    [ title_input; br ()
-    ; lenta_input; br ()
-    ; pcdata "Date"; date_input; pcdata "Time";  time_input; br ()
-    ; text_input ; br ()
-    ; string_input ~a:[a_class ["button"]; a_onclick submit_clicked ]
-        ~input_type:`Button ~value:"Update event" ()
-    ]
-    ) userId
-  in
-  let content_div_onload = {Dom_html.event Js.t -> unit { fun _event ->
-    (* I don't do this in input.onload event because by some reason is didn't work for me *)
-    (* TODO: understand how to do it typesafe *)
-    let el = get_element_by_id_exn add_event_date_input_id in
-    let date_params: timepicker_options Js.t =
-      (* International english format *)
-      Js.Unsafe.eval_string "new Object({dateFormat: 'DD-MM-YY'})"
-    in
-
-    el |> jQelt |> (jq_datepicker date_params) |> ignore;
-    let el = get_element_by_id_exn add_event_time_input_id in
-    let time_params: timepicker_options Js.t = Js.Unsafe.obj [||] in
-    time_params##step <- Js.string "5";
-    time_params##timeFormat <- Js.string "H:i:s";
-    el |> jQelt |> (jq_timepicker time_params) |> ignore;
-  }} in
-  let content_div = div ~a:[a_onload content_div_onload] [ form ] in
-
-  Lwt.return (Ukraine_container.page ~user:userId [ content_div ])
-
-let () = Ebapp.App.register Ukraine_services.edit_event_service
-    (Ebapp.Page.connected_page handler)

File edituser.eliom

  • Ignore whitespace
-(* Editing user as moderator
- * toggle switch grabbed from here: http://ghinda.net/css-toggle-switch/
- *)
-{shared{
-open Eliom_content.Html5
-open Eliom_content.Html5.F
-open Types
-open Helpers
-open Printf
-open ClientHelpers
-
-let user_editinfo_div_id = "user_editinfo_div"
-}}
-
-let dummy_edit_user_service =
-  Eliom_service.Http.post_coservice'
-    ~name:"set_data"
-    ~post_params:Eliom_parameter.(int64 "dummyid" ** (string "dummyfn" ** string "dummyln") )
-    ()
-
-let get_user_rpc: (userId_t, Ukraine_user.t) Eliom_pervasives.server_function
-  = server_function Json.t<userId_t> (fun userId -> Ukraine_user.user_of_uid userId)
-
-let update_user:  Ukraine_user.t -> unit Lwt.t =
-  fun {Ukraine_user.fn; Ukraine_user.ln; Ukraine_user.uid; _} ->
-  let open Ukraine_user in
-  (* update fn and ln *)
-  printf "Update user: %s and %s\n%!" ln fn;
-  lwt () = Ukraine_user.update ~firstname:fn ~lastname:ln uid in
-  Lwt.return ()
-
-let update_user_rpc: (Ukraine_user.t,unit) Eliom_pervasives.server_function
-  = server_function Json.t<Ukraine_user.t> update_user
-
-let toggle_moderator_group ~enable ~userId =
-  if enable then Ukraine_groups.set_moderation ~userId
-  else Ukraine_groups.unset_moderation ~userId
-
-let toggle_moderator_group_rpc: (userId_t*bool,unit) Eliom_pervasives.server_function
-  = server_function Json.t<userId_t*bool>
-    (fun (userId,enable) -> toggle_moderator_group ~userId ~enable)
-
-let is_moderator_rpc: (userId_t,bool) Eliom_pervasives.server_function
-  = server_function Json.t<userId_t> (fun userId -> Ukraine_groups.is_moderator ~userId)
-
-{client{
-open Helpers
-let refresh_userinfo ~with_groups userId =
-  Firebug.console##log (Js.string "refresh_user_data");
-  lwt userinfo     = %get_user_rpc userId in
-  lwt is_moderator = %is_moderator_rpc userId in
-  Firebug.console##log (Js.string @@ sprintf "user.fn = %s" userinfo.Ukraine_user.fn);
-  with_element_by_id_exn user_editinfo_div_id ~ok:(fun el ->
-    let form = post_form ~a:[a_class ["user_editinfo_form"]] ~service: %dummy_edit_user_service
-	 (fun (id,(fnname,lnname)) ->
-      let open Eliom_content.Html5.D in
-      let input_fn = string_input ~a:[a_class["user_editinfo_lastname"]] ~name:fnname ~input_type:`Text
-	  ~value: userinfo.Ukraine_user.fn () in
-      let input_ln = string_input ~a:[a_class["user_editinfo_lastname"]] ~name:lnname ~input_type:`Text
-	  ~value: userinfo.Ukraine_user.ln () in
-      let apply_clicked _ =
-	let fn = (To_dom.of_input input_fn)##value |> Js.to_string in
-	let ln = (To_dom.of_input input_ln)##value |> Js.to_string in
-        Firebug.console##log (Js.string @@ sprintf "update clicked for %s ans %s" fn ln);
-        %update_user_rpc Ukraine_user.({uid=userId; fn; ln; avatar=None}) |> Lwt.ignore_result;
-      in
-
-      let apply_btn = div ~a:[ a_class ["button"; "user_editinfo_apply_btn"]
-			     ; a_onclick apply_clicked ]         [pcdata "Apply"] in
-      [ label ~a:[a_for fnname] [pcdata "First name"]; input_fn; br ()
-      ; label ~a:[a_for lnname] [pcdata "Last name"];  input_ln; br ()
-      ; apply_btn
-      ]
-    ) () in
-    let roles_switch = match with_groups with
-      | true ->
-	let set_user_role_clicked _ =
-          Firebug.console##log (Js.string "set role = user");
-	  Lwt.ignore_result (%toggle_moderator_group_rpc (userId,false))
-        in
-	let set_moder_role_clicked _ =
-          Firebug.console##log (Js.string "set role = moder");
-          Lwt.ignore_result (%toggle_moderator_group_rpc (userId,true))
-	in
-        div ~a:[a_class ["user_editinfo_roles_div"]] [
-          div ~a:[a_class ["switch-toggle";"switch-candy"]]
-          [ input ~a:([a_id "user_role"; a_name "view"] @
-		      (if not is_moderator then [a_checked `Checked] else []))
-              ~input_type:`Radio ()
-          ; Unsafe.node "label" ~a:[ Unsafe.string_attrib "for" "user_role"
-				   ; a_onclick set_user_role_clicked] [pcdata "User"]
-
-          ; input ~a:([a_id "moder_role"; a_name "view"] @
-                      (if is_moderator then [a_checked `Checked] else []))
-              ~input_type:`Radio ()
-          ; Unsafe.node "label" ~a:[ Unsafe.string_attrib "for" "moder_role"
-				   ; a_onclick set_moder_role_clicked] [pcdata "Moderator"]
-          ; Unsafe.node "a" []
-          ]
-        ]
-      | false -> div []
-    in
-    (* Some shit here: form and roles div don't want to be stacked horizontally *)
-    Manip.replaceChildren (el |> Of_dom.of_element) [div [roles_switch;br();form]]
-  ) ~bad:(fun id -> Firebug.console##warn (Js.string @@ sprintf "can't get element by id '%s'" id));
-
-  Lwt.return ()
-
-}}
-
-let view_handler (moderatorId: userId_t) (userId: userId_t) () =
-  lwt user = Ukraine_user.user_of_uid userId in
-
-  let refresh_userinfo_btn_clicked = { Dom_html.mouseEvent Js.t -> unit { fun _event ->
-      Dom.preventDefault _event;
-      Lwt.ignore_result @@ refresh_userinfo ~with_groups:true %userId
-  }} in
-  let onload_userinfo_div = { Dom_html.event Js.t -> unit { fun _ ->
-      Lwt.ignore_result @@ refresh_userinfo ~with_groups:true %userId;
-  }} in
-
-  let content_div =
-    div ~a:[a_class ["user_editinfo_div_parent"]]
-      [ div ~a:[a_class ["user_editinfo_refresh_btn"]; a_onclick refresh_userinfo_btn_clicked]
-          [ dummy_img() ]
-      ; br ()
-      ; div ~a:[a_id user_editinfo_div_id; a_onload onload_userinfo_div] []
-      ; br ()
-      ]
-  in
-
-  Lwt.return (Ukraine_container.page ~user:moderatorId [
-    content_div
-  ])
-
-let profile_handler (userId: userId_t) () () =
-  let refresh_userinfo_btn_clicked = { Dom_html.mouseEvent Js.t -> unit { fun _event ->
-      Dom.preventDefault _event;
-      Lwt.ignore_result @@ refresh_userinfo ~with_groups:false %userId
-  }} in
-  let onload_userinfo_div = { Dom_html.event Js.t -> unit { fun _ ->
-      Lwt.ignore_result @@ refresh_userinfo ~with_groups:false %userId;
-  }} in
-
-  let content_div =
-    div ~a:[a_class ["user_editinfo_div_parent"]]
-      [ div ~a:[a_class ["user_editinfo_refresh_btn"]; a_onclick refresh_userinfo_btn_clicked]
-          [ dummy_img() ]
-      ; br ()
-      ; div ~a:[a_id user_editinfo_div_id; a_onload onload_userinfo_div] []
-      ; br ()
-      ]
-  in
-
-  Lwt.return @@ Ukraine_container.page ~user:userId [ content_div ]
-
-(* TODO: we should check that moderator can't edit its own profile there *)
-let () = Ebapp.App.register Ukraine_services.edit_user_service
-    (Ebapp.Page.connected_page ~fallback:LoginError.page  view_handler)
-
-let () = Ebapp.App.register Ukraine_services.edit_profile_service
-    (Ebapp.Page.connected_page ~fallback:LoginError.page profile_handler)

File smartadd.eliom

  • Ignore whitespace
-(* Adding new events in smart way: enter the date and it will decide where to place it
- *)
-{shared{
-open Printf
-open Types
-open Helpers
-open Eliom_content.Html5
-open Eliom_content.Html5.F
-
-let add_event_date_input_id = "add_event_date_input"
-let add_event_time_input_id = "add_event_time_input"
-let smart_add_btn_id = "smart_add_btn"
-let smart_add_message_text_id = "smart_add_message_text"
-}}
-
-{client{
-open ClientHelpers
-open Ojquery
-open Firebug
-
-let curParent: int64 option ref  = ref None
-}}
-
-let dummy_service' =
-  Eliom_service.Http.post_coservice  ~fallback:Ukraine_services.view_event_service
-    ~post_params:Eliom_parameter.
-                   (string "title"**string "image" ** string "lenta_text" ** string "lenta_url")
-    ()
-
-let insert_event_rpc
-  : (eventId_t*string*string*string*string,eventId_t) Eliom_pervasives.server_function
-  = server_function Json.t<eventId_t*string*string*string*string>
-    (fun (parentId,title,text,link,datetime_str) ->
-       Events_db.insert_after ~text ~link ~title ~datetime_str ~parentId)
-
-let find_position2_rpc
-  : (timeline_t*string, Types.Event.t option * Types.Event.t option) Eliom_pervasives.server_function
-  = server_function Json.t<timeline_t*string>
-    (fun (tlid,s) -> Events_db.find_position_by_datetime_2 tlid s)
-
-
-let handler userId tlid () : _ Lwt.t =
-  let () =
-    try ignore (Types.timeline_of_id tlid)
-    with _ -> raise (Failure "Bad timeline id")
-  in
-
-  let open Eliom_content.Html5.D in
-  let form = post_form ~service:dummy_service' (fun (title,(image,(lenta_text,lenta_url))) ->
-    let datetime_changed = {Dom_html.event Js.t  -> unit{ fun _ ->
-      let date: Dom_html.inputElement Js.t =
-        Js.Unsafe.coerce (get_element_by_id_exn %add_event_date_input_id) in
-      let time: Dom_html.inputElement Js.t =
-        Js.Unsafe.coerce (get_element_by_id_exn %add_event_time_input_id) in
-      let text_block = get_element_by_id_exn %smart_add_message_text_id in
-      let prev_desc  = get_element_by_id_exn "smart_add_event_prev_desc" in
-      let next_desc  = get_element_by_id_exn "smart_add_event_next_desc" in
-      let update_desc ~msg el event =
-        let xs = match event with
-          | Some e ->
-            [ pcdata msg; br ()
-            ; pcdata @@ sprintf "Id    = %Ld" e.Event.id; br ()
-            ; pcdata @@ sprintf "Title = %s" e.Event.title; br ()
-            ; pcdata @@ sprintf "When  = %s" (string_of_calendar e.Event.datetime); br ()
-            ]
-          | None -> []
-        in
-        Manip.replaceChildren (Of_dom.of_element el) xs
-      in
-      let open Ojquery in
-      (try_lwt
-        let s = sprintf "%s %s" (Js.to_string date##value) (Js.to_string time##value) in
-        console##log (Js.string s);
-        let _ = calendar_of_string s in
-        (
-         lwt (l,r) = %find_position2_rpc (timeline_of_id %tlid,s) in
-         curParent := (match l with Some x -> Some x.Event.id | None -> None);
-         update_desc ~msg:"PREV" prev_desc l;
-         update_desc ~msg:"NEXT" next_desc r;
-         Lwt.return ()
-        )
-      with
-      | exc ->
-        console##log_2 (Js.string @@ Exn.to_string exc, Js.string "datetime changed");
-        Lwt.return ()
-      )  |> Lwt.ignore_result;
-      let () = match !curParent with
-        | Some id -> text_set (jQelt text_block) "OK" |> ignore
-        | None -> text_set (jQelt text_block) "wrong date time" |> ignore
-      in
-      ()
-    }} in
-    let date_input = string_input ~name:lenta_text ~input_type:`Text ()
-                                  (*~value:("14-03-2014") *)
-        ~a:[ a_placeholder "date"; a_class ["datepicker";"add_node_date_input"]
-           ; a_id add_event_date_input_id; a_onchange datetime_changed ]
-    in
-    let time_input = string_input ~name:lenta_text ~input_type:`Text ()
-                                  (* ~value:("00:20:00") *)
-        ~a:[ a_placeholder "time"; a_class ["timepicker";"add_node_time_input"]
-           ; a_id add_event_time_input_id; a_onchange datetime_changed  ]
-    in
-
-    let title_input = string_input ~a:[a_placeholder "title"; a_class ["add_node_line_input"]]
-        ~name:title ~input_type:`Text () in
-    let lenta_input = string_input ~a:[a_placeholder "url"; a_class ["add_node_line_input"]]
-        ~name:lenta_url ~input_type:`Url () in
-    let text_input = textarea ~a:[a_placeholder "text"; a_class ["smart_add_textarea"]]
-        ~name:lenta_text ()
-    in
-    let submit_clicked = {Dom_html.mouseEvent Js.t -> unit { fun _event ->
-      Dom.preventDefault _event;
-
-      let title    = (To_dom.of_input %title_input)##value |>  Js.to_string in
-      let text     = (To_dom.of_textarea %text_input)##value |> Js.to_string in
-      let link     = (To_dom.of_input %lenta_input)##value |> Js.to_string in
-      let datetime = sprintf "%s %s"
-         ( (To_dom.of_input %date_input)##value |> Js.to_string )
-         ( (To_dom.of_input %time_input)##value |> Js.to_string )
-      in
-      Lwt.ignore_result begin
-      let parentId = Option.get_exn !curParent in
-      lwt newId = %insert_event_rpc (parentId, title, text, link, datetime) in
-      Eliom_client.exit_to ~service: %Ukraine_services.view_event_service newId ();
-      Lwt.return ()
-      end
-    }} in
-
-    [ pcdata "Date"; date_input; br ()
-    ; pcdata "Time"; time_input; br ()
-    ; div ~a:[a_id smart_add_message_text_id] [pcdata ""]; br ()
-    ; title_input; br ()
-    ; lenta_input; br ()
-    ; text_input ; br ()
-    ; string_input ~a:[a_class ["button"]; a_id smart_add_btn_id; a_onclick submit_clicked ]
-        ~input_type:`Button ~value:"Add new node" ()
-    ]
-    ) userId
-  in
-  let content_div_onload = {Dom_html.event Js.t -> unit { fun _event ->
-    (* I don't do this in input.onload event because by some reason is didn't work for me *)
-    (* TODO: understand how to do it typesafe *)
-    let el = get_element_by_id_exn add_event_date_input_id in
-    let date_params: datepicker_options Js.t = Js.Unsafe.obj [||] in
-    date_params##dateFormat <- Js.string "dd-mm-yy";
-    el |> jQelt |> (jq_datepicker date_params) |> ignore;
-
-    let el = get_element_by_id_exn add_event_time_input_id in
-    let time_params: timepicker_options Js.t =
-      Js.Unsafe.eval_string "new Object({step: 5, timeFormat: 'H:i:s'})" in
-    el |> jQelt |> (jq_timepicker time_params) |> ignore;
-  }} in
-  let content_div = div ~a:[a_onload content_div_onload]
-    [ div ~a:[a_class  ["float-left"]; a_id "smart_add_event_prev_desc"] []
-    ; div ~a:[a_class ["float-right"]; a_id "smart_add_event_next_desc"] []
-    ; form
-    ]
-  in
-
-  Lwt.return (Ukraine_container.page ~user:userId [
-    content_div
-  ])
-
-let () = Ebapp.App.register Ukraine_services.smart_add_service
-    (Ebapp.Page.connected_page ~fallback:LoginError.page handler)

File treeview.eliom

  • Ignore whitespace
-(* There you can find service which draws in pretty tree-like structure
- * My goal is to create web-page with easy navigation over timeline.
- *)
-
-open Helpers
-open Printf
-open Types
-
-{shared{
-  open Eliom_content.Html5
-  open Eliom_content.Html5.F
-}}
-
-let tree_view_handler userId startEventId () =
-  lwt nodes = Events_db.event_chain startEventId in
-
-  let cell_width = 230 in
-  let make_cell o x y =
-    div ~a:[ a_style @@ sprintf "top: %dpx; left: %dpx;" (cell_width*y) (cell_width*x)
-	   ; a_class ["tree_node_holder"] ]
-      [ div ~a:[a_class ["tree_node_text"]]           [pcdata o.Event.title]
-      ; a ~a:[a_class ["tree_node_more_info_link"]] ~service:Ukraine_services.view_event_service
-	  [pcdata "more info"] o.Event.id
-      ; a ~a:[a_class ["tree_node_center_link"]] ~service:Ukraine_services.tree_view_service
-	  [pcdata "Center"] o.Event.id
-      ]
-  in
-  let content_div =
-    div
-      [ pcdata "depth = 4"
-      ; br ()
-      ; div ~a:[ a_class ["tree_nodes_holder"]; a_style @@ sprintf "height: %dpx;" cell_width]
-	  (List.mapi nodes ~f:(fun i o -> make_cell o i 0))
-      ]
-  in
-
-  Lwt.return (Ukraine_container.page ~user:userId  [
-    content_div
-  ])
-
-
-
-let () =
-  Ebapp.App.register
-    (Ukraine_services.tree_view_service)
-    (Ebapp.Page.connected_page ~fallback:LoginError.page tree_view_handler)
-
-
-

File view.eliom

  • Ignore whitespace
-(* There you will find page for full description of node in timeline.
- * Below the description some space for user's comments to the node
- * should be.
- *)
-
-{shared{
-  open Eliom_content.Html5
-  open Eliom_content.Html5.F
-  open Printf
-  open Helpers
-  open Types
-
-  let (>|=) = Lwt.(>|=)
-}}
-
-{client{
-open ClientHelpers
-open Ojquery
-
-let _bad id = Firebug.console##log (Js.string @@ sprintf "Can't get element by id '%s'" id)
-let prompt_line ?text ~title ~ok =
-  let ans = Dom_html.window##prompt
-    (Js.string title, Js.string @@ match text with Some x -> x | None -> "") in
-    Js.Opt.iter ans (fun text -> ok (Js.to_string text))
-
-}}
-
-
-let dummy_add_comment_service = Eliom_service.Http.post_coservice'
-  ~name:"set_data"
-  ~post_params:(Eliom_parameter.(int64 "id" ** string "text")) ()
-
-{shared{
-type operation_mode = [ `Guest | `User of int64 | `Moderator of int64 ]
-let event_comments_real_holder_id = "event_comments_real_holder_id"
-let event_description_holder_id   = "event_description_holder"
-}}
-
-let add_comment_rpc
-  : (userId_t*eventId_t*(commentId_t option)*string, bool) Eliom_pervasives.server_function
-  = server_function Json.t<userId_t*eventId_t*(commentId_t option)*string>
-    (fun (userId, nodeId, commentId, text) ->
-       match commentId with
-       | Some parentId ->
-         printf "adding comment by %Ld to node %Ld as subcomment of %Ld with text '%s'\n%!"
-           userId nodeId parentId text;
-         lwt () = Comments_db.insert_subcomment ~text ~nodeId ~parentId ~userId in
-         Lwt.return true
-       | None          ->
-         lwt () = Comments_db.insert_comment ~text ~nodeId ~userId in
-         Lwt.return true
-    )
-
-let comments_for_node_rpc
-  : (eventId_t, CommentWithUINFO.t list) Eliom_pervasives.server_function
-  = server_function Json.t<eventId_t> Comments_db.comment_data_for_event
-
-{client{
-let refresh_comments_data () =
-  with_element_by_id_exn "refresh_comments_btn" ~ok:(fun ddd -> ddd |> jQelt |> click |> ignore)
-    ~bad:_bad
-
-let add_comment_client ~userId ~eventId ~commentId ~text =
-  lwt res = %add_comment_rpc (userId, eventId, commentId, Js.to_string text) in
-  let () = refresh_comments_data () in
-  Lwt.return res
-
-let make_comment_div ~mode ~eventId padding (o: CommentWithUINFO.t) =
-  let open Eliom_content.Html5.D in
-  let comment_id = o.CommentWithUINFO.id in
-  let comment_div_id = sprintf "node-comment-%Ld" comment_id in
-
-  let answer_form_div = div ~a:[a_class ["node_comment_reply_block"]; a_style "display: none;"]
-    [ post_form ~service: %dummy_add_comment_service (fun (id,text) ->
-       let area = textarea ~a:[a_class ["node_comment_reply_textarea"]] ~name:text
-	 ~value:"comment text here" () in
-       let btn = match mode with
-         | `Moderator user
-         | `User user ->
-           let add_comment_clicked _event =
-             Dom.preventDefault _event;
-             let jsarea = To_dom.of_textarea area in
-             let text = jsarea##value in
-             Firebug.console##log (text);
-             let userId = user.Ukraine_user.uid in
-             begin
-             lwt res = add_comment_client ~userId ~eventId ~commentId:(Some comment_id) ~text in
-             if not res then Firebug.console##log (Js.string "can't add comment")
-             else jsarea##value <- Js.string "";
-             Lwt.return ()
-             end |> Lwt.ignore_result
-           in
-           raw_input ~a:[a_onclick add_comment_clicked] ~input_type:`Submit ~value:"Comment" ()
-         | `Guest -> div []
-       in
-       [ area
-       ; int64_input ~input_type:`Hidden ~name:id ~value:comment_id ()
-       ; btn
-       ]) ()
-    ]
-  in
-  let reply_btn = match mode with
-    | `User user
-    | `Moderator user ->
-      let reply_clicked _ =
-          Firebug.console##log (Js.string @@ sprintf "reply on comment %Ld" comment_id);
-          Manip.SetCss.display answer_form_div "block";
-          Firebug.console##log (Js.string @@ sprintf "reply on comment %Ld" comment_id);
-      in
-      div ~a:[a_class ["button";"node_comment_reply_btn"]; a_onclick reply_clicked]
-		[pcdata "Reply"]
-    | `Guest -> div []
-  in
-  let comment_header =
-    let nick = sprintf "%s %s" o.CommentWithUINFO.fn o.CommentWithUINFO.ln in
-    div ~a:[a_class ["node_comment_header"]]
-      [ div ~a:[a_class ["node_comment_avatar"]]
-	  [ img ~src:(Xml.uri_of_string Consts.no_image_url) ~alt:"alt" () ]
-      ; div ~a:[a_class ["node_comment_nick"]] [pcdata nick]
-      ]
-  in
-  div ~a:[ a_style @@ sprintf "margin-left: %dpx;" (30*padding)
-	 ; a_id comment_div_id; a_class ["node_comment"]
-	 ]
-      [ div ~a:[a_class ["node_comment_holder"]]
-          (* comment static data here *)
-	  [ comment_header
-	  ; div ~a:[a_class ["node_comment_text"]]  [ pcdata o.CommentWithUINFO.text ]
-	  ; reply_btn
-	  ]
-      ; answer_form_div
-      ]
-
-let generate_comments_divs ~mode ~eventId comments : _ elt list =
-  let (tree, non_parsed_part) = Path.make_tree_of_nodes (fun o -> o.CommentWithUINFO.path) comments in
-
-  let rec to_divs acc depth : CommentWithUINFO.t Path.tree -> _ elt list = function
-    | Path.Node (x,xs) ->
-       let r = make_comment_div ~mode ~eventId depth x in
-       List.fold_left ~init:(r::acc) xs ~f:(fun acc node -> to_divs acc (depth+1) node )
-  in
-  List.concat (List.map (List.rev tree) ~f:(to_divs [] 0 ) ) |> List.rev
-
-}}
-
-
-let questions_and_options_rpc
-    : (eventId_t, Types.Question.t list) Eliom_pervasives.server_function
-  = server_function Json.t<eventId_t> Events_db.questions_with_options_of_nodeId
-
-let get_node_by_id_rpc : (eventId_t, Types.Event.t) Eliom_pervasives.server_function
-  = server_function Json.t<eventId_t> Events_db.event_by_id
-
-let get_event_by_pos_rpc : (int64*timeline_t, Types.Event.t option) Eliom_pervasives.server_function
-  = server_function Json.t<int64*timeline_t> (fun (p,id) -> Events_db.get_by_pos p id)
-
-let add_question_rpc: (eventId_t*string, bool) Eliom_pervasives.server_function
-  = server_function Json.t<eventId_t*string>
-    (fun (nodeId,text) -> Events_db.insert_question ~nodeId ~text)
-
-let remove_question_rpc: (questionId_t, bool) Eliom_pervasives.server_function
-  = server_function Json.t<questionId_t> (fun questionId -> Events_db.remove_question ~questionId)
-
-let remove_event_rpc
-  : (int64, int64) Eliom_pervasives.server_function
-  = server_function Json.t<int64> Events_db.remove_and_get_prev
-
-let add_option_rpc: (optionId_t*string, bool) Eliom_pervasives.server_function
-  = server_function Json.t<optionId_t*string>
-    (fun (questionId,text) -> Events_db.insert_option ~questionId ~text)
-
-let remove_option_rpc: (optionId_t, bool) Eliom_pervasives.server_function
-  = server_function Json.t<optionId_t> (fun optionId -> Events_db.remove_option ~optionId)
-
-let get_user_by_id_rpc : (int64, Ukraine_user.t) Eliom_pervasives.server_function
-  = server_function Json.t<int64> Ukraine_user.by_id
-
-let is_moderator_rpc : (int64, bool) Eliom_pervasives.server_function
-  = server_function Json.t<int64> (fun userId -> Ukraine_groups.is_moderator ~userId)
-
-{client{
-
-let make_question_div ~refresh ~ismoderator ~eventId q =
-  let remove_question_onclicked = fun _event ->
-    Dom.preventDefault _event;
-    Firebug.console##log (Js.string "remove_question_onclicked");
-    let do_confirm = Dom_html.window##confirm (Js.string "Really remove question and its interpretations?")  in
-    if Js.to_bool do_confirm then
-    begin
-    lwt (_:bool) = %remove_question_rpc q.Question.id in
-    refresh eventId;
-    Lwt.return ()
-    end |> Lwt.ignore_result
-  in
-
-  let add_option_clicked = fun _event ->
-      Dom.preventDefault _event;
-      Firebug.console##log (Js.string "add_option_onclicked");
-      prompt_line ~title:"Enter new option text" ~text:"" ~ok:begin fun text ->
-	Firebug.console##log (Js.string @@ sprintf  "your option value =  '%s'" text);
-        (lwt res = %add_option_rpc (q.Question.id, text) in
-	 let () = if res then begin
-           Firebug.console##log (Js.string "Added new option");
-           refresh eventId;
-         end else
-           Firebug.console##error (Js.string "Server can't add option ");
-         in
-         Lwt.return ()
-	) |> Lwt.ignore_result
-       end;
-      ()
-  in
-  let make_option_div (cid,text) =
-    let remove_option_clicked = fun _event ->
-      Dom.preventDefault _event;
-      Firebug.console##log (Js.string "remove_option_onclicked");
-      begin
-	lwt (_:bool) = %remove_option_rpc cid in
-        refresh eventId;
-        Lwt.return ()
-      end |> Lwt.ignore_result
-    in
-    div ~a:[a_class ["question_option_div"]]
-      (if not ismoderator then [pcdata text]
-       else
-         [ pcdata text
-         ; dummy_img ~a:[a_onclick remove_option_clicked;
-		         a_class ["remove_option_btn"]; a_title "Remove option"] ()
-         ]
-      )
-  in
-  let buttons = div ~a:[a_class ["question_buttons_div"]] (if not ismoderator then [] else
-        [ dummy_img ~a:[a_onclick remove_question_onclicked; a_class ["remove_question_btn"];
-			a_title "Remove question"] ()
-        ; dummy_img ~a:[ a_onclick add_option_clicked
-                       ; a_class ["add_option_btn"]; a_title "Add new option"] ()
-        ])
-  in
-  Lwt.return @@
-    div ~a:[a_class ["question_div"]]
-        [ dummy_img ~a:[a_class ["question_icon_img"]] ()
-        ; div ~a:[a_class ["question_div_text"]] [pcdata q.Question.text]
-        ; buttons
-        ; br ()
-        ; div ~a:[a_class ["question_options_div"]] (List.map q.Question.options ~f:make_option_div)
-        ; hr ()
-        ]
-
-}}
-
-
-{client{
-(* we don't use Str module because missing primitives *)
-let make_description s =
-  [Of_dom.of_div @@ Wiki_syntax.xml_of_wiki s]
-
-let rec refresh_event_data ~mode eventId = Lwt.ignore_result begin
-  Firebug.console##log (Js.string @@ sprintf "refresh_event_data id=%Ld" eventId);
-
-  lwt curnode = %get_node_by_id_rpc eventId in
-  lwt questions = %questions_and_options_rpc eventId in
-  let ismoderator = match mode with `Moderator _ -> true | _ -> false in
-
-  lwt question_divs =
-    questions
-    |> List.map ~f:(make_question_div ~ismoderator ~refresh:(refresh_event_data ~mode) ~eventId)
-    |> Lwt_list.map_p (fun x -> x)
-  in
-
-  with_element_by_id_exn %event_description_holder_id ~ok:(fun el ->
-    let nodes =
-	[ div ~a:[a_class ["view_event_title"]] [pcdata @@ curnode.Event.title]
-	; br ()
-	; div ~a:[a_class ["view_event_description"]]
-	     (make_description curnode.Event.text)
-        ; hr ()
-        ; div ~a:[a_class ["view_event_original_link_holder"]]
-                 (match curnode.Event.link with
-                  | Some link when String.length link > 0 ->
-                    [Unsafe.node "a" ~a:[a_href @@ Xml.uri_of_string link]
-                       [pcdata "Link to original news"]]
-                  | _ -> []
-                 )
-        ; hr ()
-        ; div ~a:[a_class ["questions_block"]] question_divs
-	]
-      in
-      Manip.replaceChildren (el |> Of_dom.of_element) nodes
-  ) ~bad:_bad;
-  Lwt.return ()
-end
-
-}}
-
-let make_event_links ~ismoderator ~eventId ~nextEventId ~prevEventId tlsort message_div xs =
-  let f ev =
-    div ~a:[a_class @@ if ev.Event.id=eventId then ["view_event_selected_event"] else []]
-      [ a ~a:[a_class ["event_view_link"]] ~service:Ukraine_services.view_event_service
-	  [pcdata ev.Event.title] ev.Event.id
-      ; br ()
-      ; div ~a:[a_class ["event_view_link_time"]] [pcdata @@ string_of_time ev.Event.datetime]
-      ; br ()
-      ]
-  in
-
-  let d = div ~a:[a_class ["view_event_links_heading"]]
-      [ (match prevEventId with
-        | Some id ->
-          a ~a:[a_class ["view_event_prev_day"]] ~service:Ukraine_services.view_event_service
-	    [dummy_img ()] id
-        | None  -> div ~a:[a_class ["view_event_prev_day_unclickable"]] [dummy_img ()])
-      ; message_div
-      ; (match nextEventId with
-        | Some id ->
-          a ~a:[a_class ["view_event_next_day"]] ~service:Ukraine_services.view_event_service
-	    [dummy_img ()] id
-        | None  -> div ~a:[a_class ["view_event_next_day_unclickable"]] [dummy_img ()])
-      ]
-  in
-  Lwt.return @@ div ~a:[a_class ["event_view_links_holder"]]
-    ( d :: (List.map ~f xs) )
-
-let handler mode (eventId: eventId_t) () =
-  let ismoderator = match mode with `Moderator _ -> true | _ -> false in
-  lwt event = Events_db.get_by_id eventId  in
-  let tlsort = timeline_of_id event.Event.timelineId in
-  let date = CalendarLib.Calendar.(to_date event.Event.datetime) in
-  let dd = CalendarLib.Date.(day_of_month date) in
-  let mm = CalendarLib.Date.(int_of_month @@ month date) in
-  let yy = CalendarLib.Date.(year date) in
-  lwt events = Events_db.by_date tlsort ~yy ~dd ~mm in
-
-  (* next two ids are used to make navigation links (back/forward) *)
-  lwt (nextEventId,prevEventId) =
-    match events with
-    | [] -> Lwt.return (None,None)
-    | xs ->
-      let right = List.hd_exn events in (* Right on the top *)
-      lwt next =
-          Events_db.get_by_pos Int64.(add 1L right.Event.position) tlsort
-          >|= Helpers.Option.map ~f:(fun x -> x.Event.id)
-      in
-      (* Left event is drawn on the bottom *)
-      let left  = List.last_exn events in
-      lwt prev =
-        if left.Event.id = timeline_start_event tlsort then Lwt.return None
-        else
-            Events_db.get_by_pos Int64.(sub left.Event.position 1L) tlsort
-            >|= Helpers.Option.map ~f:(fun x -> x.Event.id)
-      in
-      Lwt.return (next,prev)
-  in
-
-  let comments_holder =
-    let node_comments_real_holder =
-      let refresh_onload = {Dom_html.event Js.t -> unit { fun _ -> refresh_comments_data () }} in
-      D.div ~a:[ a_class ["node_comments_real_holder"]; a_id event_comments_real_holder_id
-               ; a_onload refresh_onload] []
-    in
-    let refresh_clicked = {Dom_html.mouseEvent Js.t -> unit { fun _ ->
-        Firebug.console##log (Js.string "refresh comments clicked");
-        Lwt.ignore_result (
-          lwt comments = %comments_for_node_rpc %eventId in
-          lwt mode = match %mode with
-            | `Guest -> Lwt.return `Guest
-            | `User uid      -> %get_user_by_id_rpc uid >|= (fun u -> `User u)
-            | `Moderator uid -> %get_user_by_id_rpc uid >|= (fun u -> `Moderator u)
-          in
-          let eventId = %eventId in
-	  let divs = generate_comments_divs ~mode ~eventId comments in
-	  Manip.removeChildren %node_comments_real_holder;
-          Manip.appendChildren %node_comments_real_holder divs;
-          Lwt.return ()
-        )
-    }} in
-    let refresh_button = div [pcdata "Refresh comments"]
-      ~a:[a_class ["button"]; a_id "refresh_comments_btn"; a_onclick refresh_clicked ]
-    in
-    div ~a:[a_class ["node_comments_holder"]]
-	[div ~a:[a_class ["node_comments_holder1"]] [refresh_button]
-	; hr ()
-	; node_comments_real_holder
-	]
-  in
-
-  let onload_event_description_div = {Dom_html.event Js.t -> unit{ fun _ ->
-    refresh_event_data ~mode: %mode %eventId;
-  }} in
-  let refresh_event_data_btn_clicked = {Dom_html.mouseEvent Js.t -> unit{ fun _event ->
-    Dom.preventDefault _event;
-    refresh_event_data ~mode: %mode %eventId
-  }} in
-
-  let event_comment_root_block = match mode with
-    | `Moderator userId
-    | `User userId ->
-      div ~a:[a_class ["node_comment_root_reply_block"]]
-	[ post_form ~service:dummy_add_comment_service (fun (id,text) ->
-            let open Eliom_content.Html5.D in
-            let area = textarea ~a:[a_class ["node_comment_root_reply_textarea"]]
-	        ~name:text ~value:"comment text here" () in
-            let add_comment_onclick = {Dom_html.mouseEvent Js.t -> unit { fun _event ->
-              Dom.preventDefault _event;
-              let jsarea = To_dom.of_textarea %area in
-              let text = jsarea##value in
-              Firebug.console##log (text);
-              begin
-              lwt res = add_comment_client ~userId:%userId ~eventId:%eventId ~text ~commentId:None in
-              if not res then Firebug.console##log (Js.string "Can't add comment")
-              else jsarea##value <- Js.string "";
-              Lwt.return ()
-              end |> Lwt.ignore_result
-            }} in
-            [ div ~a:[a_style "float: left;"] [pcdata "Comment node:"]
-	    ; br ()
-	    ; area
-	    ; br ()
-	    ; raw_input ~a:[a_onclick add_comment_onclick; a_class ["node_comment_root_submit_btn"]]
-                ~input_type:`Submit ~value:"Comment" ()
-	    ]) ()
-        ]
-    | `Guest -> div []
-  in
-
-  let add_question_btn_clicked = {Dom_html.mouseEvent Js.t -> unit{ fun _event ->
-    Dom.preventDefault _event;
-    prompt_line ~title:"Enter new question" ~text:"" ~ok:begin fun text ->
-      Firebug.console##log (Js.string @@ sprintf  "your value %s" text);
-      (lwt res = %add_question_rpc (%eventId, text) in
-      let () = if res then begin
-        Firebug.console##log (Js.string "Added");
-        refresh_event_data ~mode: %mode %eventId;
-      end else begin
-        Firebug.console##error (Js.string "Server can't add question");
-      end in
-      Lwt.return ()) |> Lwt.ignore_result
-    end
-  }} in
-  let delete_event_btn_clicked = {Dom_html.mouseEvent Js.t -> unit{ fun _event ->
-    Dom.preventDefault _event;
-    match %mode with
-    | `Guest  -> Firebug.console##error (Js.string "guests can't remove events")
-    | `User _ -> Firebug.console##error (Js.string "Simple users can't remove events")
-    | `Moderator _ ->
-      (lwt prev = %remove_event_rpc %eventId in
-       Lwt.return @@ Eliom_client.exit_to ~service: %Ukraine_services.view_event_service prev ()
-      ) |> Lwt.ignore_result
-  }} in
-
-  let buttons_bar =
-    let make_btn ?title onclick clas =
-      let classes = match title with
-        | Some  _ -> [clas;"need_tooltip"]
-        | None    -> [clas]
-      in
-      let a = match title with
-        | Some t -> [a_onclick onclick; a_class classes; a_title t]
-        | None   -> [a_onclick onclick; a_class classes ]
-      in
-      Some (div ~a [dummy_img () ])
-    in
-    let make_href ?title ~service clas =
-      match title with
-      | None       -> a ~a:[a_class [clas]] ~service  [dummy_img()]
-      | Some title -> a ~a:[a_class [clas;"need_tooltip"]; a_title title] ~service [dummy_img()]
-    in
-    let make_tooltips = {Dom_html.event Js.t-> unit{ fun _ ->
-        Ojquery.(".need_tooltip" |> js_jQ |> jQelt |> jq_tooltip) }} in
-    div ~a:[a_class ["event_buttons_bar"]; a_onload make_tooltips] @@
-    List.filter_map (fun f -> f ())
-      [ begin fun () -> make_btn refresh_event_data_btn_clicked "refresh_event_data_btn" end
-      ; begin fun () ->
-        if ismoderator && eventId <> 1L
-        then make_btn ~title:"Delete event" delete_event_btn_clicked "delete_event_btn"
-        else None
-        end
-      ; begin fun () ->
-        if ismoderator
-        then Some (make_href ~title:"Edit event" ~service:Ukraine_services.edit_event_service
-                     "edit_event_btn" eventId)
-        else None
-        end
-      ; begin fun () ->
-        if ismoderator
-        then Some (make_href ~title:"Insert after" ~service:Ukraine_services.add_node_service
-                     "insert_event_after_btn" eventId)
-        else None
-        end
-      ; begin fun () ->
-        if ismoderator
-        then make_btn ~title:"Add question" add_question_btn_clicked "event_toolbar_add_question_btn"
-        else None
-        end
-      ; begin fun () ->
-        if ismoderator
-        then Some(make_href ~title:"Smart add event" ~service:Ukraine_services.smart_add_service
-                    "event_toolbar_smart_add_question_btn" (Types.id_of_timeline tlsort) )
-        else None
-        end
-      ]
-  in
-  let content_div = div ~a:[a_class ["event_data_holder"]]
-    [ buttons_bar
-    ; div ~a:[ a_class ["event_description_holder"]
-	     ; a_id event_description_holder_id; a_onload onload_event_description_div] []
-    ; comments_holder
-    ; hr ()
-    ; event_comment_root_block
-    ]
-  in
-
-  lwt content_div =
-    let message_div = div ~a:[a_class ["event_view_links_heading_msg"]]
-	[ pcdata @@ Types.string_of_date event.Event.datetime ]
-    in
-    lwt left_side_links = make_event_links ~ismoderator ~prevEventId ~nextEventId
-        ~eventId tlsort message_div events in
-    Lwt.return @@ div [ left_side_links
-                      ; content_div
-	              ]
-  in
-  Lwt.return (match mode with
-        | `Moderator user
-        | `User user -> Ukraine_container.page ~user [content_div]
-        | `Guest     -> Ukraine_container.page [content_div]
-  )
-
-let () =
-  let onerror  = LoginError.page None in
-  let open Ebapp.Session in
-  let handler' mode eventId () =
-    match mode with
-    | `GuestDenied
-    | `GuestConnected -> handler `Guest eventId ()
-    | `Allowed userId -> handler (`Moderator userId) eventId ()
-    | `Denied userId  -> handler (`User userId) eventId ()
-  in
-
-  Ebapp.App.register Ukraine_services.view_event_service
-    (Ebapp.Page.how_connected_page ~allow:[Ukraine_groups.moderator_group] ~onerror handler')

File viewdate.eliom

  • Ignore whitespace
-(* There you will find page for full description of node in timeline.
- * Below the description some space for user's comments to the node
- * should be.
- *)
-
-{shared{
-  open Eliom_content.Html5
-  open Eliom_content.Html5.F
-  open Printf
-  open Helpers
-  open Types
-}}
-
-{client{
-  open Ojquery
-
-  let _bad = fun id -> Firebug.console##log (Js.string @@ sprintf "Can't get element by id '%s'" id)
-  let prompt_line ?text ~title ~ok =
-    let ans = Dom_html.window##prompt
-	(Js.string title, Js.string @@ match text with Some x -> x | None -> "") in
-    Js.Opt.iter ans (fun text -> ok (Js.to_string text))
-
-}}
-(*
-let dummy_add_comment_service =
-  Eliom_service.Http.post_coservice'
-    ~name:"set_data"
-    ~post_params:(Eliom_parameter.(int64 "id" ** string "text"))
-    ()
-
-{shared{
-let node_comments_real_holder_id = "node_comments_real_holder_id"
-let node_description_holder_id   = "node_description_holder"
-}}
-
-let add_comment (userId, nodeId, commentId, text) =
-  match commentId with
-  | Some parentId ->
-    printf "adding comment by %Ld to node %Ld as subcomment of %Ld with text '%s'\n%!"
-      userId nodeId parentId text;
-    lwt () = Comments_db.insert_subcomment ~text ~nodeId ~parentId ~userId in
-    Lwt.return true
-  | None          ->
-    lwt () = Comments_db.insert_comment ~text ~nodeId ~userId in
-    Lwt.return true
-
-let add_comment_rpc : (userId_t*eventId_t*(commentId_t option)*string, bool) Eliom_pervasives.server_function
-  = server_function Json.t<userId_t*eventId_t*(commentId_t option)*string> add_comment
-
-let filter_ans xs id =
-  let open StdLabels in
-  let cur = List.find ~f:(fun o -> o.Node.id = id) xs in
-  List.filter xs ~f:(fun o ->
-    (List.length o.Node.path = 1 + List.length cur.Node.path)
-  )
-
-{client{
-let refresh_comments_data () =
-  Js.Opt.case (Dom_html.document##getElementById (Js.string "refresh_comments_btn") )
-    (fun () -> Firebug.console##log (Js.string "no refresh_comments_btn"))
-    (fun ddd -> ddd |> jQelt |> click |> ignore);
-}}
-
-let make_comment_div ~userId ~nodeId padding (o: Comment.t) =
-  let open Eliom_content.Html5.D in
-  let comment_id: int64 = o.Comment.id in
-  let comment_div_id = sprintf "node-comment-%Ld" comment_id in
-
-  let answer_form_div = div ~a:[a_class ["node_comment_reply_block"]; a_style "display: none;"]
-    [ post_form ~service:dummy_add_comment_service (fun (id,text) ->
-       let area = textarea ~a:[a_class ["node_comment_reply_textarea"]] ~name:text
-		  ~value:"comment text here" () in
-       let add_comment_onclick = {Dom_html.mouseEvent Js.t -> unit { fun _event ->
-          Dom.preventDefault _event;
-          let jsarea = To_dom.of_textarea %area in
-	  Firebug.console##log (jsarea##value);
-	  begin
-	  lwt res = %add_comment_rpc (%userId, %nodeId, Some %comment_id, Js.to_string jsarea##value) in
-          refresh_comments_data ();
-	  Lwt.return ()
-	  end |> Lwt.ignore_result
-       }} in
-       [ area
-       ; int64_input ~input_type:`Hidden ~name:id ~value:comment_id ()
-       ; raw_input ~a:[a_onclick add_comment_onclick]
-		   ~input_type:`Submit ~value:"Comment" ()
-       ]) ()
-    ]
-  in
-  let reply_clicked  = {Dom_html.mouseEvent Js.t -> unit { fun _ ->
-    Firebug.console##log (Js.string @@ sprintf "reply on comment %Ld" %comment_id);
-    Js.Opt.case (Dom_html.document##getElementById (Js.string %comment_div_id) )
-		(fun () -> Firebug.console##log (Js.string "WTF"))
-     (fun ddd ->
-       Manip.SetCss.display %answer_form_div "block";
-       Firebug.console##log (Js.string @@ sprintf "reply on comment %Ld" %comment_id);
-     )
-  }} in
-
-  div ~a: [ a_style @@ sprintf "margin-left: %dpx;" (30*padding); a_class ["node_comment"]
-	  ; a_id comment_div_id
-	  ]
-      [ div ~a:[a_class ["node_comment_holder"]] [
-	    (* comment static data here *)
-	    div ~a:[a_class ["node_comment_header"]]
-		[ div ~a:[a_class ["node_comment_avatar"]]
-		      [ img ~src:(Xml.uri_of_string Consts.no_image_url) ~alt:"alt" () ]
-		; div ~a:[a_class ["node_comment_nick"]] [pcdata "nickname"]
-		]
-	  ; div ~a:[a_class ["node_comment_text"]]  [ pcdata o.Comment.text ]
-	  ; div ~a:[a_class ["button";"node_comment_reply_btn"]; a_onclick reply_clicked]
-		[pcdata "Reply"]
-	  ]
-      ; answer_form_div
-      ]
-
-let generate_comments_div (userId, nodeId) : _ elt list Lwt.t =
-  lwt comments = Comments_db.comments_for_node nodeId in
-  let (tree, non_parsed_part) = Path.make_tree_of_nodes (fun o -> o.Comment.path) comments in
-
-  let rec to_divs acc depth : Types.Comment.t Path.tree -> _ elt list = function
-    | Path.Node (x,xs) ->
-       let r = make_comment_div ~userId ~nodeId depth x in
-       List.fold_left ~init:(r::acc) xs ~f:(fun acc node -> to_divs acc (depth+1) node )
-  in
-  Lwt.return @@ ( List.concat (List.map (List.rev tree) ~f:(to_divs [] 0 ) ) |> List.rev  )
-
-let generate_comments_div_rpc
-    : (userId_t*eventId_t, [Html5_types.div] elt list) Eliom_pervasives.server_function
-  = server_function Json.t<userId_t*eventId_t> generate_comments_div
-
-let make_comments_holder (userId: Int64.t) nodeId  =
-  lwt comment_divs = generate_comments_div (userId, nodeId) in
-  let _ = Int64.to_int userId in
-  let node_comments_real_holder =
-    let open Eliom_content.Html5.D in
-    div ~a:[a_class ["node_comments_real_holder"]; a_id node_comments_real_holder_id] comment_divs
-  in
-  let refresh_onclick = {Dom_html.mouseEvent Js.t -> unit { fun _ ->
-    Firebug.console##log (Js.string "clicked");
-    Lwt.ignore_result (
-	lwt divs = %generate_comments_div_rpc (%userId,%nodeId) in
-	Firebug.console##log (Js.string @@ string_of_int @@ List.length divs);
-	Manip.removeAllChild %node_comments_real_holder;
-	Manip.appendChilds %node_comments_real_holder divs;
-	Lwt.return ()
-      )
-  }} in
-  let refresh_button = div ~a:[a_class ["button"]; a_id "refresh_comments_btn"; a_onclick refresh_onclick ]
-			   [pcdata "Refresh"] in
-  Lwt.return @@
-    div ~a:[a_class ["node_comments_holder"]]
-	[div ~a:[a_class ["node_comments_holder1"]] [refresh_button]
-	(* some buttons there *)
-	; hr ()
-	; node_comments_real_holder
-	]
-
-let questions_and_options nodeId =
-  Events_db.questions_with_options_of_nodeId nodeId
-
-let questions_and_options_rpc
-    : (eventId_t, Types.Question.t list) Eliom_pervasives.server_function
-  = server_function Json.t<eventId_t> questions_and_options
-
-let get_node_by_id_rpc : (eventId_t, Types.Event.t) Eliom_pervasives.server_function
-  = server_function Json.t<eventId_t> Events_db.event_by_id
-
-let remove_question_rpc: (questionId_t, bool) Eliom_pervasives.server_function
-  = server_function Json.t<questionId_t> (fun questionId -> Events_db.remove_question ~questionId)
-
-let add_option_rpc: (optionId_t*string, bool) Eliom_pervasives.server_function
-  = server_function Json.t<optionId_t*string>
-    (fun (questionId,text) -> Events_db.insert_option ~questionId ~text)
-
-let remove_option_rpc: (optionId_t, bool) Eliom_pervasives.server_function
-  = server_function Json.t<optionId_t> (fun optionId -> Events_db.remove_option ~optionId)
-
-{client{
-
-let make_question_div ~refresh (nodeId, q) =
-  let remove_question_onclicked = fun _event ->
-    Dom.preventDefault _event;
-    Firebug.console##log (Js.string "remove_question_onclicked");
-    begin
-    lwt (_:bool) = %remove_question_rpc q.Question.id in
-    let () = refresh nodeId in
-    Lwt.return ()
-    end |> Lwt.ignore_result
-  in
-
-  let add_option_clicked = fun _event ->
-      Dom.preventDefault _event;
-      Firebug.console##log (Js.string "add_option_onclicked");
-      prompt_line ~title:"Enter new option text" ~text:"" ~ok:begin fun text ->
-	Firebug.console##log (Js.string @@ sprintf  "your option value =  '%s'" text);
-        (lwt res = %add_option_rpc (q.Question.id, text) in
-	 let () = if res then begin
-           Firebug.console##log (Js.string "Added new option");
-           refresh nodeId;
-         end else
-           Firebug.console##error (Js.string "Server can't add option ");
-         in
-         Lwt.return ()
-	) |> Lwt.ignore_result
-       end;
-      ()
-  in
-  let make_option_div (cid,text) =
-    let remove_option_clicked = fun _event ->
-      Dom.preventDefault _event;
-      Firebug.console##log (Js.string "remove_option_onclicked");
-      begin
-	lwt (_:bool) = %remove_option_rpc cid in
-        let () = refresh nodeId in
-        Lwt.return ()
-      end |> Lwt.ignore_result
-    in
-
-    div ~a:[a_class ["question_option_div"]]
-      [ pcdata text
-      ; dummy_img ~a:[a_onclick remove_option_clicked;
-		      a_class ["remove_option_btn"]; a_title "Remove option"] ()
-      ]
-  in
-  Lwt.return @@
-    div ~a:[a_class ["question_div"]]
-        [ dummy_img ~a:[a_class ["question_icon_img"]] ()
-        ; div ~a:[a_class ["question_div_text"]] [pcdata q.Question.text]
-        ; dummy_img ~a:[a_onclick remove_question_onclicked; a_class ["remove_question_btn"];
-			a_title "Remove question"] ()
-        ; dummy_img ~a:[a_onclick add_option_clicked; a_class ["add_option_btn"]; a_title "Add new option"]()
-        ; br ()
-        ; div ~a:[a_class ["question_options_div"]] (List.map q.Question.options ~f:make_option_div)
-        ; hr ()
-        ]
-
-}}
-
-let add_question_rpc: (eventId_t*string, bool) Eliom_pervasives.server_function
-  = server_function Json.t<eventId_t*string> (fun (nodeId,text) -> Events_db.insert_question ~nodeId ~text)
-
-{client{
-let rec refresh_node_data nodeId = Lwt.ignore_result begin
-  Firebug.console##log (Js.string @@ sprintf "refresh_node_data %Ld" nodeId);
-  let add_question_clicked = fun _event ->
-    Dom.preventDefault _event;
-    Firebug.console##log (Js.string "add_question_onclicked");
-    prompt_line ~title:"Enter new question" ~text:"" ~ok:begin fun text ->
-      Firebug.console##log (Js.string @@ sprintf  "your value %s" text);
-      (lwt res = %add_question_rpc (nodeId, text) in
-      let () = if res then begin
-        Firebug.console##log (Js.string "Added");
-        refresh_node_data nodeId;
-      end else begin
-        Firebug.console##error (Js.string "Server can't add question");
-      end in
-      Lwt.return ()) |> Lwt.ignore_result
-    end
-  in
-
-  lwt curnode = %get_node_by_id_rpc nodeId in
-
-  lwt questions = %questions_and_options_rpc nodeId in
-  let () = Firebug.console##log (Js.string @@ string_of_int @@ List.length questions) in
-  let qdivs = List.map ~f:(fun q -> make_question_div ~refresh:refresh_node_data (nodeId,q)) questions in
-  lwt question_divs = Lwt_list.map_p (fun x -> x) qdivs in
-  Firebug.console##log (Js.string @@ sprintf "refresh_node_data: q.len = %d" (List.length question_divs));
-  with_element_by_id_exn "node_description_holder" ~ok:(fun el ->
-      let nodes =
-	[ div ~a:[a_class ["node_title"]] [pcdata @@ curnode.Event.title]
-	; br ()
-	; (let src = Helpers.Option.get ~default:Consts.no_image_url curnode.Event.picture
-	      |> Xml.uri_of_string in
-          img ~src ~alt:"alt" ())
-	; br ()
-	; div ~a:[a_class ["node_description"]]
-	   [ p [pcdata @@ if String.length curnode.Event.text = 0 then "<no description>" else curnode.Event.text ]
-	   ]
-        ; hr ()
-        (* Button for adding new question *)
-        ; div ~a:[a_class ["button"; "add_new_question_btn"]; a_onclick add_question_clicked] [pcdata "Add question"]
-        ; div ~a:[a_class ["questions_block"]] question_divs
-	]
-      in
-      Manip.replaceAllChild (el |> Of_dom.of_element) nodes
-  ) ~bad:_bad;
-  Lwt.return ()
-end
-}}
-					     *)
-let make_event_links xs =
-  let f ev =
-    div [ a ~a:[a_class ["when_view_link"]] ~service:Ukraine_services.view_event_service
-	    [pcdata ev.Event.title] ev.Event.id
-        ; br ()
-	; div ~a:[a_class ["when_view_link_time"]] [pcdata @@ string_of_calendar ev.Event.datetime]
-        ; br ()
-        ; br ()
-	]
-  in
-  div ~a:[a_class ["when_view_links_holder"]]
-    (List.map ~f xs)
-
-let handler tlsort (userId: userId_t) (yy,(mm,dd)) () =
-  lwt events = Events_db.by_date tlsort ~yy ~dd ~mm in
-
-(*
-  lwt curnode = Events_db.event_by_id nodeId  in
-  lwt comments_holder = make_comments_holder userId nodeId in
-
-  let onload_node_description_div = { Dom_html.event Js.t -> unit { fun _ ->
-      refresh_node_data %nodeId;
-  }} in
-  let refresh_node_data_btn_clicked = { Dom_html.mouseEvent Js.t -> unit { fun _event ->
-      Dom.preventDefault _event;
-      refresh_node_data %nodeId
-  }} in
-  let content_div = div ~a:[a_class ["node_data_holder"]]
-    [ div ~a:[a_onclick refresh_node_data_btn_clicked; a_id "refresh_node_data_btn"]
-        [img ~src:(Xml.uri_of_string "") ~alt:"" () ]
-    ; div ~a:[a_class ["node_description_holder"]; a_id node_description_holder_id; a_onload onload_node_description_div] []
-    ; div ~a:[a_class ["node_buttons"]]
-      [ div ~a:[a_class ["node_fork_button"]]
-	  [ a ~a:[a_class ["item"; "left-bar"]]
-		~service:Ukraine_services.add_node_service
-		[ pcdata "Add branch"
-		] curnode.Event.id
-	  ; br ()
-	  ]
-      ; br()
-      ; a ~a:[a_class ["item"; "left-bar"]]
-	  ~service:Ukraine_services.tree_view_service
-	  [ pcdata "View tree from there"
-	  ] curnode.Event.id
-      ; br ()
-      ]
-    ; br ()
-    ; comments_holder
-    ; br ()
-    ; div ~a:[a_class ["node_comment_root_reply_block"]]
-	  [ post_form ~service:dummy_add_comment_service (fun (id,text) ->
-	      let open Eliom_content.Html5.D in
-	      let area = textarea ~a:[a_class ["node_comment_root_reply_textarea"]]
-				  ~name:text  ~value:"comment text here" () in
-	      let add_comment_onclick = {Dom_html.mouseEvent Js.t -> unit { fun _event ->
-		Dom.preventDefault _event;
-		let jsarea = To_dom.of_textarea %area in
-	        Firebug.console##log (jsarea##value);
-		begin
-		lwt res = %add_comment_rpc (%userId, %nodeId, None, Js.to_string jsarea##value) in
-                if res then (
-		  Js.Opt.case (Dom_html.document##getElementById (Js.string %node_comments_real_holder_id) )
-			      (fun () -> Firebug.console##log (Js.string "WTF"); Lwt.return ())
-		  (fun ddd ->
-                     lwt divs = %generate_comments_div_rpc (%userId,%nodeId) in
-		     let holder = Of_dom.of_div ddd in
-                     Firebug.console##log (Js.string@@ string_of_int @@ List.length divs);
-		     Manip.removeAllChild holder;
-		     Manip.appendChilds holder divs;
-		     Firebug.console##log (Js.string "refreshed");
-		     Lwt.return ()
-		  )
-		) else (
-		  Firebug.console##log (Js.string "WTF");
-		  Lwt.return ()
-                ) end |> Lwt.ignore_result
-	      }} in
-	      [ hr ()
-	      ; div ~a:[a_style "float: left;"] [pcdata "Comment node:"]
-	      ; br ()
-	      ; area
-	      ; br ()
-	      ; raw_input ~a:[a_onclick add_comment_onclick; a_class ["node_comment_root_submit_btn"]]
-			  ~input_type:`Submit ~value:"Comment" ()
-	      ]) ()
-	   ]
-    ]
-    in
- *)
-  let content_div = div ~a:[a_class ["when_view_content_div"]]
-    [ a ~a:[a_class ["when_view_back_btn"]] ~service:Ukraine_services.view_date_service
-	[pcdata "Back"] (yy,(mm,dd-1))
-    (* FIXME don't do +1 and -1 *)
-    ; div ~a:[a_class ["when_view_today_label"]] [pcdata @@ sprintf "Today: %d/%d/%d" yy mm dd]
-    ; a ~a:[a_class ["when_view_forward_btn"]] ~service:Ukraine_services.view_date_service
-	[pcdata "Forward"] (yy,(mm,dd+1))
-    ; hr ()
-    ; make_event_links events
-    ]
-  in
-  Lwt.return (Ukraine_container.page ~user:userId [
-    content_div
-  ])
-
-let () =
-  let handler = handler Maidan2013 in
-  Ebapp.App.register Ukraine_services.view_date_service
-    (Ebapp.Page.connected_page ~fallback:LoginError.page handler)

File wiki_syntax.eliom

  • Ignore whitespace
-(* Ocsimore
- * Copyright (C) 2008
- * Laboratoire PPS - Universit� Paris Diderot - CNRS
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *)
-(**
-   Pretty print wiki to DOM elements
-   @author Vincent Balat
-*)
-{client{
-module Html = Dom_html
-
-module W = Wikicreole
-
-(*
-let create n ?attrs children =
-  let m = create n ?attrs () in
-  List.iter (Js.Node.append m) children ;
-  m
-*)
-let node x = (x : #Dom.node Js.t :> Dom.node Js.t)
-
-let (<|) e l = List.iter (fun c -> Dom.appendChild e c) l; node e
-
-let list_builder d tag c =
-  d##createElement (Js.string tag) <|
-    (List.map
-       (fun (c, l) ->
-          d##createElement (Js.string "li") <|
-            (c @ match l with Some v -> [v] | None -> []))
-       c)
-
-let builder =
-  let d = Html.document in
-  { W.chars = (fun s -> node (d##createTextNode (Js.string s)));
-    W.strong_elem = (fun s -> d##createElement (Js.string "strong") <| s);
-    W.em_elem = (fun s -> d##createElement (Js.string "em") <| s);
-    W.a_elem =
-      (fun addr s ->
-         let a = Html.createA d in a##href <- Js.string addr; a <| s);
-
-    W.youtube_elem = (fun addr s ->
-        let i = Html.createIframe d in
-        i##width <- Js.string "480";
-        i##height <- Js.string "360";
-        let video_link =
-          "http://youtube.com/embed/" ^
-          Js.to_string (Js.encodeURI (Js.string addr)) in
-        i##src <- Js.string video_link;
-        i##frameBorder <- Js.string "0";
-        node i
-    );
-    W.br_elem = (fun () -> node (d##createElement (Js.string "br")));
-    W.img_elem =
-      (fun addr alt ->
-         let i = Html.createImg d in
-         i##src <- Js.string addr; i##alt <- Js.string alt;
-         node i);
-    W.tt_elem = (fun s -> d##createElement (Js.string "tt") <| s);
-    W.p_elem = (fun s -> d##createElement (Js.string "p") <| s);
-    W.pre_elem =
-      (fun s ->
-         let p = d##createElement (Js.string "pre") in
-         Dom.appendChild p
-           (d##createTextNode (Js.string (String.concat "" s)));
-         node p);
-    W.h1_elem = (fun s -> d##createElement (Js.string "h1") <| s);
-    W.h2_elem = (fun s -> d##createElement (Js.string "h2") <| s);
-    W.h3_elem = (fun s -> d##createElement (Js.string "h3") <| s);
-    W.h4_elem = (fun s -> d##createElement (Js.string "h4") <| s);
-    W.h5_elem = (fun s -> d##createElement (Js.string "h5") <| s);
-    W.h6_elem = (fun s -> d##createElement (Js.string "h6") <| s);
-    W.ul_elem = (fun s -> list_builder d "ul" s);
-    W.ol_elem = (fun s -> list_builder d "ol" s);
-    W.hr_elem = (fun () -> node (d##createElement (Js.string "hr")));
-    W.table_elem =
-      (fun rows ->
-         let rows =
-           List.map
-             (fun entries ->
-                d##createElement (Js.string "tr") <|
-                  (List.map
-                     (fun (h, c) ->
-                        let kind = if h then "th" else "td" in
-                        d##createElement (Js.string kind) <| c)
-                     entries))
-             rows
-         in
-         d##createElement (Js.string "table") <|
-           [d##createElement (Js.string "tbody") <| rows]);
-    W.inline = (fun x -> x)
-  }
-
-let xml_of_wiki s =
-  let ans = Html.createDiv Html.document in
-  List.iter (Dom.appendChild ans) (W.from_string builder s);
-  ans
-
-}}

File wikicreole.ml

  • Ignore whitespace
-# 1 "wikicreole.mll"
- 
-(* Ocsimore
- * Copyright (C) 2008
- * Laboratoire PPS - Universit� Paris Diderot - CNRS
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *)
-(**
-   Parser for Wikicreole
-   @author J�r�me Vouillon
-*)
-
-type ('flow, 'inline, 'a_content) builder =
-  { chars : string -> 'a_content;
-    strong_elem : 'inline list -> 'a_content;
-    em_elem : 'inline list -> 'a_content;
-    br_elem : unit -> 'a_content;
-    img_elem : string -> string -> 'a_content;
-    tt_elem : 'inline list -> 'a_content;
-    a_elem : string -> 'a_content list -> 'inline;
-    youtube_elem : string -> 'a_content list -> 'inline;
-    p_elem : 'inline list -> 'flow;
-    pre_elem : string list -> 'flow;
-    h1_elem : 'inline list -> 'flow;
-    h2_elem : 'inline list -> 'flow;
-    h3_elem : 'inline list -> 'flow;
-    h4_elem : 'inline list -> 'flow;
-    h5_elem : 'inline list -> 'flow;
-    h6_elem : 'inline list -> 'flow;
-    ul_elem : ('inline list * 'flow option) list -> 'flow;
-    ol_elem : ('inline list * 'flow option) list -> 'flow;
-    hr_elem : unit -> 'flow;
-    table_elem : (bool * 'inline list) list list -> 'flow;
-    inline : 'a_content -> 'inline }
-
-type style = Bold | Italic
-
-type list_kind = Unordered | Ordered
-
-type ('inline, 'flow) stack =
-    Style of style * 'inline list * ('inline, 'flow) stack
-  | Link of string * ('inline, 'flow) stack
-      (* Not that we do not save anything in the case of links, as
-         links cannot be nested *)
-  | Paragraph
-  | Heading of int
-  | List_item of ('inline, 'flow) stack
-  | List of
-      list_kind * ('inline list * 'flow option) list * ('inline, 'flow) stack
-  | Table of (bool * 'inline list) list list
-  | Row of (bool * 'inline list) list * ('inline, 'flow) stack
-  | Entry of bool * ('inline, 'flow) stack
-
-type ('flow, 'inline, 'a_content) ctx =
-  { build : ('flow, 'inline, 'a_content) builder;
-    mutable italic : bool;
-    mutable bold : bool;
-    mutable heading : bool;
-    mutable link : bool;
-    mutable list_level : int;
-    mutable inline_mix : 'inline list;
-    mutable link_content : 'a_content list;
-    mutable pre_content : string list;
-    mutable list : ('inline list * 'flow option) list;
-    mutable flow : 'flow list;
-    mutable stack : ('inline, 'flow) stack }
-
-let count c s =
-  let n = ref 0 in
-  for i = 0 to String.length s - 1 do if s.[i] = c then incr n done;
-  !n
-
-let push c v =
-  match c.stack with
-    Link _ -> c.link_content <- v :: c.link_content
-  | _      -> c.inline_mix <- c.build.inline v :: c.inline_mix
-
-let push_string c s = push c (c.build.chars s)
-
-let push_chars c lexbuf = push_string c (Lexing.lexeme lexbuf)
-
-let get_style c style =
-  match style with Bold -> c.bold | Italic -> c.italic
-
-let set_style c style v =
-  match style with Bold -> c.bold <- v | Italic -> c.italic <- v
-
-let pop_style c style inline stack =
-  let elt =
-    match style with
-      Bold   -> c.build.strong_elem
-    | Italic -> c.build.em_elem
-  in
-  let inline' = c.inline_mix in
-  c.stack <- stack;
-  c.inline_mix <- inline;
-  push c (elt (List.rev inline'));
-  set_style c style false
-
-let style_change c style =
-  if get_style c style then begin
-    match c.stack with
-      Style (s, inline, stack) when s = style ->
-        pop_style c style inline stack
-    | _ ->
-        match style with
-          Italic -> push_string c "//"
-        | Bold   -> push_string c "**"
-  end else begin
-    c.stack <- Style (style, c.inline_mix, c.stack);
-    c.inline_mix <- [];
-    set_style c style true
-  end
-
-let pop_link c addr stack =
-  c.stack <- stack;
-  c.inline_mix <-
-    c.build.a_elem addr (List.rev c.link_content) :: c.inline_mix;
-  c.link_content <- [];
-  c.link <- false
-
-let close_entry c =
-  match c.stack with
-    Entry (heading, Row (entries, stack)) ->
-      c.stack <- Row ((heading, List.rev c.inline_mix) :: entries, stack);
-      c.inline_mix <- [];
-      true
-  | Row _ ->
-      true
-  | Table _ ->
-      c.stack <- Row ([(false, List.rev c.inline_mix)], c.stack);
-      c.inline_mix <- [];
-      true
-  | _ ->
-      false
-
-let close_row c =
-  close_entry c &&
-  match c.stack with
-    Row (entries, Table rows) ->
-      c.stack <- Table (List.rev entries :: rows);
-      true
-  | Table _ ->
-      true
-  | _ ->
-      assert false
-
-let rec end_paragraph c lev =
-  match c.stack with
-    Style (style, inline, stack) ->
-      pop_style c style inline stack;
-      end_paragraph c lev
-  | Link (addr, stack) ->
-      pop_link c addr stack;
-      end_paragraph c lev
-  | Paragraph ->
-      if c.inline_mix <> [] then begin
-        c.flow <- c.build.p_elem (List.rev c.inline_mix) :: c.flow;
-        c.inline_mix <- []
-      end;
-      c.stack <- Paragraph
-  | Heading l ->
-      let f =
-        match l with
-          | 1 -> c.build.h1_elem
-          | 2 -> c.build.h2_elem
-          | 3 -> c.build.h3_elem
-          | 4 -> c.build.h4_elem
-          | 5 -> c.build.h5_elem
-          | _ -> c.build.h6_elem
-      in
-      c.flow <- f (List.rev c.inline_mix) :: c.flow;
-      c.inline_mix <- [];
-      c.heading <- false;
-      c.stack <- Paragraph
-  | List_item stack ->
-      c.list <- (List.rev c.inline_mix, None) :: c.list;
-      c.stack <- stack;
-      c.inline_mix <- [];
-      end_paragraph c lev
-  | List (kind, lst, stack) ->
-      if lev < c.list_level then begin
-        c.list_level <- c.list_level - 1;
-        let elt =
-          match kind with
-            Unordered -> c.build.ul_elem
-          | Ordered   -> c.build.ol_elem
-        in
-        let cur_lst = elt (List.rev c.list) in
-        if c.list_level = 0 then
-          c.flow <- cur_lst :: c.flow
-        else begin
-          match lst with
-            (l, None) :: rem -> c.list <- (l, Some cur_lst) :: rem;
-          | _                -> assert false
-        end;
-        c.stack <- stack;
-        end_paragraph c lev
-      end
-  | Entry _ ->
-      ignore (close_row c);
-      end_paragraph c lev
-  | Row _ ->
-      assert false
-  | Table rows ->
-      c.flow <- c.build.table_elem (List.rev rows) :: c.flow;
-      c.stack <- Paragraph
-
-let rec correct_kind_rec stack kind n =
-  match stack with
-    List_item stack ->
-      correct_kind_rec stack kind n
-  | List (k, lst, stack) ->
-      if n = 0 then k = kind else
-      correct_kind_rec stack kind (n - 1)
-  | Style (_, _, stack) ->
-      correct_kind_rec stack kind n
-  | Link _ | Heading _ | Paragraph | Entry _ | Row _ | Table _ ->
-      assert false
-
-let correct_kind c kind lev =
-  lev = c.list_level + 1
-    ||
-  (lev <= c.list_level &&
-   correct_kind_rec c.stack kind (c.list_level - lev))
-
-let start_list_item c kind lev =
-  let correct = correct_kind c kind lev in
-  if lev = 1 || correct then begin
-    (* If we have an item of a different kind at level 1, we close the
-       previous list and start a new one of the right kind *)
-    end_paragraph c (if correct then lev else 0);
-    if lev = c.list_level then begin
-      c.stack <- List_item c.stack
-    end else (* if lev = c.list_level + 1 then *) begin
-      c.list_level <- lev;
-      c.stack <- List_item (List (kind, c.list, c.stack));
-      c.list <- []
-    end;
-    true
-  end else
-    false
-
-let start_table_row c heading =
-  if not (close_row c) then begin
-    end_paragraph c 0;
-    c.stack <- Table []
-  end;
-  c.stack <- Entry (heading, Row ([], c.stack))
-
-
-# 266 "wikicreole.ml"
-let __ocaml_lex_tables = {
-  Lexing.lex_base = 
-   "\000\000\001\000\002\000\001\000\001\000\001\000\002\000\005\000\
-    \001\000\255\255\003\000\004\000\006\000\007\000\254\255\003\000\
-    \004\000\006\000\251\255\002\000\003\000\007\000\250\255\008\000\
-    \248\255\011\000\237\255\047\000\020\000\046\000\070\000\085\000\
-    \108\000\155\000\193\000\208\000\008\001\025\001\077\001\081\001\
-    \012\000\255\255\254\255\253\255\252\255\013\000\148\001\064\000\
-    \066\000\074\000\249\255\120\000\251\255\152\001\204\001\219\001\
-    \001\002\053\002\069\002\121\002\159\002\174\002\031\000\227\002\
-    \245\002\025\003\042\003\096\000\250\255\248\255\089\003\095\003\
-    \142\003\215\003\014\004\058\004\100\004\105\004\128\004\246\255\
-    \106\000\097\000\215\000\135\000\171\000\245\255\182\000\210\000\
-    \011\000\243\255\240\255\242\255\015\000\143\000\112\001\016\000\
-    \253\255\223\000\254\255\101\001\143\001\123\001\137\001\228\000\
-    \255\255\017\000\154\001\004\001\018\000";
-  Lexing.lex_backtrk = 
-   "\008\000\006\000\255\255\255\255\003\000\002\000\001\000\255\255\
-    \000\000\255\255\001\000\001\000\001\000\001\000\255\255\255\255\
-    \255\255\255\255\255\255\004\000\255\255\255\255\255\255\005\000\
-    \255\255\255\255\255\255\016\000\014\000\016\000\016\000\016\000\
-    \016\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\
-    \000\000\255\255\255\255\255\255\255\255\003\000\016\000\255\255\
-    \255\255\255\255\255\255\255\255\255\255\016\000\016\000\016\000\
-    \016\000\016\000\016\000\016\000\016\000\016\000\255\255\016\000\
-    \016\000\016\000\005\000\255\255\255\255\255\255\016\000\016\000\
-    \016\000\016\000\008\000\008\000\255\255\016\000\016\000\255\255\
-    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\011\000\
-    \011\000\255\255\255\255\255\255\013\000\255\255\255\255\002\000\
-    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
-    \255\255\000\000\255\255\255\255\001\000";
-  Lexing.lex_default = 
-   "\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
-    \255\255\000\000\255\255\255\255\255\255\255\255\000\000\255\255\
-    \255\255\255\255\000\000\255\255\255\255\255\255\000\000\255\255\
-    \000\000\027\000\000\000\027\000\255\255\089\000\027\000\027\000\
-    \027\000\027\000\027\000\027\000\027\000\027\000\027\000\027\000\
-    \255\255\000\000\000\000\000\000\000\000\255\255\027\000\048\000\
-    \048\000\048\000\000\000\048\000\000\000\027\000\027\000\027\000\
-    \027\000\027\000\027\000\027\000\027\000\063\000\062\000\063\000\
-    \063\000\063\000\027\000\062\000\000\000\000\000\027\000\027\000\
-    \027\000\075\000\074\000\075\000\074\000\027\000\027\000\000\000\
-    \082\000\081\000\082\000\083\000\083\000\000\000\081\000\081\000\
-    \255\255\000\000\000\000\000\000\255\255\255\255\097\000\255\255\
-    \000\000\097\000\000\000\097\000\097\000\097\000\097\000\097\000\
-    \000\000\255\255\097\000\097\000\255\255";
-  Lexing.lex_trans = 
-   "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\007\000\009\000\009\000\018\000\008\000\007\000\017\000\
-    \018\000\022\000\022\000\019\000\023\000\041\000\041\000\044\000\
-    \040\000\091\000\096\000\104\000\098\000\093\000\091\000\000\000\
-    \007\000\092\000\000\000\004\000\004\000\007\000\017\000\000\000\
-    \004\000\255\255\005\000\005\000\255\255\003\000\015\000\005\000\
-    \016\000\017\000\003\000\000\000\093\000\039\000\000\000\255\255\
-    \255\255\255\255\038\000\255\255\255\255\006\000\024\000\010\000\
-    \011\000\012\000\006\000\013\000\014\000\000\000\000\000\035\000\
-    \037\000\000\000\255\255\000\000\255\255\255\255\255\255\255\255\
-    \255\255\090\000\000\000\255\255\255\255\000\000\000\000\255\255\
-    \000\000\255\255\000\000\000\000\000\000\067\000\255\255\255\255\
-    \000\000\000\000\255\255\000\000\000\000\000\000\036\000\031\000\
-    \034\000\000\000\255\255\255\255\255\255\255\255\255\255\000\000\
-    \255\255\032\000\000\000\033\000\255\255\255\255\255\255\255\255\
-    \000\000\255\255\000\000\002\000\001\000\020\000\021\000\255\255\
-    \002\000\001\000\255\255\255\255\255\255\255\255\030\000\028\000\
-    \088\000\029\000\255\255\255\255\255\255\000\000\000\000\000\000\
-    \000\000\255\255\255\255\000\000\255\255\255\255\255\255\255\255\
-    \093\000\091\000\000\000\255\255\092\000\049\000\068\000\051\000\
-    \000\000\255\255\255\255\255\255\000\000\255\255\000\000\255\255\
-    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\093\000\
-    \255\255\079\000\255\255\000\000\000\000\255\255\000\000\000\000\
-    \255\255\000\000\000\000\255\255\255\255\255\255\050\000\000\000\
-    \255\255\080\000\255\255\255\255\255\255\255\255\255\255\255\255\
-    \255\255\255\255\255\255\255\255\000\000\000\000\255\255\000\000\
-    \255\255\255\255\255\255\255\255\255\255\052\000\000\000\000\000\
-    \255\255\000\000\255\255\000\000\255\255\255\255\086\000\255\255\
-    \077\000\255\255\000\000\000\000\255\255\081\000\255\255\255\255\
-    \255\255\096\000\255\255\255\255\095\000\000\000\104\000\000\000\
-    \255\255\105\000\000\000\000\000\255\255\000\000\255\255\255\255\
-    \255\255\000\000\255\255\000\000\000\000\000\000\255\255\255\255\
-    \000\000\255\255\000\000\255\255\084\000\000\000\018\000\022\000\
-    \000\000\000\000\000\000\026\000\053\000\255\255\098\000\070\000\
-    \000\000\108\000\255\255\000\000\091\000\255\255\255\255\255\255\
-    \000\000\255\255\000\000\000\000\255\255\255\255\069\000\255\255\
-    \000\000\000\000\046\000\044\000\000\000\000\000\045\000\255\255\
-    \085\000\255\255\000\000\255\255\255\255\255\255\255\255\255\255\
-    \000\000\000\000\255\255\087\000\000\000\000\000\255\255\255\255\
-    \255\255\046\000\000\000\000\000\255\255\255\255\000\000\255\255\
-    \255\255\000\000\255\255\255\255\000\000\255\255\255\255\000\000\
-    \255\255\000\000\255\255\255\255\255\255\000\000\255\255\088\000\
-    \000\000\000\000\000\000\083\000\000\000\255\255\037\000\255\255\
-    \000\000\000\000\255\255\255\255\000\000\000\000\255\255\000\000\
-    \255\255\255\255\000\000\047\000\255\255\255\255\000\000\000\000\
-    \000\000\000\000\255\255\000\000\255\255\000\000\255\255\096\000\
-    \255\255\000\000\095\000\000\000\255\255\255\255\255\255\255\255\
-    \255\255\100\000\096\000\042\000\043\000\095\000\000\000\255\255\
-    \255\255\255\255\000\000\255\255\255\255\096\000\255\255\255\255\
-    \095\000\000\000\255\255\000\000\000\000\000\000\255\255\091\000\
-    \100\000\000\000\000\000\096\000\255\255\255\255\095\000\255\255\
-    \100\000\096\000\000\000\255\255\095\000\046\000\044\000\000\000\
-    \000\000\045\000\255\255\000\000\096\000\255\255\000\000\095\000\
-    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\100\000\
-    \000\000\000\000\000\000\255\255\046\000\255\255\255\255\255\255\
-    \000\000\255\255\000\000\000\000\000\000\000\000\255\255\000\000\
-    \000\000\255\255\255\255\255\255\000\000\000\000\000\000\255\255\
-    \255\255\255\255\000\000\255\255\255\255\255\255\000\000\255\255\
-    \255\255\255\255\255\255\000\000\000\000\255\255\255\255\255\255\
-    \000\000\255\255\000\000\000\000\000\000\000\000\000\000\096\000\
-    \000\000\000\000\106\000\000\000\104\000\255\255\000\000\000\000\
-    \255\255\000\000\000\000\000\000\000\000\099\000\000\000\255\255\
-    \255\255\255\255\000\000\255\255\255\255\255\255\255\255\000\000\
-    \102\000\000\000\255\255\255\255\255\255\000\000\255\255\000\000\
-    \255\255\000\000\000\000\000\000\098\000\255\255\103\000\000\000\
-    \255\255\255\255\255\255\255\255\101\000\000\000\255\255\255\255\
-    \255\255\054\000\255\255\255\255\255\255\000\000\255\255\107\000\
-    \255\255\044\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\255\
-    \255\255\255\255\000\000\255\255\000\000\000\000\000\000\000\000\
-    \255\255\000\000\255\255\000\000\255\255\000\000\255\255\255\255\
-    \255\255\000\000\000\000\055\000\000\000\000\000\255\255\255\255\
-    \000\000\255\255\255\255\255\255\000\000\000\000\000\000\255\255\
-    \255\255\000\000\255\255\000\000\000\000\255\255\000\000\255\255\
-    \056\000\255\255\255\255\000\000\000\000\000\000\255\255\255\255\
-    \000\000\255\255\000\000\000\000\255\255\255\255\255\255\255\255\
-    \000\000\000\000\000\000\000\000\255\255\096\000\000\000\255\255\
-    \000\000\255\255\000\000\000\000\000\000\000\000\000\000\255\255\
-    \098\000\000\000\255\255\000\000\255\255\057\000\000\000\000\000\
-    \000\000\000\000\000\000\096\000\255\255\255\255\000\000\255\255\
-    \000\000\000\000\255\255\255\255\000\000\000\000\255\255\000\000\
-    \000\000\096\000\000\000\000\000\000\000\000\000\000\000\096\000\
-    \255\255\255\255\255\255\000\000\044\000\000\000\000\000\000\000\
-    \255\255\000\000\096\000\255\255\000\000\255\255\000\000\000\000\
-    \255\255\255\255\255\255\255\255\000\000\000\000\000\000\059\000\
-    \255\255\255\255\058\000\255\255\255\255\255\255\000\000\000\000\
-    \255\255\255\255\000\000\255\255\000\000\000\000\255\255\000\000\
-    \255\255\000\000\000\000\255\255\000\000\000\000\000\000\061\000\
-    \255\255\255\255\000\000\255\255\000\000\000\000\000\000\000\000\
-    \000\000\255\255\000\000\000\000\255\255\000\000\255\255\000\000\
-    \000\000\000\000\000\000\000\000\255\255\255\255\255\255\000\000\
-    \062\000\000\000\000\000\255\255\255\255\062\000\060\000\255\255\
-    \000\000\255\255\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\062\000\064\000\255\255\000\000\000\000\
-    \255\255\000\000\000\000\000\000\255\255\255\255\000\000\255\255\
-    \000\000\000\000\255\255\255\255\255\255\000\000\000\000\255\255\
-    \000\000\255\255\255\255\000\000\000\000\255\255\000\000\255\255\
-    \000\000\062\000\062\000\062\000\000\000\062\000\000\000\000\000\
-    \000\000\000\000\062\000\000\000\062\000\000\000\062\000\000\000\
-    \000\000\000\000\255\255\255\255\000\000\255\255\000\000\062\000\
-    \062\000\065\000\000\000\255\255\062\000\000\000\255\255\000\000\
-    \000\000\062\000\062\000\000\000\062\000\000\000\000\000\000\000\
-    \000\000\000\000\062\000\027\000\255\255\255\255\000\000\255\255\
-    \000\000\000\000\000\000\000\000\000\000\000\000\062\000\062\000\
-    \062\000\000\000\000\000\062\000\000\000\255\255\000\000\000\000\
-    \062\000\062\000\000\000\062\000\000\000\000\000\000\000\000\000\
-    \062\000\062\000\062\000\000\000\255\255\000\000\062\000\066\000\
-    \000\000\255\255\000\000\062\000\000\000\062\000\062\000\062\000\
-    \000\000\062\000\000\000\255\255\000\000\000\000\255\255\255\255\
-    \000\000\255\255\000\000\000\000\255\255\000\000\000\000\000\000\
-    \062\000\062\000\000\000\062\000\062\000\062\000\062\000\000\000\
-    \000\000\255\255\000\000\000\000\000\000\000\000\000\000\062\000\
-    \000\000\062\000\000\000\255\255\000\000\255\255\255\255\255\255\
-    \255\255\255\255\000\000\000\000\000\000\000\000\255\255\000\000\
-    \255\255\000\000\255\255\000\000\062\000\062\000\255\255\062\000\
-    \255\255\000\000\000\000\255\255\255\255\000\000\000\000\255\255\
-    \000\000\000\000\000\000\000\000\000\000\255\255\255\255\000\000\
-    \255\255\000\000\000\000\000\000\000\000\000\000\255\255\000\000\
-    \000\000\000\000\000\000\000\000\255\255\255\255\255\255\000\000\
-    \255\255\000\000\255\255\255\255\255\255\255\255\000\000\255\255\
-    \000\000\255\255\000\000\000\000\000\000\255\255\000\000\255\255\
-    \073\000\000\000\000\000\255\255\000\000\071\000\000\000\072\000\
-    \000\000\000\000\000\000\000\000\255\255\255\255\000\000\255\255\
-    \000\000\000\000\255\255\255\255\000\000\255\255\000\000\000\000\
-    \027\000\255\255\000\000\255\255\255\255\000\000\000\000\000\000\
-    \000\000\255\255\255\255\255\255\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\255\255\255\255\255\255\027\000\
-    \073\000\073\000\000\000\000\000\000\000\000\000\073\000\000\000\
-    \000\000\074\000\000\000\073\000\000\000\073\000\074\000\000\000\
-    \000\000\255\255\255\255\000\000\255\255\000\000\000\000\000\000\
-    \000\000\073\000\073\000\000\000\074\000\000\000\073\000\255\255\
-    \255\255\255\255\000\000\255\255\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\255\255\000\000\000\000\000\000\255\255\076\000\
-    \076\000\000\000\074\000\074\000\074\000\076\000\000\000\000\000\
-    \000\000\000\000\076\000\000\000\076\000\074\000\000\000\074\000\
-    \000\000\000\000\000\000\027\000\255\255\000\000\000\000\255\255\
-    \076\000\076\000\000\000\000\000\000\000\076\000\000\000\000\000\
-    \000\000\000\000\074\000\074\000\000\000\074\000\000\000\000\000\
-    \000\000\255\255\027\000\073\000\073\000\000\000\000\000\255\255\
-    \000\000\073\000\000\000\000\000\074\000\000\000\073\000\000\000\
-    \073\000\074\000\000\000\000\000\000\000\255\255\255\255\000\000\
-    \000\000\255\255\000\000\255\255\073\000\073\000\255\255\074\000\
-    \000\000\073\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\255\255\076\000\076\000\000\000\
-    \000\000\000\000\255\255\076\000\000\000\255\255\255\255\000\000\
-    \076\000\000\000\076\000\255\255\000\000\074\000\074\000\074\000\
-    \255\255\000\000\000\000\000\000\000\000\000\000\076\000\076\000\
-    \074\000\000\000\074\000\076\000\000\000\000\000\255\255\000\000\
-    \000\000\000\000\255\255\000\000\000\000\000\000\000\000\255\255\
-    \000\000\000\000\000\000\000\000\000\000\074\000\074\000\000\000\
-    \074\000\000\000\073\000\000\000\000\000\255\255\000\000\000\000\
-    \000\000\000\000\000\000\000\000\255\255\255\255\255\255\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\255\
-    \000\000\255\255\000\000\000\000\000\000\000\000\000\000\255\255\
-    \000\000\078\000\000\000\255\255\255\255\255\255\000\000\000\000\
-    \000\000\000\000\000\000\000\000\255\255\255\255\255\255\255\255\
-    \255\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\255\255\255\255\000\000\255\255\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\255\255\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\255\255\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\255\255\000\000\000\000\000\000\
-    \000\000\255\255\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
-    \255\255";
-  Lexing.lex_check = 
-   "\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
-    \255\255\000\000\000\000\008\000\019\000\000\000\007\000\017\000\
-    \017\000\021\000\023\000\017\000\021\000\025\000\040\000\045\000\
-    \025\000\092\000\095\000\105\000\108\000\028\000\028\000\255\255\
-    \000\000\028\000\255\255\000\000\004\000\007\000\017\000\255\255\
-    \007\000\062\000\000\000\005\000\062\000\000\000\003\000\007\000\
-    \015\000\016\000\007\000\255\255\028\000\025\000\255\255\029\000\
-    \029\000\027\000\025\000\029\000\027\000\000\000\001\000\006\000\
-    \010\000\011\000\007\000\012\000\013\000\255\255\255\255\025\000\
-    \025\000\255\255\047\000\255\255\048\000\047\000\029\000\048\000\
-    \030\000\028\000\255\255\030\000\049\000\255\255\255\255\049\000\
-    \255\255\027\000\255\255\255\255\255\255\062\000\027\000\031\000\
-    \255\255\255\255\031\000\255\255\255\255\255\255\025\000\025\000\
-    \025\000\255\255\067\000\081\000\027\000\067\000\081\000\255\255\
-    \030\000\025\000\255\255\025\000\080\000\030\000\032\000\080\000\
-    \255\255\032\000\255\255\000\000\000\000\002\000\020\000\031\000\
-    \007\000\007\000\051\000\030\000\031\000\051\000\025\000\025\000\
-    \088\000\025\000\027\000\027\000\027\000\255\255\255\255\255\255\
-    \255\255\083\000\031\000\255\255\083\000\027\000\032\000\027\000\
-    \093\000\093\000\255\255\032\000\093\000\047\000\067\000\048\000\
-    \255\255\030\000\030\000\030\000\255\255\033\000\255\255\049\000\
-    \033\000\032\000\027\000\027\000\030\000\027\000\030\000\093\000\
-    \031\000\031\000\031\000\255\255\255\255\084\000\255\255\255\255\
-    \084\000\255\255\255\255\031\000\047\000\031\000\048\000\255\255\
-    \086\000\030\000\030\000\086\000\030\000\033\000\049\000\032\000\
-    \032\000\032\000\033\000\034\000\255\255\255\255\034\000\255\255\
-    \031\000\031\000\032\000\031\000\032\000\051\000\255\255\255\255\
-    \033\000\255\255\035\000\255\255\087\000\035\000\081\000\087\000\
-    \032\000\082\000\255\255\255\255\082\000\080\000\080\000\032\000\
-    \032\000\097\000\032\000\034\000\097\000\255\255\103\000\255\255\
-    \034\000\103\000\255\255\255\255\051\000\255\255\033\000\033\000\
-    \033\000\255\255\035\000\255\255\255\255\255\255\034\000\035\000\
-    \255\255\033\000\255\255\033\000\083\000\255\255\017\000\021\000\
-    \255\255\255\255\255\255\025\000\035\000\035\000\107\000\033\000\
-    \255\255\107\000\036\000\255\255\028\000\036\000\033\000\033\000\
-    \255\255\033\000\255\255\255\255\034\000\034\000\034\000\062\000\
-    \255\255\255\255\037\000\037\000\255\255\255\255\037\000\034\000\
-    \084\000\034\000\255\255\035\000\035\000\035\000\029\000\027\000\
-    \255\255\255\255\036\000\086\000\255\255\255\255\035\000\036\000\
-    \035\000\037\000\255\255\255\255\034\000\034\000\255\255\034\000\
-    \047\000\255\255\048\000\037\000\255\255\036\000\030\000\255\255\
-    \037\000\255\255\049\000\035\000\035\000\255\255\035\000\087\000\
-    \255\255\255\255\255\255\082\000\255\255\031\000\037\000\038\000\
-    \255\255\255\255\038\000\039\000\255\255\255\255\039\000\255\255\
-    \067\000\081\000\255\255\036\000\036\000\036\000\255\255\255\255\
-    \255\255\255\255\080\000\255\255\032\000\255\255\036\000\099\000\
-    \036\000\255\255\099\000\255\255\037\000\037\000\037\000\038\000\
-    \051\000\094\000\094\000\039\000\038\000\094\000\255\255\037\000\
-    \039\000\037\000\255\255\036\000\036\000\101\000\036\000\083\000\
-    \101\000\255\255\038\000\255\255\255\255\255\255\039\000\093\000\
-    \094\000\255\255\255\255\102\000\037\000\037\000\102\000\037\000\
-    \100\000\100\000\255\255\033\000\100\000\046\000\046\000\255\255\
-    \255\255\046\000\053\000\255\255\106\000\053\000\255\255\106\000\
-    \038\000\038\000\038\000\084\000\039\000\039\000\039\000\100\000\
-    \255\255\255\255\255\255\038\000\046\000\038\000\086\000\039\000\
-    \255\255\039\000\255\255\255\255\255\255\255\255\046\000\255\255\
-    \255\255\034\000\053\000\046\000\255\255\255\255\255\255\053\000\
-    \038\000\038\000\255\255\038\000\039\000\039\000\255\255\039\000\
-    \035\000\046\000\087\000\255\255\255\255\053\000\054\000\082\000\
-    \255\255\054\000\255\255\255\255\255\255\255\255\255\255\097\000\
-    \255\255\255\255\099\000\255\255\103\000\055\000\255\255\255\255\
-    \055\000\255\255\255\255\255\255\255\255\094\000\255\255\046\000\
-    \046\000\046\000\255\255\053\000\053\000\053\000\054\000\255\255\
-    \101\000\255\255\046\000\054\000\046\000\255\255\053\000\255\255\
-    \053\000\255\255\255\255\255\255\107\000\055\000\102\000\255\255\
-    \036\000\054\000\055\000\056\000\100\000\255\255\056\000\046\000\
-    \046\000\053\000\046\000\053\000\053\000\255\255\053\000\106\000\
-    \055\000\037\000\255\255\255\255\255\255\255\255\255\255\255\255\
-    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\054\000\
-    \054\000\054\000\255\255\056\000\255\255\255\255\255\255\255\255\
-    \056\000\255\255\054\000\255\255\054\000\255\255\055\000\055\000\
-    \055\000\255\255\255\255\054\000\255\255\255\255\056\000\057\000\
-    \255\255\055\000\057\000\055\000\255\255\255\255\255\255\054\000\
-    \054\000\255\255\054\000\255\255\255\255\038\000\255\255\058\000\
-    \055\000\039\000\058\000\255\255\255\255\255\255\055\000\055\000\
-    \255\255\055\000\255\255\255\255\056\000\056\000\056\000\057\000\
-    \255\255\255\255\255\255\255\255\057\000\099\000\255\255\056\000\
-    \255\255\056\000\255\255\255\255\255\255\255\255\255\255\058\000\
-    \094\000\255\255\057\000\255\255\058\000\056\000\255\255\255\255\
-    \255\255\255\255\255\255\101\000\056\000\056\000\255\255\056\000\
-    \255\255\255\255\058\000\059\000\255\255\255\255\059\000\255\255\
-    \255\255\102\000\255\255\255\255\255\255\255\255\255\255\100\000\
-    \057\000\057\000\057\000\255\255\046\000\255\255\255\255\255\255\
-    \053\000\255\255\106\000\057\000\255\255\057\000\255\255\255\255\
-    \058\000\058\000\058\000\059\000\255\255\255\255\255\255\058\000\
-    \059\000\060\000\057\000\058\000\060\000\058\000\255\255\255\255\
-    \057\000\057\000\255\255\057\000\255\255\255\255\059\000\255\255\
-    \061\000\255\255\255\255\061\000\255\255\255\255\255\255\060\000\
-    \058\000\058\000\255\255\058\000\255\255\255\255\255\255\255\255\
-    \255\255\060\000\255\255\255\255\054\000\255\255\060\000\255\255\
-    \255\255\255\255\255\255\255\255\059\000\059\000\059\000\255\255\
-    \061\000\255\255\255\255\055\000\060\000\061\000\059\000\059\000\
-    \255\255\059\000\255\255\255\255\255\255\255\255\255\255\255\255\
-    \255\255\255\255\255\255\061\000\061\000\063\000\255\255\255\255\
-    \063\000\255\255\255\255\255\255\059\000\059\000\255\255\059\000\
-    \255\255\255\255\060\000\060\000\060\000\255\255\255\255\064\000\
-    \255\255\056\000\064\000\255\255\255\255\060\000\255\255\060\000\
-    \255\255\061\000\061\000\061\000\255\255\063\000\255\255\255\255\
-    \255\255\255\255\063\000\255\255\061\000\255\255\061\000\255\255\
-    \255\255\255\255\060\000\060\000\255\255\060\000\255\255\064\000\
-    \063\000\063\000\255\255\065\000\064\000\255\255\065\000\255\255\
-    \255\255\061\000\061\000\255\255\061\000\255\255\255\255\255\255\
-    \255\255\255\255\064\000\064\000\066\000\057\000\255\255\066\000\
-    \255\255\255\255\255\255\255\255\255\255\255\255\063\000\063\000\
-    \063\000\255\255\255\255\065\000\255\255\058\000\255\255\255\255\
-    \065\000\063\000\255\255\063\000\255\255\255\255\255\255\255\255\
-    \064\000\064\000\064\000\255\255\066\000\255\255\065\000\065\000\
-    \255\255\066\000\255\255\064\000\255\255\064\000\063\000\063\000\
-    \255\255\063\000\255\255\070\000\255\255\255\255\070\000\066\000\
-    \255\255\071\000\255\255\255\255\071\000\255\255\255\255\255\255\
-    \064\000\064\000\255\255\064\000\065\000\065\000\065\000\255\255\
-    \255\255\059\000\255\255\255\255\255\255\255\255\255\255\065\000\
-    \255\255\065\000\255\255\070\000\255\255\066\000\066\000\066\000\
-    \070\000\071\000\255\255\255\255\255\255\255\255\071\000\255\255\
-    \066\000\255\255\066\000\255\255\065\000\065\000\070\000\065\000\
-    \072\000\255\255\255\255\072\000\071\000\255\255\255\255\060\000\
-    \255\255\255\255\255\255\255\255\255\255\066\000\066\000\255\255\
-    \066\000\255\255\255\255\255\255\255\255\255\255\061\000\255\255\
-    \255\2