Add a new "mdtrace" for debugging the md package with the trace codec.

This commit is contained in:
Qi Xiao 2022-11-02 02:20:28 +00:00
parent b61dc859ad
commit 96e4f75e43
7 changed files with 50 additions and 29 deletions

View File

@ -14,7 +14,5 @@ func main() {
if err != nil {
log.Fatal(err)
}
var codec md.FmtCodec
md.Render(string(text), &codec)
fmt.Print(codec.String())
fmt.Print(md.RenderString(string(text), &md.FmtCodec{}))
}

18
cmd/mdtrace/mdtrace.go Normal file
View File

@ -0,0 +1,18 @@
package main
import (
"fmt"
"io"
"log"
"os"
"src.elv.sh/pkg/md"
)
func main() {
text, err := io.ReadAll(os.Stdin)
if err != nil {
log.Fatal(err)
}
fmt.Print(md.RenderString(string(text), &md.TraceCodec{}))
}

View File

@ -5,7 +5,7 @@ import (
"testing"
"github.com/google/go-cmp/cmp"
"src.elv.sh/pkg/md"
. "src.elv.sh/pkg/md"
"src.elv.sh/pkg/testutil"
)
@ -47,7 +47,7 @@ var supplementalFmtCases = []testCase{
var fmtTestCases = concat(htmlTestCases, supplementalFmtCases)
func TestFmtPreservesHTMLRender(t *testing.T) {
testutil.Set(t, &md.UnescapeEntities, html.UnescapeString)
testutil.Set(t, &UnescapeEntities, html.UnescapeString)
for _, tc := range fmtTestCases {
t.Run(tc.testName(), func(t *testing.T) {
testFmtPreservesHTMLRender(t, tc.Markdown)
@ -64,20 +64,23 @@ func FuzzFmtPreservesHTMLRender(f *testing.F) {
func testFmtPreservesHTMLRender(t *testing.T, original string) {
t.Helper()
formatted := render(original, &md.FmtCodec{})
formattedRender := render(formatted, &htmlCodec{})
originalRender := render(original, &htmlCodec{})
formatted := RenderString(original, &FmtCodec{})
formattedRender := RenderString(formatted, &htmlCodec{})
originalRender := RenderString(original, &htmlCodec{})
if formattedRender != originalRender {
t.Errorf("original:\n%s\nformatted:\n%s\n"+
"HTML diff (-original +formatted):\n%sops diff (-original +formatted):\n%s",
"markdown diff (-original +formatted):\n%s"+
"HTML diff (-original +formatted):\n%s"+
"ops diff (-original +formatted):\n%s",
hr+"\n"+original+hr, hr+"\n"+formatted+hr,
cmp.Diff(original, formatted),
cmp.Diff(originalRender, formattedRender),
cmp.Diff(render(original, &md.OpTraceCodec{}), render(formatted, &md.OpTraceCodec{})))
cmp.Diff(RenderString(original, &TraceCodec{}), RenderString(formatted, &TraceCodec{})))
}
}
func TestFmtIsIdempotent(t *testing.T) {
testutil.Set(t, &md.UnescapeEntities, html.UnescapeString)
testutil.Set(t, &UnescapeEntities, html.UnescapeString)
for _, tc := range fmtTestCases {
t.Run(tc.testName(), func(t *testing.T) {
testFmtIsIdempotent(t, tc.Markdown)
@ -94,8 +97,8 @@ func FuzzFmtIsIdempotent(f *testing.F) {
func testFmtIsIdempotent(t *testing.T, original string) {
t.Helper()
formatted1 := render(original, &md.FmtCodec{})
formatted2 := render(formatted1, &md.FmtCodec{})
formatted1 := RenderString(original, &FmtCodec{})
formatted2 := RenderString(formatted1, &FmtCodec{})
if formatted1 != formatted2 {
t.Errorf("original:\n%s\nformatted1:\n%s\nformatted2:\n%s\n"+
"diff (-formatted1 +formatted2):\n%s",

View File

@ -97,12 +97,25 @@ const (
OpOrderedListEnd
)
// Render parses markdown and renders it according to the output syntax.
// Render parses markdown and renders it with a Codec.
func Render(text string, codec Codec) {
p := blockParser{lines: lineSplitter{text, 0}, codec: codec}
p.render()
}
// CodecStringer is a Codec that also implements the String method.
type CodecStringer interface {
Codec
String() string
}
// Render parses markdown, renders it with a Codec, and returns the result of
// the String() method of the Codec.
func RenderString(text string, codec CodecStringer) string {
Render(text, codec)
return codec.String()
}
type blockParser struct {
lines lineSplitter
codec Codec

View File

@ -17,7 +17,7 @@ func TestRender(t *testing.T) {
for _, tc := range htmlTestCases {
t.Run(tc.testName(), func(t *testing.T) {
tc.skipIfNotSupported(t)
got := render(tc.Markdown, &htmlCodec{})
got := RenderString(tc.Markdown, &htmlCodec{})
// Try to hide the difference between tight and loose lists by
// "loosifying" the output. This only works for tight lists whose
// items consist of single lines, so more complex cases are still

View File

@ -8,7 +8,6 @@ import (
"strings"
"testing"
"src.elv.sh/pkg/md"
"src.elv.sh/pkg/must"
)
@ -266,13 +265,3 @@ func loosifyLists(html string) string {
looseListItem.ReplaceAllString(html, "<li>\n<p>$1</p>\n</li>"),
"<li></li>", "<li>\n</li>")
}
type codecStringer interface {
md.Codec
String() string
}
func render(markdown string, codec codecStringer) string {
md.Render(markdown, codec)
return codec.String()
}

View File

@ -5,10 +5,10 @@ import (
"strings"
)
// OpTraceCodec is a Codec that records all the Op's passed to its Do method.
type OpTraceCodec struct{ strings.Builder }
// TraceCodec is a Codec that records all the Op's passed to its Do method.
type TraceCodec struct{ strings.Builder }
func (c *OpTraceCodec) Do(op Op) {
func (c *TraceCodec) Do(op Op) {
if c.Len() > 0 {
c.WriteByte('\n')
}