parent
e7b5b55f67
commit
c23030733f
@ -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 |
||||
} |
||||
} |
||||
|
||||
} |
@ -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()) |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,2 @@ |
||||
// Package gmi contains utilities for working with gemini and gemtext
|
||||
package gmi |
@ -1,5 +1,8 @@ |
||||
<div style="text-align: center;"> |
||||
<a href="{{ AssetURL .ID }}" target="_blank"> |
||||
<img src="{{ AssetURL .ID }}{{ if .Resizable }}?w=800{{ end }}" /> |
||||
<img |
||||
src="{{ AssetURL .ID }}{{ if .Resizable }}?w=800{{ end }}" |
||||
alt="{{ .Descr }}" |
||||
/> |
||||
</a> |
||||
</div> |
||||
|
Loading…
Reference in new issue