123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152(*
* Copyright (c) 2010-2013 Anil Madhavapeddy <anil@recoil.org>
* Copyright (c) 2013 Richard Mortier <mort@cantab.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)(** Wiki management: entries, ATOM feeds, etc. *)openPrintfopenLwt.InfixopenCowopenAtom_feedopenDateopenCow.Htmltypebody=|Fileofstring|HtmlofHtml.ttypeentry={updated:date;author:Atom.author;subject:string;body:body;permalink:string;}lethtml_of_authorauthor=list[string"Last modified by ";matchauthor.Atom.uriwith|None->stringauthor.Atom.name|Someuri->a~href:(Uri.of_stringuri)(stringauthor.Atom.name)]letatom_dated=(d.year,d.month,d.day,d.hour,d.min)letshort_html_of_dated=Xml.(list[intd.day;string" ";xml_of_monthd.month;string" ";intd.year])letbody_of_entry{read_entry;_}e=matche.bodywith|Filex->read_entryx|Htmlx->Lwt.returnxletcompare_datese1e2=letd1=e1.updatedinletd2=e2.updatedincompare(d1.year,d1.month,d1.day)(d2.year,d2.month,d2.day)(* Convert a wiki record into an Html.t fragment *)lethtml_of_entryread_filee=body_of_entryread_filee>|=funb->h3(a~href:(Uri.of_stringe.permalink)(stringe.subject))++blethtml_of_indexfeed=feed.read_entry"index.md">|=funb->div~cls:"wiki_entry"(div~cls:"wiki_entry_body"b)letpermalinkfeede=sprintf"%s%s%s"feed.base_urifeed.ide.permalinklethtml_of_recent_updatesfeed(entries:entrylist)=letents=List.rev(List.sortcompare_datesentries)inlethtml_of_ente=a~href:(Uri.of_string@@permalinkfeede)(stringe.subject)++span~cls:"lastmod"(string"("++short_html_of_datee.updated++string")")inh6(string"Recent Updates")++ul~cls:"side-nav"(List.maphtml_of_entents)(* Main wiki page; disqus comments are for full entry pages *)lethtml_of_page~content~sidebar=content>|=funcontent->letsidebar=matchsidebarwith|[]->[]|sidebar->aside~cls:"medium-3 large-3 columns panel"sidebarinletopenHtmlindiv~cls:"row"(div~cls:"small-12 medium-10 large-9 columns"(h2(list[string"Documentation ";small(string"and guides")])))++div~cls:"row"(div~cls:"small-12 medium-10 large-9 columns"content++sidebar)letcmp_entab=Atom.compare(atom_datea.updated)(atom_dateb.updated)letpermalink_existsxentries=List.exists(fune->e.permalink=x)entriesletatom_entry_of_ent(feed:Atom_feed.t)e=letperma_uri=Uri.of_string(permalinkfeede)inletlinks=[Atom.mk_link~rel:`alternate~typ:"text/html"perma_uri]inbody_of_entryfeede>|=funcontent->letmeta={Atom.id=Uri.to_stringperma_uri;title=e.subject;subtitle=None;author=Somee.author;updated=atom_datee.updated;rights=feed.rights;links;}in{Atom.entry=meta;summary=None;base=None;content}letto_atom~feed~entries=let{title;subtitle;base_uri;id;rights;_}=feedinletid=base_uri^idinletmk_urix=Uri.of_string(id^x)inletes=List.rev(List.sortcmp_ententries)inletupdated=atom_date(List.hdes).updatedinletlinks=[Atom.mk_link(mk_uri"atom.xml");Atom.mk_link~rel:`alternate~typ:"text/html"(mk_uri"")]inLwt_list.map_s(atom_entry_of_entfeed)es>|=funentries->letfeed={Atom.id;title;subtitle;author=feed.Atom_feed.author;rights;updated;links}in{Atom.feed=feed;entries}