Discussion:
Package html/template already contextually escapes all pipelines to
produce HTML output safe against code injection. Manually escaping
pipeline output using the predefined escapers "html" or "urlquery" is
unnecessary, and may affect the correctness or safety of the escaped
pipeline output in Go 1.8 and earlier.
In most cases, such as the given example, this error can be resolved by
simply removing the predefined escaper from the pipeline and letting the
contextual autoescaper handle the escaping of the pipeline. In other
instances, where the predefined escaper occurs in the middle of a
pipeline where subsequent commands expect escaped input, e.g.
{{.X | html | makeALink}}
where makeALink does
return `
link`
consider refactoring the surrounding template to make use of the
contextual autoescaper, i.e.
link
To ease migration to Go 1.9 and beyond, "html" and "urlquery" will
continue to be allowed as the last command in a pipeline. However, if the
pipeline occurs in an unquoted attribute value context, "html" is
disallowed. Avoid using "html" and "urlquery" entirely in new templates.
const ErrPredefinedEscaper
ErrRangeLoopReentry
const
#
const ErrRangeLoopReentry
ErrSlashAmbig
const
#
const ErrSlashAmbig
OK
const
#
const OK ErrorCode = iota
_attr_index
var
#
var _attr_index = [...]uint8{...}
_attr_name
const
#
const _attr_name = "attrNoneattrScriptattrScriptTypeattrStyleattrURLattrSrcset"
_delim_index
var
#
var _delim_index = [...]uint8{...}
_delim_name
const
#
const _delim_name = "delimNonedelimDoubleQuotedelimSingleQuotedelimSpaceOrTagEnd"
_element_index
var
#
var _element_index = [...]uint8{...}
_element_name
const
#
const _element_name = "elementNoneelementScriptelementStyleelementTextareaelementTitle"
_jsCtx_index
var
#
var _jsCtx_index = [...]uint8{...}
_jsCtx_name
const
#
const _jsCtx_name = "jsCtxRegexpjsCtxDivOpjsCtxUnknown"
_state_index
var
#
var _state_index = [...]uint16{...}
_state_name
const
#
const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSTmplLitstateJSRegexpstateJSBlockCmtstateJSLineCmtstateJSHTMLOpenCmtstateJSHTMLCloseCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
_urlPart_index
var
#
var _urlPart_index = [...]uint8{...}
_urlPart_name
const
#
const _urlPart_name = "urlPartNoneurlPartPreQueryurlPartQueryOrFragurlPartUnknown"
attrNone
const
#
const attrNone attr = iota
attrScript
const
#
const attrScript
attrScriptType
const
#
const attrScriptType
attrSrcset
const
#
const attrSrcset
attrStartStates
var
#
var attrStartStates = [...]state{...}
attrStyle
const
#
const attrStyle
attrTypeMap
var
#
var attrTypeMap = map[string]contentType{...}
attrURL
const
#
const attrURL
contentTypeCSS
const
#
const contentTypeCSS
contentTypeHTML
const
#
const contentTypeHTML
contentTypeHTMLAttr
const
#
const contentTypeHTMLAttr
contentTypeJS
const
#
const contentTypeJS
contentTypeJSStr
const
#
const contentTypeJSStr
contentTypePlain
const
#
const contentTypePlain contentType = iota
contentTypeSrcset
const
#
const contentTypeSrcset
contentTypeURL
const
#
const contentTypeURL
contentTypeUnsafe
const
#
const contentTypeUnsafe
cssReplacementTable
var
#
var cssReplacementTable = []string{...}
debugAllowActionJSTmpl
var
#
var debugAllowActionJSTmpl = *ast.CallExpr
delimDoubleQuote
const
#
const delimDoubleQuote
delimEnds
var
#
var delimEnds = [...]string{...}
delimNone
const
#
const delimNone delim = iota
delimSingleQuote
const
#
const delimSingleQuote
delimSpaceOrTagEnd
const
#
const delimSpaceOrTagEnd
doctypeBytes
var
#
var doctypeBytes = *ast.CallExpr
elementContentType
var
#
var elementContentType = [...]state{...}
elementNameMap
var
#
var elementNameMap = map[string]element{...}
elementNone
const
#
const elementNone element = iota
elementScript
const
#
var htmlNospaceReplacementTable = []string{...}
htmlReplacementTable
var
#
var htmlReplacementTable = []string{...}
htmlSpaceAndASCIIAlnumBytes
const
#
const htmlSpaceAndASCIIAlnumBytes = "\x00\x36\x00\x00\x01\x00\xff\x03\xfe\xff\xff\x07\xfe\xff\xff\x07"
jsBqStrReplacementTable
var
#
var jsBqStrReplacementTable = []string{...}
jsCtxDivOp
const
#
const jsCtxDivOp
jsCtxRegexp
const
#
const jsCtxRegexp jsCtx = iota
jsCtxUnknown
const
#
const jsCtxUnknown
jsRegexpReplacementTable
var
#
var jsRegexpReplacementTable = []string{...}
jsStrNormReplacementTable
var
#
var jsStrNormReplacementTable = []string{...}
jsStrReplacementTable
var
#
var jsStrReplacementTable = []string{...}
jsWhitespace
const
#
const jsWhitespace = "\f\n\r\t\v\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\ufeff"
jsonMarshalType
var
#
var jsonMarshalType = *ast.CallExpr
lowUnicodeReplacementTable
var
#
var lowUnicodeReplacementTable = []string{...}
mozBindingBytes
var
#
var mozBindingBytes = *ast.CallExpr
predefinedEscapers
var
#
var predefinedEscapers = map[string]bool{...}
redundantFuncs
var
#
var redundantFuncs = map[string]map[string]bool{...}
regexpPrecederKeywords
var
#
var regexpPrecederKeywords = map[string]bool{...}
scriptTagRe
var
#
var scriptTagRe = *ast.CallExpr
specialScriptTagRE
var
#
const stateHTMLCmt
stateJS
const
#
const stateJS
stateJSBlockCmt
const
#
const stateJSBlockCmt
stateJSDqStr
const
#
const stateJSDqStr
stateJSHTMLCloseCmt
const
#
const stateJSHTMLCloseCmt
stateJSHTMLOpenCmt
const
#