Source

OCaml-WebFramework / cgi-bin / template.ml

Full commit
(*
** template.ml for OCaml-WebFramework
**
** Copyright (C) 2012 Pierre Surply
** <pierre.surply@gmail.com>
**
** This file is part of OCaml-WebFramework.
**
**    OCaml-WebFramework 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 3 of the License, or
**    (at your option) any later version.
**
**    OCaml-WebFramework 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 OCaml-WebFramework.  If not, see <http://www.gnu.org/licenses/>.
**
** Started on  Sat Sep 15 13:45:19 2012 Pierre Surply
Last update Thu Oct 11 15:33:20 2012 pierre surply
*)

let template_dir = "../templates/"
let base = "base"

let regex_link = Str.regexp "{@ \\(.*\\) @}"
let regex_fun = Str.regexp "{% \\(.*\\) %}"
let regex_include = Str.regexp "{ \\([^{}]*\\) }"
let regex_part = Str.regexp
  "\\[begin \\(.*\\)\\]\\(\\([^][]\\|\n\\)*\\)\\[end\\]"

let apply_function s =
  Cgi_functions.get_function (Str.matched_group 1 s)

let rec extract_part s start org_list=
  if (try Str.search_forward regex_part s start
    with Not_found -> -1) > -1 then
    begin
      let start = Str.match_end () in
      let label = Str.matched_group 1 s in
      let content = Str.matched_group 2 s in
      (label, content)::extract_part s start org_list
    end
  else org_list

let rec get_part label = function
  | [] -> "<!-- " ^ label ^ " -->"
  | (l, c)::t ->
    if l = label then c
    else get_part label t

let fill_part part s =
  get_part (Str.matched_group 1 s) part

let make_page file =
  let rec r_load_template f =
    try
      let line = input_line f in
      line ^ "\n" ^ r_load_template f
    with End_of_file -> close_in f; ""
  in
  let rec r_load file part=
    let s = r_load_template (open_in (template_dir ^ file)) in
    let s_applied_fun = Str.global_substitute regex_fun
      apply_function s in
    let s_filled = Str.global_substitute regex_include
      (fill_part part) s_applied_fun in
    let part = extract_part s_filled 0 part in
    if (try Str.search_forward regex_link s_filled 0
      with Not_found -> -1) > -1 then
      r_load (Str.matched_group 1 s_filled) part
    else
      get_part base part
  in
  r_load file []