Blame


1 f3a795ae 2021-08-03 op Some time ago I wrote a text/gemini parser for Clojure. More than a real parser was a hack, an extremely verbose one, just to play with this transducer thing.
2 f3a795ae 2021-08-03 op
3 f3a795ae 2021-08-03 op Well, I got tired of that and rewrote it as a standalone library that is now available on clojars.
4 f3a795ae 2021-08-03 op
5 f3a795ae 2021-08-03 op => https://clojars.org/com.omarpolo/gemtext/ com.omarpolo/gemtext on Clojars.
6 f3a795ae 2021-08-03 op
7 f3a795ae 2021-08-03 op There’s still a transducer at the heart of the library, but it’s a more reasonable one this time. It allows to build up pipelines where parsing text/gemini is only one of the steps, or to parse streaming text/gemini, which is a cool thing (even tho not widespread.)
8 f3a795ae 2021-08-03 op
9 f3a795ae 2021-08-03 op Since this is a library and not a hack inside this blog codebase, ‘parse’ is now a multimethod (Clojure own generic functions if you came from CL-land) with default implementations for strings, sequence of strings and java Reader.
10 f3a795ae 2021-08-03 op
11 f3a795ae 2021-08-03 op Since the parser is built using nothing more than the clojure stdlib, I thought “why not” and called the file ‘core.cljc’, so it’s available also for ClojureScript. (The beforementioned multimethod is available also there, with a default implementation for vectors, lists and strings.)
12 f3a795ae 2021-08-03 op
13 f3a795ae 2021-08-03 op The library emits “almost usual” hiccup:
14 f3a795ae 2021-08-03 op
15 f3a795ae 2021-08-03 op ```clojure
16 f3a795ae 2021-08-03 op user=> (gemtext/parse "some\nlines\nof\ntext")
17 f3a795ae 2021-08-03 op [[:text "some"] [:text "lines"] [:text "of"] [:text "text"]]
18 f3a795ae 2021-08-03 op
19 f3a795ae 2021-08-03 op user=> (gemtext/parse (repeat 3 "* test"))
20 f3a795ae 2021-08-03 op [[:item "test"] [:item "test"] [:item "test"]]
21 f3a795ae 2021-08-03 op ```
22 f3a795ae 2021-08-03 op
23 f3a795ae 2021-08-03 op and is able to turn ’em back to strings:
24 f3a795ae 2021-08-03 op
25 f3a795ae 2021-08-03 op ```clojure
26 f3a795ae 2021-08-03 op user=> (gemtext/unparse [[:link "/foo" "A link"]])
27 f3a795ae 2021-08-03 op "=> /foo A link\n"
28 f3a795ae 2021-08-03 op ```
29 f3a795ae 2021-08-03 op
30 f3a795ae 2021-08-03 op but also to return “HTML” hiccup
31 f3a795ae 2021-08-03 op
32 f3a795ae 2021-08-03 op ```clojure
33 f3a795ae 2021-08-03 op user=> (gemtext/to-hiccup [[:header-1 "text/gemini"] [:text "..."]])
34 f3a795ae 2021-08-03 op [[:h1 "text/gemini"] [:p "..."]]
35 f3a795ae 2021-08-03 op ```
36 f3a795ae 2021-08-03 op
37 f3a795ae 2021-08-03 op so you can use it with other Clojure/script libraries, and to convert text/gemini to HTML.
38 f3a795ae 2021-08-03 op
39 f3a795ae 2021-08-03 op It was fun: I use clojure a lot, but never actually wrote a library, so this was a chance to play with different things. First of, the (small) documentation is available also on cljdoc, and second I played with ‘seancorfield/readme’, a Clojure library that transforms your README to a REPL session!
40 f3a795ae 2021-08-03 op
41 f3a795ae 2021-08-03 op A final note: the design is done, but in the following weeks I may slighly change something here and there (for instance, only now I realize that you can parse text/gemini on the fly, but not convert it to HTML one bit at a time, i.e. “convert text/gemini to html streamingly” (?) which can be useful, or unparse into anything other than a string.)
42 f3a795ae 2021-08-03 op
43 f3a795ae 2021-08-03 op
44 f3a795ae 2021-08-03 op (P.S. I took the chance to also to restyle the capsule. I removed the ASCII banners and followed the subscription spec, yay!)