all repos — honk @ a96588b4643747fab14389ce3c8b13ed31f590fe

my fork of honk

markitzero.go (view raw)

  1//
  2// Copyright (c) 2019 Ted Unangst <tedu@tedunangst.com>
  3//
  4// Permission to use, copy, modify, and distribute this software for any
  5// purpose with or without fee is hereby granted, provided that the above
  6// copyright notice and this permission notice appear in all copies.
  7//
  8// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 10// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 11// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 12// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 13// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 14// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 15
 16package main
 17
 18import (
 19	"fmt"
 20	"regexp"
 21	"strings"
 22
 23	"golang.org/x/net/html"
 24)
 25
 26var re_bolder = regexp.MustCompile(`(^|\W)\*\*([\w\s,.!?':_-]+)\*\*($|\W)`)
 27var re_italicer = regexp.MustCompile(`(^|\W)\*([\w\s,.!?':_-]+)\*($|\W)`)
 28var re_bigcoder = regexp.MustCompile("```\n?((?s:.*?))\n?```\n?")
 29var re_coder = regexp.MustCompile("`([^`]*)`")
 30var re_quoter = regexp.MustCompile(`(?m:^&gt; (.*)\n?)`)
 31var re_link = regexp.MustCompile(`.?.?https?://[^\s"]+[\w/)]`)
 32var re_zerolink = regexp.MustCompile(`\[([^]]*)\]\(([^)]*\)?)\)`)
 33
 34func markitzero(s string) string {
 35	// prepare the string
 36	s = strings.TrimSpace(s)
 37	s = strings.Replace(s, "\r", "", -1)
 38	s = html.EscapeString(s)
 39	s = strings.Replace(s, "&#39;", "'", -1) // dammit go
 40
 41	// save away the code blocks so we don't mess them up further
 42	var bigcodes, lilcodes []string
 43	s = re_bigcoder.ReplaceAllStringFunc(s, func(code string) string {
 44		bigcodes = append(bigcodes, code)
 45		return "``````"
 46	})
 47	s = re_coder.ReplaceAllStringFunc(s, func(code string) string {
 48		lilcodes = append(lilcodes, code)
 49		return "`x`"
 50	})
 51
 52	// mark it zero
 53	s = re_bolder.ReplaceAllString(s, "$1<b>$2</b>$3")
 54	s = re_italicer.ReplaceAllString(s, "$1<i>$2</i>$3")
 55	s = re_quoter.ReplaceAllString(s, "<blockquote>$1</blockquote><p>")
 56	s = re_link.ReplaceAllStringFunc(s, linkreplacer)
 57	s = re_zerolink.ReplaceAllString(s, `<a class="mention u-url" href="$2">$1</a>`)
 58
 59	// now restore the code blocks
 60	s = re_coder.ReplaceAllStringFunc(s, func(s string) string {
 61		code := lilcodes[0]
 62		lilcodes = lilcodes[1:]
 63		return code
 64	})
 65	s = re_bigcoder.ReplaceAllStringFunc(s, func(s string) string {
 66		code := bigcodes[0]
 67		bigcodes = bigcodes[1:]
 68		return code
 69	})
 70	s = re_bigcoder.ReplaceAllString(s, "<pre><code>$1</code></pre><p>")
 71	s = re_coder.ReplaceAllString(s, "<code>$1</code>")
 72
 73	// some final fixups
 74	s = strings.Replace(s, "\n", "<br>", -1)
 75	s = strings.Replace(s, "<br><blockquote>", "<blockquote>", -1)
 76	s = strings.Replace(s, "<br><pre>", "<pre>", -1)
 77	s = strings.Replace(s, "<p><br>", "<p>", -1)
 78	return s
 79}
 80
 81func linkreplacer(url string) string {
 82	if url[0:2] == "](" {
 83		return url
 84	}
 85	prefix := ""
 86	for !strings.HasPrefix(url, "http") {
 87		prefix += url[0:1]
 88		url = url[1:]
 89	}
 90	addparen := false
 91	adddot := false
 92	if strings.HasSuffix(url, ")") && strings.IndexByte(url, '(') == -1 {
 93		url = url[:len(url)-1]
 94		addparen = true
 95	}
 96	if strings.HasSuffix(url, ".") {
 97		url = url[:len(url)-1]
 98		adddot = true
 99	}
100	url = fmt.Sprintf(`<a class="mention u-url" href="%s">%s</a>`, url, url)
101	if adddot {
102		url += "."
103	}
104	if addparen {
105		url += ")"
106	}
107	return prefix + url
108}