summaryrefslogtreecommitdiff
path: root/src/gmi
diff options
context:
space:
mode:
authorBrian Picciano <mediocregopher@gmail.com>2023-01-19 16:02:27 +0100
committerBrian Picciano <mediocregopher@gmail.com>2023-01-19 16:02:27 +0100
commitc23030733fe4cba578b14ad2c1d1292891202562 (patch)
tree05e200767b1a99e686dfcd18455e08fa977ebb56 /src/gmi
parente7b5b55f6718b25a437a891a06a26c21384b6818 (diff)
Add support for gemtext posts
Diffstat (limited to 'src/gmi')
-rw-r--r--src/gmi/gemtext.go73
-rw-r--r--src/gmi/gemtext_test.go51
-rw-r--r--src/gmi/gmi.go2
3 files changed, 126 insertions, 0 deletions
diff --git a/src/gmi/gemtext.go b/src/gmi/gemtext.go
new file mode 100644
index 0000000..a1136bd
--- /dev/null
+++ b/src/gmi/gemtext.go
@@ -0,0 +1,73 @@
+package gmi
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "path"
+ "regexp"
+ "strings"
+)
+
+func hasImgExt(p string) bool {
+ switch path.Ext(strings.ToLower(p)) {
+ case ".jpg", ".jpeg", ".png", ".gif", ".svg":
+ return true
+ default:
+ return false
+ }
+}
+
+// matches `=> dstURL [optional description]`
+var linkRegexp = regexp.MustCompile(`^=>\s+(\S+)\s*(.*?)\s*$`)
+
+// GemtextToMarkdown reads a gemtext formatted body from the Reader and writes
+// the markdown version of that body to the Writer.
+func GemtextToMarkdown(dst io.Writer, src io.Reader) error {
+
+ bufSrc := bufio.NewReader(src)
+
+ for {
+
+ line, err := bufSrc.ReadString('\n')
+ if err != nil && !errors.Is(err, io.EOF) {
+ return fmt.Errorf("reading: %w", err)
+ }
+
+ last := err == io.EOF
+
+ if match := linkRegexp.FindStringSubmatch(line); len(match) > 0 {
+
+ isImg := hasImgExt(match[1])
+
+ descr := match[2]
+
+ if descr != "" {
+ // ok
+ } else if isImg {
+ descr = "Image"
+ } else {
+ descr = "Link"
+ }
+
+ log.Printf("descr:%q", descr)
+
+ line = fmt.Sprintf("[%s](%s)\n", descr, match[1])
+
+ if isImg {
+ line = "!" + line
+ }
+ }
+
+ if _, err := dst.Write([]byte(line)); err != nil {
+ return fmt.Errorf("writing: %w", err)
+ }
+
+ if last {
+ return nil
+ }
+ }
+
+}
diff --git a/src/gmi/gemtext_test.go b/src/gmi/gemtext_test.go
new file mode 100644
index 0000000..23cb97f
--- /dev/null
+++ b/src/gmi/gemtext_test.go
@@ -0,0 +1,51 @@
+package gmi
+
+import (
+ "bytes"
+ "strconv"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGemtextToMarkdown(t *testing.T) {
+
+ tests := []struct {
+ in, exp string
+ }{
+ {
+ in: "",
+ exp: "",
+ },
+ {
+ in: "=> foo",
+ exp: "[Link](foo)\n",
+ },
+ {
+ in: "what\n=> foo\n=> bar",
+ exp: "what\n[Link](foo)\n[Link](bar)\n",
+ },
+ {
+ in: "=> foo description is here ",
+ exp: "[description is here](foo)\n",
+ },
+ {
+ in: "=> img.png",
+ exp: "![Image](img.png)\n",
+ },
+ {
+ in: "=> img.png description is here ",
+ exp: "![description is here](img.png)\n",
+ },
+ }
+
+ for i, test := range tests {
+ t.Run(strconv.Itoa(i), func(t *testing.T) {
+
+ got := new(bytes.Buffer)
+ err := GemtextToMarkdown(got, bytes.NewBufferString(test.in))
+ assert.NoError(t, err)
+ assert.Equal(t, test.exp, got.String())
+ })
+ }
+}
diff --git a/src/gmi/gmi.go b/src/gmi/gmi.go
new file mode 100644
index 0000000..358d935
--- /dev/null
+++ b/src/gmi/gmi.go
@@ -0,0 +1,2 @@
+// Package gmi contains utilities for working with gemini and gemtext
+package gmi