[swift-evolution] HTML rendering output (was: Strings in Swift 4)

David Waite david at alkaline-solutions.com
Fri Jan 20 11:41:37 CST 2017


With the current model, I’d make a first pass of this sort of functionality by doing:

1. Define a HtmlEncoded wrapping struct that indicated a value was meant to be safe to output directly, rather than be encoded. This would make encoding safe by default (opt out)
2. HTML content built via string interpolation would escape any data input not wrapped in a HtmlEncoded struct.
3. Define functions for the common tags which output nested html data, rather than having people write the tags themselves.

With all that, your code would probably be:

let title = "<script>boom();</script>"
result.render(h1(title)); // outputs '<h1>&lt;script>boom();&lt;/script></h1>'

4. (maybe) HtmlEncoded is ExpressibleByStringInterpolation, so that

var username = “<script>boom();</script>”
var encoded:HtmlEncoded = “Hello, \(username)”
print(encoded) //  ‘Hello, &lt;script>boom();&lt;/script>'

This is somewhat analogous to Rails 3’s String.html_safe functionality, and avoids interpreting string safety based on a string being a literal .

-DW

> On Jan 20, 2017, at 9:27 AM, Gwendal Roué via swift-evolution <swift-evolution at swift.org> wrote:
> 
>> One ask - make string interpolation great again?
> 
> I have a dream, that ExpressibleByStringInterpolation would allow to distinguish literal segments and embedded inputs.
> 
> Today, the documentation of this protocol [1] says:
> 
> 	"One cookie: $\(price), \(number) cookies: $\(price * number)."
> 	// <=>
> 	let message = String(stringInterpolation:
> 		String(stringInterpolationSegment: "One cookie: $"),
> 		String(stringInterpolationSegment: price),
> 		String(stringInterpolationSegment: ", "),
> 		String(stringInterpolationSegment: number),
> 		String(stringInterpolationSegment: " cookies: $"),
> 		String(stringInterpolationSegment: price * number),
> 		String(stringInterpolationSegment: "."))
> 
> This means that ExpressibleByStringInterpolation can't distinguish "foo" from `bar` in "foo\(bar)".
> 
> If this distinction were possible, some nice features could emerge, such as context-sensitive escaping:
> 
> 	// func render(_ html: HTML)
> 	let title = "<script>boom();</script>"
> 	render("<h1>\(title)</h1>") // escapes input
> 	
> 	// func query(_ sql: SQL)
> 	let name = "Robert'); DROP TABLE students; --"
> 	query("SELECT * FROM students WHERE name = \(name)") // avoids SQL injection
> 
> Ideally, a solution for multi-line literals (for strings and interpolated strings) would be found, too.
> 
> I wish the manifesto would address these topics as well :-)
> 
> Regards,
> Gwendal Roué
> 
> [1] https://developer.apple.com/reference/swift/expressiblebystringinterpolation
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170120/294f3738/attachment.html>


More information about the swift-evolution mailing list