Index: trunk/cli/html.ml
===================================================================
--- trunk/cli/html.ml	(revision 2)
+++ trunk/cli/html.ml	(revision 3)
@@ -1,25 +1,56 @@
-let wrap (title:string) (subtitle:string) body =
-  {|<!DOCTYPE HTML>|}
-  ^ {|<html><head><title>|}
-  ^ subtitle ^ " | " ^ title
-  ^ {|</title><link rel="stylesheet" href="main.css">|}
-  ^ {|<link rel="alternate" href="feed.atom" type="application/atom+xml">|}
-  ^ {|<meta charset="utf-8"/>|}
-  ^ {|<meta name="viewport" content="width=device-width, initial-scale=1.0">|}
-  ^ {|</head><body><header><a href=".">|} ^ title
-  ^ {|</a> <nav><a href="feed.atom" id="feed">feed</a></nav></header>|} ^ body
-  ^ "</body></html>"
+type templates_t = { header: string option; footer: string option }
+type t = { templates : templates_t }
+
+let ext = ".htm"
+let empty_templates = { header = None; footer = None }
+let default_opts = { templates = empty_templates }
+
+let init kv =
+	let open Logarion in
+	let header = match  Store.KV.find "HTM-header" kv with
+		| fname -> Some (File_store.to_string fname)
+		| exception Not_found -> None in
+	let footer = match  Store.KV.find "HTM-footer" kv with
+		| fname -> Some (File_store.to_string fname)
+		| exception Not_found -> None in
+	{ templates = { header; footer} }
+
+let wrap c htm text_title body =
+	let site_title = try Logarion.Store.KV.find "Title" c.Conversion.kv
+		with Not_found -> "" in
+	let replace x = let open Str in
+		global_replace (regexp "{{archive-title}}") site_title x
+		|> global_replace (regexp "{{text-title}}") text_title
+	in
+	let header = match htm.templates.header with 
+	| Some x -> replace x
+	| None -> "<header><a href='.'>" ^ site_title ^
+		"</a><nav><a href='feed.atom' id='feed'>feed</a></nav></header>"
+	in
+	let footer = match htm.templates.footer with  None -> "" | Some x -> replace x in
+  "<!DOCTYPE HTML><html><head><title>" ^ text_title ^ " • " ^ site_title ^ "</title>\n\
+  <link rel='stylesheet' href='main.css'>\
+  <link rel='alternate' href='feed.atom' type='application/atom+xml'>\
+  <meta charset='utf-8'/><meta name='viewport' content='width=device-width, initial-scale=1.0'>\
+  </head><body>\n" ^ header ^ body ^ footer ^ "</body></html>"
 
 let topic_link root topic = 
   let replaced_space = String.map (function ' '->'+' | x->x) in
-  {|<a href="index.|} ^ root ^ {|.htm#|} ^ replaced_space topic ^ {|">|}
+  "<a href='index." ^ replaced_space root ^ ".htm#" ^ replaced_space topic ^ "'>"
   ^ String.capitalize_ascii topic ^ "</a>"
 
-let page archive_title text =
+module HtmlConverter = struct
+	include Converter.Html
+	let angled_uri u a = if String.sub u 0 10 <> "urn:txtid:" then
+		angled_uri u a else angled_uri (String.(sub u 10 (length u - 10)) ^ ext) a
+end
+
+let page htm conversion text =
   let open Logarion in
   let open Text in
-  let module T = Parsers.Plain_text.Make (Converter.Html) in
+  let module T = Parsers.Plain_text.Make (HtmlConverter) in
   let sep_append ?(sep=", ") a x = match a,x with "",_ -> x | _, "" -> a | _ -> a ^ sep ^ x in
-  let opt_kv key value = if String.length value > 0 then "<dt>" ^ key ^ "<dd>" ^ value else "" in
+  let opt_kv key value = if String.length value > 0
+  	then "<dt>" ^ key ^ "<dd>" ^ value else "" in
 (*  let author acc auth = sep_append acc Person.(auth.name ^ " ") in*)
   let authors = (Person.Set.to_string text.authors ^ " ") in
@@ -39,7 +70,7 @@
     ^ opt_kv "Topics: " (topic_links (set "topics" text))
     ^ opt_kv "Keywords: " keywords
-    ^ opt_kv "Id: " (Id.to_string text.uuid)
+    ^ opt_kv "Id: " text.id
     ^ {|</dl></header><pre style="white-space:pre-wrap">|} in
-  wrap archive_title text.title ((T.of_string text.body header) ^ "</pre></article>")
+  wrap conversion htm text.title ((T.of_string text.body header) ^ "</pre></article>")
 
 let to_dated_links ?(limit) meta_list =
@@ -58,8 +89,8 @@
     "" meta_list
 
-let date_index ?(limit) title meta_list =
+let date_index ?(limit) conv htm meta_list =
   match limit with
-  | Some limit -> wrap title "Index" (to_dated_links ~limit meta_list)
-  | None -> wrap title "Index" (to_dated_links meta_list)
+  | Some limit -> wrap conv htm "Index" (to_dated_links ~limit meta_list)
+  | None -> wrap conv htm "Index" (to_dated_links meta_list)
 
 let fold_topic_roots topic_roots =
@@ -113,13 +144,34 @@
   "<nav><h1>Texts</h1>" ^ item_group topic_roots ^ "</nav>"
 
-let topic_main_index title topic_roots metas =
-  wrap title "Topics"
+let topic_main_index conv htm topic_roots metas =
+  wrap conv htm "Topics"
     (fold_topic_roots topic_roots
      ^ "<nav><h1>Latest</h1>" ^ to_dated_links ~limit:10 metas
      ^ {|<a href="index.date.htm">More by date</a></nav>|} )
 
-let topic_sub_index title topic_map topic_root metas =
-  wrap title topic_root
+let topic_sub_index conv htm topic_map topic_root metas =
+  wrap conv htm topic_root
     (fold_topics topic_map [topic_root] metas
 (*     ^ {|<a href=".atom" id="feed">|}^ String.capitalize_ascii topic_root ^{| feed </a>|}*)
      ^ listing_index topic_map [topic_root] "" metas)
+
+open Logarion
+let indices htm c =
+	let file name = Logarion.File_store.file (Filename.concat c.Conversion.dir name) in
+	let index_name = try Store.KV.find "HTM-index" c.Conversion.kv with Not_found -> "index.html" in
+	let title = try Store.KV.find "Title" c.Conversion.kv with Not_found -> "" in
+
+	if index_name <> "" then
+		file index_name (topic_main_index c htm c.topic_roots c.texts);
+
+	file "index.date.htm" (date_index c htm c.texts);
+
+	List.iter
+		(fun root -> file ("index." ^ root ^ ".htm") (topic_sub_index c htm c.topics root c.texts))
+		c.topic_roots;
+
+	let base_url = try
+		let _i = Str.(search_forward (regexp "https?://[^;]*") (Store.KV.find "Locations" c.kv) 0) in
+		Str.(matched_string (Store.KV.find "Locations" c.kv))
+		with Not_found -> prerr_endline "Missing location for HTTP(S)"; "" in
+	file "feed.atom" (Atom.feed title c.id base_url "text/html" c.texts)
