From b221594b33a1fdefc6e2867b505d28e80b58fb33 Mon Sep 17 00:00:00 2001 From: Adrian Hesketh Date: Sat, 12 Jun 2021 22:10:04 +0100 Subject: [PATCH] added documentation for CSS --- README.md | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++-- runtime.go | 17 +++++++++ types.go | 17 --------- 3 files changed, 116 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 3b4dcd18f..1a439bcc5 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ ## Current state -This is beta software, and the template language may still have breaking changes. There's no guarantees of stability or correctness at the moment. +This is beta software, and the template language may still have breaking changes. There's no guarantees of stability or correctness at the moment, but it has at least one production user. If you're keen to see Go be practical for Web projects, see "Help needed" for where the project needs your help. @@ -26,7 +26,43 @@ The language generates Go code, some sections of the template (e.g. `package`, ` ## Security -templ currently uses context unaware escaping, see https://github.com/a-h/templ/issues/6 for a proposal to add context-aware content escaping. +templ will automatically escape content according to the following rules. + +``` +{% templ Example() %} + +
+ {%= "will be HTML encoded using templ.Escape" %}
+ + +
+
+
{%= "will be escaped using templ.Escape" %}
+ Text + + +{% endtempl %} +``` + +CSS property names, and constant CSS property values are not sanitized or escaped. + +``` +{% css className() %} + background-color: #ffffff; +{% endcss %} +``` + +CSS property values based on expressions are passed through `templ.SanitizeCSS` to replace potentially unsafe values with placeholders. + +``` +{% css className() %} + color: {%= red %}; +{% endcss %} +``` ## Design @@ -127,9 +163,15 @@ HTML elements look like HTML and you can write static attributes into them, just You can also have dynamic attributes that use template parameter, other Go variables that happen to be in scope, or call Go functions that return a string. Don't worry about HTML encoding element text and attribute values, that will be taken care of automatically. ``` -{%= strings.ToUpper(p.Name()) %} +{%= strings.ToUpper(p.Name()) %} ``` +However, the `a` element's `href` attribute is treated differently. Templ expects you to provide a `templ.SafeURL`. A `templ.SafeURL` is a URL that is definitely safe to use (i.e. has come from a configuration system controlled by the developer), or has been through a sanitization process to filter out potential XSS attacks. + +Templ provides a `templ.URL` function that sanitizes input URLs and checks that the protocol is http/https/mailto rather than `javascript` or another unexpected protocol. + +{%= strings.ToUpper(p.Name()) %} + ### Text Text is rendered from Go expressions, which includes constant values: @@ -158,6 +200,60 @@ Or using a string parameter, or variable that's in scope. What you can't do, is write text directly between elements (e.g. `
Some text
`, because the parser would have to become more complex to support HTML entities and the various mistakes people make when they're doing that (bare ampersands etc.). Go strings support UTF-8 which is much easier, and the escaping rules are well known by Go programmers. +### CSS + +Templ components can have CSS associated with them. CSS classes are created with the `css` template expression. CSS properties can be set to string variables or functions (e.g. `{%= red %}`). However, functions should be idempotent - i.e. return the same value every time. + +All variable CSS values are passed through a value sanitizer to provide some protection against malicious data being added to CSS. + +``` +{% css className() %} + background-color: #ffffff; + color: {%= red %}; +{% endcss %} +``` + +CSS class components can be used within templates. + +``` +{% templ Button(text string) %} + +{% endtempl %} +``` + +The first time that the component is rendered in a HTTP request, it will render the CSS class to the output. The next time the same component is rendered, templ will skip rendering the CSS to the output because it is no longer required. + +For example, if this template is rendered in a request: + +``` +{% templ TwoButtons() %} + {%! Button("A") %} + {%! Button("B") %} +{% endtempl %} +``` + +The output would contain one class. Note that the name contains a unique value is addition to the class name to reduce the likelihood of clashes. Don't rely on this name being consistent. + +```html + + +` +``` + +#### CSS Middleware + +If you want to provide a global stylesheet that includes this CSS to remove `