Browse Source

parse links

master
Wojciech Kwolek 2 months ago
commit
f789c8d652
4 changed files with 138 additions and 0 deletions
  1. +94
    -0
      gemini/gemini.go
  2. +29
    -0
      gemini/gemini_test.go
  3. +5
    -0
      go.mod
  4. +10
    -0
      go.sum

+ 94
- 0
gemini/gemini.go View File

@ -0,0 +1,94 @@
package gemini
import (
"strings"
"unicode"
)
type LineType int
type Line interface {
Content() string
}
type LineParser struct {
inPreformatted bool
}
type PreformattingToggleLine struct{}
func (p PreformattingToggleLine) Content() string { return "" }
type PreformattedTextLine struct{ content string }
func (p PreformattedTextLine) Content() string { return p.content }
type LinkLine struct {
content string
href string
title string
}
func (l LinkLine) Content() string { return l.content }
func (l LinkLine) Href() string { return l.href }
func (l LinkLine) Title() string { return l.title }
const (
parsingURLStart int = 1
parsingURL = 2
parsingTitleStart = 3
parsingTitle = 4
)
func ParseLinkLine(line string) LinkLine {
l := LinkLine{content: line, href: "", title: ""}
state := parsingURL
for _, ch := range strings.TrimSpace(strings.TrimPrefix(line, "=>")) {
switch state {
case parsingURLStart:
if unicode.IsSpace(ch) {
continue
}
state = parsingURL
l.href += string(ch)
case parsingURL:
if unicode.IsSpace(ch) {
state = parsingTitleStart
continue
}
l.href += string(ch)
case parsingTitleStart:
if unicode.IsSpace(ch) {
continue
}
state = parsingTitle
l.title += string(ch)
case parsingTitle:
l.title += string(ch)
}
}
if len(l.title) == 0 {
l.title = l.href
}
return l
}
func (l *LineParser) ParseLine(lineStr string) Line {
switch {
case strings.HasPrefix(lineStr, "```"):
l.inPreformatted = !l.inPreformatted
return PreformattingToggleLine{}
case l.inPreformatted:
return PreformattedTextLine{lineStr}
case strings.HasPrefix(lineStr, "=>"):
return ParseLinkLine(lineStr)
}
return nil
}

+ 29
- 0
gemini/gemini_test.go View File

@ -0,0 +1,29 @@
package gemini_test
import (
"testing"
"git.r23s.eu/wojciech/gm2html/gemini"
"github.com/stretchr/testify/assert"
)
func TestParseLinkLine(t *testing.T) {
tests := []struct {
line string
href string
title string
}{
{"=> gemini://example.org/", "gemini://example.org/", "gemini://example.org/"},
{"gemini://example.org/ An example link", "gemini://example.org/", "An example link"},
{"gemini://example.org/foo Another example link at the same host", "gemini://example.org/foo", "Another example link at the same host"},
{"=>gemini://example.org/bar Yet another example link at the same host", "gemini://example.org/bar", "Yet another example link at the same host"},
{"=> foo/bar/baz.txt A relative link ", "foo/bar/baz.txt", "A relative link"},
{"=> gopher://example.org:70/1 A gopher link", "gopher://example.org:70/1", "A gopher link"},
}
for _, test := range tests {
l := gemini.ParseLinkLine(test.line)
assert.Equal(t, test.href, l.Href(), "Incorrect href: \"%s\"", test.line)
assert.Equal(t, test.title, l.Title(), "Incorrect title: \"%s\"", test.line)
}
}

+ 5
- 0
go.mod View File

@ -0,0 +1,5 @@
module git.r23s.eu/wojciech/gm2html
go 1.14
require github.com/stretchr/testify v1.6.1

+ 10
- 0
go.sum View File

@ -0,0 +1,10 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

Loading…
Cancel
Save