Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to Goldmark #54

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions go.mod
Expand Up @@ -5,19 +5,21 @@ go 1.16
require (
github.com/BurntSushi/toml v1.0.0
github.com/Masterminds/sprig/v3 v3.2.2
github.com/gomarkdown/markdown v0.0.0-20220310201231-552c6011c0b8
github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c
github.com/google/uuid v1.3.0 // indirect
github.com/grokify/html-strip-tags-go v0.0.1
github.com/hexops/gotextdiff v1.0.3
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/niklasfasching/go-org v1.6.2
github.com/olekukonko/tablewriter v0.0.5
github.com/rivo/uniseg v0.4.3 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/yuin/goldmark v1.5.3
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
Expand Down
13 changes: 8 additions & 5 deletions go.sum
Expand Up @@ -12,8 +12,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/gomarkdown/markdown v0.0.0-20220310201231-552c6011c0b8 h1:YVvt637ygnOO9qjLBVmPOvrUmCz/i8YECSu/8UlOQW0=
github.com/gomarkdown/markdown v0.0.0-20220310201231-552c6011c0b8/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c h1:iyaGYbCmcYK0Ja9a3OUa2Fo+EaN0cbLu0eKpBwPFzc8=
github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
Expand All @@ -36,8 +36,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
Expand All @@ -50,8 +50,9 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
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/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
Expand All @@ -65,6 +66,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.5.3 h1:3HUJmBFbQW9fhQOzMgseU134xfi6hU+mjWywx5Ty+/M=
github.com/yuin/goldmark v1.5.3/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
Expand Down
18 changes: 18 additions & 0 deletions internal/renderer2/doc.go
@@ -0,0 +1,18 @@
// This file is part of gmnhg.

// gmnhg is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// gmnhg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with gmnhg. If not, see <https://www.gnu.org/licenses/>.

// Package renderer contains an implementation of markdown =>
// text/gemini renderer for github.com/yuin/goldmark.
package renderer
37 changes: 37 additions & 0 deletions internal/renderer2/renderer.go
@@ -0,0 +1,37 @@
// This file is part of gmnhg.

// gmnhg is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// gmnhg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with gmnhg. If not, see <https://www.gnu.org/licenses/>.

package renderer

import (
"io"

"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/renderer"
)

// Renderer implements renderer.Renderer.
type Renderer struct{}

// NewRenderer returns a new Renderer.
func NewRenderer() Renderer {
return Renderer{}
}

func (r Renderer) Render(w io.Writer, source []byte, node ast.Node) error {
return nil
}

func (r Renderer) AddOptions(...renderer.Option) {}
43 changes: 36 additions & 7 deletions render.go
Expand Up @@ -23,6 +23,10 @@ import (
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/parser"
"github.com/tdemin/gmnhg/internal/renderer"
renderer2 "github.com/tdemin/gmnhg/internal/renderer2"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/text"
)

// Settings is a bitmask for renderer preferences.
Expand All @@ -40,19 +44,44 @@ const (

var trailing = []byte("\n\n")

func stripTrailingNewlines(content []byte) []byte {
stripped := content
for li := bytes.LastIndex(stripped, trailing); li != -1; li = bytes.LastIndex(stripped, trailing) {
if li != len(stripped)-len(trailing) {
break
}
stripped = stripped[:len(stripped)-1]
}
return stripped
}

// RenderMarkdown converts Markdown text to Gemtext using gomarkdown. It
// ignores front matter if any has been provided in the text.
func RenderMarkdown(md []byte, settings Settings) (geminiText []byte, err error) {
ast := markdown.Parse(md, parser.NewWithExtensions(parser.CommonExtensions|
parser.NoEmptyLineBeforeBlock|
parser.Footnotes))
content := markdown.Render(ast, renderer.NewRenderer())
// strip trailing newlines if any
for li := bytes.LastIndex(content, trailing); li != -1; li = bytes.LastIndex(content, trailing) {
if li != len(content)-len(trailing) {
break
}
content = content[:len(content)-1]
return stripTrailingNewlines(content), nil
}

// RenderMarkdown2 converts Markdown text to Gemtext using Goldmark. It
// ignores front matter if any has been provided in the text.
func RenderMarkdown2(md []byte, settings Settings) (geminiText []byte, err error) {
r := renderer2.NewRenderer()
gm := goldmark.New(
goldmark.WithExtensions(
extension.GFM,
extension.Footnote,
extension.DefinitionList,
),
goldmark.WithRenderer(r),
)
ast := gm.Parser().Parse(text.NewReader(md))

buf := bytes.Buffer{}
if err := gm.Renderer().Render(&buf, md, ast); err != nil {
return nil, err
}
return content, nil
return stripTrailingNewlines(buf.Bytes()), nil
}
26 changes: 26 additions & 0 deletions render_test.go
Expand Up @@ -75,3 +75,29 @@ func TestRenderer(t *testing.T) {
}
}
}

func TestRenderer2(t *testing.T) {
for _, testName := range fileList {
t.Logf("testing %s", testName)
mdContents, err := ioutil.ReadFile(path.Join("testdata", testName+".md"))
if err != nil {
t.Fatalf("failed to open Markdown test %s: %v", testName, err)
}
gmiContents, err := ioutil.ReadFile(path.Join("testdata", testName+".gmi"))
if err != nil {
t.Logf("%s: cannot open Gemtext file, skipping: %v", testName, err)
continue
}
content, _ := gmnhg.ParseMetadata(mdContents)
geminiContent, err := RenderMarkdown2(content, Defaults)
if err != nil {
t.Errorf("failed to convert %s Markdown to Gemtext: %v", testName, err)
}
if !bytes.Equal(geminiContent, gmiContents) {
diff := myers.ComputeEdits(span.URIFromPath("a.gmi"),
string(geminiContent), string(gmiContents))
t.Errorf("content mismatch on %s, diff:\n%s", testName,
gotextdiff.ToUnified("a.gmi", "b.gmi", string(geminiContent), diff))
}
}
}