From c1a6908801b47f4a48e1b8391854d71842098edb Mon Sep 17 00:00:00 2001 From: Ted Unangst Date: Sun, 6 Oct 2019 15:14:18 -0400 Subject: [PATCH] better markdown linebreaks (and add the file, doh) --- markitzero.go | 101 +++++++++++++++++++++++++++++++++++++++++++++ markitzero_test.go | 36 ++++++++++++++-- 2 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 markitzero.go diff --git a/markitzero.go b/markitzero.go new file mode 100644 index 0000000..ade5089 --- /dev/null +++ b/markitzero.go @@ -0,0 +1,101 @@ +// +// Copyright (c) 2019 Ted Unangst +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +package main + +import ( + "fmt" + "regexp" + "strings" + + "golang.org/x/net/html" +) + + +var re_bolder = regexp.MustCompile(`(^|\W)\*\*([\w\s,.!?':_-]+)\*\*($|\W)`) +var re_italicer = regexp.MustCompile(`(^|\W)\*([\w\s,.!?':_-]+)\*($|\W)`) +var re_bigcoder = regexp.MustCompile("```\n?((?s:.*?))\n?```\n?") +var re_coder = regexp.MustCompile("`([^`]*)`") +var re_quoter = regexp.MustCompile(`(?m:^> (.*)\n?)`) + +func markitzero(s string) string { + // prepare the string + s = strings.TrimSpace(s) + s = strings.Replace(s, "\r", "", -1) + s = html.EscapeString(s) + s = strings.Replace(s, "'", "'", -1) // dammit go + + // save away the code blocks so we don't mess them up further + var bigcodes, lilcodes []string + s = re_bigcoder.ReplaceAllStringFunc(s, func(code string) string { + bigcodes = append(bigcodes, code) + return "``````" + }) + s = re_coder.ReplaceAllStringFunc(s, func(code string) string { + lilcodes = append(lilcodes, code) + return "`x`" + }) + + // mark it zero + s = re_bolder.ReplaceAllString(s, "$1$2$3") + s = re_italicer.ReplaceAllString(s, "$1$2$3") + s = re_quoter.ReplaceAllString(s, "
$1

") + s = re_link.ReplaceAllStringFunc(s, linkreplacer) + + // now restore the code blocks + s = re_coder.ReplaceAllStringFunc(s, func(s string) string { + code := lilcodes[0] + lilcodes = lilcodes[1:] + return code + }) + s = re_bigcoder.ReplaceAllStringFunc(s, func(s string) string { + code := bigcodes[0] + bigcodes = bigcodes[1:] + return code + }) + s = re_bigcoder.ReplaceAllString(s, "

$1

") + s = re_coder.ReplaceAllString(s, "$1") + + // some final fixups + s = strings.Replace(s, "\n", "
", -1) + s = strings.Replace(s, "

", "
", -1) + s = strings.Replace(s, "
", "
", -1)
+	s = strings.Replace(s, "


", "

", -1) + return s +} + +func linkreplacer(url string) string { + if url[0] == '@' { + return url + } + addparen := false + adddot := false + if strings.HasSuffix(url, ")") && strings.IndexByte(url, '(') == -1 { + url = url[:len(url)-1] + addparen = true + } + if strings.HasSuffix(url, ".") { + url = url[:len(url)-1] + adddot = true + } + url = fmt.Sprintf(`%s`, url, url) + if adddot { + url += "." + } + if addparen { + url += ")" + } + return url +} diff --git a/markitzero_test.go b/markitzero_test.go index a26b234..e6874bd 100644 --- a/markitzero_test.go +++ b/markitzero_test.go @@ -4,12 +4,40 @@ import ( "testing" ) -func TestMarkitzero(t *testing.T) { - input := `link to https://example.com/ with **bold** text` - output := `link to https://example.com/ with bold text` - +func onetest(t *testing.T, input, output string) { result := markitzero(input) if result != output { t.Errorf("\nexpected:\n%s\noutput:\n%s", output, result) } } + +func basictest(t *testing.T) { + input := `link to https://example.com/ with **bold** text` + output := `link to https://example.com/ with bold text` + onetest(t, input, output) +} + +func linebreak1(t *testing.T) { + input := "hello\n> a quote\na comment" + output := "hello

a quote

a comment" + onetest(t, input, output) +} + +func linebreak2(t *testing.T) { + input := "hello\n\n> a quote\n\na comment" + output := "hello

a quote

a comment" + onetest(t, input, output) +} + +func linebreak3(t *testing.T) { + input := "hello\n\n```\nfunc(s string)\n```\n\ndoes it go?" + output := "hello

func(s string)

does it go?" + onetest(t, input, output) +} + +func TestMarkitzero(t *testing.T) { + basictest(t) + linebreak1(t) + linebreak2(t) + linebreak3(t) +}