From 3af00b955ee405fff5c9b729198937655cbffc0c Mon Sep 17 00:00:00 2001
From: manu
Date: Tue, 21 Oct 2014 21:04:03 +1300
Subject: [PATCH 1/8] initial commit
---
Makefile | 6 +-
feeds/Makefile | 20 ++++
feeds/atom_feeds.txt | 1 +
feeds/blog_summary.ml | 215 ++++++++++++++++++++++++++++++++++++++++++
src/dispatch.ml | 1 +
src/pages.ml | 17 ++++
tmpl/news/0.html | 73 ++++++++++++++
tmpl/news/1.html | 19 ++++
8 files changed, 351 insertions(+), 1 deletion(-)
create mode 100644 feeds/Makefile
create mode 100644 feeds/atom_feeds.txt
create mode 100644 feeds/blog_summary.ml
create mode 100644 tmpl/news/0.html
create mode 100644 tmpl/news/1.html
diff --git a/Makefile b/Makefile
index 7da60c193..6c41df621 100644
--- a/Makefile
+++ b/Makefile
@@ -37,7 +37,10 @@ configure:
depend:
cd src && make depend
-build:
+feeds:
+ cd feeds && make run
+
+build: feeds
cd src && make build
run:
@@ -45,4 +48,5 @@ run:
clean:
cd src && make clean
+ cd feeds && make clean
$(RM) log src/mir-www src/*.img src/make-fat*.sh
diff --git a/feeds/Makefile b/feeds/Makefile
new file mode 100644
index 000000000..84d1967f0
--- /dev/null
+++ b/feeds/Makefile
@@ -0,0 +1,20 @@
+all: build
+
+run: build
+ ./blog_summary
+
+build:
+#
+ ocamlfind ocamlopt -syntax camlp4o -package cow -package cow.syntax -package lwt -package cohttp -package cohttp.lwt -package xmlm -package syndic -linkpkg blog_summary.ml -o blog_summary
+
+#test: run
+
+clean:
+ rm *.cmi *.cmx *.o
+
+
+test:
+ ocamlfind ocamlopt -package async -package cohttp -package cohttp.async -linkpkg -thread test.ml -o test
+
+runtest: test
+ ./test
diff --git a/feeds/atom_feeds.txt b/feeds/atom_feeds.txt
new file mode 100644
index 000000000..8d7f675a7
--- /dev/null
+++ b/feeds/atom_feeds.txt
@@ -0,0 +1 @@
+Amir Chaudhry|http://amirchaudhry.com/tags/ocaml-atom.xml
diff --git a/feeds/blog_summary.ml b/feeds/blog_summary.ml
new file mode 100644
index 000000000..15096e504
--- /dev/null
+++ b/feeds/blog_summary.ml
@@ -0,0 +1,215 @@
+(* ocamlfind ocamlopt -package lwt -package cohttp -package cohttp.lwt -package xmlm -package syndic -linkpkg test.ml -o test *)
+
+(* open Lwt
+open Cohttp
+open Cohttp_lwt_unix
+*)
+open Cohttp
+open Lwt
+open Cow
+open Syndic_atom
+
+let (>>=) = Lwt.bind
+
+
+(* change name to list_of_feeds *)
+let list_of_feeds (file : string) : (string * string) list =
+ let ic = open_in file in
+ let assoc = ref [] in
+ (try
+ while true do
+ let line = input_line ic in
+ let p = Str.split_delim (Str.regexp "|") line in
+ assert (List.length p = 2);
+ let [n;u] = p in
+ assoc := (n,u) :: !assoc
+ done
+ with End_of_file -> ());
+ !assoc
+
+
+let get (uri_str : string) : string Lwt.t =
+ Cohttp_lwt_unix.Client.get (Uri.of_string uri_str) >>= fun (_, body) ->
+ Cohttp_lwt_body.to_string body
+
+let string_of_text (t:text_construct) : string = match t with
+ | Text(s) -> s
+ | Html(s) -> s
+ | Xhtml(xs) -> List.fold_left (fun acc x -> acc ^ Syndic_xml.to_string x) "" xs
+
+
+(* parsing the XML feeds *)
+exception Invalid_feed of string
+
+let parse_feed (u : string) (s : string) : Syndic_atom.feed =
+ let str : Xmlm.source = `String(0, s) in
+ let inp = Xmlm.make_input str in
+ (* try *)
+ Syndic_atom.parse inp
+ (* with _ ->
+ try
+ Syndic_rss2.to_atom (Syndic_rss2.parse inp)
+ *)
+ (* with _ -> raise (Invalid_feed u) *)
+
+(*
+let parse_atom (s : string) : feed =
+ let str : Xmlm.source = `String(0, s) in
+ Syndic_atom.parse (Xmlm.make_input str)
+*)
+
+let rec join = function
+ [] -> []
+ | xs::xss -> xs @ join xss
+
+let by_date (e1 : entry) (e2 : entry) : int = (* TODO -- published = CalendarLib.Calendar.t *)
+ CalendarLib.Calendar.compare e2.updated e1.updated
+
+let take n xs =
+ let rec take_aux n xs acc =
+ match (n, xs) with
+ (n, _) when n <= 0 -> acc
+ | (_, []) -> acc
+ | (n, x::xs) -> take_aux (n-1) xs (x::acc)
+ in List.rev (take_aux n xs [])
+
+let rec drop n xs =
+ match (n, xs) with
+ (n, xs) when n <= 0 -> xs
+ | (_, []) -> []
+ | (n, x::xs) -> drop (n-1) xs
+
+let rec paginate (n : int) (xs : 'a list) : 'a list list =
+ if n < 1 then invalid_arg "paginate";
+ match xs with
+ [] -> []
+ | xs -> take n xs :: paginate n (drop n xs)
+
+
+(* Using an ordered set of entries *)
+(*
+module S = Set.Make(struct type t = Syndic_atom.entry let compare (e1:t) (e2:t) = CalendarLib.Calendar.compare e1.updated e2.updated end);;
+*)
+
+
+
+let paginated_entries items_per_page : entry list list Lwt.t =
+ let l = list_of_feeds "atom_feeds.txt" in
+ Lwt_list.map_p (fun (_n, u) -> (* let's not bother about names just yet *)
+ get u >>= fun s ->
+ let f = parse_feed u s in
+ Lwt.return (f.entries)) l >>= fun ess ->
+ let jess = join ess in
+ let sess = List.sort by_date jess in
+ let pess = paginate items_per_page sess in
+ Lwt.return pess
+
+(* Lwt.return @@ paginate 10 (List.sort by_date (join ess)) *)
+
+
+
+
+(*
+ <:html< $list:List.map items li_of_item$ &>>
+
+
+
+type text_construct =
+ | Text of string
+ | Html of string
+ | Xhtml of Syndic_xml.t list
+
+
+type content =
+ | Text of string
+ | Html of string
+ | Xhtml of Syndic_xml.t list
+ | Mime of mime * string
+ | Src of mime option * Uri.t
+
+*)
+
+let string_of_content = function
+ | Text s -> s
+ | Html s -> s
+ | Xhtml _ -> ""
+ | Mime _ -> ""
+ | Src _ -> ""
+
+
+let news_item (e : entry) =
+ let date = Html.of_string
+ (CalendarLib.Printer.Calendar.to_string e.updated) in
+ let title = Html.of_string (string_of_text e.title) in
+ (*
+ let content =
+ try Html.of_string (string_of_content (
+ match e.content with
+ None -> Text ""
+ | Some (Mime _) | Some (Xhtml _)
+ | Some (Src _) -> Text "no content"
+ | Some c -> c)
+ )
+ with _ -> <:html< No content
>>
+ in
+ *)
+ let uri = match e.links with
+ [] -> ""
+ | link :: _ -> Uri.to_string link.href
+ in
+ <:html<
+
+
+>>
+
+let news_href n = "news" ^ (string_of_int n) ^ ".html"
+
+
+let pagination (n : int) (total : int) =
+ let older_uri = news_href (n+1) in
+ let newer_uri = news_href (n-1) in
+ let older = <:html< Older >> in
+ let newer = <:html< Newer >> in
+ match n with
+ 0 -> <:html< $older$ >>
+ | n when n = total-1 -> <:html< $newer$ >>
+ | _ -> <:html< $newer$ $older$ >>
+
+
+let news_page (n : int) (total: int) (es : entry list) =
+
+ <:html<
+
+
+
News Feed
+
+ Here, we aggregate various blogs from the Mirage community. If you would like to be added, please send us an email.
+
+
+ $list:List.map news_item es$
+
+
+
+ >>
+
+
+let write_news_page (total :int) (n : int) (es : entry list) : unit Lwt.t =
+ let page = news_page n total es in
+ let fname = news_href n in
+ Lwt_io.with_file
+ Lwt_io.output fname (fun ch -> Lwt_io.fprint ch (Html.to_string page))
+
+
+
+let write_news (ess : entry list list) : unit Lwt.t =
+ Lwt_list.iteri_p (write_news_page (List.length ess)) ess
+
+let _ =
+ (* Lwt_main.run print_titles *)
+ Lwt_main.run (paginated_entries 10 >>= write_news)
diff --git a/src/dispatch.ml b/src/dispatch.ml
index e42cab31f..0188a05f5 100644
--- a/src/dispatch.ml
+++ b/src/dispatch.ml
@@ -67,6 +67,7 @@ module Main
| ["about"]
| ["community"] ->
return (`Html (Pages.About.t read_tmpl))
+ | ["community"; "blogs"] -> return (`Html (Pages.Blogs.t read_fs))
| "releases" :: tl -> return (`Page (releases_dispatch tl))
| "blog" :: tl -> return (`Page (blog_dispatch tl))
diff --git a/src/pages.ml b/src/pages.ml
index bd2e9cc3c..22cdb4887 100644
--- a/src/pages.ml
+++ b/src/pages.ml
@@ -191,6 +191,23 @@ module About = struct
return (Global.page ~title:"Community" ~headers:[] ~content)
end
+
+(* todo *)
+module Blogs = struct
+ let lines s = Str.split (Str.regexp "[\r\n]+") s
+
+ let t read_fn =
+ lwt bf = read_file read_fn "/news/1.html" in
+ let content = <:html<
+
+ >> in
+ return (Global.page ~title:"Community" ~headers:[] ~content)
+end
+
+
+
module Releases = struct
let content_type_xhtml = Cowabloga.Headers.html
diff --git a/tmpl/news/0.html b/tmpl/news/0.html
new file mode 100644
index 000000000..28c8be084
--- /dev/null
+++ b/tmpl/news/0.html
@@ -0,0 +1,73 @@
+
+
+
+
News Feed
+
+ Here, we aggregate various blogs from the Mirage community. If you would like to be added, please send us an email.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tmpl/news/1.html b/tmpl/news/1.html
new file mode 100644
index 000000000..f45c75214
--- /dev/null
+++ b/tmpl/news/1.html
@@ -0,0 +1,19 @@
+
+
+
+
News Feed
+
+ Here, we aggregate various blogs from the Mirage community. If you would like to be added, please send us an email.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
From 709dd7c34c7f3b5a81e529c84e4259f00c3c4ece Mon Sep 17 00:00:00 2001
From: manu
Date: Thu, 25 Dec 2014 10:31:37 +1300
Subject: [PATCH 2/8] added a route for other blogs
---
Makefile | 10 +++++-----
src/dispatch.ml | 13 ++++++-------
src/pages.ml | 8 +++-----
3 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/Makefile b/Makefile
index 7bda88fed..8a90e4e06 100644
--- a/Makefile
+++ b/Makefile
@@ -26,12 +26,12 @@ IPADDR ?= static
FLAGS ?=
-.PHONY: all configure build run clean
+.PHONY: all configure build run clean feeds
all:
- @echo To build this website, look in the Makefile and set
- @echo the appropriate variables (MODE, FS, NET, IPADDR).
- @echo make configure && make depend && make build
+ @echo "To build this website, look in the Makefile and set"
+ @echo "the appropriate variables (MODE, FS, NET, IPADDR)."
+ @echo "make configure && make depend && make build"
configure:
$(MIRAGE) configure src/config.ml $(FLAGS) --$(MODE)
@@ -42,7 +42,7 @@ depend:
feeds:
cd feeds && make run
-build: feeds
+build:
cd src && make build
run:
diff --git a/src/dispatch.ml b/src/dispatch.ml
index 0188a05f5..c791e535d 100644
--- a/src/dispatch.ml
+++ b/src/dispatch.ml
@@ -48,7 +48,7 @@ module Main
`Blog (blog_feed, Data.Blog.entries);
`Wiki (wiki_feed, Data.Wiki.entries);
] in
-
+
lwt blog_dispatch = Blog.dispatch blog_feed Data.Blog.entries in
lwt wiki_dispatch = Wiki.dispatch wiki_feed Data.Wiki.entries in
lwt releases_dispatch = Pages.Releases.dispatch read_tmpl in
@@ -65,15 +65,14 @@ module Main
return (`Html (Pages.Index.t ~feeds:updates_feeds read_tmpl))
| ["about"]
- | ["community"] ->
- return (`Html (Pages.About.t read_tmpl))
- | ["community"; "blogs"] -> return (`Html (Pages.Blogs.t read_fs))
+ | ["community"] -> return (`Html (Pages.About.t read_tmpl))
+ | ["blogs"] -> return (`Html (Pages.Blogs.t read_tmpl))
| "releases" :: tl -> return (`Page (releases_dispatch tl))
| "blog" :: tl -> return (`Page (blog_dispatch tl))
| "links" :: tl -> return (links_dispatch tl)
| "updates" :: tl -> return (`Page (updates_dispatch tl))
-
+
| "docs" :: tl
| "wiki" :: tl -> return (`Page (wiki_dispatch tl))
@@ -98,10 +97,10 @@ module Main
in
Cowabloga.Dispatch.f io dispatcher uri
in
- let conn_closed (_,conn_id) () =
+ let conn_closed (_,conn_id) =
let cid = Cohttp.Connection.to_string conn_id in
C.log c (Printf.sprintf "conn %s closed" cid)
in
- http { S.callback = callback; conn_closed }
+ http (S.make ~callback ~conn_closed ())
end
diff --git a/src/pages.ml b/src/pages.ml
index 22cdb4887..5c21e145a 100644
--- a/src/pages.ml
+++ b/src/pages.ml
@@ -194,16 +194,14 @@ end
(* todo *)
module Blogs = struct
- let lines s = Str.split (Str.regexp "[\r\n]+") s
-
let t read_fn =
- lwt bf = read_file read_fn "/news/1.html" in
+ lwt bs = read_file read_fn "blogs.html" in
let content = <:html<
>> in
- return (Global.page ~title:"Community" ~headers:[] ~content)
+ return (Global.page ~title:"Blogs" ~headers:[] ~content)
end
From de5925a1abb31dbfe65465748770b14a25ae34ab Mon Sep 17 00:00:00 2001
From: manu
Date: Tue, 27 Jan 2015 11:58:24 +1300
Subject: [PATCH 3/8] cleaning up News
---
Makefile | 8 +-
feeds/Makefile | 20 ----
feeds/atom_feeds.txt | 1 -
feeds/blog_summary.ml | 215 ------------------------------------------
news/.merlin | 8 ++
news/Makefile | 17 ++++
news/feeds.ml | 9 ++
news/news.ml | 117 +++++++++++++++++++++++
src/dispatch.ml | 2 +-
src/pages.ml | 14 +--
tmpl/news/0.html | 73 --------------
tmpl/news/1.html | 19 ----
12 files changed, 160 insertions(+), 343 deletions(-)
delete mode 100644 feeds/Makefile
delete mode 100644 feeds/atom_feeds.txt
delete mode 100644 feeds/blog_summary.ml
create mode 100644 news/.merlin
create mode 100644 news/Makefile
create mode 100644 news/feeds.ml
create mode 100644 news/news.ml
delete mode 100644 tmpl/news/0.html
delete mode 100644 tmpl/news/1.html
diff --git a/Makefile b/Makefile
index 8a90e4e06..0217e3701 100644
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,7 @@ IPADDR ?= static
FLAGS ?=
-.PHONY: all configure build run clean feeds
+.PHONY: all configure build run clean news
all:
@echo "To build this website, look in the Makefile and set"
@@ -39,10 +39,10 @@ configure:
depend:
cd src && make depend
-feeds:
- cd feeds && make run
+news:
+ cd news && make run
-build:
+build: news
cd src && make build
run:
diff --git a/feeds/Makefile b/feeds/Makefile
deleted file mode 100644
index 84d1967f0..000000000
--- a/feeds/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-all: build
-
-run: build
- ./blog_summary
-
-build:
-#
- ocamlfind ocamlopt -syntax camlp4o -package cow -package cow.syntax -package lwt -package cohttp -package cohttp.lwt -package xmlm -package syndic -linkpkg blog_summary.ml -o blog_summary
-
-#test: run
-
-clean:
- rm *.cmi *.cmx *.o
-
-
-test:
- ocamlfind ocamlopt -package async -package cohttp -package cohttp.async -linkpkg -thread test.ml -o test
-
-runtest: test
- ./test
diff --git a/feeds/atom_feeds.txt b/feeds/atom_feeds.txt
deleted file mode 100644
index 8d7f675a7..000000000
--- a/feeds/atom_feeds.txt
+++ /dev/null
@@ -1 +0,0 @@
-Amir Chaudhry|http://amirchaudhry.com/tags/ocaml-atom.xml
diff --git a/feeds/blog_summary.ml b/feeds/blog_summary.ml
deleted file mode 100644
index 15096e504..000000000
--- a/feeds/blog_summary.ml
+++ /dev/null
@@ -1,215 +0,0 @@
-(* ocamlfind ocamlopt -package lwt -package cohttp -package cohttp.lwt -package xmlm -package syndic -linkpkg test.ml -o test *)
-
-(* open Lwt
-open Cohttp
-open Cohttp_lwt_unix
-*)
-open Cohttp
-open Lwt
-open Cow
-open Syndic_atom
-
-let (>>=) = Lwt.bind
-
-
-(* change name to list_of_feeds *)
-let list_of_feeds (file : string) : (string * string) list =
- let ic = open_in file in
- let assoc = ref [] in
- (try
- while true do
- let line = input_line ic in
- let p = Str.split_delim (Str.regexp "|") line in
- assert (List.length p = 2);
- let [n;u] = p in
- assoc := (n,u) :: !assoc
- done
- with End_of_file -> ());
- !assoc
-
-
-let get (uri_str : string) : string Lwt.t =
- Cohttp_lwt_unix.Client.get (Uri.of_string uri_str) >>= fun (_, body) ->
- Cohttp_lwt_body.to_string body
-
-let string_of_text (t:text_construct) : string = match t with
- | Text(s) -> s
- | Html(s) -> s
- | Xhtml(xs) -> List.fold_left (fun acc x -> acc ^ Syndic_xml.to_string x) "" xs
-
-
-(* parsing the XML feeds *)
-exception Invalid_feed of string
-
-let parse_feed (u : string) (s : string) : Syndic_atom.feed =
- let str : Xmlm.source = `String(0, s) in
- let inp = Xmlm.make_input str in
- (* try *)
- Syndic_atom.parse inp
- (* with _ ->
- try
- Syndic_rss2.to_atom (Syndic_rss2.parse inp)
- *)
- (* with _ -> raise (Invalid_feed u) *)
-
-(*
-let parse_atom (s : string) : feed =
- let str : Xmlm.source = `String(0, s) in
- Syndic_atom.parse (Xmlm.make_input str)
-*)
-
-let rec join = function
- [] -> []
- | xs::xss -> xs @ join xss
-
-let by_date (e1 : entry) (e2 : entry) : int = (* TODO -- published = CalendarLib.Calendar.t *)
- CalendarLib.Calendar.compare e2.updated e1.updated
-
-let take n xs =
- let rec take_aux n xs acc =
- match (n, xs) with
- (n, _) when n <= 0 -> acc
- | (_, []) -> acc
- | (n, x::xs) -> take_aux (n-1) xs (x::acc)
- in List.rev (take_aux n xs [])
-
-let rec drop n xs =
- match (n, xs) with
- (n, xs) when n <= 0 -> xs
- | (_, []) -> []
- | (n, x::xs) -> drop (n-1) xs
-
-let rec paginate (n : int) (xs : 'a list) : 'a list list =
- if n < 1 then invalid_arg "paginate";
- match xs with
- [] -> []
- | xs -> take n xs :: paginate n (drop n xs)
-
-
-(* Using an ordered set of entries *)
-(*
-module S = Set.Make(struct type t = Syndic_atom.entry let compare (e1:t) (e2:t) = CalendarLib.Calendar.compare e1.updated e2.updated end);;
-*)
-
-
-
-let paginated_entries items_per_page : entry list list Lwt.t =
- let l = list_of_feeds "atom_feeds.txt" in
- Lwt_list.map_p (fun (_n, u) -> (* let's not bother about names just yet *)
- get u >>= fun s ->
- let f = parse_feed u s in
- Lwt.return (f.entries)) l >>= fun ess ->
- let jess = join ess in
- let sess = List.sort by_date jess in
- let pess = paginate items_per_page sess in
- Lwt.return pess
-
-(* Lwt.return @@ paginate 10 (List.sort by_date (join ess)) *)
-
-
-
-
-(*
- <:html< $list:List.map items li_of_item$ &>>
-
-
-
-type text_construct =
- | Text of string
- | Html of string
- | Xhtml of Syndic_xml.t list
-
-
-type content =
- | Text of string
- | Html of string
- | Xhtml of Syndic_xml.t list
- | Mime of mime * string
- | Src of mime option * Uri.t
-
-*)
-
-let string_of_content = function
- | Text s -> s
- | Html s -> s
- | Xhtml _ -> ""
- | Mime _ -> ""
- | Src _ -> ""
-
-
-let news_item (e : entry) =
- let date = Html.of_string
- (CalendarLib.Printer.Calendar.to_string e.updated) in
- let title = Html.of_string (string_of_text e.title) in
- (*
- let content =
- try Html.of_string (string_of_content (
- match e.content with
- None -> Text ""
- | Some (Mime _) | Some (Xhtml _)
- | Some (Src _) -> Text "no content"
- | Some c -> c)
- )
- with _ -> <:html< No content
>>
- in
- *)
- let uri = match e.links with
- [] -> ""
- | link :: _ -> Uri.to_string link.href
- in
- <:html<
-
-
->>
-
-let news_href n = "news" ^ (string_of_int n) ^ ".html"
-
-
-let pagination (n : int) (total : int) =
- let older_uri = news_href (n+1) in
- let newer_uri = news_href (n-1) in
- let older = <:html< Older >> in
- let newer = <:html< Newer >> in
- match n with
- 0 -> <:html< $older$ >>
- | n when n = total-1 -> <:html< $newer$ >>
- | _ -> <:html< $newer$ $older$ >>
-
-
-let news_page (n : int) (total: int) (es : entry list) =
-
- <:html<
-
-
-
News Feed
-
- Here, we aggregate various blogs from the Mirage community. If you would like to be added, please send us an email.
-
-
- $list:List.map news_item es$
-
-
-
- >>
-
-
-let write_news_page (total :int) (n : int) (es : entry list) : unit Lwt.t =
- let page = news_page n total es in
- let fname = news_href n in
- Lwt_io.with_file
- Lwt_io.output fname (fun ch -> Lwt_io.fprint ch (Html.to_string page))
-
-
-
-let write_news (ess : entry list list) : unit Lwt.t =
- Lwt_list.iteri_p (write_news_page (List.length ess)) ess
-
-let _ =
- (* Lwt_main.run print_titles *)
- Lwt_main.run (paginated_entries 10 >>= write_news)
diff --git a/news/.merlin b/news/.merlin
new file mode 100644
index 000000000..14ec7b7e5
--- /dev/null
+++ b/news/.merlin
@@ -0,0 +1,8 @@
+PKG cow
+PKG cow.syntax
+PKG cowabloga
+PKG lwt
+PKG cohttp
+PKG cohttp.lwt
+PKG xmlm
+PKG syndic
diff --git a/news/Makefile b/news/Makefile
new file mode 100644
index 000000000..10263b641
--- /dev/null
+++ b/news/Makefile
@@ -0,0 +1,17 @@
+LIBS = -pkgs lwt.syntax,cow.syntax,cowabloga,lwt,cohttp,cohttp.lwt,xmlm,syndic
+
+SYNTAX = -tags "syntax(camlp4o)"
+
+.PHONY: all run build clean test
+
+all: build
+
+run: build
+ @echo "updating news pages"
+ @./news.native
+
+build:
+ ocamlbuild -use-ocamlfind $(LIBS) $(SYNTAX) news.native
+
+clean:
+ rm *.cmi *.cmx *.o *.html
diff --git a/news/feeds.ml b/news/feeds.ml
new file mode 100644
index 000000000..783ff490a
--- /dev/null
+++ b/news/feeds.ml
@@ -0,0 +1,9 @@
+let feeds = [
+ ("Anil Madhavapeddy", "http://anil.recoil.org/feeds/atom.xml");
+ ("Mindy Preston", "http://www.somerandomidiot.com/atom.xml");
+ ("Andrej Bauer", "http://math.andrej.com/feed/");
+ ("Amir Chaudhry", "http://amirchaudhry.com/rss.xml");
+ ("Inria", "http://caml.inria.fr/hump.rss");
+ ("My Little Garden of Code", "https://philtomson.github.io/atom.xml");
+ ("Thomas Leonard", "http://roscidus.com/blog/atom.xml");
+]
diff --git a/news/news.ml b/news/news.ml
new file mode 100644
index 000000000..e1240bfb1
--- /dev/null
+++ b/news/news.ml
@@ -0,0 +1,117 @@
+open Lwt
+open Cohttp
+open Cow
+open Cowabloga
+open Syndic_atom
+
+
+(*** Syndic and RSS feeds ***)
+
+let string_of_text (t:text_construct) : string = match t with
+ | Text(s) -> s
+ | Html(s) -> s
+ | Xhtml(xs) -> List.fold_left (fun acc x -> acc ^ Syndic_xml.to_string x) "" xs
+
+(* given a feed as a string, try parsing it as Atom, then as RSS2 *)
+let feed_of_string (u : string) (s : string) : Syndic_atom.feed option =
+ try
+ Some (Syndic_atom.parse (Xmlm.make_input (`String(0, s))))
+ with _ -> try
+ let rss = Syndic_rss2.parse (Xmlm.make_input (`String(0, s))) in
+ let atom = Syndic_rss2.to_atom rss in
+ Some atom
+ with _ ->
+ Printf.fprintf stderr "Error parsing feed: %s\n" u;
+ None
+
+(* compare Syndic entries by date *)
+let by_date (e1 : entry) (e2 : entry) : int =
+ Syndic_date.compare e2.updated e1.updated
+
+
+(*** HTML formatting ***)
+
+(* format an entry to HTML *)
+let news_item ((n: string), (e : entry)) =
+ let date = e.updated in
+ let title = Html.of_string (string_of_text e.title) in
+ let uri = match e.links with
+ [] -> ""
+ | link :: _ -> Uri.to_string link.href
+ in
+ let open Syndic_date in
+ let day = day date in
+ let year = year date in
+ let month = month date |> string_of_month in
+ let date = Printf.sprintf "%s %d, %d" month day year in
+ <:html<
+
+
+
$str:n$ - $str:date$
+
+
+>>
+
+(* format a feed an HTML list item *)
+let feeds_item (name, uri) =
+ <:html<
+ $str:name$
+>>
+
+(* format the news page as a list of entries and a list of feeds *)
+let news_page feeds (es : (string * entry) list) =
+ <:html<
+
+
+
+
+ Here, we aggregate various blogs from the Mirage community.
+ If you would like to be added, please
+ get in touch .
+
+
+ $list:List.map news_item es$
+
+
+ Syndication
+
+ $list:List.map feeds_item feeds$
+
+
+
+ >>
+
+
+(*** Feeds retrieval and processing ***)
+
+(* return a list of named, Syndic entries, in chronological order *)
+let named_entries feeds : (string * entry) list Lwt.t =
+ let http_get (uri : string) : string Lwt.t =
+ Cohttp_lwt_unix.Client.get (Uri.of_string uri) >>= fun (_, body) ->
+ Cohttp_lwt_body.to_string body
+ in
+ let rec join = function [] -> [] | xs::xss -> xs @ join xss
+ in
+ Lwt_list.map_p (fun (n, u) ->
+ http_get u >>= fun s -> return
+ (match feed_of_string u s with
+ Some(f) -> List.map (fun e -> (n, e)) f.entries
+ | None -> [])
+ ) feeds >>= fun ess ->
+ let es = join ess in
+ Lwt.return @@ List.sort (fun (_,e1) (_,e2) -> by_date e1 e2) es
+
+(* write HTML news page *)
+let write_news_page feeds (es : (string * entry) list) : unit Lwt.t =
+ let html_page = news_page feeds es in
+ let fname = "../tmpl/news.html" in
+ Lwt_io.with_file
+ Lwt_io.output fname (fun ch -> Lwt_io.fprint ch (Html.to_string html_page))
+
+let _ =
+ let feeds = List.sort (fun (n1,_) (n2,_) -> compare n1 n2) Feeds.feeds in
+ Lwt_main.run (named_entries feeds >>= (write_news_page feeds))
diff --git a/src/dispatch.ml b/src/dispatch.ml
index c791e535d..f2f7c5b89 100644
--- a/src/dispatch.ml
+++ b/src/dispatch.ml
@@ -66,7 +66,7 @@ module Main
| ["about"]
| ["community"] -> return (`Html (Pages.About.t read_tmpl))
- | ["blogs"] -> return (`Html (Pages.Blogs.t read_tmpl))
+ | ["news"] -> return (`Html (Pages.News.t read_tmpl))
| "releases" :: tl -> return (`Page (releases_dispatch tl))
| "blog" :: tl -> return (`Page (blog_dispatch tl))
diff --git a/src/pages.ml b/src/pages.ml
index 0b1a0fe5a..b18e797d5 100644
--- a/src/pages.ml
+++ b/src/pages.ml
@@ -37,7 +37,7 @@ module Global = struct
Background
Contact
Team
- Blogroll
+ News
Links
@@ -166,7 +166,6 @@ module About = struct
lwt r = read_file read_fn "/about-community.md" in
lwt b = read_file read_fn "/about-b.md" in
lwt f = read_file read_fn "/about-funding.md" in
- lwt br = read_file read_fn "/about-blogroll.md" in
let content = <:html<
@@ -184,25 +183,20 @@ module About = struct
$l$
$r$
-
-
- >> in
return (Global.page ~title:"Community" ~headers:[] ~content)
end
-(* todo *)
-module Blogs = struct
+module News = struct
let t read_fn =
- lwt bs = read_file read_fn "blogs.html" in
+ lwt bs = read_file read_fn "news.html" in
let content = <:html<
>> in
- return (Global.page ~title:"Blogs" ~headers:[] ~content)
+ return (Global.page ~title:"News" ~headers:[] ~content)
end
diff --git a/tmpl/news/0.html b/tmpl/news/0.html
deleted file mode 100644
index 28c8be084..000000000
--- a/tmpl/news/0.html
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
News Feed
-
- Here, we aggregate various blogs from the Mirage community. If you would like to be added, please send us an email.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/tmpl/news/1.html b/tmpl/news/1.html
deleted file mode 100644
index f45c75214..000000000
--- a/tmpl/news/1.html
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
News Feed
-
- Here, we aggregate various blogs from the Mirage community. If you would like to be added, please send us an email.
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
From 1bfbf8b2191210547a4c6c31c6a6599aae946723 Mon Sep 17 00:00:00 2001
From: manu
Date: Wed, 28 Jan 2015 10:19:25 +1300
Subject: [PATCH 4/8] add latest news to homepage
---
files/css/site.css | 2 +-
news/news.ml | 67 +++++++++++++++++++++++++++++++++++++---------
src/pages.ml | 4 +++
3 files changed, 60 insertions(+), 13 deletions(-)
diff --git a/files/css/site.css b/files/css/site.css
index 3311b9bbd..ffa15f26e 100644
--- a/files/css/site.css
+++ b/files/css/site.css
@@ -7,7 +7,7 @@ h4,h5,h6 { color: #222222; font-size: 1.4rem; font-weight: 600; }
.front_updates h4 { font-style: italic; font-size: 1.2rem; }
.front_updates ul { font-size: 1.0rem; }
.front_updates a i { font-style: normal; color: #332222; }
-.front_updates .front_date { color: #777799; }
+.front_date { color: #777799; }
.panel {
padding-top: 0.5rem;
diff --git a/news/news.ml b/news/news.ml
index e1240bfb1..52140d352 100644
--- a/news/news.ml
+++ b/news/news.ml
@@ -30,11 +30,17 @@ let by_date (e1 : entry) (e2 : entry) : int =
(*** HTML formatting ***)
+type news_item = {
+ title: string;
+ author:string;
+ date:int * string * int;
+ uri:string
+}
-(* format an entry to HTML *)
-let news_item ((n: string), (e : entry)) =
+(* extract data required to display a news item *)
+let mk_news_item ((n: string), (e : entry)) : news_item =
let date = e.updated in
- let title = Html.of_string (string_of_text e.title) in
+ let title = string_of_text e.title in
let uri = match e.links with
[] -> ""
| link :: _ -> Uri.to_string link.href
@@ -43,17 +49,32 @@ let news_item ((n: string), (e : entry)) =
let day = day date in
let year = year date in
let month = month date |> string_of_month in
- let date = Printf.sprintf "%s %d, %d" month day year in
+ {title; author=n; date=(day, month, year); uri}
+
+
+(* format a news item for news page *)
+let news_page_item ((n: string), (e : entry)) =
+ let {title; author; date=(day, month, year); uri} = mk_news_item (n,e) in
+ let date = Printf.sprintf "%d %s %d" day month year in
<:html<
-
-
$str:n$ - $str:date$
+
+
$str:author$ ($str:date$)
-
->>
+ &>>
+
+(* format a news item for home page *)
+let home_page_item ((n: string), (e : entry)) =
+ let {title; date=(day, month, year); uri} = mk_news_item (n,e) in
+ let date = Printf.sprintf "%d %s %d" day month year in
+ <:html<
+
+ $str:title$
+ ($str:date$) &>>
+
(* format a feed an HTML list item *)
-let feeds_item (name, uri) =
+let syndication_item (name, uri) =
<:html<
$str:name$
>>
@@ -74,17 +95,22 @@ let news_page feeds (es : (string * entry) list) =
get in touch .
- $list:List.map news_item es$
+ $list:List.map news_page_item es$
Syndication
- $list:List.map feeds_item feeds$
+ $list:List.map syndication_item feeds$
>>
+(* format the latest news as a list *)
+let latest_news es =
+ let ns = List.map (fun (n, e) -> home_page_item (n, e)) es in
+ <:html< &>>
+
(*** Feeds retrieval and processing ***)
@@ -112,6 +138,23 @@ let write_news_page feeds (es : (string * entry) list) : unit Lwt.t =
Lwt_io.with_file
Lwt_io.output fname (fun ch -> Lwt_io.fprint ch (Html.to_string html_page))
+(* write a list of latest news for homepage *)
+let write_latest_news es =
+ let take n xs =
+ let rec take_aux n xs acc =
+ match (n, xs) with
+ (n, _) when n <= 0 -> acc
+ | (_, []) -> acc
+ | (n, x::xs) -> take_aux (n-1) xs (x::acc)
+ in List.rev (take_aux n xs [])
+ in
+ let latest_news = latest_news (take 10 es) in
+ let fname = "../tmpl/latest_news.html" in
+ Lwt_io.with_file
+ Lwt_io.output fname (fun ch -> Lwt_io.fprint ch (Html.to_string latest_news))
+
+let write_news feeds es =
+ (write_news_page feeds es) <&> (write_latest_news es)
let _ =
let feeds = List.sort (fun (n1,_) (n2,_) -> compare n1 n2) Feeds.feeds in
- Lwt_main.run (named_entries feeds >>= (write_news_page feeds))
+ Lwt_main.run (named_entries feeds >>= (write_news feeds))
diff --git a/src/pages.ml b/src/pages.ml
index b18e797d5..067b92feb 100644
--- a/src/pages.ml
+++ b/src/pages.ml
@@ -71,6 +71,7 @@ module Index = struct
lwt l2 = read_file read_fn "/intro-3.md" in
lwt footer = read_file read_fn "/intro-f.html" in
lwt recent = Cowabloga.Feed.to_html ~limit:12 feeds in
+ lwt latest_news = read_file read_fn "/latest_news.html" in
let content = <:html<
@@ -83,6 +84,9 @@ module Index = struct
Recent Updates (all)
$recent$
+
+ Latest News (all)
+ $latest_news$
From 6b574c7e69a8e81d1432ab5f3752e201e0d8fde7 Mon Sep 17 00:00:00 2001
From: manu
Date: Wed, 28 Jan 2015 10:20:13 +1300
Subject: [PATCH 5/8] remove non-mirage blogs from news feeds
---
news/feeds.ml | 2 --
1 file changed, 2 deletions(-)
diff --git a/news/feeds.ml b/news/feeds.ml
index 783ff490a..f7a9109a9 100644
--- a/news/feeds.ml
+++ b/news/feeds.ml
@@ -1,9 +1,7 @@
let feeds = [
("Anil Madhavapeddy", "http://anil.recoil.org/feeds/atom.xml");
("Mindy Preston", "http://www.somerandomidiot.com/atom.xml");
- ("Andrej Bauer", "http://math.andrej.com/feed/");
("Amir Chaudhry", "http://amirchaudhry.com/rss.xml");
- ("Inria", "http://caml.inria.fr/hump.rss");
("My Little Garden of Code", "https://philtomson.github.io/atom.xml");
("Thomas Leonard", "http://roscidus.com/blog/atom.xml");
]
From d8ffcf61e80d9a0137e84264fa2293a22961c4db Mon Sep 17 00:00:00 2001
From: manu
Date: Wed, 28 Jan 2015 11:02:35 +1300
Subject: [PATCH 6/8] Correcting Amir's feed
---
news/feeds.ml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/news/feeds.ml b/news/feeds.ml
index f7a9109a9..25cd1a6a2 100644
--- a/news/feeds.ml
+++ b/news/feeds.ml
@@ -1,7 +1,7 @@
let feeds = [
("Anil Madhavapeddy", "http://anil.recoil.org/feeds/atom.xml");
("Mindy Preston", "http://www.somerandomidiot.com/atom.xml");
- ("Amir Chaudhry", "http://amirchaudhry.com/rss.xml");
+ ("Amir Chaudhry", "http://feeds.feedburner.com/amirmc");
("My Little Garden of Code", "https://philtomson.github.io/atom.xml");
("Thomas Leonard", "http://roscidus.com/blog/atom.xml");
]
From 0c4305744ab13f02e7214a85780af19fb98c4d81 Mon Sep 17 00:00:00 2001
From: Manu
Date: Tue, 10 Mar 2015 14:32:13 +1300
Subject: [PATCH 7/8] update for Syndic 1.2
---
news/news.ml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/news/news.ml b/news/news.ml
index 52140d352..e73d4cf78 100644
--- a/news/news.ml
+++ b/news/news.ml
@@ -9,8 +9,8 @@ open Syndic_atom
let string_of_text (t:text_construct) : string = match t with
| Text(s) -> s
- | Html(s) -> s
- | Xhtml(xs) -> List.fold_left (fun acc x -> acc ^ Syndic_xml.to_string x) "" xs
+ | Html(_,s) -> s
+ | Xhtml(_,xs) -> List.fold_left (fun acc x -> acc ^ Syndic_xml.to_string x) "" xs
(* given a feed as a string, try parsing it as Atom, then as RSS2 *)
let feed_of_string (u : string) (s : string) : Syndic_atom.feed option =
From 18401fbafddd37308a6eb992cf89bb4469f12aa2 Mon Sep 17 00:00:00 2001
From: Manu
Date: Tue, 10 Mar 2015 14:32:56 +1300
Subject: [PATCH 8/8] check package dependencies
---
news/Makefile | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/news/Makefile b/news/Makefile
index 10263b641..9441ff6d5 100644
--- a/news/Makefile
+++ b/news/Makefile
@@ -1,17 +1,21 @@
LIBS = -pkgs lwt.syntax,cow.syntax,cowabloga,lwt,cohttp,cohttp.lwt,xmlm,syndic
-
+PKGS = cow cowabloga lwt cohttp xmlm syndic
SYNTAX = -tags "syntax(camlp4o)"
+OPAM = opam
-.PHONY: all run build clean test
+.PHONY: all depend run build clean
all: build
+depend:
+ $(OPAM) install $(PKGS) --verbose
+
run: build
@echo "updating news pages"
@./news.native
-build:
+build: depend
ocamlbuild -use-ocamlfind $(LIBS) $(SYNTAX) news.native
clean:
- rm *.cmi *.cmx *.o *.html
+ ocamlbuild -clean