mirror of
				https://github.com/osmarks/mycorrhiza.git
				synced 2025-11-04 09:33:01 +00:00 
			
		
		
		
	Store hyphae as Hypher and cast to *Hypha only wheen need
This commit is contained in:
		
				
					committed by
					
						
						Timur Ismagilov
					
				
			
			
				
	
			
			
			
						parent
						
							d0dbbe4714
						
					
				
				
					commit
					154069091e
				
			@@ -10,20 +10,20 @@ 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) {
 | 
				
			||||||
	byNames = make(map[string]*Hypha)
 | 
						byNames = make(map[string]Hypher)
 | 
				
			||||||
	ch := make(chan *Hypha, 5)
 | 
						ch := make(chan Hypher, 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go func(ch chan *Hypha) {
 | 
						go func(ch chan Hypher) {
 | 
				
			||||||
		indexHelper(path, 0, ch)
 | 
							indexHelper(path, 0, ch)
 | 
				
			||||||
		close(ch)
 | 
							close(ch)
 | 
				
			||||||
	}(ch)
 | 
						}(ch)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for h := range ch {
 | 
						for h := range ch {
 | 
				
			||||||
		// It's safe to ignore the mutex because there is a single worker right now.
 | 
							// It's safe to ignore the mutex because there is a single worker right now.
 | 
				
			||||||
		if oh := ByName(h.name); oh.Exists {
 | 
							if oh := ByName(h.CanonicalName()); oh.DoesExist() {
 | 
				
			||||||
			oh.mergeIn(h)
 | 
								oh.(*Hypha).mergeIn(h.(*Hypha))
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			insert(h)
 | 
								insert(h.(*Hypha))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	log.Println("Indexed", Count(), "hyphae")
 | 
						log.Println("Indexed", Count(), "hyphae")
 | 
				
			||||||
@@ -32,7 +32,7 @@ func Index(path string) {
 | 
				
			|||||||
// indexHelper finds all hypha files in the full `path` and sends them to the
 | 
					// indexHelper finds all hypha files in the full `path` and sends them to the
 | 
				
			||||||
// channel. Handling of duplicate entries and attachment and counting them is
 | 
					// channel. Handling of duplicate entries and attachment and counting them is
 | 
				
			||||||
// up to the caller.
 | 
					// up to the caller.
 | 
				
			||||||
func indexHelper(path string, nestLevel uint, ch chan *Hypha) {
 | 
					func indexHelper(path string, nestLevel uint, ch chan Hypher) {
 | 
				
			||||||
	nodes, err := os.ReadDir(path)
 | 
						nodes, err := os.ReadDir(path)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Fatal(err)
 | 
							log.Fatal(err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,7 +47,7 @@ func (h *Hypha) CanonicalName() string {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (h *Hypha) Kind() HyphaKind {
 | 
					func (h *Hypha) Kind() HyphaKind {
 | 
				
			||||||
	if !h.Exists {
 | 
						if !h.DoesExist() {
 | 
				
			||||||
		return HyphaEmpty
 | 
							return HyphaEmpty
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if h.HasAttachment() {
 | 
						if h.HasAttachment() {
 | 
				
			||||||
@@ -77,7 +77,7 @@ func (h *Hypha) HasAttachment() bool {
 | 
				
			|||||||
	return h.binaryPath != ""
 | 
						return h.binaryPath != ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var byNames = make(map[string]*Hypha)
 | 
					var byNames = make(map[string]Hypher)
 | 
				
			||||||
var byNamesMutex = sync.Mutex{}
 | 
					var byNamesMutex = sync.Mutex{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EmptyHypha returns an empty hypha struct with given name.
 | 
					// EmptyHypha returns an empty hypha struct with given name.
 | 
				
			||||||
@@ -91,7 +91,7 @@ func EmptyHypha(hyphaName string) *Hypha {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ByName returns a hypha by name. It may have been recorded to the storage.
 | 
					// 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 Hypher) {
 | 
				
			||||||
	h, recorded := byNames[hyphaName]
 | 
						h, recorded := byNames[hyphaName]
 | 
				
			||||||
	if recorded {
 | 
						if recorded {
 | 
				
			||||||
		return h
 | 
							return h
 | 
				
			||||||
@@ -99,21 +99,21 @@ func ByName(hyphaName string) (h *Hypha) {
 | 
				
			|||||||
	return EmptyHypha(hyphaName)
 | 
						return EmptyHypha(hyphaName)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func storeHypha(h *Hypha) {
 | 
					func storeHypha(h Hypher) {
 | 
				
			||||||
	byNamesMutex.Lock()
 | 
						byNamesMutex.Lock()
 | 
				
			||||||
	byNames[h.name] = h
 | 
						byNames[h.CanonicalName()] = h
 | 
				
			||||||
	byNamesMutex.Unlock()
 | 
						byNamesMutex.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	h.Lock()
 | 
						h.Lock()
 | 
				
			||||||
	h.Exists = true
 | 
						h.(*Hypha).Exists = true
 | 
				
			||||||
	h.Unlock()
 | 
						h.Unlock()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// insert inserts the hypha into the storage. A previous record is used if possible. Count incrementation is done if needed.
 | 
					// insert inserts the hypha into the storage. A previous record is used if possible. Count incrementation is done if needed.
 | 
				
			||||||
func insert(h *Hypha) (madeNewRecord bool) {
 | 
					func insert(h Hypher) (madeNewRecord bool) {
 | 
				
			||||||
	hp, recorded := byNames[h.name]
 | 
						hp, recorded := byNames[h.CanonicalName()]
 | 
				
			||||||
	if recorded {
 | 
						if recorded {
 | 
				
			||||||
		hp.mergeIn(h)
 | 
							hp.(*Hypha).mergeIn(h)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		storeHypha(h)
 | 
							storeHypha(h)
 | 
				
			||||||
		incrementCount()
 | 
							incrementCount()
 | 
				
			||||||
@@ -123,34 +123,23 @@ func insert(h *Hypha) (madeNewRecord bool) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// InsertIfNew checks whether hypha exists and returns `true` if it didn't and has been created.
 | 
					// InsertIfNew checks whether hypha exists and returns `true` if it didn't and has been created.
 | 
				
			||||||
func InsertIfNew(h *Hypha) (madeNewRecord bool) {
 | 
					func InsertIfNew(h Hypher) (madeNewRecord bool) {
 | 
				
			||||||
	if h.DoesExist() {
 | 
						if h.DoesExist() {
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return insert(h)
 | 
						return insert(h)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RenameTo renames a hypha and performs respective changes in the storage.
 | 
					 | 
				
			||||||
func (h *Hypha) RenameTo(newName string) {
 | 
					 | 
				
			||||||
	byNamesMutex.Lock()
 | 
					 | 
				
			||||||
	h.Lock()
 | 
					 | 
				
			||||||
	delete(byNames, h.CanonicalName())
 | 
					 | 
				
			||||||
	h.SetName(newName)
 | 
					 | 
				
			||||||
	byNames[h.CanonicalName()] = h
 | 
					 | 
				
			||||||
	byNamesMutex.Unlock()
 | 
					 | 
				
			||||||
	h.Unlock()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 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 Hypher) {
 | 
				
			||||||
	if h == oh {
 | 
						if h == oh {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	h.Lock()
 | 
						h.Lock()
 | 
				
			||||||
	if h.TextPath == "" && oh.TextPath != "" {
 | 
						if h.TextPath == "" && oh.HasTextPart() {
 | 
				
			||||||
		h.TextPath = oh.TextPath
 | 
							h.TextPath = oh.TextPartPath()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if oh.binaryPath != "" {
 | 
						if oh := oh.(*Hypha); oh.Kind() == HyphaMedia {
 | 
				
			||||||
		if h.binaryPath != "" {
 | 
							if h.binaryPath != "" {
 | 
				
			||||||
			log.Println("There is a file collision for attachment of a hypha:", h.binaryPath, "and", oh.binaryPath, "-- going on with the latter")
 | 
								log.Println("There is a file collision for attachment of a hypha:", h.binaryPath, "and", oh.binaryPath, "-- going on with the latter")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,3 +31,14 @@ func DeleteHypha(h Hypher) {
 | 
				
			|||||||
	byNamesMutex.Unlock()
 | 
						byNamesMutex.Unlock()
 | 
				
			||||||
	h.Unlock()
 | 
						h.Unlock()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RenameHyphaTo renames a hypha and performs respective changes in the storage.
 | 
				
			||||||
 | 
					func RenameHyphaTo(h Hypher, newName string) {
 | 
				
			||||||
 | 
						byNamesMutex.Lock()
 | 
				
			||||||
 | 
						h.Lock()
 | 
				
			||||||
 | 
						delete(byNames, h.CanonicalName())
 | 
				
			||||||
 | 
						h.(*Hypha).SetName(newName)
 | 
				
			||||||
 | 
						byNames[h.CanonicalName()] = h.(*Hypha)
 | 
				
			||||||
 | 
						byNamesMutex.Unlock()
 | 
				
			||||||
 | 
						h.Unlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ func YieldExistingHyphae() chan Hypher {
 | 
				
			|||||||
	ch := make(chan Hypher)
 | 
						ch := make(chan Hypher)
 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		for _, h := range byNames {
 | 
							for _, h := range byNames {
 | 
				
			||||||
			if h.Exists {
 | 
								if h.DoesExist() {
 | 
				
			||||||
				ch <- h
 | 
									ch <- h
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteHypha deletes hypha and makes a history record about that.
 | 
					// DeleteHypha deletes hypha and makes a history record about that.
 | 
				
			||||||
func DeleteHypha(u *user.User, h *hyphae.Hypha, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
 | 
					func DeleteHypha(u *user.User, h hyphae.Hypher, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
 | 
				
			||||||
	hop = history.Operation(history.TypeDeleteHypha)
 | 
						hop = history.Operation(history.TypeDeleteHypha)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if errtitle, err := CanDelete(u, h, lc); errtitle != "" {
 | 
						if errtitle, err := CanDelete(u, h, lc); errtitle != "" {
 | 
				
			||||||
@@ -21,7 +21,7 @@ func DeleteHypha(u *user.User, h *hyphae.Hypha, lc *l18n.Localizer) (hop *histor
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	originalText, _ := FetchTextPart(h)
 | 
						originalText, _ := FetchTextPart(h)
 | 
				
			||||||
	hop.
 | 
						hop.
 | 
				
			||||||
		WithFilesRemoved(h.TextPath, h.BinaryPath()).
 | 
							WithFilesRemoved(h.TextPartPath(), h.(*hyphae.Hypha).BinaryPath()).
 | 
				
			||||||
		WithMsg(fmt.Sprintf("Delete ‘%s’", h.CanonicalName())).
 | 
							WithMsg(fmt.Sprintf("Delete ‘%s’", h.CanonicalName())).
 | 
				
			||||||
		WithUser(u).
 | 
							WithUser(u).
 | 
				
			||||||
		Apply()
 | 
							Apply()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,12 +11,12 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	globals.HyphaExists = func(hyphaName string) bool {
 | 
						globals.HyphaExists = func(hyphaName string) bool {
 | 
				
			||||||
		return hyphae.ByName(hyphaName).Exists
 | 
							return hyphae.ByName(hyphaName).DoesExist()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	globals.HyphaAccess = func(hyphaName string) (rawText, binaryBlock string, err error) {
 | 
						globals.HyphaAccess = func(hyphaName string) (rawText, binaryBlock string, err error) {
 | 
				
			||||||
		if h := hyphae.ByName(hyphaName); h.Exists {
 | 
							if h := hyphae.ByName(hyphaName); h.DoesExist() {
 | 
				
			||||||
			rawText, err = FetchTextPart(h)
 | 
								rawText, err = FetchTextPart(h)
 | 
				
			||||||
			if h.BinaryPath() != "" {
 | 
								if h.(*hyphae.Hypha).BinaryPath() != "" {
 | 
				
			||||||
				// the view is localized, but we can't pass it, so...
 | 
									// the view is localized, but we can't pass it, so...
 | 
				
			||||||
				binaryBlock = views.AttachmentHTMLRaw(h)
 | 
									binaryBlock = views.AttachmentHTMLRaw(h)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,7 +71,7 @@ func RenameHypha(h hyphae.Hypher, newHypha hyphae.Hypher, recursive bool, u *use
 | 
				
			|||||||
		for _, h := range hyphaeToRename {
 | 
							for _, h := range hyphaeToRename {
 | 
				
			||||||
			h := h.(*hyphae.Hypha) // ontology think
 | 
								h := h.(*hyphae.Hypha) // ontology think
 | 
				
			||||||
			oldName := h.CanonicalName()
 | 
								oldName := h.CanonicalName()
 | 
				
			||||||
			h.RenameTo(replaceName(h.CanonicalName()))
 | 
								hyphae.RenameHyphaTo(h, replaceName(h.CanonicalName()))
 | 
				
			||||||
			h.Lock()
 | 
								h.Lock()
 | 
				
			||||||
			h.TextPath = replaceName(h.TextPath)
 | 
								h.TextPath = replaceName(h.TextPath)
 | 
				
			||||||
			h.SetBinaryPath(replaceName(h.BinaryPath()))
 | 
								h.SetBinaryPath(replaceName(h.BinaryPath()))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,16 +10,17 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UnattachHypha unattaches hypha and makes a history record about that.
 | 
					// UnattachHypha unattaches hypha and makes a history record about that.
 | 
				
			||||||
func UnattachHypha(u *user.User, h *hyphae.Hypha, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
 | 
					func UnattachHypha(u *user.User, h hyphae.Hypher, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
 | 
				
			||||||
	hop = history.Operation(history.TypeUnattachHypha)
 | 
						hop = history.Operation(history.TypeUnattachHypha)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if errtitle, err := CanUnattach(u, h, lc); errtitle != "" {
 | 
						if errtitle, err := CanUnattach(u, h, lc); errtitle != "" {
 | 
				
			||||||
		hop.WithErrAbort(err)
 | 
							hop.WithErrAbort(err)
 | 
				
			||||||
		return hop, errtitle
 | 
							return hop, errtitle
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						H := h.(*hyphae.Hypha)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hop.
 | 
						hop.
 | 
				
			||||||
		WithFilesRemoved(h.BinaryPath()).
 | 
							WithFilesRemoved(H.BinaryPath()).
 | 
				
			||||||
		WithMsg(fmt.Sprintf("Unattach ‘%s’", h.CanonicalName())).
 | 
							WithMsg(fmt.Sprintf("Unattach ‘%s’", h.CanonicalName())).
 | 
				
			||||||
		WithUser(u).
 | 
							WithUser(u).
 | 
				
			||||||
		Apply()
 | 
							Apply()
 | 
				
			||||||
@@ -30,11 +31,11 @@ func UnattachHypha(u *user.User, h *hyphae.Hypha, lc *l18n.Localizer) (hop *hist
 | 
				
			|||||||
		return hop.WithErrAbort(fmt.Errorf("Could not unattach this hypha due to internal server errors: <code>%v</code>", hop.Errs)), "Error"
 | 
							return hop.WithErrAbort(fmt.Errorf("Could not unattach this hypha due to internal server errors: <code>%v</code>", hop.Errs)), "Error"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if h.BinaryPath() != "" {
 | 
						if H.BinaryPath() != "" {
 | 
				
			||||||
		h.SetBinaryPath("")
 | 
							H.SetBinaryPath("")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// If nothing is left of the hypha
 | 
						// If nothing is left of the hypha
 | 
				
			||||||
	if h.TextPath == "" {
 | 
						if H.TextPath == "" {
 | 
				
			||||||
		hyphae.DeleteHypha(h)
 | 
							hyphae.DeleteHypha(h)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return hop, ""
 | 
						return hop, ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,10 +21,10 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UploadText edits a hypha' text part and makes a history record about that.
 | 
					// UploadText edits a hypha' text part and makes a history record about that.
 | 
				
			||||||
func UploadText(h *hyphae.Hypha, data []byte, message string, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
 | 
					func UploadText(h hyphae.Hypher, data []byte, message string, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
 | 
				
			||||||
	hop = history.Operation(history.TypeEditText)
 | 
						hop = history.Operation(history.TypeEditText)
 | 
				
			||||||
	var action string
 | 
						var action string
 | 
				
			||||||
	if h.Exists {
 | 
						if h.DoesExist() {
 | 
				
			||||||
		action = "Edit"
 | 
							action = "Edit"
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		action = "Create"
 | 
							action = "Create"
 | 
				
			||||||
@@ -39,7 +39,7 @@ func UploadText(h *hyphae.Hypha, data []byte, message string, u *user.User, lc *
 | 
				
			|||||||
	if errtitle, err := CanEdit(u, h, lc); err != nil {
 | 
						if errtitle, err := CanEdit(u, h, lc); err != nil {
 | 
				
			||||||
		return hop.WithErrAbort(err), errtitle
 | 
							return hop.WithErrAbort(err), errtitle
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(bytes.TrimSpace(data)) == 0 && h.BinaryPath() == "" {
 | 
						if len(bytes.TrimSpace(data)) == 0 && h.Kind() != hyphae.HyphaMedia {
 | 
				
			||||||
		return hop.WithErrAbort(errors.New("No data passed")), "Empty"
 | 
							return hop.WithErrAbort(errors.New("No data passed")), "Empty"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -47,7 +47,7 @@ func UploadText(h *hyphae.Hypha, data []byte, message string, u *user.User, lc *
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UploadBinary edits a hypha' attachment and makes a history record about that.
 | 
					// UploadBinary edits a hypha' attachment and makes a history record about that.
 | 
				
			||||||
func UploadBinary(h *hyphae.Hypha, mime string, file multipart.File, u *user.User, lc *l18n.Localizer) (*history.Op, string) {
 | 
					func UploadBinary(h hyphae.Hypher, mime string, file multipart.File, u *user.User, lc *l18n.Localizer) (*history.Op, string) {
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		hop       = history.Operation(history.TypeEditBinary).WithMsg(fmt.Sprintf("Upload attachment for ‘%s’ with type ‘%s’", h.CanonicalName(), mime))
 | 
							hop       = history.Operation(history.TypeEditBinary).WithMsg(fmt.Sprintf("Upload attachment for ‘%s’ with type ‘%s’", h.CanonicalName(), mime))
 | 
				
			||||||
		data, err = io.ReadAll(file)
 | 
							data, err = io.ReadAll(file)
 | 
				
			||||||
@@ -67,7 +67,7 @@ func UploadBinary(h *hyphae.Hypha, mime string, file multipart.File, u *user.Use
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// uploadHelp is a helper function for UploadText and UploadBinary
 | 
					// uploadHelp is a helper function for UploadText and UploadBinary
 | 
				
			||||||
func uploadHelp(h *hyphae.Hypha, hop *history.Op, ext string, data []byte, u *user.User) (*history.Op, string) {
 | 
					func uploadHelp(h hyphae.Hypher, hop *history.Op, ext string, data []byte, u *user.User) (*history.Op, string) {
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		fullPath       = filepath.Join(files.HyphaeDir(), h.CanonicalName()+ext)
 | 
							fullPath       = filepath.Join(files.HyphaeDir(), h.CanonicalName()+ext)
 | 
				
			||||||
		sourceFullPath = h.TextPartPath()
 | 
							sourceFullPath = h.TextPartPath()
 | 
				
			||||||
@@ -77,7 +77,7 @@ func uploadHelp(h *hyphae.Hypha, hop *history.Op, ext string, data []byte, u *us
 | 
				
			|||||||
		err := errors.New("bad path")
 | 
							err := errors.New("bad path")
 | 
				
			||||||
		return hop.WithErrAbort(err), err.Error()
 | 
							return hop.WithErrAbort(err), err.Error()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if hop.Type == history.TypeEditBinary {
 | 
						if h := h.(*hyphae.Hypha); hop.Type == history.TypeEditBinary {
 | 
				
			||||||
		sourceFullPath = h.BinaryPath()
 | 
							sourceFullPath = h.BinaryPath()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -93,7 +93,7 @@ func uploadHelp(h *hyphae.Hypha, hop *history.Op, ext string, data []byte, u *us
 | 
				
			|||||||
		return hop.WithErrAbort(err), err.Error()
 | 
							return hop.WithErrAbort(err), err.Error()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if h.Exists && sourceFullPath != fullPath && sourceFullPath != "" {
 | 
						if h.DoesExist() && sourceFullPath != fullPath && sourceFullPath != "" {
 | 
				
			||||||
		if err := history.Rename(sourceFullPath, fullPath); err != nil {
 | 
							if err := history.Rename(sourceFullPath, fullPath); err != nil {
 | 
				
			||||||
			return hop.WithErrAbort(err), err.Error()
 | 
								return hop.WithErrAbort(err), err.Error()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -101,11 +101,11 @@ func uploadHelp(h *hyphae.Hypha, hop *history.Op, ext string, data []byte, u *us
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hyphae.InsertIfNew(h)
 | 
						hyphae.InsertIfNew(h)
 | 
				
			||||||
	if h.Exists && h.TextPath != "" && hop.Type == history.TypeEditText && !history.FileChanged(fullPath) {
 | 
						if h.DoesExist() && h.HasTextPart() && hop.Type == history.TypeEditText && !history.FileChanged(fullPath) {
 | 
				
			||||||
		return hop.Abort(), "No changes"
 | 
							return hop.Abort(), "No changes"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// TODO: test
 | 
						// TODO: test
 | 
				
			||||||
	if hop.Type == history.TypeEditBinary {
 | 
						if h := h.(*hyphae.Hypha); hop.Type == history.TypeEditBinary {
 | 
				
			||||||
		h.SetBinaryPath(fullPath)
 | 
							h.SetBinaryPath(fullPath)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		h.TextPath = fullPath
 | 
							h.TextPath = fullPath
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,11 +8,11 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FetchTextPart tries to read text file of the given hypha. If there is no file, empty string is returned.
 | 
					// FetchTextPart tries to read text file of the given hypha. If there is no file, empty string is returned.
 | 
				
			||||||
func FetchTextPart(h *hyphae.Hypha) (string, error) {
 | 
					func FetchTextPart(h hyphae.Hypher) (string, error) {
 | 
				
			||||||
	if !h.HasTextPart() {
 | 
						if !h.HasTextPart() {
 | 
				
			||||||
		return "", nil
 | 
							return "", nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	text, err := os.ReadFile(h.TextPath)
 | 
						text, err := os.ReadFile(h.TextPartPath())
 | 
				
			||||||
	if os.IsNotExist(err) {
 | 
						if os.IsNotExist(err) {
 | 
				
			||||||
		return "", nil
 | 
							return "", nil
 | 
				
			||||||
	} else if err != nil {
 | 
						} else if err != nil {
 | 
				
			||||||
@@ -23,10 +23,10 @@ func FetchTextPart(h *hyphae.Hypha) (string, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// SetHeaderLinks initializes header links by reading the configured hypha, if there is any, or resorting to default values.
 | 
					// SetHeaderLinks initializes header links by reading the configured hypha, if there is any, or resorting to default values.
 | 
				
			||||||
func SetHeaderLinks() {
 | 
					func SetHeaderLinks() {
 | 
				
			||||||
	if userLinksHypha := hyphae.ByName(cfg.HeaderLinksHypha); !userLinksHypha.Exists {
 | 
						if userLinksHypha := hyphae.ByName(cfg.HeaderLinksHypha); !userLinksHypha.DoesExist() {
 | 
				
			||||||
		cfg.SetDefaultHeaderLinks()
 | 
							cfg.SetDefaultHeaderLinks()
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		contents, err := os.ReadFile(userLinksHypha.TextPath)
 | 
							contents, err := os.ReadFile(userLinksHypha.TextPartPath())
 | 
				
			||||||
		if err != nil || len(contents) == 0 {
 | 
							if err != nil || len(contents) == 0 {
 | 
				
			||||||
			cfg.SetDefaultHeaderLinks()
 | 
								cfg.SetDefaultHeaderLinks()
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,7 @@
 | 
				
			|||||||
{% import "github.com/bouncepaw/mycorrhiza/history" %}
 | 
					{% import "github.com/bouncepaw/mycorrhiza/history" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% func PrimitiveDiffHTML(rq *http.Request, h *hyphae.Hypha, u *user.User, hash string) %}
 | 
					{% func PrimitiveDiffHTML(rq *http.Request, h hyphae.Hypher, u *user.User, hash string) %}
 | 
				
			||||||
{% code
 | 
					{% code
 | 
				
			||||||
lc := l18n.FromRequest(rq)
 | 
					lc := l18n.FromRequest(rq)
 | 
				
			||||||
text, err := history.PrimitiveDiffAtRevision(h.TextPartPath(), hash)
 | 
					text, err := history.PrimitiveDiffAtRevision(h.TextPartPath(), hash)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,7 +42,7 @@ var (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/history.qtpl:12
 | 
					//line views/history.qtpl:12
 | 
				
			||||||
func StreamPrimitiveDiffHTML(qw422016 *qt422016.Writer, rq *http.Request, h *hyphae.Hypha, u *user.User, hash string) {
 | 
					func StreamPrimitiveDiffHTML(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.Hypher, u *user.User, hash string) {
 | 
				
			||||||
//line views/history.qtpl:12
 | 
					//line views/history.qtpl:12
 | 
				
			||||||
	qw422016.N().S(`
 | 
						qw422016.N().S(`
 | 
				
			||||||
`)
 | 
					`)
 | 
				
			||||||
@@ -76,7 +76,7 @@ func StreamPrimitiveDiffHTML(qw422016 *qt422016.Writer, rq *http.Request, h *hyp
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/history.qtpl:28
 | 
					//line views/history.qtpl:28
 | 
				
			||||||
func WritePrimitiveDiffHTML(qq422016 qtio422016.Writer, rq *http.Request, h *hyphae.Hypha, u *user.User, hash string) {
 | 
					func WritePrimitiveDiffHTML(qq422016 qtio422016.Writer, rq *http.Request, h hyphae.Hypher, u *user.User, hash string) {
 | 
				
			||||||
//line views/history.qtpl:28
 | 
					//line views/history.qtpl:28
 | 
				
			||||||
	qw422016 := qt422016.AcquireWriter(qq422016)
 | 
						qw422016 := qt422016.AcquireWriter(qq422016)
 | 
				
			||||||
//line views/history.qtpl:28
 | 
					//line views/history.qtpl:28
 | 
				
			||||||
@@ -87,7 +87,7 @@ func WritePrimitiveDiffHTML(qq422016 qtio422016.Writer, rq *http.Request, h *hyp
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/history.qtpl:28
 | 
					//line views/history.qtpl:28
 | 
				
			||||||
func PrimitiveDiffHTML(rq *http.Request, h *hyphae.Hypha, u *user.User, hash string) string {
 | 
					func PrimitiveDiffHTML(rq *http.Request, h hyphae.Hypher, u *user.User, hash string) string {
 | 
				
			||||||
//line views/history.qtpl:28
 | 
					//line views/history.qtpl:28
 | 
				
			||||||
	qb422016 := qt422016.AcquireByteBuffer()
 | 
						qb422016 := qt422016.AcquireByteBuffer()
 | 
				
			||||||
//line views/history.qtpl:28
 | 
					//line views/history.qtpl:28
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
{% func mycoLink(lc *l18n.Localizer) %}<a href="/help/en/mycomarkup" class="shy-link">{%s lc.Get("ui.notexist_write_myco") %}</a>{% endfunc %}
 | 
					{% func mycoLink(lc *l18n.Localizer) %}<a href="/help/en/mycomarkup" class="shy-link">{%s lc.Get("ui.notexist_write_myco") %}</a>{% endfunc %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% func nonExistentHyphaNotice(h *hyphae.Hypha, u *user.User, lc *l18n.Localizer) %}
 | 
					{% func nonExistentHyphaNotice(h hyphae.Hypher, u *user.User, lc *l18n.Localizer) %}
 | 
				
			||||||
<section class="non-existent-hypha">
 | 
					<section class="non-existent-hypha">
 | 
				
			||||||
	<h2 class="non-existent-hypha__title">{%s lc.Get("ui.notexist_heading") %}</h2>
 | 
						<h2 class="non-existent-hypha__title">{%s lc.Get("ui.notexist_heading") %}</h2>
 | 
				
			||||||
	{% if cfg.UseAuth && u.Group == "anon" %}
 | 
						{% if cfg.UseAuth && u.Group == "anon" %}
 | 
				
			||||||
@@ -47,7 +47,7 @@
 | 
				
			|||||||
</section>
 | 
					</section>
 | 
				
			||||||
{% endfunc %}
 | 
					{% endfunc %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% func NaviTitleHTML(h *hyphae.Hypha) %}
 | 
					{% func NaviTitleHTML(h hyphae.Hypher) %}
 | 
				
			||||||
{% code 
 | 
					{% code 
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		prevAcc = "/hypha/"
 | 
							prevAcc = "/hypha/"
 | 
				
			||||||
@@ -75,10 +75,10 @@
 | 
				
			|||||||
</h1>
 | 
					</h1>
 | 
				
			||||||
{% endfunc %}
 | 
					{% endfunc %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% func AttachmentHTMLRaw(h *hyphae.Hypha) %}{%= AttachmentHTML(h, l18n.New("en", "en")) %}{% endfunc %}
 | 
					{% func AttachmentHTMLRaw(h hyphae.Hypher) %}{%= AttachmentHTML(h, l18n.New("en", "en")) %}{% endfunc %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% func AttachmentHTML(h *hyphae.Hypha, lc *l18n.Localizer) %}
 | 
					{% func AttachmentHTML(h hyphae.Hypher, lc *l18n.Localizer) %}
 | 
				
			||||||
	{% switch filepath.Ext(h.BinaryPath()) %}
 | 
						{% switch filepath.Ext(h.(*hyphae.Hypha).BinaryPath()) %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	{% case ".jpg", ".gif", ".png", ".webp", ".svg", ".ico" %}
 | 
						{% case ".jpg", ".gif", ".png", ".webp", ".svg", ".ico" %}
 | 
				
			||||||
	<div class="binary-container binary-container_with-img">
 | 
						<div class="binary-container binary-container_with-img">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -117,7 +117,7 @@ func mycoLink(lc *l18n.Localizer) string {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/hypha.qtpl:14
 | 
					//line views/hypha.qtpl:14
 | 
				
			||||||
func streamnonExistentHyphaNotice(qw422016 *qt422016.Writer, h *hyphae.Hypha, u *user.User, lc *l18n.Localizer) {
 | 
					func streamnonExistentHyphaNotice(qw422016 *qt422016.Writer, h hyphae.Hypher, u *user.User, lc *l18n.Localizer) {
 | 
				
			||||||
//line views/hypha.qtpl:14
 | 
					//line views/hypha.qtpl:14
 | 
				
			||||||
	qw422016.N().S(`
 | 
						qw422016.N().S(`
 | 
				
			||||||
<section class="non-existent-hypha">
 | 
					<section class="non-existent-hypha">
 | 
				
			||||||
@@ -230,7 +230,7 @@ func streamnonExistentHyphaNotice(qw422016 *qt422016.Writer, h *hyphae.Hypha, u
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/hypha.qtpl:48
 | 
					//line views/hypha.qtpl:48
 | 
				
			||||||
func writenonExistentHyphaNotice(qq422016 qtio422016.Writer, h *hyphae.Hypha, u *user.User, lc *l18n.Localizer) {
 | 
					func writenonExistentHyphaNotice(qq422016 qtio422016.Writer, h hyphae.Hypher, u *user.User, lc *l18n.Localizer) {
 | 
				
			||||||
//line views/hypha.qtpl:48
 | 
					//line views/hypha.qtpl:48
 | 
				
			||||||
	qw422016 := qt422016.AcquireWriter(qq422016)
 | 
						qw422016 := qt422016.AcquireWriter(qq422016)
 | 
				
			||||||
//line views/hypha.qtpl:48
 | 
					//line views/hypha.qtpl:48
 | 
				
			||||||
@@ -241,7 +241,7 @@ func writenonExistentHyphaNotice(qq422016 qtio422016.Writer, h *hyphae.Hypha, u
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/hypha.qtpl:48
 | 
					//line views/hypha.qtpl:48
 | 
				
			||||||
func nonExistentHyphaNotice(h *hyphae.Hypha, u *user.User, lc *l18n.Localizer) string {
 | 
					func nonExistentHyphaNotice(h hyphae.Hypher, u *user.User, lc *l18n.Localizer) string {
 | 
				
			||||||
//line views/hypha.qtpl:48
 | 
					//line views/hypha.qtpl:48
 | 
				
			||||||
	qb422016 := qt422016.AcquireByteBuffer()
 | 
						qb422016 := qt422016.AcquireByteBuffer()
 | 
				
			||||||
//line views/hypha.qtpl:48
 | 
					//line views/hypha.qtpl:48
 | 
				
			||||||
@@ -256,7 +256,7 @@ func nonExistentHyphaNotice(h *hyphae.Hypha, u *user.User, lc *l18n.Localizer) s
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/hypha.qtpl:50
 | 
					//line views/hypha.qtpl:50
 | 
				
			||||||
func StreamNaviTitleHTML(qw422016 *qt422016.Writer, h *hyphae.Hypha) {
 | 
					func StreamNaviTitleHTML(qw422016 *qt422016.Writer, h hyphae.Hypher) {
 | 
				
			||||||
//line views/hypha.qtpl:50
 | 
					//line views/hypha.qtpl:50
 | 
				
			||||||
	qw422016.N().S(`
 | 
						qw422016.N().S(`
 | 
				
			||||||
`)
 | 
					`)
 | 
				
			||||||
@@ -323,7 +323,7 @@ func StreamNaviTitleHTML(qw422016 *qt422016.Writer, h *hyphae.Hypha) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/hypha.qtpl:76
 | 
					//line views/hypha.qtpl:76
 | 
				
			||||||
func WriteNaviTitleHTML(qq422016 qtio422016.Writer, h *hyphae.Hypha) {
 | 
					func WriteNaviTitleHTML(qq422016 qtio422016.Writer, h hyphae.Hypher) {
 | 
				
			||||||
//line views/hypha.qtpl:76
 | 
					//line views/hypha.qtpl:76
 | 
				
			||||||
	qw422016 := qt422016.AcquireWriter(qq422016)
 | 
						qw422016 := qt422016.AcquireWriter(qq422016)
 | 
				
			||||||
//line views/hypha.qtpl:76
 | 
					//line views/hypha.qtpl:76
 | 
				
			||||||
@@ -334,7 +334,7 @@ func WriteNaviTitleHTML(qq422016 qtio422016.Writer, h *hyphae.Hypha) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/hypha.qtpl:76
 | 
					//line views/hypha.qtpl:76
 | 
				
			||||||
func NaviTitleHTML(h *hyphae.Hypha) string {
 | 
					func NaviTitleHTML(h hyphae.Hypher) string {
 | 
				
			||||||
//line views/hypha.qtpl:76
 | 
					//line views/hypha.qtpl:76
 | 
				
			||||||
	qb422016 := qt422016.AcquireByteBuffer()
 | 
						qb422016 := qt422016.AcquireByteBuffer()
 | 
				
			||||||
//line views/hypha.qtpl:76
 | 
					//line views/hypha.qtpl:76
 | 
				
			||||||
@@ -349,14 +349,14 @@ func NaviTitleHTML(h *hyphae.Hypha) string {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/hypha.qtpl:78
 | 
					//line views/hypha.qtpl:78
 | 
				
			||||||
func StreamAttachmentHTMLRaw(qw422016 *qt422016.Writer, h *hyphae.Hypha) {
 | 
					func StreamAttachmentHTMLRaw(qw422016 *qt422016.Writer, h hyphae.Hypher) {
 | 
				
			||||||
//line views/hypha.qtpl:78
 | 
					//line views/hypha.qtpl:78
 | 
				
			||||||
	StreamAttachmentHTML(qw422016, h, l18n.New("en", "en"))
 | 
						StreamAttachmentHTML(qw422016, h, l18n.New("en", "en"))
 | 
				
			||||||
//line views/hypha.qtpl:78
 | 
					//line views/hypha.qtpl:78
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/hypha.qtpl:78
 | 
					//line views/hypha.qtpl:78
 | 
				
			||||||
func WriteAttachmentHTMLRaw(qq422016 qtio422016.Writer, h *hyphae.Hypha) {
 | 
					func WriteAttachmentHTMLRaw(qq422016 qtio422016.Writer, h hyphae.Hypher) {
 | 
				
			||||||
//line views/hypha.qtpl:78
 | 
					//line views/hypha.qtpl:78
 | 
				
			||||||
	qw422016 := qt422016.AcquireWriter(qq422016)
 | 
						qw422016 := qt422016.AcquireWriter(qq422016)
 | 
				
			||||||
//line views/hypha.qtpl:78
 | 
					//line views/hypha.qtpl:78
 | 
				
			||||||
@@ -367,7 +367,7 @@ func WriteAttachmentHTMLRaw(qq422016 qtio422016.Writer, h *hyphae.Hypha) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/hypha.qtpl:78
 | 
					//line views/hypha.qtpl:78
 | 
				
			||||||
func AttachmentHTMLRaw(h *hyphae.Hypha) string {
 | 
					func AttachmentHTMLRaw(h hyphae.Hypher) string {
 | 
				
			||||||
//line views/hypha.qtpl:78
 | 
					//line views/hypha.qtpl:78
 | 
				
			||||||
	qb422016 := qt422016.AcquireByteBuffer()
 | 
						qb422016 := qt422016.AcquireByteBuffer()
 | 
				
			||||||
//line views/hypha.qtpl:78
 | 
					//line views/hypha.qtpl:78
 | 
				
			||||||
@@ -382,12 +382,12 @@ func AttachmentHTMLRaw(h *hyphae.Hypha) string {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/hypha.qtpl:80
 | 
					//line views/hypha.qtpl:80
 | 
				
			||||||
func StreamAttachmentHTML(qw422016 *qt422016.Writer, h *hyphae.Hypha, lc *l18n.Localizer) {
 | 
					func StreamAttachmentHTML(qw422016 *qt422016.Writer, h hyphae.Hypher, lc *l18n.Localizer) {
 | 
				
			||||||
//line views/hypha.qtpl:80
 | 
					//line views/hypha.qtpl:80
 | 
				
			||||||
	qw422016.N().S(`
 | 
						qw422016.N().S(`
 | 
				
			||||||
	`)
 | 
						`)
 | 
				
			||||||
//line views/hypha.qtpl:81
 | 
					//line views/hypha.qtpl:81
 | 
				
			||||||
	switch filepath.Ext(h.BinaryPath()) {
 | 
						switch filepath.Ext(h.(*hyphae.Hypha).BinaryPath()) {
 | 
				
			||||||
//line views/hypha.qtpl:83
 | 
					//line views/hypha.qtpl:83
 | 
				
			||||||
	case ".jpg", ".gif", ".png", ".webp", ".svg", ".ico":
 | 
						case ".jpg", ".gif", ".png", ".webp", ".svg", ".ico":
 | 
				
			||||||
//line views/hypha.qtpl:83
 | 
					//line views/hypha.qtpl:83
 | 
				
			||||||
@@ -486,7 +486,7 @@ func StreamAttachmentHTML(qw422016 *qt422016.Writer, h *hyphae.Hypha, lc *l18n.L
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/hypha.qtpl:109
 | 
					//line views/hypha.qtpl:109
 | 
				
			||||||
func WriteAttachmentHTML(qq422016 qtio422016.Writer, h *hyphae.Hypha, lc *l18n.Localizer) {
 | 
					func WriteAttachmentHTML(qq422016 qtio422016.Writer, h hyphae.Hypher, lc *l18n.Localizer) {
 | 
				
			||||||
//line views/hypha.qtpl:109
 | 
					//line views/hypha.qtpl:109
 | 
				
			||||||
	qw422016 := qt422016.AcquireWriter(qq422016)
 | 
						qw422016 := qt422016.AcquireWriter(qq422016)
 | 
				
			||||||
//line views/hypha.qtpl:109
 | 
					//line views/hypha.qtpl:109
 | 
				
			||||||
@@ -497,7 +497,7 @@ func WriteAttachmentHTML(qq422016 qtio422016.Writer, h *hyphae.Hypha, lc *l18n.L
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/hypha.qtpl:109
 | 
					//line views/hypha.qtpl:109
 | 
				
			||||||
func AttachmentHTML(h *hyphae.Hypha, lc *l18n.Localizer) string {
 | 
					func AttachmentHTML(h hyphae.Hypher, lc *l18n.Localizer) string {
 | 
				
			||||||
//line views/hypha.qtpl:109
 | 
					//line views/hypha.qtpl:109
 | 
				
			||||||
	qb422016 := qt422016.AcquireByteBuffer()
 | 
						qb422016 := qt422016.AcquireByteBuffer()
 | 
				
			||||||
//line views/hypha.qtpl:109
 | 
					//line views/hypha.qtpl:109
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@
 | 
				
			|||||||
{% import "github.com/bouncepaw/mycorrhiza/user" %}
 | 
					{% import "github.com/bouncepaw/mycorrhiza/user" %}
 | 
				
			||||||
{% import "github.com/bouncepaw/mycorrhiza/hyphae" %}
 | 
					{% import "github.com/bouncepaw/mycorrhiza/hyphae" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% func hyphaInfoEntry(h *hyphae.Hypha, u *user.User, action, displayText string) %}
 | 
					{% func hyphaInfoEntry(h hyphae.Hypher, u *user.User, action, displayText string) %}
 | 
				
			||||||
{% if u.CanProceed(action) %}
 | 
					{% if u.CanProceed(action) %}
 | 
				
			||||||
<li class="hypha-info__entry hypha-info__entry_{%s action %}">
 | 
					<li class="hypha-info__entry hypha-info__entry_{%s action %}">
 | 
				
			||||||
	<a class="hypha-info__link" href="/{%s action %}/{%s h.CanonicalName() %}">{%s displayText %}</a>
 | 
						<a class="hypha-info__link" href="/{%s action %}/{%s h.CanonicalName() %}">{%s displayText %}</a>
 | 
				
			||||||
@@ -13,7 +13,7 @@
 | 
				
			|||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
{% endfunc %}
 | 
					{% endfunc %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% func hyphaInfo(rq *http.Request, h *hyphae.Hypha) %}
 | 
					{% func hyphaInfo(rq *http.Request, h hyphae.Hypher) %}
 | 
				
			||||||
{% code
 | 
					{% code
 | 
				
			||||||
	u := user.FromRequest(rq)
 | 
						u := user.FromRequest(rq)
 | 
				
			||||||
	lc := l18n.FromRequest(rq)
 | 
						lc := l18n.FromRequest(rq)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,7 @@ var (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/nav.qtpl:8
 | 
					//line views/nav.qtpl:8
 | 
				
			||||||
func streamhyphaInfoEntry(qw422016 *qt422016.Writer, h *hyphae.Hypha, u *user.User, action, displayText string) {
 | 
					func streamhyphaInfoEntry(qw422016 *qt422016.Writer, h hyphae.Hypher, u *user.User, action, displayText string) {
 | 
				
			||||||
//line views/nav.qtpl:8
 | 
					//line views/nav.qtpl:8
 | 
				
			||||||
	qw422016.N().S(`
 | 
						qw422016.N().S(`
 | 
				
			||||||
`)
 | 
					`)
 | 
				
			||||||
@@ -73,7 +73,7 @@ func streamhyphaInfoEntry(qw422016 *qt422016.Writer, h *hyphae.Hypha, u *user.Us
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/nav.qtpl:14
 | 
					//line views/nav.qtpl:14
 | 
				
			||||||
func writehyphaInfoEntry(qq422016 qtio422016.Writer, h *hyphae.Hypha, u *user.User, action, displayText string) {
 | 
					func writehyphaInfoEntry(qq422016 qtio422016.Writer, h hyphae.Hypher, u *user.User, action, displayText string) {
 | 
				
			||||||
//line views/nav.qtpl:14
 | 
					//line views/nav.qtpl:14
 | 
				
			||||||
	qw422016 := qt422016.AcquireWriter(qq422016)
 | 
						qw422016 := qt422016.AcquireWriter(qq422016)
 | 
				
			||||||
//line views/nav.qtpl:14
 | 
					//line views/nav.qtpl:14
 | 
				
			||||||
@@ -84,7 +84,7 @@ func writehyphaInfoEntry(qq422016 qtio422016.Writer, h *hyphae.Hypha, u *user.Us
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/nav.qtpl:14
 | 
					//line views/nav.qtpl:14
 | 
				
			||||||
func hyphaInfoEntry(h *hyphae.Hypha, u *user.User, action, displayText string) string {
 | 
					func hyphaInfoEntry(h hyphae.Hypher, u *user.User, action, displayText string) string {
 | 
				
			||||||
//line views/nav.qtpl:14
 | 
					//line views/nav.qtpl:14
 | 
				
			||||||
	qb422016 := qt422016.AcquireByteBuffer()
 | 
						qb422016 := qt422016.AcquireByteBuffer()
 | 
				
			||||||
//line views/nav.qtpl:14
 | 
					//line views/nav.qtpl:14
 | 
				
			||||||
@@ -99,7 +99,7 @@ func hyphaInfoEntry(h *hyphae.Hypha, u *user.User, action, displayText string) s
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/nav.qtpl:16
 | 
					//line views/nav.qtpl:16
 | 
				
			||||||
func streamhyphaInfo(qw422016 *qt422016.Writer, rq *http.Request, h *hyphae.Hypha) {
 | 
					func streamhyphaInfo(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.Hypher) {
 | 
				
			||||||
//line views/nav.qtpl:16
 | 
					//line views/nav.qtpl:16
 | 
				
			||||||
	qw422016.N().S(`
 | 
						qw422016.N().S(`
 | 
				
			||||||
`)
 | 
					`)
 | 
				
			||||||
@@ -149,7 +149,7 @@ func streamhyphaInfo(qw422016 *qt422016.Writer, rq *http.Request, h *hyphae.Hyph
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/nav.qtpl:32
 | 
					//line views/nav.qtpl:32
 | 
				
			||||||
func writehyphaInfo(qq422016 qtio422016.Writer, rq *http.Request, h *hyphae.Hypha) {
 | 
					func writehyphaInfo(qq422016 qtio422016.Writer, rq *http.Request, h hyphae.Hypher) {
 | 
				
			||||||
//line views/nav.qtpl:32
 | 
					//line views/nav.qtpl:32
 | 
				
			||||||
	qw422016 := qt422016.AcquireWriter(qq422016)
 | 
						qw422016 := qt422016.AcquireWriter(qq422016)
 | 
				
			||||||
//line views/nav.qtpl:32
 | 
					//line views/nav.qtpl:32
 | 
				
			||||||
@@ -160,7 +160,7 @@ func writehyphaInfo(qq422016 qtio422016.Writer, rq *http.Request, h *hyphae.Hyph
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/nav.qtpl:32
 | 
					//line views/nav.qtpl:32
 | 
				
			||||||
func hyphaInfo(rq *http.Request, h *hyphae.Hypha) string {
 | 
					func hyphaInfo(rq *http.Request, h hyphae.Hypher) string {
 | 
				
			||||||
//line views/nav.qtpl:32
 | 
					//line views/nav.qtpl:32
 | 
				
			||||||
	qb422016 := qt422016.AcquireByteBuffer()
 | 
						qb422016 := qt422016.AcquireByteBuffer()
 | 
				
			||||||
//line views/nav.qtpl:32
 | 
					//line views/nav.qtpl:32
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -80,7 +80,7 @@
 | 
				
			|||||||
If `contents` == "", a helpful message is shown instead.
 | 
					If `contents` == "", a helpful message is shown instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you rename .prevnext, change the docs too.
 | 
					If you rename .prevnext, change the docs too.
 | 
				
			||||||
{% func HyphaHTML(rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents string) %}
 | 
					{% func HyphaHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents string) %}
 | 
				
			||||||
{% code
 | 
					{% code
 | 
				
			||||||
	siblings, subhyphae, prevHyphaName, nextHyphaName := tree.Tree(h.CanonicalName())
 | 
						siblings, subhyphae, prevHyphaName, nextHyphaName := tree.Tree(h.CanonicalName())
 | 
				
			||||||
	u := user.FromRequest(rq)
 | 
						u := user.FromRequest(rq)
 | 
				
			||||||
@@ -106,7 +106,7 @@ If you rename .prevnext, change the docs too.
 | 
				
			|||||||
		{% endif %}
 | 
							{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		{%s= NaviTitleHTML(h) %}
 | 
							{%s= NaviTitleHTML(h) %}
 | 
				
			||||||
		{% if h.Exists %}
 | 
							{% if h.DoesExist() %}
 | 
				
			||||||
			{%s= contents %}
 | 
								{%s= contents %}
 | 
				
			||||||
		{% else %}
 | 
							{% else %}
 | 
				
			||||||
		    {%= nonExistentHyphaNotice(h, u, lc) %}
 | 
							    {%= nonExistentHyphaNotice(h, u, lc) %}
 | 
				
			||||||
@@ -130,7 +130,7 @@ If you rename .prevnext, change the docs too.
 | 
				
			|||||||
{%= viewScripts() %}
 | 
					{%= viewScripts() %}
 | 
				
			||||||
{% endfunc %}
 | 
					{% endfunc %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% func RevisionHTML(rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents, revHash string) %}
 | 
					{% func RevisionHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents, revHash string) %}
 | 
				
			||||||
{% code
 | 
					{% code
 | 
				
			||||||
	siblings, subhyphae, _, _ := tree.Tree(h.CanonicalName())
 | 
						siblings, subhyphae, _, _ := tree.Tree(h.CanonicalName())
 | 
				
			||||||
%}
 | 
					%}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -295,7 +295,7 @@ func AttachmentMenuHTML(rq *http.Request, h *hyphae.Hypha, u *user.User) string
 | 
				
			|||||||
// If you rename .prevnext, change the docs too.
 | 
					// If you rename .prevnext, change the docs too.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/readers.qtpl:83
 | 
					//line views/readers.qtpl:83
 | 
				
			||||||
func StreamHyphaHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents string) {
 | 
					func StreamHyphaHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents string) {
 | 
				
			||||||
//line views/readers.qtpl:83
 | 
					//line views/readers.qtpl:83
 | 
				
			||||||
	qw422016.N().S(`
 | 
						qw422016.N().S(`
 | 
				
			||||||
`)
 | 
					`)
 | 
				
			||||||
@@ -372,7 +372,7 @@ func StreamHyphaHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Local
 | 
				
			|||||||
	qw422016.N().S(`
 | 
						qw422016.N().S(`
 | 
				
			||||||
		`)
 | 
							`)
 | 
				
			||||||
//line views/readers.qtpl:109
 | 
					//line views/readers.qtpl:109
 | 
				
			||||||
	if h.Exists {
 | 
						if h.DoesExist() {
 | 
				
			||||||
//line views/readers.qtpl:109
 | 
					//line views/readers.qtpl:109
 | 
				
			||||||
		qw422016.N().S(`
 | 
							qw422016.N().S(`
 | 
				
			||||||
			`)
 | 
								`)
 | 
				
			||||||
@@ -465,7 +465,7 @@ func StreamHyphaHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Local
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/readers.qtpl:131
 | 
					//line views/readers.qtpl:131
 | 
				
			||||||
func WriteHyphaHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents string) {
 | 
					func WriteHyphaHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents string) {
 | 
				
			||||||
//line views/readers.qtpl:131
 | 
					//line views/readers.qtpl:131
 | 
				
			||||||
	qw422016 := qt422016.AcquireWriter(qq422016)
 | 
						qw422016 := qt422016.AcquireWriter(qq422016)
 | 
				
			||||||
//line views/readers.qtpl:131
 | 
					//line views/readers.qtpl:131
 | 
				
			||||||
@@ -476,7 +476,7 @@ func WriteHyphaHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Local
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/readers.qtpl:131
 | 
					//line views/readers.qtpl:131
 | 
				
			||||||
func HyphaHTML(rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents string) string {
 | 
					func HyphaHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents string) string {
 | 
				
			||||||
//line views/readers.qtpl:131
 | 
					//line views/readers.qtpl:131
 | 
				
			||||||
	qb422016 := qt422016.AcquireByteBuffer()
 | 
						qb422016 := qt422016.AcquireByteBuffer()
 | 
				
			||||||
//line views/readers.qtpl:131
 | 
					//line views/readers.qtpl:131
 | 
				
			||||||
@@ -491,7 +491,7 @@ func HyphaHTML(rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents s
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/readers.qtpl:133
 | 
					//line views/readers.qtpl:133
 | 
				
			||||||
func StreamRevisionHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents, revHash string) {
 | 
					func StreamRevisionHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents, revHash string) {
 | 
				
			||||||
//line views/readers.qtpl:133
 | 
					//line views/readers.qtpl:133
 | 
				
			||||||
	qw422016.N().S(`
 | 
						qw422016.N().S(`
 | 
				
			||||||
`)
 | 
					`)
 | 
				
			||||||
@@ -553,7 +553,7 @@ func StreamRevisionHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Lo
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/readers.qtpl:149
 | 
					//line views/readers.qtpl:149
 | 
				
			||||||
func WriteRevisionHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents, revHash string) {
 | 
					func WriteRevisionHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents, revHash string) {
 | 
				
			||||||
//line views/readers.qtpl:149
 | 
					//line views/readers.qtpl:149
 | 
				
			||||||
	qw422016 := qt422016.AcquireWriter(qq422016)
 | 
						qw422016 := qt422016.AcquireWriter(qq422016)
 | 
				
			||||||
//line views/readers.qtpl:149
 | 
					//line views/readers.qtpl:149
 | 
				
			||||||
@@ -564,7 +564,7 @@ func WriteRevisionHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Lo
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//line views/readers.qtpl:149
 | 
					//line views/readers.qtpl:149
 | 
				
			||||||
func RevisionHTML(rq *http.Request, lc *l18n.Localizer, h *hyphae.Hypha, contents, revHash string) string {
 | 
					func RevisionHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents, revHash string) string {
 | 
				
			||||||
//line views/readers.qtpl:149
 | 
					//line views/readers.qtpl:149
 | 
				
			||||||
	qb422016 := qt422016.AcquireByteBuffer()
 | 
						qb422016 := qt422016.AcquireByteBuffer()
 | 
				
			||||||
//line views/readers.qtpl:149
 | 
					//line views/readers.qtpl:149
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -265,8 +265,8 @@ sort.Strings(editors)
 | 
				
			|||||||
		{% code hypha := hyphae.ByName(hyphaName) %}
 | 
							{% code hypha := hyphae.ByName(hyphaName) %}
 | 
				
			||||||
		<li class="hypha-list__entry">
 | 
							<li class="hypha-list__entry">
 | 
				
			||||||
			<a class="hypha-list__link" href="/hypha/{%s hypha.CanonicalName() %}">{%s util.BeautifulName(hypha.CanonicalName()) %}</a>
 | 
								<a class="hypha-list__link" href="/hypha/{%s hypha.CanonicalName() %}">{%s util.BeautifulName(hypha.CanonicalName()) %}</a>
 | 
				
			||||||
			{% if hypha.BinaryPath() != "" %}
 | 
								{% if hypha.Kind() == hyphae.HyphaMedia %}
 | 
				
			||||||
			<span class="hypha-list__amnt-type">{%s filepath.Ext(hypha.BinaryPath())[1:] %}</span>
 | 
								<span class="hypha-list__amnt-type">{%s filepath.Ext(hypha.(*hyphae.Hypha).BinaryPath())[1:] %}</span>
 | 
				
			||||||
			{% endif %}
 | 
								{% endif %}
 | 
				
			||||||
		</li>
 | 
							</li>
 | 
				
			||||||
		{% endfor %}
 | 
							{% endfor %}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1036,12 +1036,12 @@ func StreamHyphaListHTML(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
 | 
				
			|||||||
		qw422016.N().S(`</a>
 | 
							qw422016.N().S(`</a>
 | 
				
			||||||
			`)
 | 
								`)
 | 
				
			||||||
//line views/stuff.qtpl:268
 | 
					//line views/stuff.qtpl:268
 | 
				
			||||||
		if hypha.BinaryPath() != "" {
 | 
							if hypha.Kind() == hyphae.HyphaMedia {
 | 
				
			||||||
//line views/stuff.qtpl:268
 | 
					//line views/stuff.qtpl:268
 | 
				
			||||||
			qw422016.N().S(`
 | 
								qw422016.N().S(`
 | 
				
			||||||
			<span class="hypha-list__amnt-type">`)
 | 
								<span class="hypha-list__amnt-type">`)
 | 
				
			||||||
//line views/stuff.qtpl:269
 | 
					//line views/stuff.qtpl:269
 | 
				
			||||||
			qw422016.E().S(filepath.Ext(hypha.BinaryPath())[1:])
 | 
								qw422016.E().S(filepath.Ext(hypha.(*hyphae.Hypha).BinaryPath())[1:])
 | 
				
			||||||
//line views/stuff.qtpl:269
 | 
					//line views/stuff.qtpl:269
 | 
				
			||||||
			qw422016.N().S(`</span>
 | 
								qw422016.N().S(`</span>
 | 
				
			||||||
			`)
 | 
								`)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,7 +61,7 @@ func factoryHandlerAsker(
 | 
				
			|||||||
			w,
 | 
								w,
 | 
				
			||||||
			views.BaseHTML(
 | 
								views.BaseHTML(
 | 
				
			||||||
				fmt.Sprintf(lc.Get(succTitleKey), util.BeautifulName(hyphaName)),
 | 
									fmt.Sprintf(lc.Get(succTitleKey), util.BeautifulName(hyphaName)),
 | 
				
			||||||
				succPageTemplate(rq, hyphaName, h.Exists),
 | 
									succPageTemplate(rq, hyphaName, h.DoesExist()),
 | 
				
			||||||
				lc,
 | 
									lc,
 | 
				
			||||||
				u))
 | 
									u))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -90,7 +90,7 @@ var handlerRenameAsk = factoryHandlerAsker(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func factoryHandlerConfirmer(
 | 
					func factoryHandlerConfirmer(
 | 
				
			||||||
	actionPath string,
 | 
						actionPath string,
 | 
				
			||||||
	confirmer func(*hyphae.Hypha, *user.User, *http.Request) (*history.Op, string),
 | 
						confirmer func(hyphae.Hypher, *user.User, *http.Request) (*history.Op, string),
 | 
				
			||||||
) func(http.ResponseWriter, *http.Request) {
 | 
					) func(http.ResponseWriter, *http.Request) {
 | 
				
			||||||
	return func(w http.ResponseWriter, rq *http.Request) {
 | 
						return func(w http.ResponseWriter, rq *http.Request) {
 | 
				
			||||||
		util.PrepareRq(rq)
 | 
							util.PrepareRq(rq)
 | 
				
			||||||
@@ -112,14 +112,14 @@ func factoryHandlerConfirmer(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var handlerUnattachConfirm = factoryHandlerConfirmer(
 | 
					var handlerUnattachConfirm = factoryHandlerConfirmer(
 | 
				
			||||||
	"unattach-confirm",
 | 
						"unattach-confirm",
 | 
				
			||||||
	func(h *hyphae.Hypha, u *user.User, rq *http.Request) (*history.Op, string) {
 | 
						func(h hyphae.Hypher, u *user.User, rq *http.Request) (*history.Op, string) {
 | 
				
			||||||
		return shroom.UnattachHypha(u, h, l18n.FromRequest(rq))
 | 
							return shroom.UnattachHypha(u, h, l18n.FromRequest(rq))
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var handlerDeleteConfirm = factoryHandlerConfirmer(
 | 
					var handlerDeleteConfirm = factoryHandlerConfirmer(
 | 
				
			||||||
	"delete-confirm",
 | 
						"delete-confirm",
 | 
				
			||||||
	func(h *hyphae.Hypha, u *user.User, rq *http.Request) (*history.Op, string) {
 | 
						func(h hyphae.Hypher, u *user.User, rq *http.Request) (*history.Op, string) {
 | 
				
			||||||
		return shroom.DeleteHypha(u, h, l18n.FromRequest(rq))
 | 
							return shroom.DeleteHypha(u, h, l18n.FromRequest(rq))
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -164,7 +164,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) {
 | 
				
			|||||||
			err.Error())
 | 
								err.Error())
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if h.Exists {
 | 
						if h.DoesExist() {
 | 
				
			||||||
		textAreaFill, err = shroom.FetchTextPart(h)
 | 
							textAreaFill, err = shroom.FetchTextPart(h)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.Println(err)
 | 
								log.Println(err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,7 +47,7 @@ func handlerAttachment(w http.ResponseWriter, rq *http.Request) {
 | 
				
			|||||||
	util.HTTP200Page(w,
 | 
						util.HTTP200Page(w,
 | 
				
			||||||
		views.BaseHTML(
 | 
							views.BaseHTML(
 | 
				
			||||||
			lc.Get("ui.attach_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName)}),
 | 
								lc.Get("ui.attach_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName)}),
 | 
				
			||||||
			views.AttachmentMenuHTML(rq, h, u),
 | 
								views.AttachmentMenuHTML(rq, h.(*hyphae.Hypha), u),
 | 
				
			||||||
			lc,
 | 
								lc,
 | 
				
			||||||
			u))
 | 
								u))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -138,10 +138,10 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) {
 | 
				
			|||||||
func handlerText(w http.ResponseWriter, rq *http.Request) {
 | 
					func handlerText(w http.ResponseWriter, rq *http.Request) {
 | 
				
			||||||
	util.PrepareRq(rq)
 | 
						util.PrepareRq(rq)
 | 
				
			||||||
	hyphaName := util.HyphaNameFromRq(rq, "text")
 | 
						hyphaName := util.HyphaNameFromRq(rq, "text")
 | 
				
			||||||
	if h := hyphae.ByName(hyphaName); h.Exists {
 | 
						if h := hyphae.ByName(hyphaName); h.DoesExist() {
 | 
				
			||||||
		log.Println("Serving", h.TextPath)
 | 
							log.Println("Serving", h.TextPartPath())
 | 
				
			||||||
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
 | 
							w.Header().Set("Content-Type", "text/plain; charset=utf-8")
 | 
				
			||||||
		http.ServeFile(w, rq, h.TextPath)
 | 
							http.ServeFile(w, rq, h.TextPartPath())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -149,7 +149,7 @@ func handlerText(w http.ResponseWriter, rq *http.Request) {
 | 
				
			|||||||
func handlerBinary(w http.ResponseWriter, rq *http.Request) {
 | 
					func handlerBinary(w http.ResponseWriter, rq *http.Request) {
 | 
				
			||||||
	util.PrepareRq(rq)
 | 
						util.PrepareRq(rq)
 | 
				
			||||||
	hyphaName := util.HyphaNameFromRq(rq, "binary")
 | 
						hyphaName := util.HyphaNameFromRq(rq, "binary")
 | 
				
			||||||
	if h := hyphae.ByName(hyphaName); h.Exists {
 | 
						if h := hyphae.ByName(hyphaName).(*hyphae.Hypha); h.DoesExist() {
 | 
				
			||||||
		log.Println("Serving", h.BinaryPath())
 | 
							log.Println("Serving", h.BinaryPath())
 | 
				
			||||||
		w.Header().Set("Content-Type", mimetype.FromExtension(filepath.Ext(h.BinaryPath())))
 | 
							w.Header().Set("Content-Type", mimetype.FromExtension(filepath.Ext(h.BinaryPath())))
 | 
				
			||||||
		http.ServeFile(w, rq, h.BinaryPath())
 | 
							http.ServeFile(w, rq, h.BinaryPath())
 | 
				
			||||||
@@ -167,9 +167,8 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) {
 | 
				
			|||||||
		u         = user.FromRequest(rq)
 | 
							u         = user.FromRequest(rq)
 | 
				
			||||||
		lc        = l18n.FromRequest(rq)
 | 
							lc        = l18n.FromRequest(rq)
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	if h.Exists {
 | 
						if h.DoesExist() {
 | 
				
			||||||
		fileContentsT, errT := os.ReadFile(h.TextPath)
 | 
							fileContentsT, errT := os.ReadFile(h.TextPartPath())
 | 
				
			||||||
		_, errB := os.Stat(h.BinaryPath())
 | 
					 | 
				
			||||||
		if errT == nil {
 | 
							if errT == nil {
 | 
				
			||||||
			ctx, _ := mycocontext.ContextFromStringInput(hyphaName, string(fileContentsT))
 | 
								ctx, _ := mycocontext.ContextFromStringInput(hyphaName, string(fileContentsT))
 | 
				
			||||||
			ctx = mycocontext.WithWebSiteURL(ctx, cfg.URL)
 | 
								ctx = mycocontext.WithWebSiteURL(ctx, cfg.URL)
 | 
				
			||||||
@@ -178,7 +177,7 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) {
 | 
				
			|||||||
			contents = mycomarkup.BlocksToHTML(ctx, ast)
 | 
								contents = mycomarkup.BlocksToHTML(ctx, ast)
 | 
				
			||||||
			openGraph = getOpenGraph()
 | 
								openGraph = getOpenGraph()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if !os.IsNotExist(errB) {
 | 
							if h.Kind() == hyphae.HyphaMedia {
 | 
				
			||||||
			contents = views.AttachmentHTML(h, lc) + contents
 | 
								contents = views.AttachmentHTML(h, lc) + contents
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user