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;"> |
<div style="text-align: center;"> |
||||||
<a href="{{ AssetURL .ID }}" target="_blank"> |
<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> |
</a> |
||||||
</div> |
</div> |
||||||
|
Loading…
Reference in new issue