Skip to content

Instantly share code, notes, and snippets.

@z11i
Created June 4, 2020 08:30
Show Gist options
  • Save z11i/3b24e857a8f28fdded5a569271f8f1b7 to your computer and use it in GitHub Desktop.
Save z11i/3b24e857a8f28fdded5a569271f8f1b7 to your computer and use it in GitHub Desktop.
Strip HTML tags in Golang
import (
"html"
"reflect"
"strings"
"github.com/microcosm-cc/bluemonday"
)
var p = bluemonday.UGCPolicy()
// StripHTMLTags strips the string field in `input`. The string field can be nested in other
// data types, such as a map or a slice. The method will search through all the fields.
func StripHTMLTags(input interface{}) {
values := reflect.ValueOf(input)
stripRecursive(values)
}
func stripRecursive(field reflect.Value) {
switch field.Kind() {
// String type, finally at the place we want to be, sanitize
case reflect.String:
if field.CanSet() { // Can't set for unexported type, etc.
sanitized := sanitize(sanitize(field.Interface().(string)))
field.SetString(sanitized)
}
// Pointer type, we check if it's nil. Dereference it and call recursion.
// Interface type is similar.
case reflect.Ptr,
reflect.Interface:
elem := field.Elem()
if !elem.IsValid() { // nil pointer stop processing
return
}
stripRecursive(elem)
// For slice, loop each element and call recursion.
case reflect.Slice:
for j := 0; j < field.Len(); j++ {
sj := field.Index(j)
stripRecursive(sj)
}
// For struct, loop each field and call recursion.
case reflect.Struct:
for j := 0; j < field.NumField(); j++ {
ff := field.Field(j)
stripRecursive(ff)
}
// For map, loop each key and call recursion. Note that we have to construct a new interface
// for a value in the map, or else the value cannot be able to set.
case reflect.Map:
for _, key := range field.MapKeys() {
val := field.MapIndex(key)
cloneVal := reflect.New(val.Type()).Elem()
cloneVal.Set(val)
stripRecursive(cloneVal)
field.SetMapIndex(key, cloneVal)
}
}
}
func sanitize(input string) string {
sanitized := p.Sanitize(input)
sanitized = html.UnescapeString(sanitized)
sanitized = strings.TrimSpace(sanitized)
sanitized = strings.ReplaceAll(sanitized, "`", "")
return sanitized
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment