testmark-go

Merge pull request #15 from TripleDogDare/trailing-whitespace-error

commit 00b11e2440469dc9e046ead7442d6c13901ac97d · parent 8c1550b905 · parent aefd8a6e14 · browse this tree
Eric Myhre, 2022-12-09 21:55:03 UTC

Trailing whitespace error
diff --git a/read.go b/read.go
index 6179b08..77658dc 100644
--- a/read.go
+++ b/read.go
@@ -77,21 +77,22 @@ func Parse(data []byte) (*Document, error) {
 			inCodeBlock = !inCodeBlock
 			goto next
 		}
-		// If we're in a code block, just fly by.
 		if inCodeBlock {
+			// If we're in a code block, just fly by.
 			goto next
 		}
-		// If we were expecting a code block just now, we didn't get it.
 		if expectCodeBlock {
-			// ... Log a complaint?  I don't think halting with a parse error would be helpful.
-			// But definitely don't wait around for arbitrarily distant code blocks.
-			expectCodeBlock = false
+			// If we were expecting a code block just now, we didn't get it.
+			return &doc, fmt.Errorf("invalid markdown comment on line %d. Missing code block for hunk %s", i+1, hunkInProgress.Name)
 		}
 		// Look for testmark block indicators.
 		if bytes.HasPrefix(line, sigilTestmark) {
 			// If this line, after the sigil prefix, doesn't begin with "(" and end with ")", it's not a well-formed markdown comment, and you should probably be told about that.
 			remainder := line[len(sigilTestmark):]
 			if len(remainder) < 2 || remainder[0] != '(' || remainder[len(remainder)-1] != ')' {
+				if unicode.IsSpace(rune(remainder[len(remainder)-1])) {
+					return &doc, fmt.Errorf("invalid markdown comment on line %d (should look like %q; remove trailing whitespace)", i+1, "[testmark]:# (data-name-here)")
+				}
 				return &doc, fmt.Errorf("invalid markdown comment on line %d (should look like %q, mind the parens)", i+1, "[testmark]:# (data-name-here)")
 			}
 			remainder = remainder[1 : len(remainder)-1]
diff --git a/read_test.go b/read_test.go
index 62de99f..d12a758 100644
--- a/read_test.go
+++ b/read_test.go
@@ -2,6 +2,7 @@ package testmark_test
 
 import (
 	"bytes"
+	"fmt"
 	"io/ioutil"
 	"path/filepath"
 	"regexp"
@@ -56,6 +57,48 @@ func TestParseCRLF(t *testing.T) {
 	readFixturesExample(t, doc)
 }
 
+func TestParseSimple(t *testing.T) {
+	buf := bytes.NewBuffer([]byte{})
+	fmt.Fprintln(buf, "[testmark]:# (simple)")
+	fmt.Fprintln(buf, "```")
+	fmt.Fprintln(buf, "Hello, World!")
+	fmt.Fprintln(buf, "```")
+	doc, err := testmark.Parse(buf.Bytes())
+	if err != nil {
+		t.Fatal(err)
+	}
+	hunk := doc.HunksByName["simple"]
+	assert(t, hunk.Body, "Hello, World!\n")
+}
+
+func TestParseTrailingWhitespace(t *testing.T) {
+	buf := bytes.NewBuffer([]byte{})
+	fmt.Fprintln(buf, "[testmark]:# (trailing/whitespace) ")
+	fmt.Fprintln(buf, "```")
+	fmt.Fprintln(buf, "foo")
+	fmt.Fprintln(buf, "```")
+	doc, err := testmark.Parse(buf.Bytes())
+	assert(t, err.Error(), `invalid markdown comment on line 1 (should look like "[testmark]:# (data-name-here)"; remove trailing whitespace)`)
+	_, exists := doc.HunksByName["trailing/whitespace"]
+	if exists {
+		t.Errorf("hunk should not exist")
+	}
+}
+
+func TestParseTrailingExtraLineBreak(t *testing.T) {
+	buf := bytes.NewBuffer([]byte("[testmark]:# (extra/newline)\n\n"))
+	fmt.Fprintln(buf, "```")
+	fmt.Fprintln(buf, "foo")
+	fmt.Fprintln(buf, "```")
+	doc, err := testmark.Parse(buf.Bytes())
+	assert(t, err.Error(), `invalid markdown comment on line 2. Missing code block for hunk extra/newline`)
+	hunk, exists := doc.HunksByName["extra/newline"]
+	if exists {
+		t.Errorf("testmark should ignore these")
+	}
+	assert(t, hunk.Body, "")
+}
+
 func TestDuplicateHunk(t *testing.T) {
 	testdata, err := filepath.Abs("testdata")
 	if err != nil {