1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-08-05 21:33:49 +00:00

Throw away all backlink-related stuff

This commit is contained in:
bouncepaw 2021-03-14 18:16:30 +05:00
parent 8e94048f15
commit 8fc036ba1c
11 changed files with 108 additions and 308 deletions

View File

@ -381,8 +381,6 @@ mark { background: rgba(130, 80, 30, 5); color: inherit; }
.hypha-tabs { background-color: #232323; } .hypha-tabs { background-color: #232323; }
} }
} }
.backlinks { display: none; }
`) `)
//line assets/assets.qtpl:10 //line assets/assets.qtpl:10
qw422016.N().S(` qw422016.N().S(`

View File

@ -270,5 +270,3 @@ mark { background: rgba(130, 80, 30, 5); color: inherit; }
.hypha-tabs { background-color: #232323; } .hypha-tabs { background-color: #232323; }
} }
} }
.backlinks { display: none; }

View File

@ -11,8 +11,6 @@ import (
// Index finds all hypha files in the full `path` and saves them to the hypha storage. // Index finds all hypha files in the full `path` and saves them to the hypha storage.
func Index(path string) { func Index(path string) {
byNamesMutex.Lock()
defer byNamesMutex.Unlock()
byNames = make(map[string]*Hypha) byNames = make(map[string]*Hypha)
ch := make(chan *Hypha, 5) ch := make(chan *Hypha, 5)
@ -23,11 +21,10 @@ func Index(path string) {
for h := range ch { for h := range ch {
// At this time it is safe to ignore the mutex, because there is only one worker. // At this time it is safe to ignore the mutex, because there is only one worker.
if oldHypha, ok := byNames[h.Name]; ok { if oh := ByName(h.Name); oh.Exists {
oldHypha.MergeIn(h) oh.MergeIn(h)
} else { } else {
byNames[h.Name] = h h.Insert()
IncrementCount()
} }
} }
} }

View File

@ -13,12 +13,10 @@ var HyphaPattern = regexp.MustCompile(`[^?!:#@><*|"\'&%{}]+`)
type Hypha struct { type Hypha struct {
sync.RWMutex sync.RWMutex
Name string Name string // Canonical name
Exists bool Exists bool
TextPath string TextPath string // == "" => no text part
BinaryPath string BinaryPath string // == "" => no attachment
OutLinks []*Hypha
BackLinks []*Hypha
} }
var byNames = make(map[string]*Hypha) var byNames = make(map[string]*Hypha)
@ -31,56 +29,44 @@ func EmptyHypha(hyphaName string) *Hypha {
Exists: false, Exists: false,
TextPath: "", TextPath: "",
BinaryPath: "", BinaryPath: "",
OutLinks: make([]*Hypha, 0),
BackLinks: make([]*Hypha, 0),
} }
} }
// ByName returns a hypha by name. If h.Exists, the returned hypha pointer is known to be part of the hypha index (byNames map). // ByName returns a hypha by name. It may have been recorded to the storage.
func ByName(hyphaName string) (h *Hypha) { func ByName(hyphaName string) (h *Hypha) {
h, exists := byNames[hyphaName] h, recorded := byNames[hyphaName]
if exists { if recorded {
return h return h
} }
return EmptyHypha(hyphaName) return EmptyHypha(hyphaName)
} }
// Insert inserts the hypha into the storage. It overwrites the previous record, if there was any, and returns false. If the was no previous record, return true. func storeHypha(h *Hypha) {
func (h *Hypha) Insert() (justCreated bool) {
hp := ByName(h.Name)
byNamesMutex.Lock() byNamesMutex.Lock()
defer byNamesMutex.Unlock() byNames[h.Name] = h
if hp.Exists { byNamesMutex.Unlock()
hp = h }
// Insert inserts the hypha into the storage. A previous record is used if possible. Count incrementation is done if needed.
func (h *Hypha) Insert() (justRecorded bool) {
hp, recorded := byNames[h.Name]
if recorded {
hp.MergeIn(h)
} else { } else {
h.Exists = true storeHypha(h)
byNames[h.Name] = h
IncrementCount() IncrementCount()
} }
return !hp.Exists return !recorded
} }
func (h *Hypha) InsertIfNew() (justCreated bool) { func (h *Hypha) InsertIfNew() (justRecorded bool) {
if !h.Exists { if !h.Exists {
return h.Insert() return h.Insert()
} }
return false return false
} }
func (h *Hypha) InsertIfNewKeepExistence() {
hp := ByName(h.Name)
byNamesMutex.Lock()
defer byNamesMutex.Unlock()
if hp.Exists {
hp = h
} else {
byNames[h.Name] = h
}
}
func (h *Hypha) Delete() { func (h *Hypha) Delete() {
byNamesMutex.Lock() byNamesMutex.Lock()
h.Lock() h.Lock()
@ -88,10 +74,6 @@ func (h *Hypha) Delete() {
DecrementCount() DecrementCount()
byNamesMutex.Unlock() byNamesMutex.Unlock()
h.Unlock() h.Unlock()
for _, outlinkHypha := range h.OutLinks {
outlinkHypha.DropBackLink(h)
}
} }
func (h *Hypha) RenameTo(newName string) { func (h *Hypha) RenameTo(newName string) {
@ -106,6 +88,10 @@ func (h *Hypha) RenameTo(newName string) {
// MergeIn merges in content file paths from a different hypha object. Prints warnings sometimes. // MergeIn merges in content file paths from a different hypha object. Prints warnings sometimes.
func (h *Hypha) MergeIn(oh *Hypha) { func (h *Hypha) MergeIn(oh *Hypha) {
if h == oh {
return
}
h.Lock()
if h.TextPath == "" && oh.TextPath != "" { if h.TextPath == "" && oh.TextPath != "" {
h.TextPath = oh.TextPath h.TextPath = oh.TextPath
} }
@ -115,61 +101,6 @@ func (h *Hypha) MergeIn(oh *Hypha) {
} }
h.BinaryPath = oh.BinaryPath h.BinaryPath = oh.BinaryPath
} }
} h.Exists = oh.Exists
h.Unlock()
// ## Link related stuff
// Notes in pseudocode and whatnot:
// * (Reader h) does not mutate h => safe
// * (Rename h) reuses the same hypha object => safe
// * (Unattach h) and (Attach h) do not change (Backlinks h) => safe
// * (Delete h) does not change (Backlinks h), but changes (Outlinks h), removing h from them => make it safe
// * (Unattach h) and (Attach h) => h may start or stop existing => may change (Outlinks h) => make it safe
// * (Edit h) => h may start existing => may change (Backlinks h) => make it safe
// * (Edit h) may add or remove h to or from (Outlinks h) => make it safe
func (h *Hypha) AddOutLink(oh *Hypha) (added bool) {
h.Lock()
defer h.Unlock()
for _, outlink := range h.OutLinks {
if outlink == oh {
return false
}
}
h.OutLinks = append(h.OutLinks, oh)
return true
}
func (h *Hypha) AddBackLink(bh *Hypha) (added bool) {
h.Lock()
defer h.Unlock()
for _, backlink := range h.BackLinks {
if backlink == h {
return false
}
}
h.BackLinks = append(h.BackLinks, bh)
return true
}
func (h *Hypha) DropBackLink(bh *Hypha) {
h.Lock()
defer h.Unlock()
if len(h.BackLinks) <= 1 {
h.BackLinks = make([]*Hypha, 0)
return
}
lastBackLinkIndex := len(h.BackLinks)
for i, backlink := range h.BackLinks {
if backlink == bh {
if i != lastBackLinkIndex {
h.BackLinks[i] = h.BackLinks[lastBackLinkIndex]
}
h.BackLinks = h.BackLinks[:lastBackLinkIndex]
return
}
}
} }

View File

@ -176,8 +176,6 @@ func main() {
log.Println("Wiki storage directory is", WikiDir) log.Println("Wiki storage directory is", WikiDir)
hyphae.Index(WikiDir) hyphae.Index(WikiDir)
log.Println("Indexed", hyphae.Count(), "hyphae") log.Println("Indexed", hyphae.Count(), "hyphae")
shroom.FindAllBacklinks()
log.Println("Found all backlinks")
history.Start(WikiDir) history.Start(WikiDir)
shroom.SetHeaderLinks() shroom.SetHeaderLinks()

View File

@ -13,6 +13,7 @@ import (
// * Rocketlinks // * Rocketlinks
// * Transclusion // * Transclusion
// * Image galleries // * Image galleries
// Not needed anymore, I guess.
func (md *MycoDoc) OutLinks() chan string { func (md *MycoDoc) OutLinks() chan string {
ch := make(chan string) ch := make(chan string)
if !md.parsedAlready { if !md.parsedAlready {

View File

@ -1,36 +0,0 @@
package shroom
import (
"io/ioutil"
"log"
"github.com/bouncepaw/mycorrhiza/hyphae"
"github.com/bouncepaw/mycorrhiza/markup"
)
// FindAllBacklinks iterates over all hyphae that have text parts, sets their outlinks and then sets backlinks.
func FindAllBacklinks() {
for h := range hyphae.FilterTextHyphae(hyphae.YieldExistingHyphae()) {
findBacklinkWorker(h)
}
}
func findBacklinkWorker(h *hyphae.Hypha) {
var (
textContents, err = ioutil.ReadFile(h.TextPath)
)
if err == nil {
for outlink := range markup.Doc(h.Name, string(textContents)).OutLinks() {
outlinkHypha := hyphae.ByName(outlink)
if outlinkHypha == h {
break
}
outlinkHypha.AddBackLink(h)
outlinkHypha.InsertIfNewKeepExistence()
h.AddOutLink(outlinkHypha)
}
} else {
log.Println("Error when reading text contents of %s: %s", h.Name, err.Error())
}
}

View File

@ -32,23 +32,6 @@
</h1> </h1>
{% endfunc %} {% endfunc %}
{% func BackLinksHTML(h *hyphae.Hypha) %}
<aside class="backlinks layout-card">
<h2 class="backlinks__title layout-card__title">Backlinks</h2>
<nav class="backlinks__nav">
<ul class="backlinks__list">
{% for _, backlink := range h.BackLinks %}
<li class="backlinks__entry">
<a class="backlinks__link" href="/hypha/{%s backlink.Name %}">
{%s util.BeautifulName(filepath.Base(backlink.Name)) %}
</a>
</li>
{% endfor %}
</ul>
</nav>
</aside>
{% endfunc %}
{% func AttachmentHTML(h *hyphae.Hypha) %} {% func AttachmentHTML(h *hyphae.Hypha) %}
{% switch filepath.Ext(h.BinaryPath) %} {% switch filepath.Ext(h.BinaryPath) %}

View File

@ -123,175 +123,111 @@ func NaviTitleHTML(h *hyphae.Hypha) string {
} }
//line views/hypha.qtpl:35 //line views/hypha.qtpl:35
func StreamBackLinksHTML(qw422016 *qt422016.Writer, h *hyphae.Hypha) { func StreamAttachmentHTML(qw422016 *qt422016.Writer, h *hyphae.Hypha) {
//line views/hypha.qtpl:35 //line views/hypha.qtpl:35
qw422016.N().S(` qw422016.N().S(`
<aside class="backlinks layout-card">
<h2 class="backlinks__title layout-card__title">Backlinks</h2>
<nav class="backlinks__nav">
<ul class="backlinks__list">
`)
//line views/hypha.qtpl:40
for _, backlink := range h.BackLinks {
//line views/hypha.qtpl:40
qw422016.N().S(`
<li class="backlinks__entry">
<a class="backlinks__link" href="/hypha/`)
//line views/hypha.qtpl:42
qw422016.E().S(backlink.Name)
//line views/hypha.qtpl:42
qw422016.N().S(`">
`)
//line views/hypha.qtpl:43
qw422016.E().S(util.BeautifulName(filepath.Base(backlink.Name)))
//line views/hypha.qtpl:43
qw422016.N().S(`
</a>
</li>
`)
//line views/hypha.qtpl:46
}
//line views/hypha.qtpl:46
qw422016.N().S(`
</ul>
</nav>
</aside>
`)
//line views/hypha.qtpl:50
}
//line views/hypha.qtpl:50
func WriteBackLinksHTML(qq422016 qtio422016.Writer, h *hyphae.Hypha) {
//line views/hypha.qtpl:50
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/hypha.qtpl:50
StreamBackLinksHTML(qw422016, h)
//line views/hypha.qtpl:50
qt422016.ReleaseWriter(qw422016)
//line views/hypha.qtpl:50
}
//line views/hypha.qtpl:50
func BackLinksHTML(h *hyphae.Hypha) string {
//line views/hypha.qtpl:50
qb422016 := qt422016.AcquireByteBuffer()
//line views/hypha.qtpl:50
WriteBackLinksHTML(qb422016, h)
//line views/hypha.qtpl:50
qs422016 := string(qb422016.B)
//line views/hypha.qtpl:50
qt422016.ReleaseByteBuffer(qb422016)
//line views/hypha.qtpl:50
return qs422016
//line views/hypha.qtpl:50
}
//line views/hypha.qtpl:52
func StreamAttachmentHTML(qw422016 *qt422016.Writer, h *hyphae.Hypha) {
//line views/hypha.qtpl:52
qw422016.N().S(`
`) `)
//line views/hypha.qtpl:53 //line views/hypha.qtpl:36
switch filepath.Ext(h.BinaryPath) { switch filepath.Ext(h.BinaryPath) {
//line views/hypha.qtpl:55 //line views/hypha.qtpl:38
case ".jpg", ".gif", ".png", ".webp", ".svg", ".ico": case ".jpg", ".gif", ".png", ".webp", ".svg", ".ico":
//line views/hypha.qtpl:55 //line views/hypha.qtpl:38
qw422016.N().S(` qw422016.N().S(`
<div class="binary-container binary-container_with-img"> <div class="binary-container binary-container_with-img">
<a href="/binary/`) <a href="/binary/`)
//line views/hypha.qtpl:57 //line views/hypha.qtpl:40
qw422016.N().S(h.Name) qw422016.N().S(h.Name)
//line views/hypha.qtpl:57 //line views/hypha.qtpl:40
qw422016.N().S(`"><img src="/binary/`) qw422016.N().S(`"><img src="/binary/`)
//line views/hypha.qtpl:57 //line views/hypha.qtpl:40
qw422016.N().S(h.Name) qw422016.N().S(h.Name)
//line views/hypha.qtpl:57 //line views/hypha.qtpl:40
qw422016.N().S(`"/></a> qw422016.N().S(`"/></a>
</div> </div>
`) `)
//line views/hypha.qtpl:60 //line views/hypha.qtpl:43
case ".ogg", ".webm", ".mp4": case ".ogg", ".webm", ".mp4":
//line views/hypha.qtpl:60 //line views/hypha.qtpl:43
qw422016.N().S(` qw422016.N().S(`
<div class="binary-container binary-container_with-video"> <div class="binary-container binary-container_with-video">
<video controls> <video controls>
<source src="/binary/`) <source src="/binary/`)
//line views/hypha.qtpl:63 //line views/hypha.qtpl:46
qw422016.N().S(h.Name) qw422016.N().S(h.Name)
//line views/hypha.qtpl:63 //line views/hypha.qtpl:46
qw422016.N().S(`"/> qw422016.N().S(`"/>
<p>Your browser does not support video. <a href="/binary/`) <p>Your browser does not support video. <a href="/binary/`)
//line views/hypha.qtpl:64 //line views/hypha.qtpl:47
qw422016.N().S(h.Name) qw422016.N().S(h.Name)
//line views/hypha.qtpl:64 //line views/hypha.qtpl:47
qw422016.N().S(`">Download video</a></p> qw422016.N().S(`">Download video</a></p>
</video> </video>
</div> </div>
`) `)
//line views/hypha.qtpl:68 //line views/hypha.qtpl:51
case ".mp3": case ".mp3":
//line views/hypha.qtpl:68 //line views/hypha.qtpl:51
qw422016.N().S(` qw422016.N().S(`
<div class="binary-container binary-container_with-audio"> <div class="binary-container binary-container_with-audio">
<audio controls> <audio controls>
<source src="/binary/`) <source src="/binary/`)
//line views/hypha.qtpl:71 //line views/hypha.qtpl:54
qw422016.N().S(h.Name) qw422016.N().S(h.Name)
//line views/hypha.qtpl:71 //line views/hypha.qtpl:54
qw422016.N().S(`"/> qw422016.N().S(`"/>
<p>Your browser does not support audio. <a href="/binary/`) <p>Your browser does not support audio. <a href="/binary/`)
//line views/hypha.qtpl:72 //line views/hypha.qtpl:55
qw422016.N().S(h.Name) qw422016.N().S(h.Name)
//line views/hypha.qtpl:72 //line views/hypha.qtpl:55
qw422016.N().S(`">Download audio</a></p> qw422016.N().S(`">Download audio</a></p>
</audio> </audio>
</div> </div>
`) `)
//line views/hypha.qtpl:76 //line views/hypha.qtpl:59
default: default:
//line views/hypha.qtpl:76 //line views/hypha.qtpl:59
qw422016.N().S(` qw422016.N().S(`
<div class="binary-container binary-container_with-nothing"> <div class="binary-container binary-container_with-nothing">
<p><a href="/binary/`) <p><a href="/binary/`)
//line views/hypha.qtpl:78 //line views/hypha.qtpl:61
qw422016.N().S(h.Name) qw422016.N().S(h.Name)
//line views/hypha.qtpl:78 //line views/hypha.qtpl:61
qw422016.N().S(`">Download media</a></p> qw422016.N().S(`">Download media</a></p>
</div> </div>
`) `)
//line views/hypha.qtpl:80 //line views/hypha.qtpl:63
} }
//line views/hypha.qtpl:80 //line views/hypha.qtpl:63
qw422016.N().S(` qw422016.N().S(`
`) `)
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
} }
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
func WriteAttachmentHTML(qq422016 qtio422016.Writer, h *hyphae.Hypha) { func WriteAttachmentHTML(qq422016 qtio422016.Writer, h *hyphae.Hypha) {
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
StreamAttachmentHTML(qw422016, h) StreamAttachmentHTML(qw422016, h)
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
} }
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
func AttachmentHTML(h *hyphae.Hypha) string { func AttachmentHTML(h *hyphae.Hypha) string {
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
WriteAttachmentHTML(qb422016, h) WriteAttachmentHTML(qb422016, h)
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
return qs422016 return qs422016
//line views/hypha.qtpl:81 //line views/hypha.qtpl:64
} }

View File

@ -108,7 +108,6 @@ If `contents` == "", a helpful message is shown instead.
{%= SubhyphaeHTML(subhyphae) %} {%= SubhyphaeHTML(subhyphae) %}
</main> </main>
{%= RelativeHyphaeHTML(relatives) %} {%= RelativeHyphaeHTML(relatives) %}
{%= BackLinksHTML(h) %}
</div> </div>
{% endfunc %} {% endfunc %}

View File

@ -345,110 +345,105 @@ func StreamHyphaHTML(qw422016 *qt422016.Writer, rq *http.Request, h *hyphae.Hyph
StreamRelativeHyphaeHTML(qw422016, relatives) StreamRelativeHyphaeHTML(qw422016, relatives)
//line views/readers.qtpl:110 //line views/readers.qtpl:110
qw422016.N().S(` qw422016.N().S(`
`)
//line views/readers.qtpl:111
StreamBackLinksHTML(qw422016, h)
//line views/readers.qtpl:111
qw422016.N().S(`
</div> </div>
`) `)
//line views/readers.qtpl:113 //line views/readers.qtpl:112
} }
//line views/readers.qtpl:113 //line views/readers.qtpl:112
func WriteHyphaHTML(qq422016 qtio422016.Writer, rq *http.Request, h *hyphae.Hypha, contents string) { func WriteHyphaHTML(qq422016 qtio422016.Writer, rq *http.Request, h *hyphae.Hypha, contents string) {
//line views/readers.qtpl:113 //line views/readers.qtpl:112
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line views/readers.qtpl:113 //line views/readers.qtpl:112
StreamHyphaHTML(qw422016, rq, h, contents) StreamHyphaHTML(qw422016, rq, h, contents)
//line views/readers.qtpl:113 //line views/readers.qtpl:112
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line views/readers.qtpl:113 //line views/readers.qtpl:112
} }
//line views/readers.qtpl:113 //line views/readers.qtpl:112
func HyphaHTML(rq *http.Request, h *hyphae.Hypha, contents string) string { func HyphaHTML(rq *http.Request, h *hyphae.Hypha, contents string) string {
//line views/readers.qtpl:113 //line views/readers.qtpl:112
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line views/readers.qtpl:113 //line views/readers.qtpl:112
WriteHyphaHTML(qb422016, rq, h, contents) WriteHyphaHTML(qb422016, rq, h, contents)
//line views/readers.qtpl:113 //line views/readers.qtpl:112
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line views/readers.qtpl:113 //line views/readers.qtpl:112
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line views/readers.qtpl:113 //line views/readers.qtpl:112
return qs422016 return qs422016
//line views/readers.qtpl:113 //line views/readers.qtpl:112
} }
//line views/readers.qtpl:115 //line views/readers.qtpl:114
func StreamRevisionHTML(qw422016 *qt422016.Writer, rq *http.Request, h *hyphae.Hypha, contents, revHash string) { func StreamRevisionHTML(qw422016 *qt422016.Writer, rq *http.Request, h *hyphae.Hypha, contents, revHash string) {
//line views/readers.qtpl:115 //line views/readers.qtpl:114
qw422016.N().S(` qw422016.N().S(`
`) `)
//line views/readers.qtpl:117 //line views/readers.qtpl:116
relatives, subhyphae, _, _ := tree.Tree(h.Name) relatives, subhyphae, _, _ := tree.Tree(h.Name)
//line views/readers.qtpl:118 //line views/readers.qtpl:117
qw422016.N().S(` qw422016.N().S(`
`) `)
//line views/readers.qtpl:119 //line views/readers.qtpl:118
StreamNavHTML(qw422016, rq, h.Name, "revision", revHash) StreamNavHTML(qw422016, rq, h.Name, "revision", revHash)
//line views/readers.qtpl:119 //line views/readers.qtpl:118
qw422016.N().S(` qw422016.N().S(`
<div class="layout"> <div class="layout">
<main class="main-width"> <main class="main-width">
<article> <article>
<p>Please note that viewing binary parts of hyphae is not supported in history for now.</p> <p>Please note that viewing binary parts of hyphae is not supported in history for now.</p>
`) `)
//line views/readers.qtpl:124 //line views/readers.qtpl:123
qw422016.N().S(NaviTitleHTML(h)) qw422016.N().S(NaviTitleHTML(h))
//line views/readers.qtpl:124 //line views/readers.qtpl:123
qw422016.N().S(` qw422016.N().S(`
`) `)
//line views/readers.qtpl:125 //line views/readers.qtpl:124
qw422016.N().S(contents) qw422016.N().S(contents)
//line views/readers.qtpl:125 //line views/readers.qtpl:124
qw422016.N().S(` qw422016.N().S(`
</article> </article>
`) `)
//line views/readers.qtpl:127 //line views/readers.qtpl:126
StreamSubhyphaeHTML(qw422016, subhyphae) StreamSubhyphaeHTML(qw422016, subhyphae)
//line views/readers.qtpl:127 //line views/readers.qtpl:126
qw422016.N().S(` qw422016.N().S(`
</main> </main>
`) `)
//line views/readers.qtpl:129 //line views/readers.qtpl:128
StreamRelativeHyphaeHTML(qw422016, relatives) StreamRelativeHyphaeHTML(qw422016, relatives)
//line views/readers.qtpl:129 //line views/readers.qtpl:128
qw422016.N().S(` qw422016.N().S(`
</div> </div>
`) `)
//line views/readers.qtpl:131 //line views/readers.qtpl:130
} }
//line views/readers.qtpl:131 //line views/readers.qtpl:130
func WriteRevisionHTML(qq422016 qtio422016.Writer, rq *http.Request, h *hyphae.Hypha, contents, revHash string) { func WriteRevisionHTML(qq422016 qtio422016.Writer, rq *http.Request, h *hyphae.Hypha, contents, revHash string) {
//line views/readers.qtpl:131 //line views/readers.qtpl:130
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line views/readers.qtpl:131 //line views/readers.qtpl:130
StreamRevisionHTML(qw422016, rq, h, contents, revHash) StreamRevisionHTML(qw422016, rq, h, contents, revHash)
//line views/readers.qtpl:131 //line views/readers.qtpl:130
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line views/readers.qtpl:131 //line views/readers.qtpl:130
} }
//line views/readers.qtpl:131 //line views/readers.qtpl:130
func RevisionHTML(rq *http.Request, h *hyphae.Hypha, contents, revHash string) string { func RevisionHTML(rq *http.Request, h *hyphae.Hypha, contents, revHash string) string {
//line views/readers.qtpl:131 //line views/readers.qtpl:130
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line views/readers.qtpl:131 //line views/readers.qtpl:130
WriteRevisionHTML(qb422016, rq, h, contents, revHash) WriteRevisionHTML(qb422016, rq, h, contents, revHash)
//line views/readers.qtpl:131 //line views/readers.qtpl:130
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line views/readers.qtpl:131 //line views/readers.qtpl:130
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line views/readers.qtpl:131 //line views/readers.qtpl:130
return qs422016 return qs422016
//line views/readers.qtpl:131 //line views/readers.qtpl:130
} }