Commit
+58 -61 +/-2 browse
1 | diff --git a/lib/note.ml b/lib/note.ml |
2 | index c33f8bc..afc20c9 100644 |
3 | --- a/lib/note.ml |
4 | +++ b/lib/note.ml |
5 | @@ -1,6 +1,6 @@ |
6 | open Core |
7 | |
8 | - type t = { frontmatter : Ezjsonm.t option; markdown : Omd.t; slug : Slug.t } |
9 | + type t = { frontmatter : Ezjsonm.t option; markdown : Omd.doc; slug : Slug.t } |
10 | |
11 | let build ?(tags = []) ?(content = "") ~title slug = |
12 | let frontmatter = |
13 | @@ -11,30 +11,35 @@ let build ?(tags = []) ?(content = "") ~title slug = |
14 | let markdown = Omd.of_string content in |
15 | { frontmatter; markdown; slug } |
16 | |
17 | + let rec title_of_markdown (blocks : Omd.block list) : string = |
18 | + match blocks with |
19 | + | [] -> "" |
20 | + | hd :: tl -> ( |
21 | + match hd.bl_desc with |
22 | + | Heading (_, content) -> ( |
23 | + match content.il_desc with |
24 | + | Text text -> text |
25 | + | _ -> title_of_markdown tl) |
26 | + | Paragraph content -> ( |
27 | + match content.il_desc with |
28 | + | Text text -> text |
29 | + | _ -> title_of_markdown tl) |
30 | + | _ -> "??") |
31 | + |
32 | let get_title t = |
33 | let title = |
34 | match t.frontmatter with |
35 | | Some fm -> ( |
36 | match Ezjsonm.find_opt (Ezjsonm.value fm) [ "title" ] with |
37 | | Some v -> Some (Ezjsonm.get_string v) |
38 | - | None -> None ) |
39 | + | None -> None) |
40 | | None -> None |
41 | in |
42 | match title with |
43 | | Some title -> title |
44 | (* Since we couldn't determine the title from frontmatter now we will |
45 | infer the title by looking at the markdown *) |
46 | - | None -> ( |
47 | - let title = |
48 | - List.find |
49 | - ~f:(fun entry -> |
50 | - match entry with |
51 | - | Omd.H1 _ | Omd.H2 _ | Omd.H3 _ | Omd.H4 _ | Omd.H5 _ | Omd.H6 _ -> |
52 | - true |
53 | - | _ -> false) |
54 | - t.markdown |
55 | - in |
56 | - match title with Some e -> Omd_backend.text_of_md [ e ] | None -> "???" ) |
57 | + | None -> title_of_markdown t.markdown |
58 | |
59 | let get_description t = |
60 | let description = |
61 | @@ -42,7 +47,7 @@ let get_description t = |
62 | | Some fm -> ( |
63 | match Ezjsonm.find_opt (Ezjsonm.value fm) [ "description" ] with |
64 | | Some v -> Some (Ezjsonm.get_string v) |
65 | - | None -> None ) |
66 | + | None -> None) |
67 | | None -> None |
68 | in |
69 | match description with Some description -> description | None -> "" |
70 | @@ -52,27 +57,33 @@ let get_tags t = |
71 | | Some fm -> ( |
72 | match Ezjsonm.find_opt (Ezjsonm.value fm) [ "tags" ] with |
73 | | Some v -> Ezjsonm.get_strings v |
74 | - | None -> [] ) |
75 | + | None -> []) |
76 | | None -> [] |
77 | |
78 | let get_path t = Slug.get_path t.slug |
79 | |
80 | + let rec extract_structured_data (accm : Ezjsonm.value list) (doc : Omd.doc) : |
81 | + Ezjsonm.value list = |
82 | + match doc with |
83 | + | [] -> accm |
84 | + | hd :: tl -> ( |
85 | + match hd.bl_desc with |
86 | + | Code_block (kind, content) -> ( |
87 | + match kind with |
88 | + | "json" -> |
89 | + let accm = accm @ [ Ezjsonm.from_string content ] in |
90 | + extract_structured_data accm tl |
91 | + | "yaml" -> |
92 | + let accm = accm @ [ Ezjsonm.wrap (Yaml.of_string_exn content) ] in |
93 | + extract_structured_data accm tl |
94 | + | _ -> extract_structured_data accm tl) |
95 | + | _ -> extract_structured_data accm tl) |
96 | + |
97 | let get_data t = |
98 | - let data = |
99 | - List.filter_map |
100 | - ~f:(fun entry -> |
101 | - match entry with |
102 | - | Code (language, data) | Code_block (language, data) -> ( |
103 | - match language with |
104 | - | "JSON" | "Json" | "json" -> |
105 | - Some (Ezjsonm.value (Ezjsonm.from_string data)) |
106 | - | "YAML" | "Yaml" | "yaml" -> Some (Yaml.of_string_exn data) |
107 | - | _ -> None ) |
108 | - | _ -> None) |
109 | - t.markdown |
110 | - in |
111 | + let data = extract_structured_data [] t.markdown in |
112 | Ezjsonm.list (fun value -> value) data |
113 | |
114 | + (* TODO: fix html conversion *) |
115 | let to_json t = |
116 | let frontmatter = |
117 | match t.frontmatter with |
118 | @@ -82,7 +93,7 @@ let to_json t = |
119 | Ezjsonm.dict |
120 | [ |
121 | ("frontmatter", frontmatter); |
122 | - ("content", Ezjsonm.string (Omd.to_text t.markdown)); |
123 | + ("content", Ezjsonm.string (Omd.to_html t.markdown)); |
124 | ("data", get_data t); |
125 | ] |
126 | |
127 | @@ -91,8 +102,8 @@ let to_string t = |
128 | | Some fm -> |
129 | let front_matter = Yaml.to_string_exn (Ezjsonm.value fm) in |
130 | String.concat ~sep:"\n" |
131 | - [ "---"; front_matter; "---"; Omd.to_text t.markdown ] |
132 | - | None -> Omd.to_text t.markdown |
133 | + [ "---"; front_matter; "---"; Omd.to_html t.markdown ] |
134 | + | None -> Omd.to_html t.markdown |
135 | |
136 | let of_string ~data slug = |
137 | let indexes = String.substr_index_all ~may_overlap:true ~pattern:"---" data in |
138 | @@ -109,7 +120,7 @@ let of_string ~data slug = |
139 | "frontmatter is a partial fragment, should be either a dictionary \ |
140 | or list" |
141 | in |
142 | - let markdown : Omd.t = |
143 | + let markdown : Omd.doc = |
144 | Omd.of_string |
145 | (String.slice data (List.nth_exn indexes 1 + 3) (String.length data)) |
146 | in |
147 | @@ -129,32 +140,18 @@ module Util = struct |
148 | | _ -> Some x) |
149 | (String.split ~on:' ' str) |
150 | |
151 | - let rec to_words markdown = |
152 | - match markdown with |
153 | - | [] -> [] |
154 | - | hd :: tl -> |
155 | - ( match hd with |
156 | - | Omd.Text s -> split_words s |
157 | - | Omd.H1 v |
158 | - | Omd.H2 v |
159 | - | Omd.H3 v |
160 | - | Omd.H4 v |
161 | - | Omd.H5 v |
162 | - | Omd.H6 v |
163 | - | Omd.Blockquote v |
164 | - | Omd.Bold v |
165 | - | Omd.Emph v |
166 | - | Omd.Paragraph v -> |
167 | - to_words v |
168 | - | Omd.Url (_, inner, title) -> split_words title @ to_words inner |
169 | - | Omd.Ref (_, _, title, _) -> split_words title |
170 | - | Omd.Ol l | Omd.Olp l | Omd.Ul l | Omd.Ulp l -> |
171 | - List.fold |
172 | - ~init:([] : string list) |
173 | - ~f:(fun accm elem -> accm @ to_words elem) |
174 | - l |
175 | - | _ -> [] ) |
176 | - @ to_words tl |
177 | + let rec to_words (accm : string list) (doc : Omd.doc) : string list = |
178 | + let split_words inline = |
179 | + match inline with Omd.Text text -> String.split ~on:' ' text | _ -> [] |
180 | + in |
181 | + match doc with |
182 | + | [] -> accm |
183 | + | hd :: tl -> ( |
184 | + match hd.bl_desc with |
185 | + | Paragraph inline -> |
186 | + let accm = accm @ split_words inline.il_desc in |
187 | + to_words accm tl |
188 | + | _ -> to_words accm tl) |
189 | end |
190 | |
191 | module Encoding = struct |
192 | @@ -183,7 +180,7 @@ module Search = struct |
193 | List.count ~f:(fun tag -> string_match expr tag 0) tags > 0 |
194 | |
195 | let content expr note = |
196 | - let words = Util.to_words note.markdown in |
197 | + let words = Util.to_words [] note.markdown in |
198 | List.count ~f:(fun word -> string_match expr word 0) words > 0 |
199 | |
200 | let match_and_rank ~args notes = |
201 | @@ -265,7 +262,7 @@ let to_cells ~columns ~styles notes = |
202 | | `WordCount -> |
203 | let text_value = |
204 | Core.sprintf "%d" |
205 | - (List.length (Util.to_words note.markdown)) |
206 | + (List.length (Util.to_words [] note.markdown)) |
207 | in |
208 | (text_value, String.length text_value, default_padding) |
209 | | `Slug -> |
210 | diff --git a/note.opam b/note.opam |
211 | index 38f9716..a2d662a 100644 |
212 | --- a/note.opam |
213 | +++ b/note.opam |
214 | @@ -13,7 +13,7 @@ depends: [ |
215 | "core" {>= "v0.14.0"} |
216 | "dune" {>= "2.7" & >= "2.7"} |
217 | "ezjsonm" {>= "1.2.0"} |
218 | - "omd" {>= "1.3.1"} |
219 | + "omd" {>= "2.0.0~alpha1"} |
220 | "re" {>= "v1.9.0"} |
221 | "stdio" {>= "v0.14.0"} |
222 | "yaml" {>= "2.1.0"} |