mirror of
				https://github.com/osmarks/mycorrhiza.git
				synced 2025-10-30 15:13:02 +00:00 
			
		
		
		
	Implement backlinks core (index, i12n and viewing)
This commit is contained in:
		 Mikhail Chekan
					Mikhail Chekan
				
			
				
					committed by
					
						 Timur Ismagilov
						Timur Ismagilov
					
				
			
			
				
	
			
			
			 Timur Ismagilov
						Timur Ismagilov
					
				
			
						parent
						
							0b2e52b99b
						
					
				
				
					commit
					820de6a0aa
				
			
							
								
								
									
										153
									
								
								hyphae/backlinks.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								hyphae/backlinks.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | |||||||
|  | package hyphae | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"os" | ||||||
|  | 	"sync" | ||||||
|  |  | ||||||
|  | 	"github.com/bouncepaw/mycorrhiza/util" | ||||||
|  |  | ||||||
|  | 	"github.com/bouncepaw/mycomarkup" | ||||||
|  | 	"github.com/bouncepaw/mycomarkup/blocks" | ||||||
|  | 	"github.com/bouncepaw/mycomarkup/links" | ||||||
|  | 	"github.com/bouncepaw/mycomarkup/mycocontext" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Using set here seems like the most appropriate solution | ||||||
|  | type linkSet map[string]struct{} | ||||||
|  |  | ||||||
|  | var backlinkIndex = make(map[string]linkSet) | ||||||
|  | var backlinkIndexMutex = sync.Mutex{} | ||||||
|  |  | ||||||
|  | // IndexBacklinks traverses all text hyphae, extracts links from them and forms an initial index | ||||||
|  | func IndexBacklinks() { | ||||||
|  | 	// It is safe to ignore the mutex, because there is only one worker. | ||||||
|  | 	src := FilterTextHyphae(YieldExistingHyphae()) | ||||||
|  | 	for h := range src { | ||||||
|  | 		fileContentsT, errT := os.ReadFile(h.TextPath) | ||||||
|  | 		if errT == nil { | ||||||
|  | 			links := ExtractHyphaLinksFromContent(h.Name, string(fileContentsT)) | ||||||
|  | 			for _, link := range links { | ||||||
|  | 				if _, exists := backlinkIndex[link]; !exists { | ||||||
|  | 					backlinkIndex[link] = make(linkSet) | ||||||
|  | 				} | ||||||
|  | 				backlinkIndex[link][h.Name] = struct{}{} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func YieldHyphaBacklinks(query string) <-chan string { | ||||||
|  | 	hyphaName := util.CanonicalName(query) | ||||||
|  | 	out := make(chan string) | ||||||
|  | 	sorted := PathographicSort(out) | ||||||
|  | 	go func() { | ||||||
|  | 		links := backlinkIndex[hyphaName] | ||||||
|  | 		for link := range links { | ||||||
|  | 			out <- link | ||||||
|  | 		} | ||||||
|  | 		close(out) | ||||||
|  | 	}() | ||||||
|  | 	return sorted | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // YieldHyphaLinks extracts hypha links from a desired hypha and iterates over them | ||||||
|  | func YieldHyphaLinks(query string) <-chan string { | ||||||
|  | 	// That is merely a debug function, but it could be useful. | ||||||
|  | 	// Should we extract them into link-specific subfile? -- chekoopa | ||||||
|  | 	hyphaName := util.CanonicalName(query) | ||||||
|  | 	out := make(chan string) | ||||||
|  | 	go func() { | ||||||
|  | 		links := ExtractHyphaLinks(hyphaName) | ||||||
|  | 		for _, link := range links { | ||||||
|  | 			out <- link | ||||||
|  | 		} | ||||||
|  | 		close(out) | ||||||
|  | 	}() | ||||||
|  | 	return out | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ExtractHyphaLinks extracts hypha links from a desired hypha | ||||||
|  | func ExtractHyphaLinks(hyphaName string) []string { | ||||||
|  | 	var h = ByName(hyphaName) | ||||||
|  | 	if h.Exists { | ||||||
|  | 		fileContentsT, errT := os.ReadFile(h.TextPath) | ||||||
|  | 		if errT == nil { | ||||||
|  | 			return ExtractHyphaLinksFromContent(hyphaName, string(fileContentsT)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return make([]string, 0) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ExtractHyphaLinksFromContent extracts hypha links from a provided text | ||||||
|  | func ExtractHyphaLinksFromContent(hyphaName string, contents string) []string { | ||||||
|  | 	ctx, _ := mycocontext.ContextFromStringInput(hyphaName, contents) | ||||||
|  | 	linkVisitor, getLinks := LinkVisitor(ctx) | ||||||
|  | 	mycomarkup.BlockTree(ctx, linkVisitor) | ||||||
|  | 	foundLinks := getLinks() | ||||||
|  | 	var result []string | ||||||
|  | 	for _, link := range foundLinks { | ||||||
|  | 		if link.OfKind(links.LinkLocalHypha) { | ||||||
|  | 			result = append(result, link.TargetHypha()) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return result | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // LinkVisitor creates a visitor which extracts all the links | ||||||
|  | func LinkVisitor(ctx mycocontext.Context) ( | ||||||
|  | 	visitor func(block blocks.Block), | ||||||
|  | 	result func() []links.Link, | ||||||
|  | ) { | ||||||
|  | 	var ( | ||||||
|  | 		collected []links.Link | ||||||
|  | 	) | ||||||
|  | 	var extractBlock func(block blocks.Block) | ||||||
|  | 	extractBlock = func(block blocks.Block) { | ||||||
|  | 		// fmt.Println(reflect.TypeOf(block)) | ||||||
|  | 		switch b := block.(type) { | ||||||
|  | 		case blocks.Paragraph: | ||||||
|  | 			extractBlock(b.Formatted) | ||||||
|  | 		case blocks.Heading: | ||||||
|  | 			extractBlock(b.GetContents()) | ||||||
|  | 		case blocks.List: | ||||||
|  | 			for _, item := range b.Items { | ||||||
|  | 				for _, sub := range item.Contents { | ||||||
|  | 					extractBlock(sub) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		case blocks.Img: | ||||||
|  | 			for _, entry := range b.Entries { | ||||||
|  | 				extractBlock(entry) | ||||||
|  | 			} | ||||||
|  | 		case blocks.ImgEntry: | ||||||
|  | 			collected = append(collected, *b.Srclink) | ||||||
|  | 		case blocks.Transclusion: | ||||||
|  | 			link := *links.From(b.Target, "", ctx.HyphaName()) | ||||||
|  | 			collected = append(collected, link) | ||||||
|  | 		case blocks.LaunchPad: | ||||||
|  | 			for _, rocket := range b.Rockets { | ||||||
|  | 				extractBlock(rocket) | ||||||
|  | 			} | ||||||
|  | 		case blocks.Formatted: | ||||||
|  | 			for _, line := range b.Lines { | ||||||
|  | 				for _, span := range line { | ||||||
|  | 					switch s := span.(type) { | ||||||
|  | 					case blocks.InlineLink: | ||||||
|  | 						collected = append(collected, *s.Link) | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		case blocks.RocketLink: | ||||||
|  | 			if !b.IsEmpty { | ||||||
|  | 				collected = append(collected, b.Link) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	visitor = func(block blocks.Block) { | ||||||
|  | 		extractBlock(block) | ||||||
|  | 	} | ||||||
|  | 	result = func() []links.Link { | ||||||
|  | 		return collected | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								main.go
									
									
									
									
									
								
							| @@ -37,6 +37,7 @@ func main() { | |||||||
|  |  | ||||||
| 	// Init the subsystems: | 	// Init the subsystems: | ||||||
| 	hyphae.Index(files.HyphaeDir()) | 	hyphae.Index(files.HyphaeDir()) | ||||||
|  | 	hyphae.IndexBacklinks() | ||||||
| 	user.InitUserDatabase() | 	user.InitUserDatabase() | ||||||
| 	history.Start() | 	history.Start() | ||||||
| 	history.InitGitRepo() | 	history.InitGitRepo() | ||||||
|   | |||||||
| @@ -11,10 +11,10 @@ | |||||||
| .modal__title_small { font-size: 1.5rem; } | .modal__title_small { font-size: 1.5rem; } | ||||||
| .modal__confirmation-msg { margin: 0 0 .5rem 0; } | .modal__confirmation-msg { margin: 0 0 .5rem 0; } | ||||||
|  |  | ||||||
| .hypha-list, .title-search__results { padding-left: 0; } | .hypha-list, .title-search__results, .backlinks__list { padding-left: 0; } | ||||||
| .hypha-list__entry, .title-search__entry { list-style-type: none; } | .hypha-list__entry, .title-search__entry, .backlinks__entry { list-style-type: none; } | ||||||
| .hypha-list__link, .title-search__link { text-decoration: none; display: inline-block; padding: .25rem; } | .hypha-list__link, .title-search__link, .backlinks__link { text-decoration: none; display: inline-block; padding: .25rem; } | ||||||
| .hypha-list__link:hover, .title-search__link:hover { text-decoration: underline; } | .hypha-list__link:hover, .title-search__link:hover, .backlinks__link:hover { text-decoration: underline; } | ||||||
| .hypha-list__amnt-type { font-size: smaller; color: #999; } | .hypha-list__amnt-type { font-size: smaller; color: #999; } | ||||||
|  |  | ||||||
| /* General element positions, from small to big */ | /* General element positions, from small to big */ | ||||||
| @@ -23,8 +23,6 @@ | |||||||
| header { width: 100%; margin-bottom: 1rem; } | header { width: 100%; margin-bottom: 1rem; } | ||||||
|  |  | ||||||
| .layout-card li { list-style-type: none; } | .layout-card li { list-style-type: none; } | ||||||
| .backlinks__list { padding: 0; margin: 0; } |  | ||||||
| .backlinks__link { text-decoration: none; display: block; padding: .25rem; padding-left: 1.25rem; } |  | ||||||
|  |  | ||||||
| @media screen and (max-width: 800px) { | @media screen and (max-width: 800px) { | ||||||
| 	.amnt-grid { grid-template-columns: 1fr; } | 	.amnt-grid { grid-template-columns: 1fr; } | ||||||
| @@ -65,13 +63,9 @@ header { width: 100%; margin-bottom: 1rem; } | |||||||
| 	.layout { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); } | 	.layout { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); } | ||||||
| 	.layout-card {max-width: 18rem;} | 	.layout-card {max-width: 18rem;} | ||||||
| 	.main-width { margin: 0 auto; } | 	.main-width { margin: 0 auto; } | ||||||
| 	.backlinks { grid-column: 1 / span 1; margin-right: 0; } |  | ||||||
| 	main { grid-column: 2 / span 1; } | 	main { grid-column: 2 / span 1; } | ||||||
| 	.sibling-hyphae, .edit-toolbar, .help-topics { grid-column: 3 / span 1; margin-left: 0; } | 	.sibling-hyphae, .edit-toolbar, .help-topics { grid-column: 3 / span 1; margin-left: 0; } | ||||||
| 	.edit-toolbar__buttons { grid-template-columns: 1fr; } | 	.edit-toolbar__buttons { grid-template-columns: 1fr; } | ||||||
|  |  | ||||||
| 	.backlinks__title { text-align: right; } |  | ||||||
| 	.backlinks__link { text-align: right; padding-right: 1.25rem; padding-left: .25rem; } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| @media screen and (min-width: 1400px) { | @media screen and (min-width: 1400px) { | ||||||
| @@ -221,7 +215,7 @@ blockquote { border-left: 2px #999 solid; } | |||||||
| .upload-amnt { border: #eee 1px solid; } | .upload-amnt { border: #eee 1px solid; } | ||||||
| td { border: #ddd 1px solid; } | td { border: #ddd 1px solid; } | ||||||
|  |  | ||||||
| .sibling-hyphae__link:hover, .backlinks__link:hover { background-color: #eee; } | .sibling-hyphae__link:hover { background-color: #eee; } | ||||||
|  |  | ||||||
| /* Dark theme! */ | /* Dark theme! */ | ||||||
| @media (prefers-color-scheme: dark) { | @media (prefers-color-scheme: dark) { | ||||||
| @@ -231,7 +225,7 @@ main,  article, header, .layout-card { background-color: #343434; color: #ddd; } | |||||||
| a, .wikilink_external { color: #f1fa8c; } | a, .wikilink_external { color: #f1fa8c; } | ||||||
| a:visited, .wikilink_external:visited { color: #ffb86c; } | a:visited, .wikilink_external:visited { color: #ffb86c; } | ||||||
| .wikilink_new, .wikilink_new:visited { color: #dd4444; } | .wikilink_new, .wikilink_new:visited { color: #dd4444; } | ||||||
| .subhyphae__link:hover, .sibling-hyphae__link:hover, .backlinks__link:hover { background-color: #444; } | .subhyphae__link:hover, .sibling-hyphae__link:hover { background-color: #444; } | ||||||
|  |  | ||||||
| .prevnext__el, .prevnext__el:visited { color: #ddd; } | .prevnext__el, .prevnext__el:visited { color: #ddd; } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ | |||||||
| 		{%= hyphaInfoEntry(h, u, "delete-ask", "Delete") %} | 		{%= hyphaInfoEntry(h, u, "delete-ask", "Delete") %} | ||||||
| 		{%= hyphaInfoEntry(h, u, "text", "View markup") %} | 		{%= hyphaInfoEntry(h, u, "text", "View markup") %} | ||||||
| 		{%= hyphaInfoEntry(h, u, "attachment", "Manage attachment") %} | 		{%= hyphaInfoEntry(h, u, "attachment", "Manage attachment") %} | ||||||
|  | 		{%= hyphaInfoEntry(h, u, "backlinks", "Backlinks") %} | ||||||
| 	</ul> | 	</ul> | ||||||
| </nav> | </nav> | ||||||
| {% endfunc %} | {% endfunc %} | ||||||
|   | |||||||
| @@ -128,133 +128,138 @@ func streamhyphaInfo(qw422016 *qt422016.Writer, rq *http.Request, h *hyphae.Hyph | |||||||
| //line views/nav.qtpl:24 | //line views/nav.qtpl:24 | ||||||
| 	streamhyphaInfoEntry(qw422016, h, u, "attachment", "Manage attachment") | 	streamhyphaInfoEntry(qw422016, h, u, "attachment", "Manage attachment") | ||||||
| //line views/nav.qtpl:24 | //line views/nav.qtpl:24 | ||||||
|  | 	qw422016.N().S(` | ||||||
|  | 		`) | ||||||
|  | //line views/nav.qtpl:25 | ||||||
|  | 	streamhyphaInfoEntry(qw422016, h, u, "backlinks", "Backlinks") | ||||||
|  | //line views/nav.qtpl:25 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| 	</ul> | 	</ul> | ||||||
| </nav> | </nav> | ||||||
| `) | `) | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| func writehyphaInfo(qq422016 qtio422016.Writer, rq *http.Request, h *hyphae.Hypha) { | func writehyphaInfo(qq422016 qtio422016.Writer, rq *http.Request, h *hyphae.Hypha) { | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| 	qw422016 := qt422016.AcquireWriter(qq422016) | 	qw422016 := qt422016.AcquireWriter(qq422016) | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| 	streamhyphaInfo(qw422016, rq, h) | 	streamhyphaInfo(qw422016, rq, h) | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| 	qt422016.ReleaseWriter(qw422016) | 	qt422016.ReleaseWriter(qw422016) | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| func hyphaInfo(rq *http.Request, h *hyphae.Hypha) string { | func hyphaInfo(rq *http.Request, h *hyphae.Hypha) string { | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| 	qb422016 := qt422016.AcquireByteBuffer() | 	qb422016 := qt422016.AcquireByteBuffer() | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| 	writehyphaInfo(qb422016, rq, h) | 	writehyphaInfo(qb422016, rq, h) | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| 	qs422016 := string(qb422016.B) | 	qs422016 := string(qb422016.B) | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| 	qt422016.ReleaseByteBuffer(qb422016) | 	qt422016.ReleaseByteBuffer(qb422016) | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| 	return qs422016 | 	return qs422016 | ||||||
| //line views/nav.qtpl:27 | //line views/nav.qtpl:28 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/nav.qtpl:29 | //line views/nav.qtpl:30 | ||||||
| func streamsiblingHyphaeHTML(qw422016 *qt422016.Writer, siblings string) { | func streamsiblingHyphaeHTML(qw422016 *qt422016.Writer, siblings string) { | ||||||
| //line views/nav.qtpl:29 | //line views/nav.qtpl:30 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| <aside class="sibling-hyphae layout-card"> | <aside class="sibling-hyphae layout-card"> | ||||||
| 	<h2 class="sibling-hyphae__title layout-card__title">Sibling hyphae</h2> | 	<h2 class="sibling-hyphae__title layout-card__title">Sibling hyphae</h2> | ||||||
| 	`) | 	`) | ||||||
| //line views/nav.qtpl:32 | //line views/nav.qtpl:33 | ||||||
| 	qw422016.N().S(siblings) | 	qw422016.N().S(siblings) | ||||||
| //line views/nav.qtpl:32 | //line views/nav.qtpl:33 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| </aside> | </aside> | ||||||
| `) | `) | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| func writesiblingHyphaeHTML(qq422016 qtio422016.Writer, siblings string) { | func writesiblingHyphaeHTML(qq422016 qtio422016.Writer, siblings string) { | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| 	qw422016 := qt422016.AcquireWriter(qq422016) | 	qw422016 := qt422016.AcquireWriter(qq422016) | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| 	streamsiblingHyphaeHTML(qw422016, siblings) | 	streamsiblingHyphaeHTML(qw422016, siblings) | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| 	qt422016.ReleaseWriter(qw422016) | 	qt422016.ReleaseWriter(qw422016) | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| func siblingHyphaeHTML(siblings string) string { | func siblingHyphaeHTML(siblings string) string { | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| 	qb422016 := qt422016.AcquireByteBuffer() | 	qb422016 := qt422016.AcquireByteBuffer() | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| 	writesiblingHyphaeHTML(qb422016, siblings) | 	writesiblingHyphaeHTML(qb422016, siblings) | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| 	qs422016 := string(qb422016.B) | 	qs422016 := string(qb422016.B) | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| 	qt422016.ReleaseByteBuffer(qb422016) | 	qt422016.ReleaseByteBuffer(qb422016) | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| 	return qs422016 | 	return qs422016 | ||||||
| //line views/nav.qtpl:34 | //line views/nav.qtpl:35 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/nav.qtpl:36 | //line views/nav.qtpl:37 | ||||||
| func StreamSubhyphaeHTML(qw422016 *qt422016.Writer, subhyphae string) { | func StreamSubhyphaeHTML(qw422016 *qt422016.Writer, subhyphae string) { | ||||||
| //line views/nav.qtpl:36 | //line views/nav.qtpl:37 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| `) | `) | ||||||
| //line views/nav.qtpl:37 | //line views/nav.qtpl:38 | ||||||
| 	if strings.TrimSpace(subhyphae) != "" { | 	if strings.TrimSpace(subhyphae) != "" { | ||||||
| //line views/nav.qtpl:37 | //line views/nav.qtpl:38 | ||||||
| 		qw422016.N().S(` | 		qw422016.N().S(` | ||||||
| <section class="subhyphae"> | <section class="subhyphae"> | ||||||
| 	<h2 class="subhyphae__title">Subhyphae</h2> | 	<h2 class="subhyphae__title">Subhyphae</h2> | ||||||
| 	<nav class="subhyphae__nav"> | 	<nav class="subhyphae__nav"> | ||||||
| 		<ul class="subhyphae__list"> | 		<ul class="subhyphae__list"> | ||||||
| 		`) | 		`) | ||||||
| //line views/nav.qtpl:42 | //line views/nav.qtpl:43 | ||||||
| 		qw422016.N().S(subhyphae) | 		qw422016.N().S(subhyphae) | ||||||
| //line views/nav.qtpl:42 | //line views/nav.qtpl:43 | ||||||
| 		qw422016.N().S(` | 		qw422016.N().S(` | ||||||
| 		</ul> | 		</ul> | ||||||
| 	</nav> | 	</nav> | ||||||
| </section> | </section> | ||||||
| `) | `) | ||||||
| //line views/nav.qtpl:46 | //line views/nav.qtpl:47 | ||||||
| 	} | 	} | ||||||
| //line views/nav.qtpl:46 | //line views/nav.qtpl:47 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| `) | `) | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| func WriteSubhyphaeHTML(qq422016 qtio422016.Writer, subhyphae string) { | func WriteSubhyphaeHTML(qq422016 qtio422016.Writer, subhyphae string) { | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| 	qw422016 := qt422016.AcquireWriter(qq422016) | 	qw422016 := qt422016.AcquireWriter(qq422016) | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| 	StreamSubhyphaeHTML(qw422016, subhyphae) | 	StreamSubhyphaeHTML(qw422016, subhyphae) | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| 	qt422016.ReleaseWriter(qw422016) | 	qt422016.ReleaseWriter(qw422016) | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| func SubhyphaeHTML(subhyphae string) string { | func SubhyphaeHTML(subhyphae string) string { | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| 	qb422016 := qt422016.AcquireByteBuffer() | 	qb422016 := qt422016.AcquireByteBuffer() | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| 	WriteSubhyphaeHTML(qb422016, subhyphae) | 	WriteSubhyphaeHTML(qb422016, subhyphae) | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| 	qs422016 := string(qb422016.B) | 	qs422016 := string(qb422016.B) | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| 	qt422016.ReleaseByteBuffer(qb422016) | 	qt422016.ReleaseByteBuffer(qb422016) | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| 	return qs422016 | 	return qs422016 | ||||||
| //line views/nav.qtpl:47 | //line views/nav.qtpl:48 | ||||||
| } | } | ||||||
|   | |||||||
| @@ -120,6 +120,21 @@ It outputs a poorly formatted JSON, but it works and is valid. | |||||||
| } | } | ||||||
| {% endfunc %} | {% endfunc %} | ||||||
|  |  | ||||||
|  | {% func BacklinksHTML(query string, generator func(string) <-chan string) %} | ||||||
|  | <div class="layout"> | ||||||
|  | <main class="main-width backlinks"> | ||||||
|  | 	<h1>Backlinks to ‘{%s query %}’</h1> | ||||||
|  | 	<p>Hyphae which have a link to the selected hypha are listed below.</p> | ||||||
|  | 	<ul class="backlinks__list"> | ||||||
|  | 	{% for hyphaName := range generator(query) %} | ||||||
|  | 		<li class="backlinks__entry"> | ||||||
|  | 			<a class="backlinks__link wikilink" href="/hypha/{%s hyphaName %}">{%s util.BeautifulName(hyphaName) %}</a> | ||||||
|  | 		</li> | ||||||
|  | 	{% endfor %} | ||||||
|  | </main> | ||||||
|  | </div> | ||||||
|  | {% endfunc %} | ||||||
|  |  | ||||||
| {% func HelpHTML(content string) %} | {% func HelpHTML(content string) %} | ||||||
| <div class="layout"> | <div class="layout"> | ||||||
| <main class="main-width help"> | <main class="main-width help"> | ||||||
|   | |||||||
| @@ -397,95 +397,161 @@ func TitleSearchJSON(query string, generator func(string) <-chan string) string | |||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:123 | //line views/stuff.qtpl:123 | ||||||
| func StreamHelpHTML(qw422016 *qt422016.Writer, content string) { | func StreamBacklinksHTML(qw422016 *qt422016.Writer, query string, generator func(string) <-chan string) { | ||||||
| //line views/stuff.qtpl:123 | //line views/stuff.qtpl:123 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| <div class="layout"> | <div class="layout"> | ||||||
|  | <main class="main-width backlinks"> | ||||||
|  | 	<h1>Backlinks to ‘`) | ||||||
|  | //line views/stuff.qtpl:126 | ||||||
|  | 	qw422016.E().S(query) | ||||||
|  | //line views/stuff.qtpl:126 | ||||||
|  | 	qw422016.N().S(`’</h1> | ||||||
|  | 	<p>Hyphae which have a link to the selected hypha are listed below.</p> | ||||||
|  | 	<ul class="backlinks__list"> | ||||||
|  | 	`) | ||||||
|  | //line views/stuff.qtpl:129 | ||||||
|  | 	for hyphaName := range generator(query) { | ||||||
|  | //line views/stuff.qtpl:129 | ||||||
|  | 		qw422016.N().S(` | ||||||
|  | 		<li class="backlinks__entry"> | ||||||
|  | 			<a class="backlinks__link wikilink" href="/hypha/`) | ||||||
|  | //line views/stuff.qtpl:131 | ||||||
|  | 		qw422016.E().S(hyphaName) | ||||||
|  | //line views/stuff.qtpl:131 | ||||||
|  | 		qw422016.N().S(`">`) | ||||||
|  | //line views/stuff.qtpl:131 | ||||||
|  | 		qw422016.E().S(util.BeautifulName(hyphaName)) | ||||||
|  | //line views/stuff.qtpl:131 | ||||||
|  | 		qw422016.N().S(`</a> | ||||||
|  | 		</li> | ||||||
|  | 	`) | ||||||
|  | //line views/stuff.qtpl:133 | ||||||
|  | 	} | ||||||
|  | //line views/stuff.qtpl:133 | ||||||
|  | 	qw422016.N().S(` | ||||||
|  | </main> | ||||||
|  | </div> | ||||||
|  | `) | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | func WriteBacklinksHTML(qq422016 qtio422016.Writer, query string, generator func(string) <-chan string) { | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | 	qw422016 := qt422016.AcquireWriter(qq422016) | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | 	StreamBacklinksHTML(qw422016, query, generator) | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | 	qt422016.ReleaseWriter(qw422016) | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | func BacklinksHTML(query string, generator func(string) <-chan string) string { | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | 	qb422016 := qt422016.AcquireByteBuffer() | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | 	WriteBacklinksHTML(qb422016, query, generator) | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | 	qs422016 := string(qb422016.B) | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | 	qt422016.ReleaseByteBuffer(qb422016) | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | 	return qs422016 | ||||||
|  | //line views/stuff.qtpl:136 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //line views/stuff.qtpl:138 | ||||||
|  | func StreamHelpHTML(qw422016 *qt422016.Writer, content string) { | ||||||
|  | //line views/stuff.qtpl:138 | ||||||
|  | 	qw422016.N().S(` | ||||||
|  | <div class="layout"> | ||||||
| <main class="main-width help"> | <main class="main-width help"> | ||||||
| 	<article> | 	<article> | ||||||
| 	`) | 	`) | ||||||
| //line views/stuff.qtpl:127 | //line views/stuff.qtpl:142 | ||||||
| 	qw422016.N().S(content) | 	qw422016.N().S(content) | ||||||
| //line views/stuff.qtpl:127 | //line views/stuff.qtpl:142 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| 	</article> | 	</article> | ||||||
| </main> | </main> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:130 | //line views/stuff.qtpl:145 | ||||||
| 	qw422016.N().S(helpTopicsHTML()) | 	qw422016.N().S(helpTopicsHTML()) | ||||||
| //line views/stuff.qtpl:130 | //line views/stuff.qtpl:145 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| </div> | </div> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| func WriteHelpHTML(qq422016 qtio422016.Writer, content string) { | func WriteHelpHTML(qq422016 qtio422016.Writer, content string) { | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| 	qw422016 := qt422016.AcquireWriter(qq422016) | 	qw422016 := qt422016.AcquireWriter(qq422016) | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| 	StreamHelpHTML(qw422016, content) | 	StreamHelpHTML(qw422016, content) | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| 	qt422016.ReleaseWriter(qw422016) | 	qt422016.ReleaseWriter(qw422016) | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| func HelpHTML(content string) string { | func HelpHTML(content string) string { | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| 	qb422016 := qt422016.AcquireByteBuffer() | 	qb422016 := qt422016.AcquireByteBuffer() | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| 	WriteHelpHTML(qb422016, content) | 	WriteHelpHTML(qb422016, content) | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| 	qs422016 := string(qb422016.B) | 	qs422016 := string(qb422016.B) | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| 	qt422016.ReleaseByteBuffer(qb422016) | 	qt422016.ReleaseByteBuffer(qb422016) | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| 	return qs422016 | 	return qs422016 | ||||||
| //line views/stuff.qtpl:132 | //line views/stuff.qtpl:147 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:134 | //line views/stuff.qtpl:149 | ||||||
| func StreamHelpEmptyErrorHTML(qw422016 *qt422016.Writer) { | func StreamHelpEmptyErrorHTML(qw422016 *qt422016.Writer) { | ||||||
| //line views/stuff.qtpl:134 | //line views/stuff.qtpl:149 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| <h1>This entry does not exist!</h1> | <h1>This entry does not exist!</h1> | ||||||
| <p>Try finding a different entry that would help you.</p> | <p>Try finding a different entry that would help you.</p> | ||||||
| <p>If you want to write this entry by yourself, consider <a class="wikilink wikilink_external wikilink_https" href="https://github.com/bouncepaw/mycorrhiza">contributing</a> to Mycorrhiza Wiki directly.</p> | <p>If you want to write this entry by yourself, consider <a class="wikilink wikilink_external wikilink_https" href="https://github.com/bouncepaw/mycorrhiza">contributing</a> to Mycorrhiza Wiki directly.</p> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| func WriteHelpEmptyErrorHTML(qq422016 qtio422016.Writer) { | func WriteHelpEmptyErrorHTML(qq422016 qtio422016.Writer) { | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| 	qw422016 := qt422016.AcquireWriter(qq422016) | 	qw422016 := qt422016.AcquireWriter(qq422016) | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| 	StreamHelpEmptyErrorHTML(qw422016) | 	StreamHelpEmptyErrorHTML(qw422016) | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| 	qt422016.ReleaseWriter(qw422016) | 	qt422016.ReleaseWriter(qw422016) | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| func HelpEmptyErrorHTML() string { | func HelpEmptyErrorHTML() string { | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| 	qb422016 := qt422016.AcquireByteBuffer() | 	qb422016 := qt422016.AcquireByteBuffer() | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| 	WriteHelpEmptyErrorHTML(qb422016) | 	WriteHelpEmptyErrorHTML(qb422016) | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| 	qs422016 := string(qb422016.B) | 	qs422016 := string(qb422016.B) | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| 	qt422016.ReleaseByteBuffer(qb422016) | 	qt422016.ReleaseByteBuffer(qb422016) | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| 	return qs422016 | 	return qs422016 | ||||||
| //line views/stuff.qtpl:138 | //line views/stuff.qtpl:153 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:140 | //line views/stuff.qtpl:155 | ||||||
| func streamhelpTopicsHTML(qw422016 *qt422016.Writer) { | func streamhelpTopicsHTML(qw422016 *qt422016.Writer) { | ||||||
| //line views/stuff.qtpl:140 | //line views/stuff.qtpl:155 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| <aside class="help-topics layout-card"> | <aside class="help-topics layout-card"> | ||||||
| 	<h2 class="layout-card__title">Help topics</h2> | 	<h2 class="layout-card__title">Help topics</h2> | ||||||
| @@ -520,87 +586,87 @@ func streamhelpTopicsHTML(qw422016 *qt422016.Writer) { | |||||||
| 	</ul> | 	</ul> | ||||||
| </aside> | </aside> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| func writehelpTopicsHTML(qq422016 qtio422016.Writer) { | func writehelpTopicsHTML(qq422016 qtio422016.Writer) { | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| 	qw422016 := qt422016.AcquireWriter(qq422016) | 	qw422016 := qt422016.AcquireWriter(qq422016) | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| 	streamhelpTopicsHTML(qw422016) | 	streamhelpTopicsHTML(qw422016) | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| 	qt422016.ReleaseWriter(qw422016) | 	qt422016.ReleaseWriter(qw422016) | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| func helpTopicsHTML() string { | func helpTopicsHTML() string { | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| 	qb422016 := qt422016.AcquireByteBuffer() | 	qb422016 := qt422016.AcquireByteBuffer() | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| 	writehelpTopicsHTML(qb422016) | 	writehelpTopicsHTML(qb422016) | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| 	qs422016 := string(qb422016.B) | 	qs422016 := string(qb422016.B) | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| 	qt422016.ReleaseByteBuffer(qb422016) | 	qt422016.ReleaseByteBuffer(qb422016) | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| 	return qs422016 | 	return qs422016 | ||||||
| //line views/stuff.qtpl:173 | //line views/stuff.qtpl:188 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:175 | //line views/stuff.qtpl:190 | ||||||
| func streamhelpTopicBadgeHTML(qw422016 *qt422016.Writer, lang, topic string) { | func streamhelpTopicBadgeHTML(qw422016 *qt422016.Writer, lang, topic string) { | ||||||
| //line views/stuff.qtpl:175 | //line views/stuff.qtpl:190 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| <a class="help-topic-badge" href="/help/`) | <a class="help-topic-badge" href="/help/`) | ||||||
| //line views/stuff.qtpl:176 | //line views/stuff.qtpl:191 | ||||||
| 	qw422016.E().S(lang) | 	qw422016.E().S(lang) | ||||||
| //line views/stuff.qtpl:176 | //line views/stuff.qtpl:191 | ||||||
| 	qw422016.N().S(`/`) | 	qw422016.N().S(`/`) | ||||||
| //line views/stuff.qtpl:176 | //line views/stuff.qtpl:191 | ||||||
| 	qw422016.E().S(topic) | 	qw422016.E().S(topic) | ||||||
| //line views/stuff.qtpl:176 | //line views/stuff.qtpl:191 | ||||||
| 	qw422016.N().S(`">?</a> | 	qw422016.N().S(`">?</a> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| func writehelpTopicBadgeHTML(qq422016 qtio422016.Writer, lang, topic string) { | func writehelpTopicBadgeHTML(qq422016 qtio422016.Writer, lang, topic string) { | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| 	qw422016 := qt422016.AcquireWriter(qq422016) | 	qw422016 := qt422016.AcquireWriter(qq422016) | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| 	streamhelpTopicBadgeHTML(qw422016, lang, topic) | 	streamhelpTopicBadgeHTML(qw422016, lang, topic) | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| 	qt422016.ReleaseWriter(qw422016) | 	qt422016.ReleaseWriter(qw422016) | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| func helpTopicBadgeHTML(lang, topic string) string { | func helpTopicBadgeHTML(lang, topic string) string { | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| 	qb422016 := qt422016.AcquireByteBuffer() | 	qb422016 := qt422016.AcquireByteBuffer() | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| 	writehelpTopicBadgeHTML(qb422016, lang, topic) | 	writehelpTopicBadgeHTML(qb422016, lang, topic) | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| 	qs422016 := string(qb422016.B) | 	qs422016 := string(qb422016.B) | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| 	qt422016.ReleaseByteBuffer(qb422016) | 	qt422016.ReleaseByteBuffer(qb422016) | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| 	return qs422016 | 	return qs422016 | ||||||
| //line views/stuff.qtpl:177 | //line views/stuff.qtpl:192 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:179 | //line views/stuff.qtpl:194 | ||||||
| func StreamUserListHTML(qw422016 *qt422016.Writer) { | func StreamUserListHTML(qw422016 *qt422016.Writer) { | ||||||
| //line views/stuff.qtpl:179 | //line views/stuff.qtpl:194 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| <div class="layout"> | <div class="layout"> | ||||||
| <main class="main-width user-list"> | <main class="main-width user-list"> | ||||||
| 	<h1>List of users</h1> | 	<h1>List of users</h1> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:184 | //line views/stuff.qtpl:199 | ||||||
| 	var ( | 	var ( | ||||||
| 		admins     = make([]string, 0) | 		admins     = make([]string, 0) | ||||||
| 		moderators = make([]string, 0) | 		moderators = make([]string, 0) | ||||||
| @@ -617,345 +683,345 @@ func StreamUserListHTML(qw422016 *qt422016.Writer) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:199 | //line views/stuff.qtpl:214 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| 	<section> | 	<section> | ||||||
| 		<h2>Admins</h2> | 		<h2>Admins</h2> | ||||||
| 		<ol>`) | 		<ol>`) | ||||||
| //line views/stuff.qtpl:202 | //line views/stuff.qtpl:217 | ||||||
| 	for _, name := range admins { | 	for _, name := range admins { | ||||||
| //line views/stuff.qtpl:202 | //line views/stuff.qtpl:217 | ||||||
| 		qw422016.N().S(` | 		qw422016.N().S(` | ||||||
| 			<li><a href="/hypha/`) | 			<li><a href="/hypha/`) | ||||||
| //line views/stuff.qtpl:203 | //line views/stuff.qtpl:218 | ||||||
| 		qw422016.E().S(cfg.UserHypha) | 		qw422016.E().S(cfg.UserHypha) | ||||||
| //line views/stuff.qtpl:203 | //line views/stuff.qtpl:218 | ||||||
| 		qw422016.N().S(`/`) | 		qw422016.N().S(`/`) | ||||||
| //line views/stuff.qtpl:203 | //line views/stuff.qtpl:218 | ||||||
| 		qw422016.E().S(name) | 		qw422016.E().S(name) | ||||||
| //line views/stuff.qtpl:203 | //line views/stuff.qtpl:218 | ||||||
| 		qw422016.N().S(`">`) | 		qw422016.N().S(`">`) | ||||||
| //line views/stuff.qtpl:203 | //line views/stuff.qtpl:218 | ||||||
| 		qw422016.E().S(name) | 		qw422016.E().S(name) | ||||||
| //line views/stuff.qtpl:203 | //line views/stuff.qtpl:218 | ||||||
| 		qw422016.N().S(`</a></li> | 		qw422016.N().S(`</a></li> | ||||||
| 		`) | 		`) | ||||||
| //line views/stuff.qtpl:204 | //line views/stuff.qtpl:219 | ||||||
| 	} | 	} | ||||||
| //line views/stuff.qtpl:204 | //line views/stuff.qtpl:219 | ||||||
| 	qw422016.N().S(`</ol> | 	qw422016.N().S(`</ol> | ||||||
| 	</section> | 	</section> | ||||||
| 	<section> | 	<section> | ||||||
| 		<h2>Moderators</h2> | 		<h2>Moderators</h2> | ||||||
| 		<ol>`) | 		<ol>`) | ||||||
| //line views/stuff.qtpl:208 | //line views/stuff.qtpl:223 | ||||||
| 	for _, name := range moderators { | 	for _, name := range moderators { | ||||||
| //line views/stuff.qtpl:208 | //line views/stuff.qtpl:223 | ||||||
| 		qw422016.N().S(` | 		qw422016.N().S(` | ||||||
| 			<li><a href="/hypha/`) | 			<li><a href="/hypha/`) | ||||||
| //line views/stuff.qtpl:209 | //line views/stuff.qtpl:224 | ||||||
| 		qw422016.E().S(cfg.UserHypha) | 		qw422016.E().S(cfg.UserHypha) | ||||||
| //line views/stuff.qtpl:209 | //line views/stuff.qtpl:224 | ||||||
| 		qw422016.N().S(`/`) | 		qw422016.N().S(`/`) | ||||||
| //line views/stuff.qtpl:209 | //line views/stuff.qtpl:224 | ||||||
| 		qw422016.E().S(name) | 		qw422016.E().S(name) | ||||||
| //line views/stuff.qtpl:209 | //line views/stuff.qtpl:224 | ||||||
| 		qw422016.N().S(`">`) | 		qw422016.N().S(`">`) | ||||||
| //line views/stuff.qtpl:209 | //line views/stuff.qtpl:224 | ||||||
| 		qw422016.E().S(name) | 		qw422016.E().S(name) | ||||||
| //line views/stuff.qtpl:209 | //line views/stuff.qtpl:224 | ||||||
| 		qw422016.N().S(`</a></li> | 		qw422016.N().S(`</a></li> | ||||||
| 		`) | 		`) | ||||||
| //line views/stuff.qtpl:210 | //line views/stuff.qtpl:225 | ||||||
| 	} | 	} | ||||||
| //line views/stuff.qtpl:210 | //line views/stuff.qtpl:225 | ||||||
| 	qw422016.N().S(`</ol> | 	qw422016.N().S(`</ol> | ||||||
| 	</section> | 	</section> | ||||||
| 	<section> | 	<section> | ||||||
| 		<h2>Editors</h2> | 		<h2>Editors</h2> | ||||||
| 		<ol>`) | 		<ol>`) | ||||||
| //line views/stuff.qtpl:214 | //line views/stuff.qtpl:229 | ||||||
| 	for _, name := range editors { | 	for _, name := range editors { | ||||||
| //line views/stuff.qtpl:214 | //line views/stuff.qtpl:229 | ||||||
| 		qw422016.N().S(` | 		qw422016.N().S(` | ||||||
| 			<li><a href="/hypha/`) | 			<li><a href="/hypha/`) | ||||||
| //line views/stuff.qtpl:215 | //line views/stuff.qtpl:230 | ||||||
| 		qw422016.E().S(cfg.UserHypha) | 		qw422016.E().S(cfg.UserHypha) | ||||||
| //line views/stuff.qtpl:215 | //line views/stuff.qtpl:230 | ||||||
| 		qw422016.N().S(`/`) | 		qw422016.N().S(`/`) | ||||||
| //line views/stuff.qtpl:215 | //line views/stuff.qtpl:230 | ||||||
| 		qw422016.E().S(name) | 		qw422016.E().S(name) | ||||||
| //line views/stuff.qtpl:215 | //line views/stuff.qtpl:230 | ||||||
| 		qw422016.N().S(`">`) | 		qw422016.N().S(`">`) | ||||||
| //line views/stuff.qtpl:215 | //line views/stuff.qtpl:230 | ||||||
| 		qw422016.E().S(name) | 		qw422016.E().S(name) | ||||||
| //line views/stuff.qtpl:215 | //line views/stuff.qtpl:230 | ||||||
| 		qw422016.N().S(`</a></li> | 		qw422016.N().S(`</a></li> | ||||||
| 		`) | 		`) | ||||||
| //line views/stuff.qtpl:216 | //line views/stuff.qtpl:231 | ||||||
| 	} | 	} | ||||||
| //line views/stuff.qtpl:216 | //line views/stuff.qtpl:231 | ||||||
| 	qw422016.N().S(`</ol> | 	qw422016.N().S(`</ol> | ||||||
| 	</section> | 	</section> | ||||||
| </main> | </main> | ||||||
| </div> | </div> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| func WriteUserListHTML(qq422016 qtio422016.Writer) { | func WriteUserListHTML(qq422016 qtio422016.Writer) { | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| 	qw422016 := qt422016.AcquireWriter(qq422016) | 	qw422016 := qt422016.AcquireWriter(qq422016) | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| 	StreamUserListHTML(qw422016) | 	StreamUserListHTML(qw422016) | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| 	qt422016.ReleaseWriter(qw422016) | 	qt422016.ReleaseWriter(qw422016) | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| func UserListHTML() string { | func UserListHTML() string { | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| 	qb422016 := qt422016.AcquireByteBuffer() | 	qb422016 := qt422016.AcquireByteBuffer() | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| 	WriteUserListHTML(qb422016) | 	WriteUserListHTML(qb422016) | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| 	qs422016 := string(qb422016.B) | 	qs422016 := string(qb422016.B) | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| 	qt422016.ReleaseByteBuffer(qb422016) | 	qt422016.ReleaseByteBuffer(qb422016) | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| 	return qs422016 | 	return qs422016 | ||||||
| //line views/stuff.qtpl:220 | //line views/stuff.qtpl:235 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:222 | //line views/stuff.qtpl:237 | ||||||
| func StreamHyphaListHTML(qw422016 *qt422016.Writer) { | func StreamHyphaListHTML(qw422016 *qt422016.Writer) { | ||||||
| //line views/stuff.qtpl:222 | //line views/stuff.qtpl:237 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| <div class="layout"> | <div class="layout"> | ||||||
| <main class="main-width"> | <main class="main-width"> | ||||||
| 	<h1>List of hyphae</h1> | 	<h1>List of hyphae</h1> | ||||||
| 	<p>This wiki has `) | 	<p>This wiki has `) | ||||||
| //line views/stuff.qtpl:226 | //line views/stuff.qtpl:241 | ||||||
| 	qw422016.N().D(hyphae.Count()) | 	qw422016.N().D(hyphae.Count()) | ||||||
| //line views/stuff.qtpl:226 | //line views/stuff.qtpl:241 | ||||||
| 	qw422016.N().S(` hyphae.</p> | 	qw422016.N().S(` hyphae.</p> | ||||||
| 	<ul class="hypha-list"> | 	<ul class="hypha-list"> | ||||||
| 		`) | 		`) | ||||||
| //line views/stuff.qtpl:228 | //line views/stuff.qtpl:243 | ||||||
| 	for h := range hyphae.YieldExistingHyphae() { | 	for h := range hyphae.YieldExistingHyphae() { | ||||||
| //line views/stuff.qtpl:228 | //line views/stuff.qtpl:243 | ||||||
| 		qw422016.N().S(` | 		qw422016.N().S(` | ||||||
| 		<li class="hypha-list__entry"> | 		<li class="hypha-list__entry"> | ||||||
| 			<a class="hypha-list__link" href="/hypha/`) | 			<a class="hypha-list__link" href="/hypha/`) | ||||||
| //line views/stuff.qtpl:230 | //line views/stuff.qtpl:245 | ||||||
| 		qw422016.E().S(h.Name) | 		qw422016.E().S(h.Name) | ||||||
| //line views/stuff.qtpl:230 | //line views/stuff.qtpl:245 | ||||||
| 		qw422016.N().S(`">`) | 		qw422016.N().S(`">`) | ||||||
| //line views/stuff.qtpl:230 | //line views/stuff.qtpl:245 | ||||||
| 		qw422016.E().S(util.BeautifulName(h.Name)) | 		qw422016.E().S(util.BeautifulName(h.Name)) | ||||||
| //line views/stuff.qtpl:230 | //line views/stuff.qtpl:245 | ||||||
| 		qw422016.N().S(`</a> | 		qw422016.N().S(`</a> | ||||||
| 			`) | 			`) | ||||||
| //line views/stuff.qtpl:231 | //line views/stuff.qtpl:246 | ||||||
| 		if h.BinaryPath != "" { | 		if h.BinaryPath != "" { | ||||||
| //line views/stuff.qtpl:231 | //line views/stuff.qtpl:246 | ||||||
| 			qw422016.N().S(` | 			qw422016.N().S(` | ||||||
| 			<span class="hypha-list__amnt-type">`) | 			<span class="hypha-list__amnt-type">`) | ||||||
| //line views/stuff.qtpl:232 | //line views/stuff.qtpl:247 | ||||||
| 			qw422016.E().S(filepath.Ext(h.BinaryPath)[1:]) | 			qw422016.E().S(filepath.Ext(h.BinaryPath)[1:]) | ||||||
| //line views/stuff.qtpl:232 | //line views/stuff.qtpl:247 | ||||||
| 			qw422016.N().S(`</span> | 			qw422016.N().S(`</span> | ||||||
| 			`) | 			`) | ||||||
| //line views/stuff.qtpl:233 | //line views/stuff.qtpl:248 | ||||||
| 		} | 		} | ||||||
| //line views/stuff.qtpl:233 | //line views/stuff.qtpl:248 | ||||||
| 		qw422016.N().S(` | 		qw422016.N().S(` | ||||||
| 		</li> | 		</li> | ||||||
| 		`) | 		`) | ||||||
| //line views/stuff.qtpl:235 | //line views/stuff.qtpl:250 | ||||||
| 	} | 	} | ||||||
| //line views/stuff.qtpl:235 | //line views/stuff.qtpl:250 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| 	</ul> | 	</ul> | ||||||
| </main> | </main> | ||||||
| </div> | </div> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| func WriteHyphaListHTML(qq422016 qtio422016.Writer) { | func WriteHyphaListHTML(qq422016 qtio422016.Writer) { | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| 	qw422016 := qt422016.AcquireWriter(qq422016) | 	qw422016 := qt422016.AcquireWriter(qq422016) | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| 	StreamHyphaListHTML(qw422016) | 	StreamHyphaListHTML(qw422016) | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| 	qt422016.ReleaseWriter(qw422016) | 	qt422016.ReleaseWriter(qw422016) | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| func HyphaListHTML() string { | func HyphaListHTML() string { | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| 	qb422016 := qt422016.AcquireByteBuffer() | 	qb422016 := qt422016.AcquireByteBuffer() | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| 	WriteHyphaListHTML(qb422016) | 	WriteHyphaListHTML(qb422016) | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| 	qs422016 := string(qb422016.B) | 	qs422016 := string(qb422016.B) | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| 	qt422016.ReleaseByteBuffer(qb422016) | 	qt422016.ReleaseByteBuffer(qb422016) | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| 	return qs422016 | 	return qs422016 | ||||||
| //line views/stuff.qtpl:239 | //line views/stuff.qtpl:254 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:241 | //line views/stuff.qtpl:256 | ||||||
| func StreamAboutHTML(qw422016 *qt422016.Writer) { | func StreamAboutHTML(qw422016 *qt422016.Writer) { | ||||||
| //line views/stuff.qtpl:241 | //line views/stuff.qtpl:256 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| <div class="layout"> | <div class="layout"> | ||||||
| <main class="main-width"> | <main class="main-width"> | ||||||
| 	<section> | 	<section> | ||||||
| 		<h1>About `) | 		<h1>About `) | ||||||
| //line views/stuff.qtpl:245 | //line views/stuff.qtpl:260 | ||||||
| 	qw422016.E().S(cfg.WikiName) | 	qw422016.E().S(cfg.WikiName) | ||||||
| //line views/stuff.qtpl:245 | //line views/stuff.qtpl:260 | ||||||
| 	qw422016.N().S(`</h1> | 	qw422016.N().S(`</h1> | ||||||
| 		<ul> | 		<ul> | ||||||
| 			<li><b><a href="https://mycorrhiza.wiki">Mycorrhiza Wiki</a> version:</b> 1.5.0</li> | 			<li><b><a href="https://mycorrhiza.wiki">Mycorrhiza Wiki</a> version:</b> 1.5.0</li> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:248 | //line views/stuff.qtpl:263 | ||||||
| 	if cfg.UseAuth { | 	if cfg.UseAuth { | ||||||
| //line views/stuff.qtpl:248 | //line views/stuff.qtpl:263 | ||||||
| 		qw422016.N().S(`			<li><b>User count:</b> `) | 		qw422016.N().S(`			<li><b>User count:</b> `) | ||||||
| //line views/stuff.qtpl:249 | //line views/stuff.qtpl:264 | ||||||
| 		qw422016.N().DUL(user.Count()) | 		qw422016.N().DUL(user.Count()) | ||||||
| //line views/stuff.qtpl:249 | //line views/stuff.qtpl:264 | ||||||
| 		qw422016.N().S(`</li> | 		qw422016.N().S(`</li> | ||||||
| 			<li><b>Home page:</b> <a href="/">`) | 			<li><b>Home page:</b> <a href="/">`) | ||||||
| //line views/stuff.qtpl:250 | //line views/stuff.qtpl:265 | ||||||
| 		qw422016.E().S(cfg.HomeHypha) | 		qw422016.E().S(cfg.HomeHypha) | ||||||
| //line views/stuff.qtpl:250 | //line views/stuff.qtpl:265 | ||||||
| 		qw422016.N().S(`</a></li> | 		qw422016.N().S(`</a></li> | ||||||
| 			<li><b>Administrators:</b>`) | 			<li><b>Administrators:</b>`) | ||||||
| //line views/stuff.qtpl:251 | //line views/stuff.qtpl:266 | ||||||
| 		for i, username := range user.ListUsersWithGroup("admin") { | 		for i, username := range user.ListUsersWithGroup("admin") { | ||||||
| //line views/stuff.qtpl:252 | //line views/stuff.qtpl:267 | ||||||
| 			if i > 0 { | 			if i > 0 { | ||||||
| //line views/stuff.qtpl:252 | //line views/stuff.qtpl:267 | ||||||
| 				qw422016.N().S(`<span aria-hidden="true">, </span> | 				qw422016.N().S(`<span aria-hidden="true">, </span> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:253 | //line views/stuff.qtpl:268 | ||||||
| 			} | 			} | ||||||
| //line views/stuff.qtpl:253 | //line views/stuff.qtpl:268 | ||||||
| 			qw422016.N().S(`				<a href="/hypha/`) | 			qw422016.N().S(`				<a href="/hypha/`) | ||||||
| //line views/stuff.qtpl:254 | //line views/stuff.qtpl:269 | ||||||
| 			qw422016.E().S(cfg.UserHypha) | 			qw422016.E().S(cfg.UserHypha) | ||||||
| //line views/stuff.qtpl:254 | //line views/stuff.qtpl:269 | ||||||
| 			qw422016.N().S(`/`) | 			qw422016.N().S(`/`) | ||||||
| //line views/stuff.qtpl:254 | //line views/stuff.qtpl:269 | ||||||
| 			qw422016.E().S(username) | 			qw422016.E().S(username) | ||||||
| //line views/stuff.qtpl:254 | //line views/stuff.qtpl:269 | ||||||
| 			qw422016.N().S(`">`) | 			qw422016.N().S(`">`) | ||||||
| //line views/stuff.qtpl:254 | //line views/stuff.qtpl:269 | ||||||
| 			qw422016.E().S(username) | 			qw422016.E().S(username) | ||||||
| //line views/stuff.qtpl:254 | //line views/stuff.qtpl:269 | ||||||
| 			qw422016.N().S(`</a>`) | 			qw422016.N().S(`</a>`) | ||||||
| //line views/stuff.qtpl:254 | //line views/stuff.qtpl:269 | ||||||
| 		} | 		} | ||||||
| //line views/stuff.qtpl:254 | //line views/stuff.qtpl:269 | ||||||
| 		qw422016.N().S(`</li> | 		qw422016.N().S(`</li> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:255 | //line views/stuff.qtpl:270 | ||||||
| 	} else { | 	} else { | ||||||
| //line views/stuff.qtpl:255 | //line views/stuff.qtpl:270 | ||||||
| 		qw422016.N().S(`			<li>This wiki does not use authorization</li> | 		qw422016.N().S(`			<li>This wiki does not use authorization</li> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:257 | //line views/stuff.qtpl:272 | ||||||
| 	} | 	} | ||||||
| //line views/stuff.qtpl:257 | //line views/stuff.qtpl:272 | ||||||
| 	qw422016.N().S(`		</ul> | 	qw422016.N().S(`		</ul> | ||||||
| 		<p>See <a href="/list">/list</a> for information about hyphae on this wiki.</p> | 		<p>See <a href="/list">/list</a> for information about hyphae on this wiki.</p> | ||||||
| 	</section> | 	</section> | ||||||
| </main> | </main> | ||||||
| </div> | </div> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| func WriteAboutHTML(qq422016 qtio422016.Writer) { | func WriteAboutHTML(qq422016 qtio422016.Writer) { | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| 	qw422016 := qt422016.AcquireWriter(qq422016) | 	qw422016 := qt422016.AcquireWriter(qq422016) | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| 	StreamAboutHTML(qw422016) | 	StreamAboutHTML(qw422016) | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| 	qt422016.ReleaseWriter(qw422016) | 	qt422016.ReleaseWriter(qw422016) | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| func AboutHTML() string { | func AboutHTML() string { | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| 	qb422016 := qt422016.AcquireByteBuffer() | 	qb422016 := qt422016.AcquireByteBuffer() | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| 	WriteAboutHTML(qb422016) | 	WriteAboutHTML(qb422016) | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| 	qs422016 := string(qb422016.B) | 	qs422016 := string(qb422016.B) | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| 	qt422016.ReleaseByteBuffer(qb422016) | 	qt422016.ReleaseByteBuffer(qb422016) | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| 	return qs422016 | 	return qs422016 | ||||||
| //line views/stuff.qtpl:263 | //line views/stuff.qtpl:278 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:265 | //line views/stuff.qtpl:280 | ||||||
| func StreamCommonScripts(qw422016 *qt422016.Writer) { | func StreamCommonScripts(qw422016 *qt422016.Writer) { | ||||||
| //line views/stuff.qtpl:265 | //line views/stuff.qtpl:280 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:266 | //line views/stuff.qtpl:281 | ||||||
| 	for _, scriptPath := range cfg.CommonScripts { | 	for _, scriptPath := range cfg.CommonScripts { | ||||||
| //line views/stuff.qtpl:266 | //line views/stuff.qtpl:281 | ||||||
| 		qw422016.N().S(` | 		qw422016.N().S(` | ||||||
| <script src="`) | <script src="`) | ||||||
| //line views/stuff.qtpl:267 | //line views/stuff.qtpl:282 | ||||||
| 		qw422016.E().S(scriptPath) | 		qw422016.E().S(scriptPath) | ||||||
| //line views/stuff.qtpl:267 | //line views/stuff.qtpl:282 | ||||||
| 		qw422016.N().S(`"></script> | 		qw422016.N().S(`"></script> | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:268 | //line views/stuff.qtpl:283 | ||||||
| 	} | 	} | ||||||
| //line views/stuff.qtpl:268 | //line views/stuff.qtpl:283 | ||||||
| 	qw422016.N().S(` | 	qw422016.N().S(` | ||||||
| `) | `) | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| func WriteCommonScripts(qq422016 qtio422016.Writer) { | func WriteCommonScripts(qq422016 qtio422016.Writer) { | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| 	qw422016 := qt422016.AcquireWriter(qq422016) | 	qw422016 := qt422016.AcquireWriter(qq422016) | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| 	StreamCommonScripts(qw422016) | 	StreamCommonScripts(qw422016) | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| 	qt422016.ReleaseWriter(qw422016) | 	qt422016.ReleaseWriter(qw422016) | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| } | } | ||||||
|  |  | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| func CommonScripts() string { | func CommonScripts() string { | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| 	qb422016 := qt422016.AcquireByteBuffer() | 	qb422016 := qt422016.AcquireByteBuffer() | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| 	WriteCommonScripts(qb422016) | 	WriteCommonScripts(qb422016) | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| 	qs422016 := string(qb422016.B) | 	qs422016 := string(qb422016.B) | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| 	qt422016.ReleaseByteBuffer(qb422016) | 	qt422016.ReleaseByteBuffer(qb422016) | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| 	return qs422016 | 	return qs422016 | ||||||
| //line views/stuff.qtpl:269 | //line views/stuff.qtpl:284 | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								web/backlinks.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								web/backlinks.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | package web | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"net/http" | ||||||
|  |  | ||||||
|  | 	"github.com/gorilla/mux" | ||||||
|  |  | ||||||
|  | 	"github.com/bouncepaw/mycorrhiza/hyphae" | ||||||
|  | 	"github.com/bouncepaw/mycorrhiza/user" | ||||||
|  | 	"github.com/bouncepaw/mycorrhiza/util" | ||||||
|  | 	"github.com/bouncepaw/mycorrhiza/views" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func initBacklinks(r *mux.Router) { | ||||||
|  | 	r.PathPrefix("/backlinks/").HandlerFunc(handlerBacklinks) | ||||||
|  | 	r.PathPrefix("/backlinks-json/").HandlerFunc(handlerBacklinksJSON) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // handlerBacklinks lists all backlinks to a hypha. | ||||||
|  | func handlerBacklinks(w http.ResponseWriter, rq *http.Request) { | ||||||
|  | 	hyphaName := util.HyphaNameFromRq(rq, "backlinks") | ||||||
|  | 	util.HTTP200Page(w, views.BaseHTML( | ||||||
|  | 		fmt.Sprintf("Backlinks to %s", util.BeautifulName(hyphaName)), | ||||||
|  | 		views.BacklinksHTML(hyphaName, hyphae.YieldHyphaBacklinks), | ||||||
|  | 		user.FromRequest(rq))) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func handlerBacklinksJSON(w http.ResponseWriter, rq *http.Request) { | ||||||
|  | 	hyphaName := util.HyphaNameFromRq(rq, "backlinks") | ||||||
|  | 	w.WriteHeader(http.StatusOK) | ||||||
|  | 	_, _ = io.WriteString( | ||||||
|  | 		w, | ||||||
|  | 		views.TitleSearchJSON(hyphaName, hyphae.YieldHyphaBacklinks), | ||||||
|  | 	) | ||||||
|  | } | ||||||
| @@ -103,6 +103,7 @@ func Handler() http.Handler { | |||||||
| 	initHistory(wikiRouter) | 	initHistory(wikiRouter) | ||||||
| 	initStuff(wikiRouter) | 	initStuff(wikiRouter) | ||||||
| 	initSearch(wikiRouter) | 	initSearch(wikiRouter) | ||||||
|  | 	initBacklinks(wikiRouter) | ||||||
|  |  | ||||||
| 	// Admin routes. | 	// Admin routes. | ||||||
| 	if cfg.UseAuth { | 	if cfg.UseAuth { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user