all repos — honk @ c5b57ac802ba0131862fdab216c7b421989366bb

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?)`)
 31
 32func markitzero(s string) string {
 33	// prepare the string
 34	s = strings.TrimSpace(s)
 35	s = strings.Replace(s, "\r", "", -1)
 36	s = html.EscapeString(s)
 37	s = strings.Replace(s, "&#39;", "'", -1) // dammit go
 38
 39	// save away the code blocks so we don't mess them up further
 40	var bigcodes, lilcodes []string
 41	s = re_bigcoder.ReplaceAllStringFunc(s, func(code string) string {
 42		bigcodes = append(bigcodes, code)
 43		return "``````"
 44	})
 45	s = re_coder.ReplaceAllStringFunc(s, func(code string) string {
 46		lilcodes = append(lilcodes, code)
 47		return "`x`"
 48	})
 49
 50	// mark it zero
 51	s = re_bolder.ReplaceAllString(s, "$1<b>$2</b>$3")
 52	s = re_italicer.ReplaceAllString(s, "$1<i>$2</i>$3")
 53	s = re_quoter.ReplaceAllString(s, "<blockquote>$1</blockquote><p>")
 54	s = re_link.ReplaceAllStringFunc(s, linkreplacer)
 55
 56	// now restore the code blocks
 57	s = re_coder.ReplaceAllStringFunc(s, func(s string) string {
 58		code := lilcodes[0]
 59		lilcodes = lilcodes[1:]
 60		return code
 61	})
 62	s = re_bigcoder.ReplaceAllStringFunc(s, func(s string) string {
 63		code := bigcodes[0]
 64		bigcodes = bigcodes[1:]
 65		return code
 66	})
 67	s = re_bigcoder.ReplaceAllString(s, "<pre><code>$1</code></pre><p>")
 68	s = re_coder.ReplaceAllString(s, "<code>$1</code>")
 69
 70	// some final fixups
 71	s = strings.Replace(s, "\n", "<br>", -1)
 72	s = strings.Replace(s, "<br><blockquote>", "<blockquote>", -1)
 73	s = strings.Replace(s, "<br><pre>", "<pre>", -1)
 74	s = strings.Replace(s, "<p><br>", "<p>", -1)
 75	return s
 76}
 77
 78func linkreplacer(url string) string {
 79	if url[0] == '@' {
 80		return url
 81	}
 82	addparen := false
 83	adddot := false
 84	if strings.HasSuffix(url, ")") && strings.IndexByte(url, '(') == -1 {
 85		url = url[:len(url)-1]
 86		addparen = true
 87	}
 88	if strings.HasSuffix(url, ".") {
 89		url = url[:len(url)-1]
 90		adddot = true
 91	}
 92	url = fmt.Sprintf(`<a class="mention u-url" href="%s">%s</a>`, url, url)
 93	if adddot {
 94		url += "."
 95	}
 96	if addparen {
 97		url += ")"
 98	}
 99	return url
100}