1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-01-05 17:40:26 +00:00

Backlinks: Make less things exported, better wording

This commit is contained in:
Timur Ismagilov 2021-12-31 00:59:28 +05:00
parent 1f36af66a5
commit b453d71364
7 changed files with 452 additions and 448 deletions

View File

@ -2,16 +2,64 @@
package backlinks
import (
"github.com/bouncepaw/mycorrhiza/hyphae"
"github.com/bouncepaw/mycorrhiza/util"
"os"
"github.com/bouncepaw/mycomarkup/v3"
"github.com/bouncepaw/mycomarkup/v3/links"
"github.com/bouncepaw/mycomarkup/v3/mycocontext"
"github.com/bouncepaw/mycomarkup/v3/tools"
"github.com/bouncepaw/mycorrhiza/hyphae"
"github.com/bouncepaw/mycorrhiza/util"
)
// YieldHyphaBacklinks gets backlinks for the desired hypha, sorts and yields them one by one.
func YieldHyphaBacklinks(hyphaName string) <-chan string {
hyphaName = util.CanonicalName(hyphaName)
out := make(chan string)
sorted := hyphae.PathographicSort(out)
go func() {
backlinks, exists := backlinkIndex[hyphaName]
if exists {
for link := range backlinks {
out <- link
}
}
close(out)
}()
return sorted
}
var backlinkConveyor = make(chan backlinkIndexOperation) // No need to buffer because these operations are rare.
// RunBacklinksConveyor runs an index operation processing loop. Call it somewhere in main.
func RunBacklinksConveyor() {
// It is supposed to run as a goroutine for all the time. So, don't blame the infinite loop.
defer close(backlinkConveyor)
for {
(<-backlinkConveyor).apply()
}
}
var backlinkIndex = make(map[string]linkSet)
// IndexBacklinks traverses all text hyphae, extracts links from them and forms an initial index. Call it when indexing and reindexing hyphae.
func IndexBacklinks() {
// It is safe to ignore the mutex, because there is only one worker.
for h := range hyphae.FilterTextHyphae(hyphae.YieldExistingHyphae()) {
foundLinks := extractHyphaLinksFromContent(h.Name, fetchText(h))
for _, link := range foundLinks {
if _, exists := backlinkIndex[link]; !exists {
backlinkIndex[link] = make(linkSet)
}
backlinkIndex[link][h.Name] = struct{}{}
}
}
}
// BacklinksCount returns the amount of backlinks to the hypha.
func BacklinksCount(h *hyphae.Hypha) int {
if _, exists := backlinkIndex[h.Name]; exists {
return len(backlinkIndex[h.Name])
}
return 0
}
// Using set here seems like the most appropriate solution
type linkSet map[string]struct{}
@ -41,18 +89,18 @@ type backlinkIndexOperation interface {
// backlinkIndexEdit contains data for backlink index update after a hypha edit
type backlinkIndexEdit struct {
Name string
OldLinks []string
NewLinks []string
name string
oldLinks []string
newLinks []string
}
// Apply changes backlink index respective to the operation data
// apply changes backlink index respective to the operation data
func (op backlinkIndexEdit) apply() {
oldLinks := toLinkSet(op.OldLinks)
newLinks := toLinkSet(op.NewLinks)
oldLinks := toLinkSet(op.oldLinks)
newLinks := toLinkSet(op.newLinks)
for link := range oldLinks {
if _, exists := newLinks[link]; !exists {
delete(backlinkIndex[link], op.Name)
delete(backlinkIndex[link], op.name)
}
}
for link := range newLinks {
@ -60,134 +108,39 @@ func (op backlinkIndexEdit) apply() {
if _, exists := backlinkIndex[link]; !exists {
backlinkIndex[link] = make(linkSet)
}
backlinkIndex[link][op.Name] = struct{}{}
backlinkIndex[link][op.name] = struct{}{}
}
}
}
// backlinkIndexDeletion contains data for backlink index update after a hypha deletion
type backlinkIndexDeletion struct {
Name string
Links []string
name string
links []string
}
// apply changes backlink index respective to the operation data
func (op backlinkIndexDeletion) apply() {
for _, link := range op.Links {
for _, link := range op.links {
if lSet, exists := backlinkIndex[link]; exists {
delete(lSet, op.Name)
delete(lSet, op.name)
}
}
}
// backlinkIndexRenaming contains data for backlink index update after a hypha renaming
type backlinkIndexRenaming struct {
OldName string
NewName string
Links []string
oldName string
newName string
links []string
}
// Apply changes backlink index respective to the operation data
func (op backlinkIndexRenaming) apply() {
for _, link := range op.Links {
for _, link := range op.links {
if lSet, exists := backlinkIndex[link]; exists {
delete(lSet, op.OldName)
backlinkIndex[link][op.NewName] = struct{}{}
delete(lSet, op.oldName)
backlinkIndex[link][op.newName] = struct{}{}
}
}
}
var backlinkIndex = make(map[string]linkSet)
var backlinkConveyor = make(chan backlinkIndexOperation, 64)
// I hope, the buffer size is enough -- chekoopa
// Do we really need the buffer though? Dunno -- bouncepaw
// 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 := hyphae.FilterTextHyphae(hyphae.YieldExistingHyphae())
for h := range src {
foundLinks := extractHyphaLinksFromContent(h.Name, fetchText(h))
for _, link := range foundLinks {
if _, exists := backlinkIndex[link]; !exists {
backlinkIndex[link] = make(linkSet)
}
backlinkIndex[link][h.Name] = struct{}{}
}
}
}
// RunBacklinksConveyor runs an index operation processing loop
func RunBacklinksConveyor() {
// It is supposed to run as a goroutine for all the time. So, don't blame the infinite loop.
defer close(backlinkConveyor)
for {
(<-backlinkConveyor).apply()
}
}
// BacklinksCount returns the amount of backlinks to the hypha.
func BacklinksCount(h *hyphae.Hypha) int {
if _, exists := backlinkIndex[h.Name]; exists {
return len(backlinkIndex[h.Name])
}
return 0
}
// BacklinksOnEdit is a creation/editing hook for backlinks index
func BacklinksOnEdit(h *hyphae.Hypha, oldText string) {
oldLinks := extractHyphaLinksFromContent(h.Name, oldText)
newLinks := extractHyphaLinks(h)
backlinkConveyor <- backlinkIndexEdit{h.Name, oldLinks, newLinks}
}
// BacklinksOnDelete is a deletion hook for backlinks index
func BacklinksOnDelete(h *hyphae.Hypha, oldText string) {
oldLinks := extractHyphaLinksFromContent(h.Name, oldText)
backlinkConveyor <- backlinkIndexDeletion{h.Name, oldLinks}
}
// BacklinksOnRename is a renaming hook for backlinks index
func BacklinksOnRename(h *hyphae.Hypha, oldName string) {
actualLinks := extractHyphaLinks(h)
backlinkConveyor <- backlinkIndexRenaming{oldName, h.Name, actualLinks}
}
// YieldHyphaBacklinks gets backlinks for a desired hypha, sorts and iterates over them
func YieldHyphaBacklinks(query string) <-chan string {
hyphaName := util.CanonicalName(query)
out := make(chan string)
sorted := hyphae.PathographicSort(out)
go func() {
backlinks, exists := backlinkIndex[hyphaName]
if exists {
for link := range backlinks {
out <- link
}
}
close(out)
}()
return sorted
}
// extractHyphaLinks extracts hypha links from a desired hypha
func extractHyphaLinks(h *hyphae.Hypha) []string {
return extractHyphaLinksFromContent(h.Name, fetchText(h))
}
// extractHyphaLinksFromContent extracts local hypha links from the provided text.
func extractHyphaLinksFromContent(hyphaName string, contents string) []string {
ctx, _ := mycocontext.ContextFromStringInput(hyphaName, contents)
linkVisitor, getLinks := tools.LinkVisitor(ctx)
// Ignore the result of BlockTree because we call it for linkVisitor.
_ = 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
}

49
hyphae/backlinks/hooks.go Normal file
View File

@ -0,0 +1,49 @@
package backlinks
import (
"github.com/bouncepaw/mycomarkup/v3"
"github.com/bouncepaw/mycomarkup/v3/links"
"github.com/bouncepaw/mycomarkup/v3/mycocontext"
"github.com/bouncepaw/mycomarkup/v3/tools"
"github.com/bouncepaw/mycorrhiza/hyphae"
)
// UpdateBacklinksAfterEdit is a creation/editing hook for backlinks index
func UpdateBacklinksAfterEdit(h *hyphae.Hypha, oldText string) {
oldLinks := extractHyphaLinksFromContent(h.Name, oldText)
newLinks := extractHyphaLinks(h)
backlinkConveyor <- backlinkIndexEdit{h.Name, oldLinks, newLinks}
}
// UpdateBacklinksAfterDelete is a deletion hook for backlinks index
func UpdateBacklinksAfterDelete(h *hyphae.Hypha, oldText string) {
oldLinks := extractHyphaLinksFromContent(h.Name, oldText)
backlinkConveyor <- backlinkIndexDeletion{h.Name, oldLinks}
}
// UpdateBacklinksAfterRename is a renaming hook for backlinks index
func UpdateBacklinksAfterRename(h *hyphae.Hypha, oldName string) {
actualLinks := extractHyphaLinks(h)
backlinkConveyor <- backlinkIndexRenaming{oldName, h.Name, actualLinks}
}
// extractHyphaLinks extracts hypha links from a desired hypha
func extractHyphaLinks(h *hyphae.Hypha) []string {
return extractHyphaLinksFromContent(h.Name, fetchText(h))
}
// extractHyphaLinksFromContent extracts local hypha links from the provided text.
func extractHyphaLinksFromContent(hyphaName string, contents string) []string {
ctx, _ := mycocontext.ContextFromStringInput(hyphaName, contents)
linkVisitor, getLinks := tools.LinkVisitor(ctx)
// Ignore the result of BlockTree because we call it for linkVisitor.
_ = 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
}

View File

@ -26,7 +26,7 @@ func DeleteHypha(u *user.User, h *hyphae.Hypha, lc *l18n.Localizer) (hop *histor
WithUser(u).
Apply()
if !hop.HasErrors() {
backlinks.BacklinksOnDelete(h, originalText)
backlinks.UpdateBacklinksAfterDelete(h, originalText)
h.Delete()
}
return hop, ""

View File

@ -75,7 +75,7 @@ func RenameHypha(h *hyphae.Hypha, newHypha *hyphae.Hypha, recursive bool, u *use
h.TextPath = replaceName(h.TextPath)
h.BinaryPath = replaceName(h.BinaryPath)
h.Unlock()
backlinks.BacklinksOnRename(h, oldName)
backlinks.UpdateBacklinksAfterRename(h, oldName)
}
}
return hop, ""

View File

@ -106,7 +106,7 @@ func uploadHelp(h *hyphae.Hypha, hop *history.Op, ext string, data []byte, u *us
}
*originalFullPath = fullPath
if hop.Type == history.TypeEditText {
backlinks.BacklinksOnEdit(h, originalText)
backlinks.UpdateBacklinksAfterEdit(h, originalText)
}
return hop.WithFiles(fullPath).WithUser(u).Apply(), ""
}

View File

@ -122,17 +122,18 @@ It outputs a poorly formatted JSON, but it works and is valid.
}
{% endfunc %}
{% func BacklinksHTML(query string, generator func(string) <-chan string, lc *l18n.Localizer) %}
{% func BacklinksHTML(hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) %}
<div class="layout">
<main class="main-width backlinks">
<h1>{%s lc.Get("ui.backlinks_query", &l18n.Replacements{"query": query})%}</h1>
<h1>{%s lc.Get("ui.backlinks_query", &l18n.Replacements{"query": hyphaName})%}</h1>
<p>{%s lc.Get("ui.backlinks_desc")%}</p>
<ul class="backlinks__list">
{% for hyphaName := range generator(query) %}
{% for hyphaName := range generator(hyphaName) %}
<li class="backlinks__entry">
<a class="backlinks__link wikilink" href="/hypha/{%s hyphaName %}">{%s util.BeautifulName(hyphaName) %}</a>
</li>
{% endfor %}
</ul>
</main>
</div>
{% endfunc %}

File diff suppressed because it is too large Load Diff