summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreltrac <hi@eltr.ac>2026-09-20 15:55:47 +0800
committereltrac <hi@eltr.ac>2026-09-20 17:15:43 +0800
commitb85d76db3e17188ee73d5c0455e8b1976ce9a5cc (patch)
treea0e6ef3c0a9b64f90249c751de9f4b39adbb8613
parentba6d01449539190c59f4f9793d0ab67dca777a23 (diff)
clj: finish clojure wrapper of wasm
add README.md
-rw-r--r--.gitignore4
-rw-r--r--Makefile6
-rw-r--r--README.md72
-rw-r--r--go/Makefile2
-rw-r--r--project.clj10
-rw-r--r--src/mf2clj/core.clj19
6 files changed, 111 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 6572aed..d3be789 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
/.clj-kondo/.cache/v1
/.lsp/.cache
/resources/mf2go.wasm
+/.lein-repl-history
+/.nrepl-port
+/target
+/native/
diff --git a/Makefile b/Makefile
index 5f54d8c..3995594 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,9 @@
build-wasm:
@cd go && tinygo build -o ../resources/mf2go.wasm -target wasip1 -buildmode=c-shared main.go
+build-jar:
+ @lein uberjar
+
+build:
+ @make build-wasm
+ @make build-jar
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a00007c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,72 @@
+# 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.*
+
+## 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 compile `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 2026. Both libraries is **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.
+
diff --git a/go/Makefile b/go/Makefile
deleted file mode 100644
index 45477be..0000000
--- a/go/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-build-wasm:
- @tinygo build -o mf2go.wasm -target wasip1 -buildmode=c-shared main.go
diff --git a/project.clj b/project.clj
new file mode 100644
index 0000000..0eba58d
--- /dev/null
+++ b/project.clj
@@ -0,0 +1,10 @@
+(defproject mf2clj "v0.0.1"
+ :description "A Clojure wrapper of Will Norris' microformats parser in Go, which runs WebAssembly under the hood."
+ :url "https://src.eltr.ac/eltrac/mf2clj"
+ :min-lein-version "2.0.0"
+ :dependencies [[org.clojure/clojure "1.12.4"]
+ [org.extism.sdk/chicory-sdk-core "0.3.0"]]
+ :profiles {:uberjar {:aot :all}}
+ :license {:name "GNU Affero General Public License"
+ :url "https://www.gnu.org/licenses/agpl-3.0.html"
+ :distribution :repo})
diff --git a/src/mf2clj/core.clj b/src/mf2clj/core.clj
new file mode 100644
index 0000000..8d655b1
--- /dev/null
+++ b/src/mf2clj/core.clj
@@ -0,0 +1,19 @@
+(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)))
+