1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-01-22 16:16:51 +00:00

Implement OpenGraph meta tags

This commit is contained in:
bouncepaw 2020-12-17 17:59:59 +05:00
parent df26dfe511
commit 7b9375da39
10 changed files with 183 additions and 102 deletions

View File

@ -10,7 +10,7 @@ import (
) )
func init() { func init() {
flag.StringVar(&util.URL, "url", "http://0.0.0.0:$port", "URL at which your wiki can be found. Used to generate feeds") flag.StringVar(&util.URL, "url", "http://0.0.0.0:$port", "URL at which your wiki can be found. Used to generate feeds and social media previews")
flag.StringVar(&util.ServerPort, "port", "1737", "Port to serve the wiki at using HTTP") flag.StringVar(&util.ServerPort, "port", "1737", "Port to serve the wiki at using HTTP")
flag.StringVar(&util.HomePage, "home", "home", "The home page name") flag.StringVar(&util.HomePage, "home", "home", "The home page name")
flag.StringVar(&util.SiteTitle, "title", "🍄", "How to call your wiki in the navititle") flag.StringVar(&util.SiteTitle, "title", "🍄", "How to call your wiki in the navititle")

View File

@ -36,7 +36,7 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) {
textContents, err = history.FileAtRevision(textPath, revHash) textContents, err = history.FileAtRevision(textPath, revHash)
) )
if err == nil { if err == nil {
contents = markup.ToHtml(hyphaName, textContents) contents = markup.Doc(hyphaName, textContents).AsHTML()
} }
treeHTML, _, _ := tree.Tree(hyphaName, IterateHyphaNamesWith) treeHTML, _, _ := tree.Tree(hyphaName, IterateHyphaNamesWith)
page := templates.RevisionHTML( page := templates.RevisionHTML(
@ -81,20 +81,27 @@ func handlerPage(w http.ResponseWriter, rq *http.Request) {
hyphaName = HyphaNameFromRq(rq, "page") hyphaName = HyphaNameFromRq(rq, "page")
data, hyphaExists = HyphaStorage[hyphaName] data, hyphaExists = HyphaStorage[hyphaName]
contents string contents string
openGraph string
) )
if hyphaExists { if hyphaExists {
fileContentsT, errT := ioutil.ReadFile(data.textPath) fileContentsT, errT := ioutil.ReadFile(data.textPath)
_, errB := os.Stat(data.binaryPath) _, errB := os.Stat(data.binaryPath)
if errT == nil { if errT == nil {
contents = markup.ToHtml(hyphaName, string(fileContentsT)) md := markup.Doc(hyphaName, string(fileContentsT))
contents = md.AsHTML()
openGraph = md.OpenGraphHTML()
} }
if !os.IsNotExist(errB) { if !os.IsNotExist(errB) {
contents = binaryHtmlBlock(hyphaName, data) + contents contents = binaryHtmlBlock(hyphaName, data) + contents
} }
} }
treeHTML, prevHypha, nextHypha := tree.Tree(hyphaName, IterateHyphaNamesWith) treeHTML, prevHypha, nextHypha := tree.Tree(hyphaName, IterateHyphaNamesWith)
util.HTTP200Page(w, base(hyphaName, templates.PageHTML(rq, hyphaName, util.HTTP200Page(w,
naviTitle(hyphaName), templates.BaseHTML(
contents, hyphaName,
treeHTML, prevHypha, nextHypha))) templates.PageHTML(rq, hyphaName,
naviTitle(hyphaName),
contents,
treeHTML, prevHypha, nextHypha),
openGraph))
} }

View File

@ -33,6 +33,12 @@ func init() {
return return
} }
markup.HyphaIterate = IterateHyphaNamesWith markup.HyphaIterate = IterateHyphaNamesWith
markup.HyphaImageForOG = func(hyphaName string) string {
if hd, isOld := GetHyphaData(hyphaName); isOld && hd.binaryPath != "" {
return util.URL + "/binary/" + hyphaName
}
return util.URL + "/favicon.ico"
}
} }
// GetHyphaData finds a hypha addressed by `hyphaName` and returns its `hyphaData`. `hyphaData` is set to a zero value if this hypha does not exist. `isOld` is false if this hypha does not exist. // GetHyphaData finds a hypha addressed by `hyphaName` and returns its `hyphaData`. `hyphaData` is set to a zero value if this hypha does not exist. `isOld` is false if this hypha does not exist.

View File

@ -4,6 +4,8 @@ import (
"fmt" "fmt"
"regexp" "regexp"
"strings" "strings"
"github.com/bouncepaw/mycorrhiza/util"
) )
var imgRe = regexp.MustCompile(`^img\s+{`) var imgRe = regexp.MustCompile(`^img\s+{`)
@ -184,6 +186,14 @@ func (img *Img) binaryPathFor(path string) string {
} }
} }
func (img *Img) ogBinaryPathFor(path string) string {
path = img.binaryPathFor(path)
if strings.HasPrefix(path, "/binary/") {
return util.URL + path
}
return path
}
func (img *Img) pagePathFor(path string) string { func (img *Img) pagePathFor(path string) string {
path = strings.TrimSpace(path) path = strings.TrimSpace(path)
if strings.IndexRune(path, ':') != -1 || strings.IndexRune(path, '/') == 0 { if strings.IndexRune(path, ':') != -1 || strings.IndexRune(path, '/') == 0 {

View File

@ -9,6 +9,9 @@ import (
// HyphaExists holds function that checks that a hypha is present. // HyphaExists holds function that checks that a hypha is present.
var HyphaExists func(string) bool var HyphaExists func(string) bool
//
var HyphaImageForOG func(string) string
// HyphaAccess holds function that accesses a hypha by its name. // HyphaAccess holds function that accesses a hypha by its name.
var HyphaAccess func(string) (rawText, binaryHtml string, err error) var HyphaAccess func(string) (rawText, binaryHtml string, err error)
@ -29,21 +32,21 @@ type GemLexerState struct {
type Line struct { type Line struct {
id int id int
// interface{} may be bad. What I need is a sum of string and Transclusion // interface{} may be bad. TODO: a proper type
contents interface{} contents interface{}
} }
func lex(name, content string) (ast []Line) { func (md *MycoDoc) lex() (ast []Line) {
var state = GemLexerState{name: name} var state = GemLexerState{name: md.hyphaName}
for _, line := range append(strings.Split(content, "\n"), "") { for _, line := range append(strings.Split(md.contents, "\n"), "") {
geminiLineToAST(line, &state, &ast) lineToAST(line, &state, &ast)
} }
return ast return ast
} }
// Lex `line` in markup and save it to `ast` using `state`. // Lex `line` in markup and save it to `ast` using `state`.
func geminiLineToAST(line string, state *GemLexerState, ast *[]Line) { func lineToAST(line string, state *GemLexerState, ast *[]Line) {
addLine := func(text interface{}) { addLine := func(text interface{}) {
*ast = append(*ast, Line{id: state.id, contents: text}) *ast = append(*ast, Line{id: state.id, contents: text})
} }

View File

@ -2,8 +2,12 @@
package markup package markup
import ( import (
"fmt"
"html" "html"
"regexp"
"strings" "strings"
"github.com/bouncepaw/mycorrhiza/util"
) )
// A Mycomarkup-formatted document // A Mycomarkup-formatted document
@ -11,24 +15,75 @@ type MycoDoc struct {
// data // data
hyphaName string hyphaName string
contents string contents string
// indicators
parsedAlready bool
// results
ast []Line
html string
firstImageURL string
description string
} }
// Constructor // Constructor
func Doc(hyphaName, contents string) *MycoDoc { func Doc(hyphaName, contents string) *MycoDoc {
return &MycoDoc{ md := &MycoDoc{
hyphaName: hyphaName, hyphaName: hyphaName,
contents: contents, contents: contents,
} }
return md
}
func (md *MycoDoc) Lex(recursionLevel int) *MycoDoc {
if !md.parsedAlready {
md.ast = md.lex()
}
md.parsedAlready = true
return md
} }
// AsHtml returns an html representation of the document // AsHtml returns an html representation of the document
func (md *MycoDoc) AsHTML() string { func (md *MycoDoc) AsHTML() string {
return "" md.html = Parse(md.Lex(0).ast, 0, 0, 0)
return md.html
} }
// Used to clear opengraph description from html tags. This method is usually bad because of dangers of malformed HTML, but I'm going to use it only for Mycorrhiza-generated HTML, so it's okay. The question mark is required; without it the whole string is eaten away.
var htmlTagRe = regexp.MustCompile(`<.*?>`)
// OpenGraphHTML returns an html representation of og: meta tags. // OpenGraphHTML returns an html representation of og: meta tags.
func (md *MycoDoc) OpenGraphHTML() string { func (md *MycoDoc) OpenGraphHTML() string {
return "" md.ogFillVars()
return strings.Join([]string{
ogTag("title", md.hyphaName),
ogTag("type", "article"),
ogTag("image", md.firstImageURL),
ogTag("url", util.URL+"/page/"+md.hyphaName),
ogTag("determiner", ""),
ogTag("description", htmlTagRe.ReplaceAllString(md.description, "")),
}, "\n")
}
func (md *MycoDoc) ogFillVars() *MycoDoc {
foundDesc := false
md.firstImageURL = HyphaImageForOG(md.hyphaName)
for _, line := range md.ast {
switch v := line.contents.(type) {
case string:
if !foundDesc {
md.description = v
foundDesc = true
}
case Img:
if len(v.entries) > 0 {
md.firstImageURL = v.entries[0].path.String()
}
}
}
return md
}
func ogTag(property, content string) string {
return fmt.Sprintf(`<meta property="og:%s" content="%s"/>`, property, content)
} }
/* The rest of this file is currently unused. TODO: use it I guess */ /* The rest of this file is currently unused. TODO: use it I guess */

View File

@ -1,35 +1,24 @@
package markup package markup
import ()
const maxRecursionLevel = 3 const maxRecursionLevel = 3
type GemParserState struct { func Parse(ast []Line, from, to int, recursionLevel int) (html string) {
recursionLevel int if recursionLevel > maxRecursionLevel {
}
func Parse(ast []Line, from, to int, state GemParserState) (html string) {
if state.recursionLevel > maxRecursionLevel {
return "Transclusion depth limit" return "Transclusion depth limit"
} }
for _, line := range ast { for _, line := range ast {
if line.id >= from && (line.id <= to || to == 0) || line.id == -1 { if line.id >= from && (line.id <= to || to == 0) || line.id == -1 {
switch v := line.contents.(type) { switch v := line.contents.(type) {
case Transclusion: case Transclusion:
html += Transclude(v, state) html += Transclude(v, recursionLevel)
case Img: case Img:
html += v.ToHtml() html += v.ToHtml()
case string: case string:
html += v html += v
default: default:
html += "Unknown" html += "<b class='error'>Unknown element.</b>"
} }
} }
} }
return html return html
} }
func ToHtml(name, text string) string {
state := GemParserState{}
return Parse(lex(name, text), 0, 0, state)
}

View File

@ -17,14 +17,14 @@ type Transclusion struct {
} }
// Transclude transcludes `xcl` and returns html representation. // Transclude transcludes `xcl` and returns html representation.
func Transclude(xcl Transclusion, state GemParserState) (html string) { func Transclude(xcl Transclusion, recursionLevel int) (html string) {
state.recursionLevel++ recursionLevel++
tmptOk := `<section class="transclusion transclusion_ok"> tmptOk := `<section class="transclusion transclusion_ok">
<a class="transclusion__link" href="/page/%s">%s</a> <a class="transclusion__link" href="/page/%s">%s</a>
<div class="transclusion__content">%s</div> <div class="transclusion__content">%s</div>
</section>` </section>`
tmptFailed := `<section class="transclusion transclusion_failed"> tmptFailed := `<section class="transclusion transclusion_failed">
<p>Failed to transclude <a href="/page/%s">%s</a></p> <p class="error">Hypha <a class="wikilink_new" href="/page/%s">%s</a> does not exist</p>
</section>` </section>`
if xcl.from == xclError || xcl.to == xclError || xcl.from > xcl.to { if xcl.from == xclError || xcl.to == xclError || xcl.from > xcl.to {
return fmt.Sprintf(tmptFailed, xcl.name, xcl.name) return fmt.Sprintf(tmptFailed, xcl.name, xcl.name)
@ -34,7 +34,8 @@ func Transclude(xcl Transclusion, state GemParserState) (html string) {
if err != nil { if err != nil {
return fmt.Sprintf(tmptFailed, xcl.name, xcl.name) return fmt.Sprintf(tmptFailed, xcl.name, xcl.name)
} }
xclText := Parse(lex(xcl.name, rawText), xcl.from, xcl.to, state) md := Doc(xcl.name, rawText)
xclText := Parse(md.lex(), xcl.from, xcl.to, recursionLevel)
return fmt.Sprintf(tmptOk, xcl.name, xcl.name, binaryHtml+xclText) return fmt.Sprintf(tmptOk, xcl.name, xcl.name, binaryHtml+xclText)
} }

View File

@ -1,10 +1,11 @@
{% func BaseHTML(title, body string) %} {% func BaseHTML(title, body string, headElements ...string) %}
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/static/common.css"> <link rel="stylesheet" type="text/css" href="/static/common.css">
<title>{%s title %}</title> <title>{%s title %}</title>
{% for _, el := range headElements %}{%s= el %}{% endfor %}
</head> </head>
<body> <body>
{%s= body %} {%s= body %}

View File

@ -18,7 +18,7 @@ var (
) )
//line templates/http_stuff.qtpl:1 //line templates/http_stuff.qtpl:1
func StreamBaseHTML(qw422016 *qt422016.Writer, title, body string) { func StreamBaseHTML(qw422016 *qt422016.Writer, title, body string, headElements ...string) {
//line templates/http_stuff.qtpl:1 //line templates/http_stuff.qtpl:1
qw422016.N().S(` qw422016.N().S(`
<!doctype html> <!doctype html>
@ -31,55 +31,64 @@ func StreamBaseHTML(qw422016 *qt422016.Writer, title, body string) {
qw422016.E().S(title) qw422016.E().S(title)
//line templates/http_stuff.qtpl:7 //line templates/http_stuff.qtpl:7
qw422016.N().S(`</title> qw422016.N().S(`</title>
`)
//line templates/http_stuff.qtpl:8
for _, el := range headElements {
//line templates/http_stuff.qtpl:8
qw422016.N().S(el)
//line templates/http_stuff.qtpl:8
}
//line templates/http_stuff.qtpl:8
qw422016.N().S(`
</head> </head>
<body> <body>
`) `)
//line templates/http_stuff.qtpl:10 //line templates/http_stuff.qtpl:11
qw422016.N().S(body) qw422016.N().S(body)
//line templates/http_stuff.qtpl:10 //line templates/http_stuff.qtpl:11
qw422016.N().S(` qw422016.N().S(`
</body> </body>
</html> </html>
`) `)
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
} }
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
func WriteBaseHTML(qq422016 qtio422016.Writer, title, body string) { func WriteBaseHTML(qq422016 qtio422016.Writer, title, body string, headElements ...string) {
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
StreamBaseHTML(qw422016, title, body) StreamBaseHTML(qw422016, title, body, headElements...)
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
} }
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
func BaseHTML(title, body string) string { func BaseHTML(title, body string, headElements ...string) string {
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
WriteBaseHTML(qb422016, title, body) WriteBaseHTML(qb422016, title, body, headElements...)
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
return qs422016 return qs422016
//line templates/http_stuff.qtpl:13 //line templates/http_stuff.qtpl:14
} }
//line templates/http_stuff.qtpl:15 //line templates/http_stuff.qtpl:16
func StreamHyphaListHTML(qw422016 *qt422016.Writer, tbody string, pageCount int) { func StreamHyphaListHTML(qw422016 *qt422016.Writer, tbody string, pageCount int) {
//line templates/http_stuff.qtpl:15 //line templates/http_stuff.qtpl:16
qw422016.N().S(` qw422016.N().S(`
<main> <main>
<h1>List of hyphae</h1> <h1>List of hyphae</h1>
<p>This wiki has `) <p>This wiki has `)
//line templates/http_stuff.qtpl:18 //line templates/http_stuff.qtpl:19
qw422016.N().D(pageCount) qw422016.N().D(pageCount)
//line templates/http_stuff.qtpl:18 //line templates/http_stuff.qtpl:19
qw422016.N().S(` hyphae.</p> qw422016.N().S(` hyphae.</p>
<table> <table>
<thead> <thead>
@ -90,105 +99,105 @@ func StreamHyphaListHTML(qw422016 *qt422016.Writer, tbody string, pageCount int)
</thead> </thead>
<tbody> <tbody>
`) `)
//line templates/http_stuff.qtpl:27 //line templates/http_stuff.qtpl:28
qw422016.N().S(tbody) qw422016.N().S(tbody)
//line templates/http_stuff.qtpl:27 //line templates/http_stuff.qtpl:28
qw422016.N().S(` qw422016.N().S(`
</tbody> </tbody>
</table> </table>
</main> </main>
`) `)
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
} }
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
func WriteHyphaListHTML(qq422016 qtio422016.Writer, tbody string, pageCount int) { func WriteHyphaListHTML(qq422016 qtio422016.Writer, tbody string, pageCount int) {
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
StreamHyphaListHTML(qw422016, tbody, pageCount) StreamHyphaListHTML(qw422016, tbody, pageCount)
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
} }
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
func HyphaListHTML(tbody string, pageCount int) string { func HyphaListHTML(tbody string, pageCount int) string {
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
WriteHyphaListHTML(qb422016, tbody, pageCount) WriteHyphaListHTML(qb422016, tbody, pageCount)
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
return qs422016 return qs422016
//line templates/http_stuff.qtpl:31 //line templates/http_stuff.qtpl:32
} }
//line templates/http_stuff.qtpl:33 //line templates/http_stuff.qtpl:34
func StreamHyphaListRowHTML(qw422016 *qt422016.Writer, hyphaName, binaryMime string, binaryPresent bool) { func StreamHyphaListRowHTML(qw422016 *qt422016.Writer, hyphaName, binaryMime string, binaryPresent bool) {
//line templates/http_stuff.qtpl:33 //line templates/http_stuff.qtpl:34
qw422016.N().S(` qw422016.N().S(`
<tr> <tr>
<td><a href="/page/`) <td><a href="/page/`)
//line templates/http_stuff.qtpl:35 //line templates/http_stuff.qtpl:36
qw422016.E().S(hyphaName) qw422016.E().S(hyphaName)
//line templates/http_stuff.qtpl:35 //line templates/http_stuff.qtpl:36
qw422016.N().S(`">`) qw422016.N().S(`">`)
//line templates/http_stuff.qtpl:35 //line templates/http_stuff.qtpl:36
qw422016.E().S(hyphaName) qw422016.E().S(hyphaName)
//line templates/http_stuff.qtpl:35 //line templates/http_stuff.qtpl:36
qw422016.N().S(`</a></td> qw422016.N().S(`</a></td>
`) `)
//line templates/http_stuff.qtpl:36 //line templates/http_stuff.qtpl:37
if binaryPresent { if binaryPresent {
//line templates/http_stuff.qtpl:36 //line templates/http_stuff.qtpl:37
qw422016.N().S(` qw422016.N().S(`
<td>`) <td>`)
//line templates/http_stuff.qtpl:37 //line templates/http_stuff.qtpl:38
qw422016.E().S(binaryMime) qw422016.E().S(binaryMime)
//line templates/http_stuff.qtpl:37 //line templates/http_stuff.qtpl:38
qw422016.N().S(`</td> qw422016.N().S(`</td>
`) `)
//line templates/http_stuff.qtpl:38 //line templates/http_stuff.qtpl:39
} else { } else {
//line templates/http_stuff.qtpl:38 //line templates/http_stuff.qtpl:39
qw422016.N().S(` qw422016.N().S(`
<td></td> <td></td>
`) `)
//line templates/http_stuff.qtpl:40 //line templates/http_stuff.qtpl:41
} }
//line templates/http_stuff.qtpl:40 //line templates/http_stuff.qtpl:41
qw422016.N().S(` qw422016.N().S(`
</tr> </tr>
`) `)
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
} }
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
func WriteHyphaListRowHTML(qq422016 qtio422016.Writer, hyphaName, binaryMime string, binaryPresent bool) { func WriteHyphaListRowHTML(qq422016 qtio422016.Writer, hyphaName, binaryMime string, binaryPresent bool) {
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
StreamHyphaListRowHTML(qw422016, hyphaName, binaryMime, binaryPresent) StreamHyphaListRowHTML(qw422016, hyphaName, binaryMime, binaryPresent)
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
} }
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
func HyphaListRowHTML(hyphaName, binaryMime string, binaryPresent bool) string { func HyphaListRowHTML(hyphaName, binaryMime string, binaryPresent bool) string {
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
WriteHyphaListRowHTML(qb422016, hyphaName, binaryMime, binaryPresent) WriteHyphaListRowHTML(qb422016, hyphaName, binaryMime, binaryPresent)
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
return qs422016 return qs422016
//line templates/http_stuff.qtpl:42 //line templates/http_stuff.qtpl:43
} }