web-dev-qa-db-fra.com

Allez template.ExecuteTemplate include html

J'ai suivi ce tutoriel: http://golang.org/doc/articles/wiki/final.go et l'ai légèrement modifié pour mes besoins/désirs. Le problème est que je voudrais supporter HTML dans les modèles. Je réalise que c'est un risque pour la sécurité mais ce n'est pas une préoccupation pour le moment.

Le résultat d'un rendu de page:

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

Laissez-moi vous expliquer un peu le code:

type Page struct {
    Title string
    Body  []byte
}

Les données que je souhaite avoir au format HTML sont stockées dans Page.Body. Il s'agit du type []byte, ce qui signifie que je ne peux pas (ou ne puis-je pas?) Exécuter html/template.HTML(Page.Body) car cette fonction attend une chaîne.

J'ai ceci qui pré-rend les modèles:

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

Et la ExecuteTemplate réelle ressemble à ceci:

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

Où w est w http.ResponseWriter, tmpl est tmpl string et p est p *Page

Enfin, mon 'view.html' (modèle) se présente comme suit:

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

Ce que j'ai essayé:

  • {{printf "%s" .Body | html}} ne fait rien 
  • J'ai inclus github.com/russross/blackfriday (processeur de Markdown) et ai exécuté p.Body = blackfriday.MarkdownCommon(p.Body) qui convertit correctement Markdown en HTML, mais le HTML est toujours généré en tant qu'entités.
  • EDIT: J'ai essayé le code suivant (je ne sais pas pourquoi le format est gâché) et le résultat est toujours identique.

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

Toute orientation est grandement appréciée. Si je suis déroutant s'il vous plaît demander et je peux modifier ma question.

19
Peter

Convertissez votre []byte ou string en dactylographiez template.HTML (documenté ici )

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

Ensuite, dans votre modèle, il suffit de:

{{.Body}}

Il sera imprimé sans s'échapper.

MODIFIER

Pour pouvoir inclure du code HTML dans le corps de votre page, vous devez modifier la déclaration de type Page:

type Page struct {
    Title string
    Body  template.HTML
}

puis lui assigner.

44
thwd

Jetez un coup d'oeil au template.HTML type. Il peut être utilisé pour encapsuler un fragment de code HTML sûr connu (comme la sortie de Markdown). Le paquet "html/template" n'échappera pas à ce type.

type Page struct {
    Title string
    Body template.HTML
}

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

J'écris habituellement ma propre méthode func Markdown(text string) html.Template qui appelle blackfriday avec la configuration appropriée et effectue des conversions de types. Une autre alternative pourrait également consister à enregistrer une fonction "html" dans l’analyseur de modèle, ce qui vous permettra de sortir n’importe quelle valeur sans échapper en faisant quelque chose comme {{html .MySafeStr}}. Le code pourrait ressembler à:

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"))
16
tux21b

J'ai créé une fonction personnalisée pour le modèle comme suit:

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

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

Puis sur votre modèle:

{{ noescape $x.Body }}
7
majidarif

Voici une approche qui ne nécessite aucune modification de vos structures existantes et une modification très minimale et additive de vos modèles:

Changer ces lignes:

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

à cela (inclure une fonction funcmap avec une fonction qui générera du code HTML non échappé):

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"))

Et puis modifiez simplement votre modèle HTML à partir de ceci:

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

à cela (utilisez votre nouvelle fonction):

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

Beaucoup plus facile!

1
Astockwell

J'utilise Beego et React.js et je me suis battu pendant des heures pour faire fonctionner l'analyseur JSX. Il s'avère que html/template supprime les commentaires, en particulier le bloc de documentation js/** @jsx React.DOM * /.

Pour contourner le problème, créez une méthode spéciale pour saisir le commentaire en tant que JS et appelez-le depuis le modèle.

// 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>
1
user2363571

Pour plus de précisions et une manière beaucoup plus simple de passer du HTML au modèle, voir 

https://groups.google.com/forum/#!topic/golang-nuts/8L4eDkr5Q84

Créez simplement votre chaîne HTML via go et passez-la dans votre modèle, par exemple:

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), })
0
user2099484