1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

encoding.html: add escape() function (#16666)

This commit is contained in:
Subhomoy Haldar 2022-12-13 20:10:57 +00:00 committed by GitHub
parent 69f7c45bec
commit b07e447764
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 8 deletions

View File

@ -0,0 +1,20 @@
module html
[params]
pub struct EscapeConfig {
quote bool = true
}
// escape converts special characters in the input, specifically "<", ">", and "&"
// to HTML-safe sequences. If `quote` is set to true (which is default), quotes in
// HTML will also be translated. Both double and single quotes will be affected.
// **Note:** escape() supports funky accents by doing nothing about them. V's UTF-8
// support through `string` is robust enough to deal with these cases.
pub fn escape(input string, config EscapeConfig) string {
tag_free_input := input.replace_each(['&', '&amp;', '<', '&lt;', '>', '&gt;'])
return if config.quote {
tag_free_input.replace_each(['"', '&quot;', "'", '&#x27;'])
} else {
tag_free_input
}
}

View File

@ -0,0 +1,22 @@
import encoding.html
fn test_escape_html() {
assert html.escape('<>&') == '&lt;&gt;&amp;'
assert html.escape('No change') == 'No change'
assert html.escape('<b>Bold text</b>') == '&lt;b&gt;Bold text&lt;/b&gt;'
assert html.escape('<img />') == '&lt;img /&gt;'
assert html.escape("' onmouseover='alert(1)'") == '&#x27; onmouseover=&#x27;alert(1)&#x27;'
assert html.escape("<a href='http://www.example.com'>link</a>") == '&lt;a href=&#x27;http://www.example.com&#x27;&gt;link&lt;/a&gt;'
assert html.escape("<script>alert('hello');</script>") == '&lt;script&gt;alert(&#x27;hello&#x27;);&lt;/script&gt;'
// Cases obtained from:
// https://github.com/apache/commons-lang/blob/master/src/test/java/org/apache/commons/lang3/StringEscapeUtilsTest.java
assert html.escape('plain text') == 'plain text'
assert html.escape('') == ''
assert html.escape('bread & butter') == 'bread &amp; butter'
assert html.escape('"bread" & butter') == '&quot;bread&quot; &amp; butter'
assert html.escape('greater than >') == 'greater than &gt;'
assert html.escape('< less than') == '&lt; less than'
// Leave accents as-is
assert html.escape('café') == 'café'
assert html.escape('<p>façade</p>') == '&lt;p&gt;façade&lt;/p&gt;'
}

View File

@ -10,6 +10,7 @@ import net.http
import net.urllib
import time
import json
import encoding.html
// A type which don't get filtered inside templates
pub type RawHtml = string
@ -725,12 +726,5 @@ fn send_string(mut conn net.TcpConn, s string) ! {
// It used by `vlib/v/gen/c/str_intp.v:130` for string interpolation inside vweb templates
// TODO: move it to template render
fn filter(s string) string {
return s.replace_each([
'<',
'&lt;',
'"',
'&quot;',
'&',
'&amp;',
])
return html.escape(s)
}