X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=scripts%2Flib%2Fwikilib.ml;h=a4a8e77ff39c02f74a610313b93d7017de953348;hb=282f080ee9105659802e955f4b0142de5e45d843;hp=557d7a95162ddab10b862d2ecf0c51a5bafa0832;hpb=a0227a655cb4a121c54e4c2762d6c2351fccc139;p=cocanwiki.git diff --git a/scripts/lib/wikilib.ml b/scripts/lib/wikilib.ml index 557d7a9..a4a8e77 100644 --- a/scripts/lib/wikilib.ml +++ b/scripts/lib/wikilib.ml @@ -1,7 +1,7 @@ (* COCANWIKI - a wiki written in Objective CAML. * Written by Richard W.M. Jones . * Copyright (C) 2004 Merjis Ltd. - * $Id: wikilib.ml,v 1.5 2006/03/27 16:43:44 rich Exp $ + * $Id: wikilib.ml,v 1.6 2006/07/26 14:59:04 rich Exp $ * * 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 @@ -348,10 +348,10 @@ let _markup_paragraph dbh hostid text = (* close tags ignored *) escape_html first :: "</" :: escape_html elem :: ">" :: loop (rest, []) - | FoundOpen (first, elem, rest) when elem = "nowiki" -> + | FoundOpen (first, "nowiki", rest) -> (* handle specially ... *) - escape_html first :: loop (rest, elem :: []) - | FoundOpen (first, elem, rest) when elem = "br" -> + escape_html first :: loop (rest, "nowiki" :: []) + | FoundOpen (first, "br", rest) -> (* handle
specially ... *) escape_html first :: "
" :: loop (rest, []) | FoundOpen (first, elem, rest) -> @@ -374,10 +374,10 @@ let _markup_paragraph dbh hostid text = | FoundClose (first, elem, rest, elem_rest) -> (* non-matching close tag *) escape_html first :: "" :: loop (elem_rest, xs) - | FoundOpen (first, elem, rest) when elem = "nowiki" -> + | FoundOpen (first, "nowiki", rest) -> (* handle specially ... *) - escape_html first :: loop (rest, elem :: stack) - | FoundOpen (first, elem, rest) when elem = "br" -> + escape_html first :: loop (rest, "nowiki" :: stack) + | FoundOpen (first, "br", rest) -> (* handle
specially ... *) escape_html first :: "
" :: loop (rest, stack) | FoundOpen (first, elem, rest) -> @@ -640,11 +640,53 @@ let numbered_re = Pcre.regexp "^(\\#)\\s+(.*)" let preformatted_re = Pcre.regexp "^ (.*)" let html_open_re = Pcre.regexp "^\\s*$" let html_close_re = Pcre.regexp "^\\s*$" +let macro_re = Pcre.regexp "^{{(\\w+)}}$" let xhtml_of_content dbh hostid text = (* Split the text into lines. *) let lines = Pcre.split ~rex:split_lines_re text in + (* Do macro expansion before anything else, because macros could + * contain sections, etc. + *) + let is_macro line = + try + let subs = Pcre.exec ~rex:macro_re line in + let name = Pcre.get_substring subs 1 in + let rows = PGSQL(dbh) "select 1 from macros + where hostid = $hostid and name = $name" in + (match rows with + | [] -> false (* Not an actual macro name from the database. *) + | [_] -> true (* Is an actual macro name. *) + | _ -> assert false (* Uniqueness should stop this from happening. *) + ) + with + Not_found -> false + in + let expand_macro line = + try + let subs = Pcre.exec ~rex:macro_re line in + let name = Pcre.get_substring subs 1 in + let content = + List.hd ( + PGSQL(dbh) "select content from macros + where hostid = $hostid and name = $name" + ) in + (* Split the content into lines of text. *) + let lines = Pcre.split ~rex:split_lines_re content in + lines + with + (Not_found | Failure "hd" | ExtList.List.Empty_list) as exn -> + failwith ("Wikilib: expand_macro: you should never see this: " ^ + Printexc.to_string exn) + in + let rec loop = function + | [] -> [] + | line :: xs when is_macro line -> expand_macro line @ loop xs + | x :: xs -> x :: loop xs + in + let lines = loop lines in + (* HTML blocks span multiple lines, so isolate these out first. *) let rec loop = function | [] -> [] @@ -670,36 +712,37 @@ let xhtml_of_content dbh hostid text = (* Iterate over the lines to isolate headers and paragraphs. *) let lines = - List.map - (function - | STpLine line -> - if Pcre.pmatch ~rex:preformatted_re line then ( - let subs = Pcre.exec ~rex:preformatted_re line in - let line = Pcre.get_substring subs 1 in - STPreformatted [line] - ) - else if Pcre.pmatch ~rex:blank_re line then - STBlank - else if Pcre.pmatch ~rex:heading_re line then ( - let subs = Pcre.exec ~rex:heading_re line in - let count = String.length (Pcre.get_substring subs 1) + 2 in - let line = Pcre.get_substring subs 2 in - STHeading (count, line) - ) - else if Pcre.pmatch ~rex:unnumbered_re line then ( - let subs = Pcre.exec ~rex:unnumbered_re line in - let line = Pcre.get_substring subs 2 in - STUnnumbered [line] - ) - else if Pcre.pmatch ~rex:numbered_re line then ( - let subs = Pcre.exec ~rex:numbered_re line in - let line = Pcre.get_substring subs 2 in - STNumbered [line] - ) else - STParagraph line - | STpHTML html -> - STHTML html - ) lines in + List.map ( + function + | STpLine line -> + if Pcre.pmatch ~rex:preformatted_re line then ( + let subs = Pcre.exec ~rex:preformatted_re line in + let line = Pcre.get_substring subs 1 in + STPreformatted [line] + ) + else if Pcre.pmatch ~rex:blank_re line then + STBlank + else if Pcre.pmatch ~rex:heading_re line then ( + let subs = Pcre.exec ~rex:heading_re line in + let count = String.length (Pcre.get_substring subs 1) + 2 in + let line = Pcre.get_substring subs 2 in + STHeading (count, line) + ) + else if Pcre.pmatch ~rex:unnumbered_re line then ( + let subs = Pcre.exec ~rex:unnumbered_re line in + let line = Pcre.get_substring subs 2 in + STUnnumbered [line] + ) + else if Pcre.pmatch ~rex:numbered_re line then ( + let subs = Pcre.exec ~rex:numbered_re line in + let line = Pcre.get_substring subs 2 in + STNumbered [line] + ) + else + STParagraph line + | STpHTML html -> + STHTML html + ) lines in (* Aggregate paragraphs and lists. *) let rec loop = function