# mf2clj [![Clojars Project](https://img.shields.io/clojars/v/ac.eltr/mf2clj.svg)](https://clojars.org/ac.eltr/mf2clj) A Clojure library that parses [microformats](http://microformats.org/). Under the hood, it's a thin wrapper of a [Extism](https://extism.org/) plugin written in Go (source of which is also in this repository), and the plugin itself is a wrapper of Will Norris' [microformats parser](https://github.com/willnorris/microformats). *Yes, that's a lot of wrappers! I have a good excuse for that.* ## Usage ``` [ac.eltr/mf2clj "0.0.3"] ``` ```clojure (require '[mf2clj.core :as mf2clj]) (mf2clj/parse html-string) ``` ## Development Make sure you have [tinygo](https://tinygo.org/) compiler, [Leiningen](https://leiningen.org/) and [just](https://github.com/casey/just) installed. *Why not `make`, you say? Because, my friend, [make is crap](https://invidio.us/watch?v=YjXfjdCmfD4).* ```sh # compile Go to WebAssembly (WASIP1) just build-wasm # compile Clojure wrapper to .jar just build-jar # or lein uberjar # compile both just build ``` --- ## How It Works 1. `go/main.go` defines `parse()` function, which wraps [microformats.Parse()](https://pkg.go.dev/willnorris.com/go/microformats#Parse) and makes it callable after compiled to WebAssembly. 2. `src/mf2clj/core.clj` loads compiled `mf2go.wasm` from `resources/` and calls `parse`. 3. User/client calls `mf2clj.core/parse` with no knowledge of the wrappers and WebAssembly. The code is so simple that you're probably better off copy-pasting it to your codebase directly. ```go // go/main.go package main import ( "bytes" "github.com/extism/go-pdk" "willnorris.com/go/microformats" ) //go:wasmexport parse func parse() int32 { input := pdk.Input() r := bytes.NewReader(input) data := microformats.Parse(r, nil) pdk.OutputJSON(data) return 0 } ``` ```clojure ;; src/mf2clj/core.clj (ns mf2clj.core (:require [clojure.java.io :as io]) (:import [org.extism.sdk.chicory Manifest ManifestWasm Plugin] [java.nio.charset StandardCharsets])) (defn- manifest-from-wasm [wasm] (Manifest/ofWasms (into-array ManifestWasm [wasm]))) (def plugin (-> "mf2go.wasm" io/resource io/input-stream .readAllBytes ManifestWasm/fromBytes .build manifest-from-wasm .build Plugin/ofManifest .build)) (defn parse [html-string] (let [charset StandardCharsets/UTF_8 html-bytes (.getBytes html-string charset)] (String. (.call plugin "parse" html-bytes) charset))) ``` Seriously, that's all of it. ## *What's your excuse?* microformats is a very *niche* standard that's only popular*-ish* in the [IndieWeb](https://indieweb.org/) community. Clojure is more niche even within this small community. It makes no sense to develop and maintain a *native* Clojure parser. Currently, the closest thing available is [this library](https://codeberg.org/alinnow/microformats) by [Alin](https://codeberg.org/alinnow), whose last commit was in 2014. The next best thing would be a Java library since Clojure can call Java code with no problem, but [mf2j](https://github.com/karadaisy/mf2j) hasn't been updated since 2016. Both libraries are **incomplete**. I see no reason why a new Clojure/Java parser wouldn't be abandoned either. The [go parser](https://github.com/willnorris/microformats) isn't exactly actively maintained, but at least it's complete and stable. It just makes more sense to use an existing stable library. Programming languages aren't really a barrier any more. Many languages can compile to WebAssembly and even more can run WebAssembly. So here we are: A Clojure library that runs WebAssembly written in Go under the hood. I suppose I could use [Rust](https://crates.io/crates/microformats/0.2.0), but it doesn't really make a difference. --- ## License mf2clj is free software licensed under the GNU Affero General Public License.