package html import ( "bytes" "code.squareroundforest.org/arpio/textedit" "io" ) const unicodeNBSP = 0xa0 func escapeEdit(nonbreakSpaces bool) func(rune, []rune) ([]rune, []rune) { return func(r rune, state []rune) ([]rune, []rune) { var rr []rune switch r { case ' ': if !nonbreakSpaces { return []rune{r}, nil } if len(state) == 0 { return nil, []rune{' '} } return []rune(" "), []rune(" ") case '<': rr = []rune("<") case '>': rr = []rune(">") case '&': rr = []rune("&") case unicodeNBSP: rr = []rune(" ") default: rr = []rune{r} } return append(state, rr...), nil } } func escapeReleaseState(state []rune) []rune { return state } func newEscapeWriter(out io.Writer, nonbreakSpaces bool) *textedit.Writer { return textedit.New( out, textedit.Func( escapeEdit(nonbreakSpaces), escapeReleaseState, ), ) } func escape(s string, nonbreakSpaces bool) string { var b bytes.Buffer w := newEscapeWriter(&b, nonbreakSpaces) w.Write([]byte(s)) w.Flush() return b.String() } func escapeAttribute(value string) string { var b bytes.Buffer w := textedit.New( &b, textedit.Replace( "&", "&", "\"", """, ), ) w.Write([]byte(value)) // w.Flush() return b.String() }