func split(s string) []string {
	var (
		words = make([]string, 0, 10)
		start = 0
	)
	appendWord := func(end int) {
		if j := strings.Index(s[start:end], "[["); j > -1 {
			if _, l := parseInlineLink(s[start+j:]); l > 0 {
				if j > 0 {
					words = append(words, s[start:start+j])
				}
				words = append(words, s[start+j:start+j+l])
				start = start + j + l
				return
			}
		}
		words = append(words, s[start:end])
		start = end
	}
	wasSpace := false
	for i, r := range s {
		isSpace := unicode.IsSpace(r)
		if i > start && isSpace != wasSpace {
			appendWord(i)
		}
		wasSpace = isSpace
	}
	for start < len(s) {
		appendWord(len(s))
	}
	return words
}
split is like strings.Fields but also returns the runs of spaces
and treats inline links as distinct words.
package present
import (
	"bytes"
	"html"
	"html/template"
	"strings"
	"unicode"
	"unicode/utf8"
)
func init() {
	funcs["style"] = Style
}
func Style(s string) template.HTML {
	return template.HTML(font(html.EscapeString(s)))
}
func font(s string) string {
	if !strings.ContainsAny(s, "[`_*") {
		return s
	}
	words := split(s)
	var b bytes.Buffer
Word:
	for w, word := range words {
		if len(word) < 2 {
			continue Word
		}
		if link, _ := parseInlineLink(word); link != "" {
			words[w] = link
			continue Word
		}
		const marker = "_*`"
		first := strings.IndexAny(word, marker)
		if first == -1 {
			continue Word
		}
		if first != 0 {
			r, _ := utf8.DecodeLastRuneInString(word[:first])
			if !unicode.IsPunct(r) {
				continue Word
			}
		}
		open, word := word[:first], word[first:]
		char := word[0]  
		close := ""
		switch char {
		default:
			continue Word
		case '_':
			open += "<i>"
			close = "</i>"
		case '*':
			open += "<b>"
			close = "</b>"
		case '`':
			open += "<code>"
			close = "</code>"
		}
		last := strings.LastIndex(word, word[:1])
		if last == 0 {
			continue Word
		}
		if last+1 != len(word) {
			r, _ := utf8.DecodeRuneInString(word[last+1:])
			if !unicode.IsPunct(r) {
				continue Word
			}
		}
		head, tail := word[:last+1], word[last+1:]
		b.Reset()
		b.WriteString(open)
		var wid int
		for i := 1; i < len(head)-1; i += wid {
			var r rune
			r, wid = utf8.DecodeRuneInString(head[i:])
			if r != rune(char) {
				b.WriteRune(r)
				continue
			}
			if head[i+1] != char {
				b.WriteRune(' ')
				continue
			}
			b.WriteByte(char)
			wid++  
		}
		b.WriteString(close)  
		b.WriteString(tail)   
		words[w] = b.String()
	}
	return strings.Join(words, "")
}