diff options
Diffstat (limited to 'pkg/libgemini')
-rw-r--r-- | pkg/libgemini/libgemini.go | 85 |
1 files changed, 50 insertions, 35 deletions
diff --git a/pkg/libgemini/libgemini.go b/pkg/libgemini/libgemini.go index 71012ef..48a8ed0 100644 --- a/pkg/libgemini/libgemini.go +++ b/pkg/libgemini/libgemini.go | |||
@@ -6,7 +6,6 @@ import ( | |||
6 | "crypto/tls" | 6 | "crypto/tls" |
7 | "errors" | 7 | "errors" |
8 | "fmt" | 8 | "fmt" |
9 | "html/template" | ||
10 | "io" | 9 | "io" |
11 | "mime" | 10 | "mime" |
12 | "net" | 11 | "net" |
@@ -74,19 +73,19 @@ type Response struct { | |||
74 | type GeminiDocSectionType byte | 73 | type GeminiDocSectionType byte |
75 | 74 | ||
76 | const ( | 75 | const ( |
77 | RAW_TEXT = SectionType(0) | 76 | RAW_TEXT = GeminiDocSectionType(0) |
78 | REFLOW_TEXT = SectionType(1) | 77 | REFLOW_TEXT = GeminiDocSectionType(1) |
79 | LINK = SectionType(2) | 78 | LINK = GeminiDocSectionType(2) |
80 | HEADING_1 = SectionType(3) | 79 | HEADING_1 = GeminiDocSectionType(3) |
81 | HEADING_2 = SectionType(4) | 80 | HEADING_2 = GeminiDocSectionType(4) |
82 | HEADING_3 = SectionType(5) | 81 | HEADING_3 = GeminiDocSectionType(5) |
83 | LIST = SectionType(6) | 82 | LIST = GeminiDocSectionType(6) |
84 | ) | 83 | ) |
85 | 84 | ||
86 | type GeminiDocSection struct { | 85 | type GeminiDocSection struct { |
87 | Type SectionType | 86 | Type GeminiDocSectionType |
88 | Text string | 87 | Text string |
89 | URL template.URL | 88 | URL string |
90 | Items []string | 89 | Items []string |
91 | } | 90 | } |
92 | 91 | ||
@@ -171,13 +170,13 @@ func ParseHeader(line string) (header *Header, err error) { | |||
171 | return | 170 | return |
172 | } | 171 | } |
173 | 172 | ||
174 | func ParseGeminiDocument(body *bytes.Buffer) (sections []Section) { | 173 | func ParseGeminiDocument(body *bytes.Buffer) (sections []GeminiDocSection) { |
175 | scanner := bufio.NewScanner(body) | 174 | scanner := bufio.NewScanner(body) |
176 | 175 | ||
177 | reflow := true | 176 | reflow := true |
178 | ignoreSection := true | 177 | ignoreSection := true |
179 | section := Section{ | 178 | section := GeminiDocSection{ |
180 | Type: REFLOW_TEXT | 179 | Type: REFLOW_TEXT, |
181 | } | 180 | } |
182 | 181 | ||
183 | for scanner.Scan() { | 182 | for scanner.Scan() { |
@@ -185,23 +184,23 @@ func ParseGeminiDocument(body *bytes.Buffer) (sections []Section) { | |||
185 | line = TermEscapeSGRPattern.ReplaceAllString(line, "") | 184 | line = TermEscapeSGRPattern.ReplaceAllString(line, "") |
186 | 185 | ||
187 | reflowMatch := ReflowModePattern.FindStringSubmatch(line) | 186 | reflowMatch := ReflowModePattern.FindStringSubmatch(line) |
188 | if len(heading3Match) != 0 { | 187 | if len(reflowMatch) != 0 && reflowMatch[0] != "" { |
189 | reflow = !reflow | 188 | reflow = !reflow |
190 | continue | 189 | continue |
191 | } | 190 | } |
192 | 191 | ||
193 | if !reflow { | 192 | if !reflow { |
194 | if !ignoreSection { | 193 | if !ignoreSection { |
195 | if section.Type != REFLOW_TEXT { | 194 | if section.Type != RAW_TEXT { |
196 | sections = append(sections, section) | 195 | sections = append(sections, section) |
197 | section = Section{ | 196 | section = GeminiDocSection{ |
198 | Type: REFLOW_TEXT | 197 | Type: RAW_TEXT, |
199 | } | 198 | } |
200 | } | 199 | } |
201 | } else { | 200 | } else { |
202 | ignoreSection = false | 201 | ignoreSection = false |
203 | section = Section{ | 202 | section = GeminiDocSection{ |
204 | Type: REFLOW_TEXT | 203 | Type: RAW_TEXT, |
205 | } | 204 | } |
206 | } | 205 | } |
207 | 206 | ||
@@ -222,80 +221,96 @@ func ParseGeminiDocument(body *bytes.Buffer) (sections []Section) { | |||
222 | } | 221 | } |
223 | 222 | ||
224 | ignoreSection = false | 223 | ignoreSection = false |
225 | section = Section{ | 224 | section = GeminiDocSection{ |
226 | Type: LINK, | 225 | Type: LINK, |
227 | Text: label, | 226 | Text: label, |
228 | URL: template.URL(resolveURI(linkMatch[1], baseURL)), | 227 | URL: linkMatch[1], |
229 | } | 228 | } |
230 | 229 | ||
231 | continue | 230 | continue |
232 | } | 231 | } |
233 | 232 | ||
234 | heading3Match := Heading3Pattern.FindStringSubmatch(line) | 233 | heading3Match := Heading3Pattern.FindStringSubmatch(line) |
235 | if len(heading3Match) != 0 { | 234 | if len(heading3Match) != 0 && heading3Match[0] != "" { |
236 | if !ignoreSection { | 235 | if !ignoreSection { |
237 | sections = append(sections, section) | 236 | sections = append(sections, section) |
238 | } | 237 | } |
239 | 238 | ||
240 | ignoreSection = false | 239 | ignoreSection = false |
241 | section = Section{ | 240 | section = GeminiDocSection{ |
242 | Type: HEADING_3, | 241 | Type: HEADING_3, |
243 | Text: heading3Match[1] | 242 | Text: heading3Match[1], |
244 | } | 243 | } |
245 | 244 | ||
246 | continue | 245 | continue |
247 | } | 246 | } |
248 | 247 | ||
249 | heading2Match := Heading2Pattern.FindStringSubmatch(line) | 248 | heading2Match := Heading2Pattern.FindStringSubmatch(line) |
250 | if len(heading2Match) != 0 { | 249 | if len(heading2Match) != 0 && heading2Match[0] != "" { |
251 | if !ignoreSection { | 250 | if !ignoreSection { |
252 | sections = append(sections, section) | 251 | sections = append(sections, section) |
253 | } | 252 | } |
254 | 253 | ||
255 | ignoreSection = false | 254 | ignoreSection = false |
256 | section = Section{ | 255 | section = GeminiDocSection{ |
257 | Type: HEADING_2, | 256 | Type: HEADING_2, |
258 | Text: heading2Match[1] | 257 | Text: heading2Match[1], |
259 | } | 258 | } |
260 | 259 | ||
261 | continue | 260 | continue |
262 | } | 261 | } |
263 | 262 | ||
264 | heading1Match := Heading1Pattern.FindStringSubmatch(line) | 263 | heading1Match := Heading1Pattern.FindStringSubmatch(line) |
265 | if len(heading1Match) != 0 { | 264 | if len(heading1Match) != 0 && heading1Match[0] != "" { |
266 | if !ignoreSection { | 265 | if !ignoreSection { |
267 | sections = append(sections, section) | 266 | sections = append(sections, section) |
268 | } | 267 | } |
269 | 268 | ||
270 | ignoreSection = false | 269 | ignoreSection = false |
271 | section = Section{ | 270 | section = GeminiDocSection{ |
272 | Type: HEADING_1, | 271 | Type: HEADING_1, |
273 | Text: heading1Match[1] | 272 | Text: heading1Match[1], |
274 | } | 273 | } |
275 | 274 | ||
276 | continue | 275 | continue |
277 | } | 276 | } |
278 | 277 | ||
279 | listItemMatch := ListItemPattern.FindStringSubmatch(line) | 278 | listItemMatch := ListItemPattern.FindStringSubmatch(line) |
280 | if len(listItemMatch) != 0 { | 279 | if len(listItemMatch) != 0 && listItemMatch[0] != "" { |
281 | if !ignoreSection { | 280 | if !ignoreSection { |
282 | if section.Type != LIST { | 281 | if section.Type != LIST { |
283 | sections = append(sections, section) | 282 | sections = append(sections, section) |
284 | section = Section{ | 283 | section = GeminiDocSection{ |
285 | Type: LIST | 284 | Type: LIST, |
286 | } | 285 | } |
287 | } | 286 | } |
288 | } else { | 287 | } else { |
289 | ignoreSection = false | 288 | ignoreSection = false |
290 | section = Section{ | 289 | section = GeminiDocSection{ |
291 | Type: LIST, | 290 | Type: LIST, |
292 | } | 291 | } |
293 | } | 292 | } |
294 | 293 | ||
295 | section.Items = append(section.Items, listItemMatch[1]) | 294 | section.Items = append(section.Items, listItemMatch[1]) |
296 | 295 | ||
297 | continue | 296 | continue |
298 | } | 297 | } |
298 | |||
299 | if !ignoreSection { | ||
300 | if section.Type != REFLOW_TEXT { | ||
301 | sections = append(sections, section) | ||
302 | section = GeminiDocSection{ | ||
303 | Type: REFLOW_TEXT, | ||
304 | } | ||
305 | } | ||
306 | } else { | ||
307 | ignoreSection = false | ||
308 | section = GeminiDocSection{ | ||
309 | Type: REFLOW_TEXT, | ||
310 | } | ||
311 | } | ||
312 | |||
313 | section.Text = section.Text + "\n" + line | ||
299 | } | 314 | } |
300 | 315 | ||
301 | if !ignoreSection { | 316 | if !ignoreSection { |