mirror of
https://github.com/golang/go
synced 2024-11-25 01:08:02 -07:00
exp/template/html: string replacement refactoring.
R=mikesamuel CC=golang-dev https://golang.org/cl/4968063
This commit is contained in:
parent
9854fd2a0e
commit
2b6d3b498c
@ -166,53 +166,43 @@ func jsValEscaper(args ...interface{}) string {
|
|||||||
// JavaScript source, in JavaScript embedded in an HTML5 <script> element,
|
// JavaScript source, in JavaScript embedded in an HTML5 <script> element,
|
||||||
// or in an HTML5 event handler attribute such as onclick.
|
// or in an HTML5 event handler attribute such as onclick.
|
||||||
func jsStrEscaper(args ...interface{}) string {
|
func jsStrEscaper(args ...interface{}) string {
|
||||||
ok := false
|
return replace(stringify(args...), jsStrReplacementTable)
|
||||||
var s string
|
}
|
||||||
|
|
||||||
|
// jsRegexpEscaper behaves like jsStrEscaper but escapes regular expression
|
||||||
|
// specials so the result is treated literally when included in a regular
|
||||||
|
// expression literal. /foo{{.X}}bar/ matches the string "foo" followed by
|
||||||
|
// the literal text of {{.X}} followed by the string "bar".
|
||||||
|
func jsRegexpEscaper(args ...interface{}) string {
|
||||||
|
return replace(stringify(args...), jsRegexpReplacementTable)
|
||||||
|
}
|
||||||
|
|
||||||
|
// stringify is an optimized form of fmt.Sprint.
|
||||||
|
func stringify(args ...interface{}) string {
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
s, ok = args[0].(string)
|
if s, ok := args[0].(string); ok {
|
||||||
}
|
return s
|
||||||
if !ok {
|
}
|
||||||
s = fmt.Sprint(args...)
|
|
||||||
}
|
}
|
||||||
|
return fmt.Sprint(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace replaces each rune r of s with replacementTable[r], provided that
|
||||||
|
// r < len(replacementTable). If replacementTable[r] is the empty string then
|
||||||
|
// no replacement is made.
|
||||||
|
// It also replaces the runes '\u2028' and '\u2029' with the strings
|
||||||
|
// `\u2028` and `\u2029`. Note the different quotes used.
|
||||||
|
func replace(s string, replacementTable []string) string {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
written := 0
|
written := 0
|
||||||
for i, r := range s {
|
for i, r := range s {
|
||||||
var repl string
|
var repl string
|
||||||
switch r {
|
switch {
|
||||||
case 0:
|
case r < len(replacementTable) && replacementTable[r] != "":
|
||||||
repl = `\0`
|
repl = replacementTable[r]
|
||||||
case '\t':
|
case r == '\u2028':
|
||||||
repl = `\t`
|
|
||||||
case '\n':
|
|
||||||
repl = `\n`
|
|
||||||
case '\v':
|
|
||||||
// "\v" == "v" on IE 6.
|
|
||||||
repl = `\x0b`
|
|
||||||
case '\f':
|
|
||||||
repl = `\f`
|
|
||||||
case '\r':
|
|
||||||
repl = `\r`
|
|
||||||
// Encode HTML specials as hex so the output can be embedded
|
|
||||||
// in HTML attributes without further encoding.
|
|
||||||
case '"':
|
|
||||||
repl = `\x22`
|
|
||||||
case '&':
|
|
||||||
repl = `\x26`
|
|
||||||
case '\'':
|
|
||||||
repl = `\x27`
|
|
||||||
case '+':
|
|
||||||
repl = `\x2b`
|
|
||||||
case '/':
|
|
||||||
repl = `\/`
|
|
||||||
case '<':
|
|
||||||
repl = `\x3c`
|
|
||||||
case '>':
|
|
||||||
repl = `\x3e`
|
|
||||||
case '\\':
|
|
||||||
repl = `\\`
|
|
||||||
case '\u2028':
|
|
||||||
repl = `\u2028`
|
repl = `\u2028`
|
||||||
case '\u2029':
|
case r == '\u2029':
|
||||||
repl = `\u2029`
|
repl = `\u2029`
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
@ -228,97 +218,55 @@ func jsStrEscaper(args ...interface{}) string {
|
|||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// jsRegexpEscaper behaves like jsStrEscaper but escapes regular expression
|
var jsStrReplacementTable = []string{
|
||||||
// specials so the result is treated literally when included in a regular
|
0: `\0`,
|
||||||
// expression literal. /foo{{.X}}bar/ matches the string "foo" followed by
|
'\t': `\t`,
|
||||||
// the literal text of {{.X}} followed by the string "bar".
|
'\n': `\n`,
|
||||||
func jsRegexpEscaper(args ...interface{}) string {
|
'\v': `\x0b`, // "\v" == "v" on IE 6.
|
||||||
ok := false
|
'\f': `\f`,
|
||||||
var s string
|
'\r': `\r`,
|
||||||
if len(args) == 1 {
|
// Encode HTML specials as hex so the output can be embedded
|
||||||
s, ok = args[0].(string)
|
// in HTML attributes without further encoding.
|
||||||
}
|
'"': `\x22`,
|
||||||
if !ok {
|
'&': `\x26`,
|
||||||
s = fmt.Sprint(args...)
|
'\'': `\x27`,
|
||||||
}
|
'+': `\x2b`,
|
||||||
var b bytes.Buffer
|
'/': `\/`,
|
||||||
written := 0
|
'<': `\x3c`,
|
||||||
for i, r := range s {
|
'>': `\x3e`,
|
||||||
var repl string
|
'\\': `\\`,
|
||||||
switch r {
|
}
|
||||||
case 0:
|
|
||||||
repl = `\0`
|
var jsRegexpReplacementTable = []string{
|
||||||
case '\t':
|
0: `\0`,
|
||||||
repl = `\t`
|
'\t': `\t`,
|
||||||
case '\n':
|
'\n': `\n`,
|
||||||
repl = `\n`
|
'\v': `\x0b`, // "\v" == "v" on IE 6.
|
||||||
case '\v':
|
'\f': `\f`,
|
||||||
// "\v" == "v" on IE 6.
|
'\r': `\r`,
|
||||||
repl = `\x0b`
|
// Encode HTML specials as hex so the output can be embedded
|
||||||
case '\f':
|
// in HTML attributes without further encoding.
|
||||||
repl = `\f`
|
'"': `\x22`,
|
||||||
case '\r':
|
'$': `\$`,
|
||||||
repl = `\r`
|
'&': `\x26`,
|
||||||
// Encode HTML specials as hex so the output can be embedded
|
'\'': `\x27`,
|
||||||
// in HTML attributes without further encoding.
|
'(': `\(`,
|
||||||
case '"':
|
')': `\)`,
|
||||||
repl = `\x22`
|
'*': `\*`,
|
||||||
case '$':
|
'+': `\x2b`,
|
||||||
repl = `\$`
|
'-': `\-`,
|
||||||
case '&':
|
'.': `\.`,
|
||||||
repl = `\x26`
|
'/': `\/`,
|
||||||
case '\'':
|
'<': `\x3c`,
|
||||||
repl = `\x27`
|
'>': `\x3e`,
|
||||||
case '(':
|
'?': `\?`,
|
||||||
repl = `\(`
|
'[': `\[`,
|
||||||
case ')':
|
'\\': `\\`,
|
||||||
repl = `\)`
|
']': `\]`,
|
||||||
case '*':
|
'^': `\^`,
|
||||||
repl = `\*`
|
'{': `\{`,
|
||||||
case '+':
|
'|': `\|`,
|
||||||
repl = `\x2b`
|
'}': `\}`,
|
||||||
case '-':
|
|
||||||
repl = `\-`
|
|
||||||
case '.':
|
|
||||||
repl = `\.`
|
|
||||||
case '/':
|
|
||||||
repl = `\/`
|
|
||||||
case '<':
|
|
||||||
repl = `\x3c`
|
|
||||||
case '>':
|
|
||||||
repl = `\x3e`
|
|
||||||
case '?':
|
|
||||||
repl = `\?`
|
|
||||||
case '[':
|
|
||||||
repl = `\[`
|
|
||||||
case '\\':
|
|
||||||
repl = `\\`
|
|
||||||
case ']':
|
|
||||||
repl = `\]`
|
|
||||||
case '^':
|
|
||||||
repl = `\^`
|
|
||||||
case '{':
|
|
||||||
repl = `\{`
|
|
||||||
case '|':
|
|
||||||
repl = `\|`
|
|
||||||
case '}':
|
|
||||||
repl = `\}`
|
|
||||||
case '\u2028':
|
|
||||||
repl = `\u2028`
|
|
||||||
case '\u2029':
|
|
||||||
repl = `\u2029`
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
b.WriteString(s[written:i])
|
|
||||||
b.WriteString(repl)
|
|
||||||
written = i + utf8.RuneLen(r)
|
|
||||||
}
|
|
||||||
if written == 0 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
b.WriteString(s[written:])
|
|
||||||
return b.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isJSIdentPart is true if the given rune is a JS identifier part.
|
// isJSIdentPart is true if the given rune is a JS identifier part.
|
||||||
|
Loading…
Reference in New Issue
Block a user