-
-
Notifications
You must be signed in to change notification settings - Fork 279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to inject a standalone <script> tag with data injected #231
Comments
Hi, thanks for raising this. We've discussed it in #126, the current solution to that is defined here #126 (comment) The current design of script templates is that they're functions with a fixed body. Any variables that are passed to script templates from Go code can then be properly sanitized to prevent XSS by JSON serializing them. Because scripts have a fixed body, it also makes it possible to identify that they've already been rendered to the output, and not to do it multiple times (allowing you to register per-component scripts). Would love your input in #126 on whether that meets your needs. |
Thanks for the comment link; I took that solution and tried to apply it, but it looks like it only works with zero-parameter functions? This is the updated code using that function, note that I needed to add func onLoad(script templ.ComponentScript) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
if _, err = io.WriteString(w, `<script type="text/javascript">`+"\r\n"+script.Function+"\r\n"+script.Call+"\r\n</script>"); err != nil {
return err
}
return nil
})
}
script example(message string) {
console.log(message);
}
templ page(message string) {
<html>
<body>
@onLoad(example(message))
</body>
</html>
} Expected<html>
<body>
<script type="text/javascript">
__templ_example_9b63("Hello, World!")
</script>
</body>
</html> Actual<html>
<body>
<script type="text/javascript">
__templ_example_9b63("Hello, World!")
</script>
</body>
</html> I believe this is because the generated code tries to sanitize the input: func example(message string) templ.ComponentScript {
return templ.ComponentScript{
Name: `__templ_example_9b63`,
Function: `function __templ_example_9b63(message){console.log(message);}`,
Call: templ.SafeScript(`__templ_example_9b63`, message),
}
} I'm not sure how to tell templ to not apply this sanitation... It seems to me that |
This code below works, but is not great in terms of ergonomics. You have to specify your parameters twice to get the generation of the script template to work, and then pass them in again to feed into import "encoding/json"
func onLoad(script templ.ComponentScript, params ...interface{}) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
if _, err = io.WriteString(w, `<script type="text/javascript">`+"\r\n"+script.Function+"\r\n"+script.Name+"("); err != nil {
return err
}
paramsLen := len(params)
for i, param := range params {
paramEncodedBytes, err := json.Marshal(param)
if err != nil {
return err
}
if _, err = w.Write(paramEncodedBytes); err != nil {
return err
}
if i + 1 != paramsLen {
if _, err = io.WriteString(w, ", "); err != nil {
return err
}
}
}
if _, err = io.WriteString(w, ")\r\n</script>"); err != nil {
return err
}
return nil
})
}
script example(message string) {
console.log(message);
}
templ TestPage(message string) {
<html>
<body>
@onLoad(example(message), message)
</body>
</html>
} This generates: <html>
<body>
<script type="text/javascript">
function __templ_example_9b63(message){console.log(message);}
__templ_example_9b63("Hello, World!")
</script>
</body>
</html> |
Relevant guide I was following: https://templ.guide/syntax-and-usage/script-templates#script-templates
I'm trying to add JavaScript at the end of the HTML (not inject it into an HTML attribute)
I'm not sure if this is possible with Templ, but it'd be really nice if it was! Maybe I'm holding it wrong?? Any pointers would be appreciated.
Expected
If passed in
Hello, world!
:Actual
If passed in
Hello, world!
:The text was updated successfully, but these errors were encountered: