mirror of
https://github.com/tmedwards/tweego.git
synced 2025-07-04 21:50:33 -04:00
Initial Bitbucket→GitHub migration commit, based on release v2.0.0.
This commit is contained in:
commit
57e1aa52ff
36 changed files with 5026 additions and 0 deletions
177
escaping.go
Normal file
177
escaping.go
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
Copyright © 2014–2019 Thomas Michael Edwards. All rights reserved.
|
||||
Use of this source code is governed by a Simplified BSD License which
|
||||
can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
/*
|
||||
HTML escaping/unescaping utilities.
|
||||
*/
|
||||
|
||||
// Escape the minimum characters required for attribute values.
|
||||
var attrEscaper = strings.NewReplacer(
|
||||
`&`, `&`,
|
||||
`"`, `"`,
|
||||
// FIXME: Keep the following? All markup we generate double quotes attribute
|
||||
// values, so escaping single quotes/apostrophes isn't actually necessary.
|
||||
`'`, `'`,
|
||||
)
|
||||
|
||||
func attrEscapeString(s string) string {
|
||||
if len(s) == 0 {
|
||||
return s
|
||||
}
|
||||
return attrEscaper.Replace(s)
|
||||
}
|
||||
|
||||
// Escape the minimum characters required for general HTML escaping—i.e. only
|
||||
// the special characters (`&`, `<`, `>`, `"`, `'`).
|
||||
//
|
||||
// NOTE: The following exists because `html.EscapeString()` converts double
|
||||
// quotes (`"`) to their decimal numeric character reference (`"`) rather
|
||||
// than to their entity (`"`). While the behavior is entirely legal, and
|
||||
// browsers will happily accept the NCRs, a not insignificant amount of JavaScript
|
||||
// code does not expect it and will fail to properly unescape the NCR—expecting
|
||||
// only `"`.
|
||||
//
|
||||
// The primary special characters (`&`, `<`, `>`, `"`) should always be
|
||||
// converted to their entity forms and never to an NCR form. Saving one byte
|
||||
// (5 vs. 6) is not worth the issues it causes.
|
||||
var htmlEscaper = strings.NewReplacer(
|
||||
`&`, `&`,
|
||||
`<`, `<`,
|
||||
`>`, `>`,
|
||||
`"`, `"`,
|
||||
`'`, `'`,
|
||||
)
|
||||
|
||||
func htmlEscapeString(s string) string {
|
||||
if len(s) == 0 {
|
||||
return s
|
||||
}
|
||||
return htmlEscaper.Replace(s)
|
||||
}
|
||||
|
||||
var tiddlerEscaper = strings.NewReplacer(
|
||||
`&`, `&`,
|
||||
`<`, `<`,
|
||||
`>`, `>`,
|
||||
`"`, `"`,
|
||||
`\`, `\s`,
|
||||
"\t", `\t`,
|
||||
"\n", `\n`,
|
||||
)
|
||||
|
||||
func tiddlerEscapeString(s string) string {
|
||||
if len(s) == 0 {
|
||||
return s
|
||||
}
|
||||
return tiddlerEscaper.Replace(s)
|
||||
}
|
||||
|
||||
// NOTE: We only need the newline, tab, and backslash escapes here since
|
||||
// `tiddlerUnescapeString()` is only used when loading Twine 1 HTML and the
|
||||
// `x/net/html` package already handles entity/reference unescaping for us.
|
||||
var tiddlerUnescaper = strings.NewReplacer(
|
||||
`\n`, "\n",
|
||||
`\t`, "\t",
|
||||
`\s`, `\`,
|
||||
)
|
||||
|
||||
func tiddlerUnescapeString(s string) string {
|
||||
if len(s) == 0 {
|
||||
return s
|
||||
}
|
||||
return tiddlerUnescaper.Replace(s)
|
||||
}
|
||||
|
||||
/*
|
||||
Twee escaping/unescaping utilities.
|
||||
*/
|
||||
|
||||
// Encode set: '\\', '[', ']', '{', '}'.
|
||||
|
||||
func tweeEscapeBytes(s []byte) []byte {
|
||||
if len(s) == 0 {
|
||||
return []byte(nil)
|
||||
}
|
||||
// e := bytes.Replace(s, []byte("\\"), []byte("\\\\"), -1)
|
||||
// e = bytes.Replace(e, []byte("["), []byte("\\["), -1)
|
||||
// e = bytes.Replace(e, []byte("]"), []byte("\\]"), -1)
|
||||
// e = bytes.Replace(e, []byte("{"), []byte("\\{"), -1)
|
||||
// e = bytes.Replace(e, []byte("}"), []byte("\\}"), -1)
|
||||
|
||||
// NOTE: The slices this will be used with will be short enough that
|
||||
// iterating a slice twice shouldn't be problematic. That said,
|
||||
// assuming an escape count of 8 or so wouldn't be a terrible way to
|
||||
// handle this either.
|
||||
cnt := 0
|
||||
for _, b := range s {
|
||||
switch b {
|
||||
case '\\', '[', ']', '{', '}':
|
||||
cnt++
|
||||
}
|
||||
}
|
||||
e := make([]byte, 0, len(s)+cnt)
|
||||
for _, b := range s {
|
||||
switch b {
|
||||
case '\\', '[', ']', '{', '}':
|
||||
e = append(e, '\\')
|
||||
}
|
||||
e = append(e, b)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
var tweeEscaper = strings.NewReplacer(
|
||||
`\`, `\\`,
|
||||
`[`, `\[`,
|
||||
`]`, `\]`,
|
||||
`{`, `\{`,
|
||||
`}`, `\}`,
|
||||
)
|
||||
|
||||
func tweeEscapeString(s string) string {
|
||||
if len(s) == 0 {
|
||||
return s
|
||||
}
|
||||
return tweeEscaper.Replace(s)
|
||||
}
|
||||
|
||||
func tweeUnescapeBytes(s []byte) []byte {
|
||||
if len(s) == 0 {
|
||||
return []byte(nil)
|
||||
}
|
||||
u := make([]byte, 0, len(s))
|
||||
for i, l := 0, len(s); i < l; i++ {
|
||||
if s[i] == '\\' {
|
||||
i++
|
||||
if i >= l {
|
||||
break
|
||||
}
|
||||
}
|
||||
u = append(u, s[i])
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
var tweeUnescaper = strings.NewReplacer(
|
||||
`\\`, `\`,
|
||||
`\[`, `[`,
|
||||
`\]`, `]`,
|
||||
`\{`, `{`,
|
||||
`\}`, `}`,
|
||||
)
|
||||
|
||||
func tweeUnescapeString(s string) string {
|
||||
if len(s) == 0 {
|
||||
return s
|
||||
}
|
||||
return tweeUnescaper.Replace(s)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue