Index: trunk/src/core/archive.ml
===================================================================
--- trunk/src/core/archive.ml	(revision 1)
+++ 	(revision )
@@ -1,89 +1,0 @@
-module Id = Meta.Id
-type alias_t = string
-
-module Configuration = struct
-  type t = {
-      repository : Lpath.repo_t;
-      title : string;
-      owner : string;
-      email : string;
-      id : Id.t;
-    }
-
-  let of_config config =
-    let open Confix in
-    let open Confix.Config in
-    let str k = ConfixToml.(string config ("archive" / k)) in
-    try
-      Ok {
-          repository =
-            (try Lpath.repo_of_string (str "repository" |> with_default ".")
-             with
-             | Invalid_argument s -> failwith ("Invalid repository: " ^ s)
-             | Failure s -> failwith ("Missing repository value: " ^ s));
-          title = str "title" |> with_default "";
-          owner = str "owner" |> with_default "";
-          email = str "email" |> with_default "";
-          id = match Id.of_string (str "uuid" |> mandatory) with Some id -> id | None -> failwith "Invalid UUID in config";
-        }
-    with Failure str -> Error str
-
-  let validity config =
-    let repo = Lpath.fpath_of_repo config.repository in
-    let open Confix.Config.Validation in
-    empty
-    &> is_directory repo
-end
-
-module AliasMap = Meta.AliasMap
-
-module Make (Store : Store.T) = struct
-  type t = {
-      config : Configuration.t;
-      store  : Store.t;
-    }
-
-  let note_lens note = note
-  let meta_lens note = note.Note.meta
-
-  let recency_order a b = Meta.(Date.compare a.date b.date)
-
-  let latest archive =
-    Store.to_list ~order:recency_order meta_lens archive.store
-
-  let listed archive =
-    let notes = Store.to_list meta_lens archive.store in
-    List.filter Meta.(fun e -> CategorySet.listed e.categories) notes
-
-  let published archive =
-    let notes = Store.to_list meta_lens archive.store in
-    List.filter Meta.(fun e -> CategorySet.published e.categories) notes
-
-  let latest_listed archive =
-    let notes = Store.to_list ~order:recency_order meta_lens archive.store in
-    List.filter Meta.(fun e -> CategorySet.listed e.categories) notes
-
-  let with_topic archive topic =
-    let notes = Store.to_list ~order:recency_order meta_lens archive.store in
-    List.filter Meta.(fun e -> StringSet.exists (fun t -> t = topic) e.topics) notes
-
-  let topics archive =
-    let notes = Store.to_list meta_lens archive.store in
-    List.fold_left Meta.(fun a e -> unique_topics a e) Meta.StringSet.empty notes
-
-  let latest_entry archive fragment =
-    let notes = Store.to_list ~order:recency_order meta_lens archive.store in
-    let containing_fragment e = Re.Str.(string_match (regexp fragment)) (e.Meta.title) 0 in
-    try Some (List.find containing_fragment notes)
-    with Not_found -> None
-
-  let note_with_id archive id = Store.note_with_id archive.store id
-  let note_with_alias archive alias = Store.note_with_alias archive.store alias
-
-  let with_note archive note = Store.with_note archive.store note
-
-  let sublist ~from ~n list =
-    let aggregate_subrange (i, elms) e = succ i, if i >= from && i <= n then e::elms else elms in
-    List.fold_left aggregate_subrange (0, []) list |> snd
-
-end
Index: trunk/src/core/jbuild
===================================================================
--- trunk/src/core/jbuild	(revision 1)
+++ 	(revision )
@@ -1,5 +1,0 @@
-(library
- ((name        logarion)
-  (public_name logarion)
-  (libraries (confix omd ptime lwt uuidm uri re.str emile))
-  ))
Index: trunk/src/core/lpath.ml
===================================================================
--- trunk/src/core/lpath.ml	(revision 1)
+++ 	(revision )
@@ -1,25 +1,0 @@
-open Fpath
-type repo_t  = Repo of t
-type note_t  = Note of { repo: repo_t; basename: t }
-
-let fpath_of_repo = function Repo p -> p
-let string_of_repo r = fpath_of_repo r |> to_string
-let repo_of_string s = Repo (v s)
-
-let fpath_of_note = function Note n -> (fpath_of_repo n.repo // n.basename)
-let string_of_note n = fpath_of_note n |> to_string
-let note_of_basename repo s = Note { repo; basename = v s }
-
-let alias_of_note = function Note n -> n.basename |> rem_ext |> to_string
-let note_of_alias repo extension alias = note_of_basename repo (alias ^ extension)
-
-let versioned_basename_of_title ?(version=0) repo extension (title : string) =
-  let notes_fpath = fpath_of_repo repo in
-  let basename = v @@ Meta.string_alias title in
-  let rec next version =
-    let candidate = basename |> add_ext (string_of_int version) |> add_ext extension in
-    if Sys.file_exists (to_string (notes_fpath // candidate))
-    then next (succ version)
-    else note_of_basename repo (to_string candidate)
-  in
-  next version
Index: trunk/src/core/meta.ml
===================================================================
--- trunk/src/core/meta.ml	(revision 1)
+++ 	(revision )
@@ -1,222 +1,0 @@
-module Date = struct
-  type t = {
-      created: Ptime.t option;
-      published: Ptime.t option;
-      edited: Ptime.t option;
-    } [@@deriving lens { submodule = true }]
-
-  let rfc_string date = match date with Some t -> Ptime.to_rfc3339 t | None -> ""
-
-  let of_string (rfc : string) = match Ptime.of_rfc3339 rfc with
-      Ok (t,_,_) -> Some t | Error _ -> None
-
-  let listing date = match date.published, date.created with
-    | Some _, _ -> date.published
-    | None, Some _ -> date.created
-    | None, None -> None
-
-  let compare = compare
-
-  let pretty_date = function
-    | Some t -> Ptime.to_date t |> fun (y, m, d) -> Printf.sprintf "%04d-%02d-%02d" y m d
-    | None -> ""
-end
-
-module Id = struct
-  let random_state = Random.State.make_self_init ()
-  type t = Uuidm.t
-  let compare = Uuidm.compare
-  let to_string = Uuidm.to_string
-  let of_string = Uuidm.of_string
-  let generate ?(random_state=random_state) = Uuidm.v4_gen random_state
-end
-
-module Author = struct
-  type name_t = string
-  type address_t = Uri.t
-  type t = {
-      name: name_t;
-      address: address_t;
-    } [@@deriving lens { submodule = true } ]
-
-  let empty = { name = ""; address = Uri.empty }
-
-  let compare = Pervasives.compare
-
-end
-
-module AuthorSet = struct
-  include Set.Make(Author)
-
-  let to_string authors =
-    let to_string a = a.Author.name ^ " <" ^ Uri.to_string a.Author.address ^ ">" in
-    let f elt acc = if String.length acc > 1 then acc ^ ", " ^ to_string elt else to_string elt in
-    fold f authors ""
-
-  let of_string s =
-    match Emile.List.of_string s with
-    | Error _ -> prerr_endline @@ "Error parsing: " ^ s; empty
-    | Ok emails ->
-       let to_author =
-         let module L = List in
-         let open Emile in
-         function
-         | `Group _ -> prerr_endline @@ "Can't deal with groups in author: " ^ s; Author.empty
-         | `Mailbox { name; local; _ } ->
-            let s_of_phrase = function `Dot -> "" | `Word w -> (match w with `Atom a -> a | `String s -> s) | `Encoded _ -> "" in
-            let name = match name with None -> "" | Some phrase -> L.fold_left (fun a e -> a ^ s_of_phrase e) "" phrase in
-            let address =
-              L.fold_left (fun a e -> a ^ match e with `Atom a -> a | `String s -> s) "" local ^ "@" (* TODO: Author address unimplemented *)
-            in
-            Author.{ name; address = Uri.of_string address }
-       in
-       of_list @@ List.map to_author emails
-end
-
-module Category = struct
-  type t = Draft | Unlisted | Published | Custom of string
-
-  let compare = Pervasives.compare
-
-  let of_string = function
-    | "draft" -> Draft
-    | "unlisted" -> Unlisted
-    | "published" -> Published
-    | c -> Custom c
-
-  let to_string = function
-    | Draft -> "draft"
-    | Unlisted -> "unlisted"
-    | Published -> "published"
-    | Custom c -> c
-end
-
-module CategorySet = struct
-  include Set.Make(Category)
-  let to_csv set =
-    let f elt a =
-      let s = Category.to_string elt in
-      if a <> "" then a ^ ", " ^ s else s
-    in
-    fold f set ""
-  let categorised categs cs = of_list categs |> (fun s -> subset s cs)
-  let published = categorised [Category.Published]
-  let listed cs = not @@ categorised [Category.Unlisted] cs
-end
-
-module StringSet = Set.Make(String)
-
-let stringset_csv set =
-  let f elt a = if a <> "" then a ^ ", " ^ elt else elt in
-  StringSet.fold f set ""
-
-let string_alias t =
-  let is_reserved = function
-    | '!' | '*' | '\'' | '(' | ')' | ';' | ':' | '@' | '&' | '=' | '+' | '$'
-      | ',' | '/' | '?' | '#' | '[' | ']' | ' ' | '\t' | '\x00' -> true
-    | _ -> false
-  in
-  let b = Buffer.create (String.length t) in
-  let filter char =
-    let open Buffer in
-    if is_reserved char then (try (if nth b (pred (length b)) <> '-' then add_char b '-') with Invalid_argument _ -> prerr_endline "reserved")
-    else add_char b char
-  in
-  String.(iter filter (lowercase_ascii t));
-  Buffer.contents b
-
-type t = {
-    title: string;
-    authors: AuthorSet.t;
-    date: Date.t;
-    categories: CategorySet.t;
-    topics: StringSet.t;
-    keywords: StringSet.t;
-    series: StringSet.t;
-    abstract: string;
-    uuid: Id.t;
-    alias: string;
-  } [@@deriving lens { submodule = true }]
-
-let blank ?(uuid=(Id.generate ())) () = {
-    title = "";
-    authors = AuthorSet.empty;
-    date = Date.({ created = None; edited = None; published = None });
-    categories = CategorySet.empty;
-    topics   = StringSet.empty;
-    keywords = StringSet.empty;
-    series   = StringSet.empty;
-    abstract = "";
-    uuid;
-    alias = "";
-  }
-
-let listed    e = CategorySet.listed e.categories
-let published e = CategorySet.published e.categories
-let unique_topics ts x = StringSet.union ts x.topics
-
-module AliasMap = Map.Make(String)
-module IdMap = Map.Make(Id)
-
-let alias meta = if meta.alias = "" then string_alias meta.title else meta.alias
-
-let value_with_name (_meta as m) = function
-  | "Title"    -> m.title
-  | "Abstract" -> m.abstract
-  | "Authors"  -> AuthorSet.to_string m.authors
-  | "Date"     -> Date.(rfc_string m.date.created)
-  | "Edited"   -> Date.(rfc_string m.date.edited)
-  | "Published"-> Date.(rfc_string m.date.published)
-  | "Human"    -> Date.(pretty_date @@ listing m.date)
-  | "Topics"     -> stringset_csv m.topics;
-  | "Categories" -> CategorySet.to_csv m.categories;
-  | "Keywords"   -> stringset_csv m.keywords;
-  | "Series"     -> stringset_csv m.series;
-  | "ID" -> Id.to_string m.uuid
-  | "Alias" -> alias m
-  | e -> invalid_arg e
-
-let with_kv meta (k,v) =
-  let list_of_csv = Re.Str.(split (regexp " *, *")) in
-  let trim = String.trim in
-  match k with
-  | "Title"     -> { meta with title = trim v }
-  | "Author"
-  | "Authors"   -> { meta with authors = AuthorSet.of_string (trim v)}
-  | "Abstract"  -> { meta with abstract = trim v }
-  | "Date"      -> { meta with date = Date.{ meta.date with created   = Date.of_string v }}
-  | "Published" -> { meta with date = Date.{ meta.date with published = Date.of_string v }}
-  | "Edited"    -> { meta with date = Date.{ meta.date with edited    = Date.of_string v }}
-  | "Topics"    -> { meta with topics   = trim v |> list_of_csv |> StringSet.of_list }
-  | "Keywords"  -> { meta with keywords = trim v |> list_of_csv |> StringSet.of_list }
-  | "Categories"->
-     let categories = trim v |> list_of_csv |> List.map Category.of_string |> CategorySet.of_list in
-     { meta with categories }
-  | "Series"    -> { meta with series = trim v |> list_of_csv |> StringSet.of_list }
-  | "ID"        -> (match Id.of_string v with Some id -> { meta with uuid = id } | None -> meta)
-  | "Alias"     -> { meta with alias = v }
-  | k -> prerr_endline ("Unknown key: " ^ k ^ ", with value: " ^ v ); meta
-
-let to_string (_meta as m) =
-  let has_len v = String.length v > 0 in
-  let s field value = if has_len value then field ^ ": " ^ value ^ "\n" else "" in
-  let a value = if AuthorSet.is_empty value then "" else "Authors: " ^ AuthorSet.to_string value ^ "\n" in
-  let d field value = match value with
-    | Some _ -> field ^ ": " ^ Date.rfc_string value ^ "\n" | None -> ""
-  in
-  let rows =
-    [ s "Title" m.title;
-      a m.authors;
-      d "Date" m.date.Date.created;
-      d "Edited" m.date.Date.edited;
-      d "Published" m.date.Date.published;
-      s "Topics" (stringset_csv m.topics);
-      s "Categories" (CategorySet.to_csv m.categories);
-      s "Keywords" (stringset_csv m.keywords);
-      s "Series"   (stringset_csv m.series);
-      s "Abstract" m.abstract;
-      s "ID" (Uuidm.to_string m.uuid);
-      s "Alias" m.alias
-    ]
-  in
-  String.concat "" rows
Index: trunk/src/core/note.ml
===================================================================
--- trunk/src/core/note.ml	(revision 1)
+++ 	(revision )
@@ -1,47 +1,0 @@
-type t = {
-    meta: Meta.t;
-    body: string;
-  } [@@deriving lens { submodule = true }]
-
-let blank ?(uuid=(Meta.Id.generate ())) () = { meta = Meta.blank ~uuid (); body = "" }
-
-let title ymd =
-  let mtitle = ymd.meta.Meta.title in
-  if String.length mtitle > 0 then mtitle else
-    let open Omd in
-    try List.find (function H1 _ -> true | _ -> false) (Omd.of_string ymd.body)
-        |> function H1 h -> to_text h | _ -> ""
-    with Not_found -> ""
-
-let categorised categs ymd = Meta.CategorySet.categorised categs ymd.meta.Meta.categories
-
-let with_kv ymd (k,v) = match k with
-  | "body" -> { ymd with body = String.trim v }
-  | _      -> { ymd with meta = Meta.with_kv ymd.meta (k,v) }
-
-let meta_pair_of_string line = match Re.Str.(bounded_split (regexp ": *")) line 2 with
-  | [ key; value ] -> Re.Str.(replace_first (regexp "^#\\+") "" key), value
-  | [ key ] -> Re.Str.(replace_first (regexp "^#\\+") "" key), ""
-  | _ -> prerr_endline line; ("","")
-
-let meta_of_string front_matter =
-  let fields = List.map meta_pair_of_string (String.split_on_char '\n' front_matter) in
-  List.fold_left Meta.with_kv (Meta.blank ()) fields
-
-exception Syntax_error of string
-
-let front_matter_body_split s =
-  if Re.Str.(string_match (regexp ".*:.*")) s 0
-  then match Re.Str.(bounded_split (regexp "\n\n")) s 2 with
-       | front::body::[] -> (front, body)
-       | _ -> ("", s)
-  else ("", s)
-
-let of_string s =
-  let (front_matter, body) = front_matter_body_split s in
-  try
-    let note = { meta = meta_of_string front_matter; body } in
-    { note with meta = { note.meta with title = title note } }
-  with _ -> prerr_endline ("Failed parsing" ^ s); blank ()
-
-let to_string ymd = Meta.to_string ymd.meta ^ "\n" ^ ymd.body
Index: trunk/src/core/store.ml
===================================================================
--- trunk/src/core/store.ml	(revision 1)
+++ 	(revision )
@@ -1,7 +1,0 @@
-module type T = sig
-  type t
-  val to_list: ?order:('a -> 'a -> int) -> (Note.t -> 'a) -> t -> 'a list
-  val note_with_id: t -> Meta.Id.t -> Note.t option
-  val note_with_alias: t -> string -> Note.t option
-  val with_note: t -> Note.t -> Note.t Lwt.t
-end
