From 43428e759d9fbc5a319c2b929bfb4469938cc386 Mon Sep 17 00:00:00 2001 From: clsr Date: Thu, 23 Dec 2021 01:54:47 +0000 Subject: Add EscapeAll and escape all spaces in links --- cnmfmt/cnmfmt.go | 2 +- cnmfmt/cnmfmt_test.go | 15 +++++++++++++-- content.go | 2 +- document.go | 4 ++-- parse_test.go | 6 ++++-- simpletext.go | 32 +++++++++++++++++++++++++++++++- simpletext_test.go | 29 +++++++++++++++++++++++++++++ write_test.go | 11 ++++++----- 8 files changed, 87 insertions(+), 14 deletions(-) diff --git a/cnmfmt/cnmfmt.go b/cnmfmt/cnmfmt.go index 1e5b6ee..3e38978 100644 --- a/cnmfmt/cnmfmt.go +++ b/cnmfmt/cnmfmt.go @@ -195,7 +195,7 @@ func (t Text) WriteIndent(w io.Writer, n int) error { if span.Text != "" { pad = " " } - line = append(line, "@@", cnm.Escape(span.Format.Link), pad) + line = append(line, "@@", cnm.EscapeAll(span.Format.Link), pad) } } } diff --git a/cnmfmt/cnmfmt_test.go b/cnmfmt/cnmfmt_test.go index 5d50b18..2ad92cb 100644 --- a/cnmfmt/cnmfmt_test.go +++ b/cnmfmt/cnmfmt_test.go @@ -127,6 +127,9 @@ var parseTests = map[string]Text{ "@@foo ": Text{[]Span{ Span{Format{Link: "foo"}, ""}, }}, + "@@foo\\ bar baz quux@@": Text{[]Span{ + Span{Format{Link: "foo bar"}, "baz quux"}, + }}, "@@foo\\": Text{[]Span{ Span{Format{Link: "foo\\"}, ""}, }}, @@ -213,9 +216,9 @@ func textEqual(a, b Text) bool { } var escapeTests = map[string]string{ - "\n\r\t\v\x00": "\\n\\r\\t\v\\x00", + "\n\r\t\v\x00": "\\n\\r\\t\v\\x00", "@@!!##\"\"//\"\"__``**%%^^&&++==\x01\x01\\": "\\@\\@!!##\\\"\\\"//\\\"\\\"\\_\\_\\`\\`\\*\\*%%^^&&++==\x01\x01\\\\", - `foo\@\@bar`: `foo\\\@\\\@bar`, + `foo\@\@bar`: `foo\\\@\\\@bar`, } func TestEscape(t *testing.T) { @@ -269,6 +272,10 @@ var parseTextTests = map[string]TextFmtContents{ Text{[]Span{Span{Format{Emphasized: true}, "foo"}}}, Text{[]Span{Span{Format{}, "bar"}}}, }}, + + "@@foo\\ bar baz quux@@": TextFmtContents{[]Text{ + Text{[]Span{Span{Format{Link: "foo bar"}, "baz quux"}}}, + }}, } func TestParseTextFmt(t *testing.T) { @@ -335,6 +342,10 @@ var writeTests = map[string]TextFmtContents{ }}, }}, + "@@foo\\ bar baz quux\n": TextFmtContents{[]Text{ + Text{[]Span{Span{Format{Link: "foo bar"}, "baz quux"}}}, + }}, + "foo**bar``baz**quux\n\n" + "\\ \"\"qwe\\ \"\"__\\ asd \\ __``zxc``**\\ \n\n" + "__@@http://example.com/__/ exa__mple@@ @@href text@@__ test\n": TextFmtContents{[]Text{ diff --git a/content.go b/content.go index dbe0fa4..572305a 100644 --- a/content.go +++ b/content.go @@ -589,7 +589,7 @@ func (e *EmbedBlock) WriteIndent(w io.Writer, n int) error { } else { s += Escape(e.Type) } - s += " " + Escape(e.URL) + s += " " + EscapeAll(e.URL) if err := WriteIndent(w, s, n); err != nil { return err } diff --git a/document.go b/document.go index 65eac3e..236782b 100644 --- a/document.go +++ b/document.go @@ -197,7 +197,7 @@ type Link struct { // WriteIndent writes the link URL, name and description indented by n tabs. func (link Link) WriteIndent(w io.Writer, n int) error { - s := Escape(link.URL) + s := EscapeAll(link.URL) if link.Name != "" { s += " " + Escape(link.Name) } @@ -226,7 +226,7 @@ type Site struct { // WriteIndent writes the sitemap indented by n tabs. func (site Site) WriteIndent(w io.Writer, n int) error { - s := Escape(site.Path) + s := EscapeAll(site.Path) if site.Name != "" { s += " " + Escape(site.Name) } diff --git a/parse_test.go b/parse_test.go index e70b833..1c7dad9 100644 --- a/parse_test.go +++ b/parse_test.go @@ -269,7 +269,7 @@ var parseTests = map[string]*Document{ "title\n\tfoo bar\n" + "links\n\tqwe asd\n\tzxc 123\n" + - "site\n\tfoo\n\t\tbar\n\t\tbaz/quux\n\t\t\t123\n" + + "site\n\tfoo Foo\n\t\tbar\n\t\tbaz/qu\\ ux Test\n\t\t\t123\n" + "title\n\tbaz\n" + "links\n\tfoo\n" + "site\n\ttest": &Document{ @@ -283,10 +283,12 @@ var parseTests = map[string]*Document{ Children: []Site{ Site{ Path: "foo", + Name: "Foo", Children: []Site{ Site{Path: "bar"}, Site{ - Path: "baz/quux", + Path: "baz/qu ux", + Name: "Test", Children: []Site{ Site{Path: "123"}, }, diff --git a/simpletext.go b/simpletext.go index 4d86d6d..00d82ec 100644 --- a/simpletext.go +++ b/simpletext.go @@ -70,7 +70,9 @@ func CollapseWhitespace(raw string) string { var escapeRe = regexp.MustCompile(`[\t\n\f\r\\\x00]|^ | $| `) -// Escape escapes whitespace, backslash and and U+0000 within s. +// Escape escapes whitespace, backslash and U+0000 within s. +// +// Only leading, trailing or multiple consecutive spaces are escaped. func Escape(s string) string { return escapeRe.ReplaceAllStringFunc(s, func(match string) string { switch match { @@ -115,6 +117,34 @@ func EscapeSpace(s string) string { }) } +var escapeAllRe = regexp.MustCompile(`[\t\n\f\r\\\x00 ]`) + +// EscapeAll escapes all whitespace, backslash and and U+0000 within s. +// +// Unlike Escape, all spaces are escaped, not just ones that would be collapsed +// into one. +func EscapeAll(s string) string { + return escapeAllRe.ReplaceAllStringFunc(s, func(match string) string { + switch match { + case "\t": + return `\t` + case "\n": + return `\n` + case "\f": + return `\f` + case "\r": + return `\r` + case "\\": + return `\\` + case "\x00": + return `\x00` + case " ": + return `\ ` + } + return match // this shouldn't happen + }) +} + var escapeNonspaceRe = regexp.MustCompile(`[\f\r\\\x00]`) // EscapeNonspace works like Escape, except it does not escape spaces, tabs and diff --git a/simpletext_test.go b/simpletext_test.go index c5b4cf9..d75a741 100644 --- a/simpletext_test.go +++ b/simpletext_test.go @@ -92,6 +92,35 @@ func TestEscapeSpace(t *testing.T) { } } +var allEscapes = map[string]string{ + "": ``, + "ContNet": `ContNet`, + "\t": `\t`, + "\n": `\n`, + "\f": `\f`, + "\r": `\r`, + " ": `\ `, + "\\": `\\`, + "\x00": `\x00`, + " ": `\ \ \ \ \ \ \ `, + " ": `\ \ \ \ \ \ `, + " ": `\ \ \ \ `, + " ": `\ \ \ `, + " ": `\ \ `, + "\b\v\\\x00\xff\u00ff\\xff": "\b\v\\\\\\x00\xff\u00ff\\\\xff", +} + +func TestEscapeAll(t *testing.T) { + for k, v := range allEscapes { + t.Run(k, func(t *testing.T) { + e := EscapeAll(k) + if e != v { + t.Errorf("EscapeAll(%q) -> %q, expected %q", k, e, v) + } + }) + } +} + var simpleUnescapes = map[string]string{ ``: "", `ContNet`: "ContNet", diff --git a/write_test.go b/write_test.go index 18809b1..8cca449 100644 --- a/write_test.go +++ b/write_test.go @@ -13,22 +13,23 @@ var writeTests = map[string]*Document{ }, "title\n\tfoo bar baz\n" + - "links\n\tqwe asd\n\tzxc 123\n\tfoo\n" + - "site\n\tfoo\n\t\tbar\n\t\tbaz/quux\n\t\t\t123\n\ttest\n": &Document{ + "links\n\tqwe\\ asd zxc 123\n\tfoo\n" + + "site\n\tfoo Foo\n\t\tbar\n\t\tbaz/qu\\ ux Test\n\t\t\t123\n\ttest\n": &Document{ Title: "foo bar baz", Links: []Link{ - Link{"qwe", "asd", ""}, - Link{"zxc", "123", ""}, + Link{"qwe asd", "zxc 123", ""}, Link{"foo", "", ""}, }, Site: Site{ Children: []Site{ Site{ Path: "foo", + Name: "Foo", Children: []Site{ Site{Path: "bar"}, Site{ - Path: "baz/quux", + Path: "baz/qu ux", + Name: "Test", Children: []Site{ Site{Path: "123"}, }, -- cgit