golang использовать переменную в шаблоне как html тег

Рейтинг: 0Ответов: 1Опубликовано: 01.03.2023

Передаю строку в html шаблон

tmpl.ExecuteTemplate(w, "main", templateMaintStruct{string(body)})

В переменной body лежит html код "<h1> Test</h1>"

В самом шаблоне я вставляю переменную

 {{.Text}}

Ожидаю, получить измененную html разметку но видимо шаблонизатор изначально заменяет спец символы для избежания XSS. Как можно отобразить строку как html разметку?

Ответы

▲ 0Принят

Есть два пути: использовать пакет text/template или использовать типизированные строки.

text/template

Пакет text/template генерирует текст без подмен символов. Просто поменяйте в импорте html/template на text/template - если вы не используете что-то особенное, ничего в коде менять не придётся.

Типизированные строки

При подстановки значений шаблоны из html/template парсятся. Результат вставки одной и той же строки зависит от того, куда именно подставляется текст. Это называется контекст.

При подстановке значений типа string специальные символы, такие как <> экранируются всегда.

В пакете html/template есть специальные строковые типы, для которых подстановка реализуется особым образом. Посмотрите тип template.HTML. При подстановке внутрь тела документа или таких элементов как div и p строки этого типа не экранируются.

Пример https://go.dev/play/p/6_4hueOZA6k

package main

import (
    "html/template"
    "os"
)

func main() {
    const tpl = `
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{{.Title}}</title>
    </head>
    <body>
        {{range .Items}}<div>{{ . }}</div>{{else}}<div><strong>no rows</strong></div>{{end}}
    </body>
</html>`

    t, _ := template.New("webpage").Parse(tpl)

    data := struct {
        Title template.HTML
        Items []template.HTML
    }{
        Title: "<em>My page</em>",
        Items: []template.HTML{
            "<b>My photos</b>",
            "<i>My blog</i>",
        },
    }

    t.Execute(os.Stdout, data)
}

Результат

<!DOCTYPE html>
<html>
        <head>
                <meta charset="UTF-8">
                <title>&lt;em&gt;My page&lt;/em&gt;</title>
        </head>
        <body>
                <div><b>My photos</b></div><div><i>My blog</i></div>
        </body>
</html>

Внутри title спецсимволы экранированы, а в div нет.