all repos — honk @ a454045f5f4c22ede8ea2448ef053449d550cd85

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