source: code/trunk/cli/html.ml@ 2

Last change on this file since 2 was 2, checked in by fox, 4 years ago

Samhain 21

Converter

  • type selection
  • subdir conversion
  • htm extension

Gemini

  • index.gmi
  • topics and latest
  • gmi.atom feed

Add pull (http(s)) operation

  • peers.pub.conf and peers.priv.conf

HTML5 format & fixes by Novaburst
Phony target (thanks Gergely)

May

Basic unit renamed from Note to Text.
New modular text-parser, internal to Logarion, for generic notation parsing. The default input format is now a much plainer text.
Logarion created texts have part of the UUID in filename.
Logarion's index re-written in Messagepack format. Removed indices command. They are generated during convert.

File size: 5.1 KB
Line 
1let wrap (title:string) (subtitle:string) body =
2 {|<!DOCTYPE HTML>|}
3 ^ {|<html><head><title>|}
4 ^ subtitle ^ " | " ^ title
5 ^ {|</title><link rel="stylesheet" href="main.css">|}
6 ^ {|<link rel="alternate" href="feed.atom" type="application/atom+xml">|}
7 ^ {|<meta charset="utf-8"/>|}
8 ^ {|<meta name="viewport" content="width=device-width, initial-scale=1.0">|}
9 ^ {|</head><body><header><a href=".">|} ^ title
10 ^ {|</a> <nav><a href="feed.atom" id="feed">feed</a></nav></header>|} ^ body
11 ^ "</body></html>"
12
13let topic_link root topic =
14 let replaced_space = String.map (function ' '->'+' | x->x) in
15 {|<a href="index.|} ^ root ^ {|.htm#|} ^ replaced_space topic ^ {|">|}
16 ^ String.capitalize_ascii topic ^ "</a>"
17
18let page archive_title text =
19 let open Logarion in
20 let open Text in
21 let module T = Parsers.Plain_text.Make (Converter.Html) in
22 let sep_append ?(sep=", ") a x = match a,x with "",_ -> x | _, "" -> a | _ -> a ^ sep ^ x in
23 let opt_kv key value = if String.length value > 0 then "<dt>" ^ key ^ "<dd>" ^ value else "" in
24(* let author acc auth = sep_append acc Person.(auth.name ^ " ") in*)
25 let authors = (Person.Set.to_string text.authors ^ " ") in
26 let keywords = str_set "keywords" text in
27 let header =
28 let time x = {|<time datetime="|} ^ x ^ {|">|} ^ x ^ "</time>" in
29 let topic_links x =
30 let to_linked t a =
31 let ts = Topic_set.of_string t in
32 sep_append a (List.fold_left (fun a t -> sep_append ~sep:" > " a (topic_link (List.hd ts) t)) "" ts) in
33 String_set.fold to_linked x "" in
34 "<article><header><dl>"
35 ^ opt_kv "Title:" text.title
36 ^ opt_kv "Authors:" authors
37 ^ opt_kv "Date: " (time (Date.(pretty_date @@ listing text.date)))
38 ^ opt_kv "Series: " (str_set "series" text)
39 ^ opt_kv "Topics: " (topic_links (set "topics" text))
40 ^ opt_kv "Keywords: " keywords
41 ^ opt_kv "Id: " (Id.to_string text.uuid)
42 ^ {|</dl></header><pre style="white-space:pre-wrap">|} in
43 wrap archive_title text.title ((T.of_string text.body header) ^ "</pre></article>")
44
45let to_dated_links ?(limit) meta_list =
46 let meta_list = match limit with
47 | None -> meta_list
48 | Some limit->
49 let rec reduced acc i = function
50 | [] -> acc
51 | h::t -> if i < limit then reduced (h::acc) (i+1) t else acc in
52 List.rev @@ reduced [] 0 meta_list
53 in
54 List.fold_left
55 (fun a m ->
56 a ^ Logarion.(Date.(pretty_date (listing m.Text.date)) ^ " ")
57 ^ {|<a href="|} ^ Logarion.Text.short_id m ^ {|.htm">|} ^ m.Logarion.Text.title ^ "</a><br>")
58 "" meta_list
59
60let date_index ?(limit) title meta_list =
61 match limit with
62 | Some limit -> wrap title "Index" (to_dated_links ~limit meta_list)
63 | None -> wrap title "Index" (to_dated_links meta_list)
64
65let fold_topic_roots topic_roots =
66 let list_item root t = "<li>" ^ topic_link root t in
67 "<nav><h2>Main topics</h2>"
68 ^ List.fold_left (fun a x -> a ^ list_item x x) "<ul>" (List.rev topic_roots)
69 ^ "</ul></nav>"
70
71let fold_topics topic_map topic_roots metas =
72 let open Logarion in
73 let rec unordered_list root topic =
74 List.fold_left (fun a x -> a ^ list_item root x) "<ul>" topic
75 ^ "</ul>"
76 and sub_items root topic = match Topic_set.Map.find_opt topic topic_map with
77 | None -> ""
78 | Some (_, subtopics) -> unordered_list root (String_set.elements subtopics)
79 and list_item root t =
80 let item =
81 if List.exists (fun x -> String_set.mem t (String_set.map Topic_set.topic (Text.set "topics" x))) metas
82 then topic_link root t else String.capitalize_ascii t
83 in
84 "<li>" ^ item ^ sub_items root t
85 in
86 "<nav><h2>Topics</h2>"
87 ^ List.fold_left (fun a x -> a ^ list_item x x) "<ul>" (List.rev topic_roots)
88 ^ "</ul></nav>"
89
90let text_item path meta =
91 let open Logarion in
92 "<time>" ^ Date.(pretty_date (listing meta.Text.date))
93 ^ {|</time> <a href="|} ^ path ^ Text.short_id meta ^ {|.htm">|} ^ meta.Text.title
94 ^ "</a><br>"
95
96let listing_index topic_map topic_roots path metas =
97 let rec item_group topics =
98 List.fold_left (fun acc topic -> acc ^ sub_groups topic ^ items topic) "" topics
99 and sub_groups topic = match Logarion.Topic_set.Map.find_opt topic topic_map with
100 | None -> ""
101 | Some (_, subtopics) -> item_group (Logarion.String_set.elements subtopics)
102 and items topic =
103 let items =
104 let open Logarion in
105 List.fold_left
106 (fun a e ->
107 if String_set.mem topic (String_set.map (Logarion.Topic_set.topic) (Text.set "Topics" e))
108 then text_item path e ^ a else a) "" metas in
109 match items with
110 | "" -> ""
111 | x -> {|<h2 id="|} ^ topic ^ {|">|} ^ String.capitalize_ascii topic ^ "</h2>" ^ x
112 in
113 "<nav><h1>Texts</h1>" ^ item_group topic_roots ^ "</nav>"
114
115let topic_main_index title topic_roots metas =
116 wrap title "Topics"
117 (fold_topic_roots topic_roots
118 ^ "<nav><h1>Latest</h1>" ^ to_dated_links ~limit:10 metas
119 ^ {|<a href="index.date.htm">More by date</a></nav>|} )
120
121let topic_sub_index title topic_map topic_root metas =
122 wrap title topic_root
123 (fold_topics topic_map [topic_root] metas
124(* ^ {|<a href=".atom" id="feed">|}^ String.capitalize_ascii topic_root ^{| feed </a>|}*)
125 ^ listing_index topic_map [topic_root] "" metas)
Note: See TracBrowser for help on using the repository browser.