Перейти шаблон.ExecuteTemplate включают в себя HTML

я следовал этому руководству:http://golang.org/doc/articles/wiki/final.go и немного изменили его для моих нужд / желаний. Проблема в том, что я хотел бы поддерживать HTML в шаблонах. Я понимаю, что это риск для безопасности, но сейчас это не проблема.

результат рендеринга страницы:

<h1>this<strong>is</strong>a test</h1>

позвольте мне объяснить немного кода:

type Page struct {
    Title string
    Body  []byte
}

данные, которые я хотел бы иметь HTML, хранятся в Page.Body. Это тип []byte что означает, что я не могу (или могу?) run html/template.HTML(Page.Body) как эта функция ожидает строку.

у меня есть это, которое предварительно отображает шаблоны:

var (
    templates = template.Must(template.ParseFiles("tmpl/edit.html", "tmpl/view.html"))
)

и фактический ExecuteTemplate выглядит так:

err := templates.ExecuteTemplate(w, tmpl+".html", p)

где w w http.ResponseWriter, tmpl является tmpl string, а p p *Page

наконец-то мой 'view.html' (шаблон) выглядит следующим образом:

<h1>{{.Title}}</h1>
<p>[<a href="/edit/{{.Title}}">edit</a>]</p>
<div>{{printf "%s" .Body}}</div>

вещи, которые у меня есть попробовал:

  • {{printf "%s" .Body | html}} ничего не происходит
  • я включил github.com/russross/blackfriday (процессор Markdown) и запустили p.Body = blackfriday.MarkdownCommon(p.Body) который правильно преобразует Markdown в HTML, но HTML по-прежнему выводится как сущности.
  • EDIT: я попытался следующий бит кода (я не знаю, почему формат испорчен), и он по-прежнему выводит точное тот же.

    var s template.HTML s = template.HTML(p.Body) p.Body = []byte(s)

любое руководство очень ценится. Если я запутываюсь, пожалуйста, спросите, и я могу изменить свой вопрос.

7 ответов


преобразовать []byte или string типа template.HTML (документально здесь)

p.Body = template.HTML(s) // where s is a string or []byte

затем, в вашем шаблоне, просто:

{{.Body}}

он будет напечатан без побега.

редактировать

для того, чтобы иметь возможность включать HTML в тело вашей страницы, вам нужно изменить Page тип объявления:

type Page struct {
    Title string
    Body  template.HTML
}

затем присвоить его.


посмотри шаблон.HTML-код тип. Его можно использовать для инкапсуляции известного безопасного фрагмента HTML (например, вывода из Markdown). Пакет "html / template"не будет избегать этого типа.

type Page struct {
    Title string
    Body template.HTML
}

page := &Page{
    Title: "Example",
    Body:  template.HTML(blackfriday.MarkdownCommon([]byte("foo bar")),
}

Я обычно пишу свои собственные func Markdown(text string) html.Template метод, который вызывает blackfriday с соответствующей конфигурацией и выполняет некоторые преобразования типов. Другой альтернативой может быть также регистрация функции "html" в синтаксическом анализаторе шаблонов, которая позволяет выводить любое значение без каких-либо побег, делая что-то вроде {{html .MySafeStr}}. Код может выглядеть так:

var tmpl = template.Must(template.New("").Funcs(template.FuncMap{
    "html": func(value interface{}) template.HTML {
        return template.HTML(fmt.Sprint(value))
    },
}).ParseFiles("file1.html", "file2.html"))

Я создал пользовательскую функцию для шаблона следующим образом:

func noescape(str string) template.HTML {
    return template.HTML(str)
}

var fn = template.FuncMap{
    "noescape": noescape,
}

затем на вашем шаблоне:

{{ noescape $x.Body }}

Я использую Beego и React.js и боролись часами, пытаясь запустить парсер JSX. Оказывается, html / шаблон удаляет комментарии, особенно блок JS doc / * * @JSX React.ДОМ./*

обошел его, создав специальный метод для ввода комментария как JS и вызывая его из шаблона.

// Create a method in your controller (I'm using Beego)
func jsxdoc()(out template.JS) {
    return template.JS(`/** @jsx React.DOM */`)
}

// Add method to your function map available to views
beego.AddFuncMap("jsxdoc", jsxdoc)

// In template
<script type="text/jsx">
    {{ jsxdoc }}
    var CommentBox = React.createClass({
      render: function() {
        return (
          <div class="commentBox">
            Hello, world! I am a CommentBox.
          </div>
        );
      }
    });
    React.renderComponent(
      <CommentBox />,
      document.getElementById('content')
    );
</script>

вот подход, который не требует каких-либо изменений в ваших существующих структурах, и очень минимальное, аддитивное изменение ваших шаблонов:

изменить эти строчки:

var (
    templates = template.Must(template.ParseFiles("tmpl/edit.html", "tmpl/view.html"))
)

к этому (включите funcmap с функцией, которая будет выводить не-экранированный HTML):

var templates = template.Must(template.New("main").Funcs(template.FuncMap{
    "safeHTML": func(b []byte) template.HTML {
        return template.HTML(b)
    },
}).ParseFiles("tmpl/edit.html", "tmpl/view.html"))

а затем просто измените свой шаблон HTML из этого:

<div>{{printf "%s" .Body}}</div>

к этому (используйте вашу новую функцию):

<div>{{ .Body | safeHTML }}</div>

гораздо проще!


для уточнения и гораздо более простого способа передачи HTML в шаблон см.

https://groups.google.com/forum#!тема/голанг-орехи/8L4eDkr5Q84

просто создайте строку HTML через go и передайте ее в свой шаблон, например:

Sout := ""
.
.

    Sout += fmt.Sprintf(`<tr><td>%s<td align=center>%.2f<td>%s<td>%s<td>%s<td>%s<td align=center>%d<td align=center>%d
                    <td align=center>%d`, AccountID, amount, remissiondetails, created, begins, ends,
                    freePDFs, freeinformants, freeSDQs)

.
.
    render(w, "templates/Waivers.html", map[string]interface{}{ "Body":template.HTML(Sout), })

почему бы не преобразовать []byte в строку? Вы можете сделать это так:

str := string(page.Body)